parent
b7985baffb
commit
a74a36b4bc
2 changed files with 87 additions and 10 deletions
|
@ -495,11 +495,22 @@ const expectEqual = std.testing.expectEqual;
|
||||||
const parse_test_cases = .{
|
const parse_test_cases = .{
|
||||||
//input, expected
|
//input, expected
|
||||||
.{ "j", &.{KeyEvent{ .key = 'j' }} },
|
.{ "j", &.{KeyEvent{ .key = 'j' }} },
|
||||||
|
.{ "J", &.{KeyEvent{ .key = 'j', .modifiers = input.mod.shift }} },
|
||||||
.{ "jk", &.{ KeyEvent{ .key = 'j' }, KeyEvent{ .key = 'k' } } },
|
.{ "jk", &.{ KeyEvent{ .key = 'j' }, KeyEvent{ .key = 'k' } } },
|
||||||
.{ "<Space>", &.{KeyEvent{ .key = input.key.space }} },
|
.{ "<Space>", &.{KeyEvent{ .key = input.key.space }} },
|
||||||
.{ "<C-x><C-c>", &.{ KeyEvent{ .key = 'x', .modifiers = input.mod.ctrl }, KeyEvent{ .key = 'c', .modifiers = input.mod.ctrl } } },
|
.{ "<C-x><C-c>", &.{ KeyEvent{ .key = 'x', .modifiers = input.mod.ctrl }, KeyEvent{ .key = 'c', .modifiers = input.mod.ctrl } } },
|
||||||
.{ "<A-x><Tab>", &.{ KeyEvent{ .key = 'x', .modifiers = input.mod.alt }, KeyEvent{ .key = input.key.tab } } },
|
.{ "<A-x><Tab>", &.{ KeyEvent{ .key = 'x', .modifiers = input.mod.alt }, KeyEvent{ .key = input.key.tab } } },
|
||||||
.{ "<S-A-x><D-Del>", &.{ KeyEvent{ .key = 'x', .modifiers = input.mod.alt | input.mod.shift }, KeyEvent{ .key = input.key.delete, .modifiers = input.mod.super } } },
|
.{ "<S-A-x><D-Del>", &.{
|
||||||
|
KeyEvent{ .key = 'x', .modifiers = input.mod.alt | input.mod.shift },
|
||||||
|
KeyEvent{ .key = input.key.delete, .modifiers = input.mod.super },
|
||||||
|
} },
|
||||||
|
.{ ".", &.{KeyEvent{ .key = '.' }} },
|
||||||
|
.{ ",", &.{KeyEvent{ .key = ',' }} },
|
||||||
|
.{ "`", &.{KeyEvent{ .key = '`' }} },
|
||||||
|
.{ "<S--><Home>", &.{
|
||||||
|
KeyEvent{ .key = '-', .modifiers = input.mod.shift },
|
||||||
|
KeyEvent{ .key = input.key.home },
|
||||||
|
} },
|
||||||
};
|
};
|
||||||
|
|
||||||
test "parse" {
|
test "parse" {
|
||||||
|
|
|
@ -14,10 +14,11 @@ pub const ParseError = error{
|
||||||
InvalidInitialCharacter,
|
InvalidInitialCharacter,
|
||||||
InvalidStartOfControlBinding,
|
InvalidStartOfControlBinding,
|
||||||
InvalidStartOfShiftBinding,
|
InvalidStartOfShiftBinding,
|
||||||
InvalidStartOfDeleteBinding,
|
InvalidStartOfDelBinding,
|
||||||
|
InvalidStartOfHomeBinding,
|
||||||
InvalidCRBinding,
|
InvalidCRBinding,
|
||||||
InvalidSpaceBinding,
|
InvalidSpaceBinding,
|
||||||
InvalidDeleteBinding,
|
InvalidDelBinding,
|
||||||
InvalidTabBinding,
|
InvalidTabBinding,
|
||||||
InvalidUpBinding,
|
InvalidUpBinding,
|
||||||
InvalidEscapeBinding,
|
InvalidEscapeBinding,
|
||||||
|
@ -29,6 +30,10 @@ pub const ParseError = error{
|
||||||
InvalidEscapeSequenceDelimiter,
|
InvalidEscapeSequenceDelimiter,
|
||||||
InvalidModifier,
|
InvalidModifier,
|
||||||
InvalidEscapeSequenceEnd,
|
InvalidEscapeSequenceEnd,
|
||||||
|
InvalidHomeBinding,
|
||||||
|
InvalidEndBinding,
|
||||||
|
InvalidBSBinding,
|
||||||
|
InvalidInsertBinding,
|
||||||
};
|
};
|
||||||
|
|
||||||
var parse_error_buf: [256]u8 = undefined;
|
var parse_error_buf: [256]u8 = undefined;
|
||||||
|
@ -62,6 +67,10 @@ pub fn parse_key_events(allocator: std.mem.Allocator, event: input.Event, str: [
|
||||||
down,
|
down,
|
||||||
left,
|
left,
|
||||||
right,
|
right,
|
||||||
|
home,
|
||||||
|
end,
|
||||||
|
insert,
|
||||||
|
bs,
|
||||||
};
|
};
|
||||||
var state: State = .base;
|
var state: State = .base;
|
||||||
var function_key_number: u8 = 0;
|
var function_key_number: u8 = 0;
|
||||||
|
@ -72,19 +81,29 @@ pub fn parse_key_events(allocator: std.mem.Allocator, event: input.Event, str: [
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (i < str.len) {
|
while (i < str.len) {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
|
// zig fmt: off
|
||||||
.base => {
|
.base => {
|
||||||
switch (str[i]) {
|
switch (str[i]) {
|
||||||
'<' => {
|
'<' => {
|
||||||
state = .escape_sequence_start;
|
state = .escape_sequence_start;
|
||||||
i += 1;
|
i += 1;
|
||||||
},
|
},
|
||||||
'a'...'z', '\\', '[', ']', '/', '`', '-', '=', ';', '0'...'9' => {
|
//lowercase characters
|
||||||
try result.append(.{ .event = event, .key = str[i] });
|
'a'...'z',
|
||||||
|
'0'...'9',
|
||||||
|
'`', '-', '=', '[', ']', '\\', ';', '\'', ',', '.', '/', => {
|
||||||
|
try result.append(.{ .key = str[i] });
|
||||||
|
i += 1;
|
||||||
|
},
|
||||||
|
//uppercase letters also allowed here
|
||||||
|
'A'...'Z', => {
|
||||||
|
try result.append(.{ .key = std.ascii.toLower(str[i]), .modifiers = input.mod.shift});
|
||||||
i += 1;
|
i += 1;
|
||||||
},
|
},
|
||||||
else => return parse_error(error.InvalidInitialCharacter, "str: {s}, i: {} c: {c}", .{ str, i, str[i] }),
|
else => return parse_error(error.InvalidInitialCharacter, "str: {s}, i: {} c: {c}", .{ str, i, str[i] }),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// zig fmt: on
|
||||||
.escape_sequence_start => {
|
.escape_sequence_start => {
|
||||||
switch (str[i]) {
|
switch (str[i]) {
|
||||||
'A' => {
|
'A' => {
|
||||||
|
@ -128,6 +147,12 @@ pub fn parse_key_events(allocator: std.mem.Allocator, event: input.Event, str: [
|
||||||
'R' => {
|
'R' => {
|
||||||
state = .right;
|
state = .right;
|
||||||
},
|
},
|
||||||
|
'I' => {
|
||||||
|
state = .insert;
|
||||||
|
},
|
||||||
|
'B' => {
|
||||||
|
state = .bs;
|
||||||
|
},
|
||||||
'E' => {
|
'E' => {
|
||||||
state = .esc;
|
state = .esc;
|
||||||
},
|
},
|
||||||
|
@ -142,12 +167,47 @@ pub fn parse_key_events(allocator: std.mem.Allocator, event: input.Event, str: [
|
||||||
'e' => {
|
'e' => {
|
||||||
state = .del;
|
state = .del;
|
||||||
},
|
},
|
||||||
else => return parse_error(error.InvalidStartOfDeleteBinding, "str: {s}, i: {} c: {c}", .{ str, i, str[i] }),
|
else => return parse_error(error.InvalidStartOfDelBinding, "str: {s}, i: {} c: {c}", .{ str, i, str[i] }),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
else => return parse_error(error.InvalidEscapeSequenceStart, "str: {s}, i: {} c: {c}", .{ str, i, str[i] }),
|
'H' => {
|
||||||
|
state = .home;
|
||||||
|
},
|
||||||
|
else => return parse_error(error.InvalidStartOfHomeBinding, "str: {s}, i: {} c: {c}", .{ str, i, str[i] }),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
.insert => {
|
||||||
|
if (std.mem.indexOf(u8, str[i..], "Insert") == 0) {
|
||||||
|
try result.append(.{ .key = input.key.insert, .modifiers = modifiers });
|
||||||
|
modifiers = 0;
|
||||||
|
state = .escape_sequence_end;
|
||||||
|
i += 4;
|
||||||
|
} else return parse_error(error.InvalidInsertBinding, "str: {s}, i: {} c: {c}", .{ str, i, str[i] });
|
||||||
|
},
|
||||||
|
.end => {
|
||||||
|
if (std.mem.indexOf(u8, str[i..], "End") == 0) {
|
||||||
|
try result.append(.{ .key = input.key.end, .modifiers = modifiers });
|
||||||
|
modifiers = 0;
|
||||||
|
state = .escape_sequence_end;
|
||||||
|
i += 3;
|
||||||
|
} else return parse_error(error.InvalidEndBinding, "str: {s}, i: {} c: {c}", .{ str, i, str[i] });
|
||||||
|
},
|
||||||
|
.home => {
|
||||||
|
if (std.mem.indexOf(u8, str[i..], "Home") == 0) {
|
||||||
|
try result.append(.{ .key = input.key.home, .modifiers = modifiers });
|
||||||
|
modifiers = 0;
|
||||||
|
state = .escape_sequence_end;
|
||||||
|
i += 4;
|
||||||
|
} else return parse_error(error.InvalidHomeBinding, "str: {s}, i: {} c: {c}", .{ str, i, str[i] });
|
||||||
|
},
|
||||||
|
.bs => {
|
||||||
|
if (std.mem.indexOf(u8, str[i..], "BS") == 0) {
|
||||||
|
try result.append(.{ .key = input.key.backspace, .modifiers = modifiers });
|
||||||
|
modifiers = 0;
|
||||||
|
state = .escape_sequence_end;
|
||||||
|
i += 2;
|
||||||
|
} else return parse_error(error.InvalidBSBinding, "str: {s}, i: {} c: {c}", .{ str, i, str[i] });
|
||||||
|
},
|
||||||
.cr => {
|
.cr => {
|
||||||
if (std.mem.indexOf(u8, str[i..], "CR") == 0) {
|
if (std.mem.indexOf(u8, str[i..], "CR") == 0) {
|
||||||
try result.append(.{ .event = event, .key = input.key.enter, .modifiers = modifiers });
|
try result.append(.{ .event = event, .key = input.key.enter, .modifiers = modifiers });
|
||||||
|
@ -170,7 +230,7 @@ pub fn parse_key_events(allocator: std.mem.Allocator, event: input.Event, str: [
|
||||||
modifiers = 0;
|
modifiers = 0;
|
||||||
state = .escape_sequence_end;
|
state = .escape_sequence_end;
|
||||||
i += 3;
|
i += 3;
|
||||||
} else return parse_error(error.InvalidDeleteBinding, "str: {s}, i: {} c: {c}", .{ str, i, str[i] });
|
} else return parse_error(error.InvalidDelBinding, "str: {s}, i: {} c: {c}", .{ str, i, str[i] });
|
||||||
},
|
},
|
||||||
.tab => {
|
.tab => {
|
||||||
if (std.mem.indexOf(u8, str[i..], "Tab") == 0) {
|
if (std.mem.indexOf(u8, str[i..], "Tab") == 0) {
|
||||||
|
@ -249,10 +309,15 @@ pub fn parse_key_events(allocator: std.mem.Allocator, event: input.Event, str: [
|
||||||
else => return parse_error(error.InvalidEscapeSequenceDelimiter, "str: {s}, i: {} c: {c}", .{ str, i, str[i] }),
|
else => return parse_error(error.InvalidEscapeSequenceDelimiter, "str: {s}, i: {} c: {c}", .{ str, i, str[i] }),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// zig fmt: off
|
||||||
.char_or_key_or_modifier => {
|
.char_or_key_or_modifier => {
|
||||||
switch (str[i]) {
|
switch (str[i]) {
|
||||||
'a'...'z', ';', '0'...'9' => {
|
//lowercase characters only inside the escape sequence
|
||||||
try result.append(.{ .event = event, .key = str[i], .modifiers = modifiers });
|
'a'...'z',
|
||||||
|
'0'...'9',
|
||||||
|
'`', '-', '=', '[', ']', '\\', ';', '\'', ',', '.', '/',
|
||||||
|
=> {
|
||||||
|
try result.append(.{ .key = str[i], .modifiers = modifiers });
|
||||||
modifiers = 0;
|
modifiers = 0;
|
||||||
state = .escape_sequence_end;
|
state = .escape_sequence_end;
|
||||||
i += 1;
|
i += 1;
|
||||||
|
@ -262,6 +327,7 @@ pub fn parse_key_events(allocator: std.mem.Allocator, event: input.Event, str: [
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// zig fmt: on
|
||||||
.modifier => {
|
.modifier => {
|
||||||
modifiers |= switch (str[i]) {
|
modifiers |= switch (str[i]) {
|
||||||
'A' => input.mod.alt,
|
'A' => input.mod.alt,
|
||||||
|
|
Loading…
Add table
Reference in a new issue