parser: add unit tests

Test (nearly?) implementation so far

Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
This commit is contained in:
Tim Culverhouse 2024-01-21 13:14:30 -06:00
parent 4ac15e2195
commit 244ad8b68e
2 changed files with 176 additions and 13 deletions

View file

@ -6,4 +6,6 @@ pub const Event = union(enum) {
key_press: Key, key_press: Key,
focus_in, focus_in,
focus_out, focus_out,
paste_start,
paste_end,
}; };

View file

@ -106,13 +106,12 @@ pub fn parse(input: []const u8) !Result {
}; };
return .{ return .{
.event = .{ .key_press = key }, .event = .{ .key_press = key },
.n = i, .n = i + 1,
}; };
}, },
} }
}, },
.ss3 => { .ss3 => {
state = .ground;
const key: Key = switch (b) { const key: Key = switch (b) {
'A' => .{ .codepoint = Key.up }, 'A' => .{ .codepoint = Key.up },
'B' => .{ .codepoint = Key.down }, 'B' => .{ .codepoint = Key.down },
@ -128,13 +127,13 @@ pub fn parse(input: []const u8) !Result {
log.warn("unhandled ss3: {x}", .{b}); log.warn("unhandled ss3: {x}", .{b});
return .{ return .{
.event = null, .event = null,
.n = i, .n = i + 1,
}; };
}, },
}; };
return .{ return .{
.event = .{ .key_press = key }, .event = .{ .key_press = key },
.n = i, .n = i + 1,
}; };
}, },
.csi => { .csi => {
@ -231,12 +230,16 @@ pub fn parse(input: []const u8) !Result {
23 => break :blk Key.f11, 23 => break :blk Key.f11,
24 => break :blk Key.f12, 24 => break :blk Key.f12,
200 => { 200 => {
// TODO: bracketed paste return .{
continue; .event = .paste_start,
.n = i + 1,
};
}, },
201 => { 201 => {
// TODO: bracketed paste return .{
continue; .event = .paste_end,
.n = i + 1,
};
}, },
57427 => break :blk Key.kp_begin, 57427 => break :blk Key.kp_begin,
else => { else => {
@ -262,10 +265,10 @@ pub fn parse(input: []const u8) !Result {
}, },
'I' => { // focus in 'I' => { // focus in
return .{ .event = .focus_in, .n = i }; return .{ .event = .focus_in, .n = i + 1 };
}, },
'O' => { // focus out 'O' => { // focus out
return .{ .event = .focus_out, .n = i }; return .{ .event = .focus_out, .n = i + 1 };
}, },
else => { else => {
log.warn("unhandled csi: CSI {s}", .{input[start + 1 .. i + 1]}); log.warn("unhandled csi: CSI {s}", .{input[start + 1 .. i + 1]});
@ -316,7 +319,7 @@ pub fn parse(input: []const u8) !Result {
} }
return .{ return .{
.event = .{ .key_press = key }, .event = .{ .key_press = key },
.n = i, .n = i + 1,
}; };
}, },
} }
@ -332,7 +335,7 @@ pub fn parse(input: []const u8) !Result {
}; };
} }
test "parse: single legacy keypress" { test "parse: single xterm keypress" {
const input = "a"; const input = "a";
const result = try parse(input); const result = try parse(input);
const expected_key: Key = .{ .codepoint = 'a' }; const expected_key: Key = .{ .codepoint = 'a' };
@ -342,7 +345,7 @@ test "parse: single legacy keypress" {
try testing.expectEqual(expected_event, result.event); try testing.expectEqual(expected_event, result.event);
} }
test "parse: single legacy keypress with more buffer" { test "parse: single xterm keypress with more buffer" {
const input = "ab"; const input = "ab";
const result = try parse(input); const result = try parse(input);
const expected_key: Key = .{ .codepoint = 'a' }; const expected_key: Key = .{ .codepoint = 'a' };
@ -351,3 +354,161 @@ test "parse: single legacy keypress with more buffer" {
try testing.expectEqual(1, result.n); try testing.expectEqual(1, result.n);
try testing.expectEqual(expected_event, result.event); try testing.expectEqual(expected_event, result.event);
} }
test "parse: xterm escape keypress" {
const input = "\x1b";
const result = try parse(input);
const expected_key: Key = .{ .codepoint = Key.escape };
const expected_event: Event = .{ .key_press = expected_key };
try testing.expectEqual(1, result.n);
try testing.expectEqual(expected_event, result.event);
}
test "parse: xterm ctrl+a" {
const input = "\x01";
const result = try parse(input);
const expected_key: Key = .{ .codepoint = 'a', .mods = .{ .ctrl = true } };
const expected_event: Event = .{ .key_press = expected_key };
try testing.expectEqual(1, result.n);
try testing.expectEqual(expected_event, result.event);
}
test "parse: xterm alt+a" {
const input = "\x1ba";
const result = try parse(input);
const expected_key: Key = .{ .codepoint = 'a', .mods = .{ .alt = true } };
const expected_event: Event = .{ .key_press = expected_key };
try testing.expectEqual(2, result.n);
try testing.expectEqual(expected_event, result.event);
}
test "parse: xterm invalid ss3" {
const input = "\x1bOZ";
const result = try parse(input);
try testing.expectEqual(3, result.n);
try testing.expectEqual(null, result.event);
}
test "parse: xterm key up" {
{
// normal version
const input = "\x1bOA";
const result = try parse(input);
const expected_key: Key = .{ .codepoint = Key.up };
const expected_event: Event = .{ .key_press = expected_key };
try testing.expectEqual(3, result.n);
try testing.expectEqual(expected_event, result.event);
}
{
// application keys version
const input = "\x1b[2~";
const result = try parse(input);
const expected_key: Key = .{ .codepoint = Key.insert };
const expected_event: Event = .{ .key_press = expected_key };
try testing.expectEqual(4, result.n);
try testing.expectEqual(expected_event, result.event);
}
}
test "parse: xterm shift+up" {
const input = "\x1b[1;2A";
const result = try parse(input);
const expected_key: Key = .{ .codepoint = Key.up, .mods = .{ .shift = true } };
const expected_event: Event = .{ .key_press = expected_key };
try testing.expectEqual(6, result.n);
try testing.expectEqual(expected_event, result.event);
}
test "parse: xterm insert" {
const input = "\x1b[1;2A";
const result = try parse(input);
const expected_key: Key = .{ .codepoint = Key.up, .mods = .{ .shift = true } };
const expected_event: Event = .{ .key_press = expected_key };
try testing.expectEqual(6, result.n);
try testing.expectEqual(expected_event, result.event);
}
test "parse: paste_start" {
const input = "\x1b[200~";
const result = try parse(input);
const expected_event: Event = .paste_start;
try testing.expectEqual(6, result.n);
try testing.expectEqual(expected_event, result.event);
}
test "parse: paste_end" {
const input = "\x1b[201~";
const result = try parse(input);
const expected_event: Event = .paste_end;
try testing.expectEqual(6, result.n);
try testing.expectEqual(expected_event, result.event);
}
test "parse: focus_in" {
const input = "\x1b[I";
const result = try parse(input);
const expected_event: Event = .focus_in;
try testing.expectEqual(3, result.n);
try testing.expectEqual(expected_event, result.event);
}
test "parse: focus_out" {
const input = "\x1b[O";
const result = try parse(input);
const expected_event: Event = .focus_out;
try testing.expectEqual(3, result.n);
try testing.expectEqual(expected_event, result.event);
}
test "parse: kitty: shift+a without text reporting" {
const input = "\x1b[97:65;2u";
const result = try parse(input);
const expected_key: Key = .{
.codepoint = 'a',
.shifted_codepoint = 'A',
.mods = .{ .shift = true },
};
const expected_event: Event = .{ .key_press = expected_key };
try testing.expectEqual(10, result.n);
try testing.expectEqual(expected_event, result.event);
}
test "parse: kitty: alt+shift+a without text reporting" {
const input = "\x1b[97:65;4u";
const result = try parse(input);
const expected_key: Key = .{
.codepoint = 'a',
.shifted_codepoint = 'A',
.mods = .{ .shift = true, .alt = true },
};
const expected_event: Event = .{ .key_press = expected_key };
try testing.expectEqual(10, result.n);
try testing.expectEqual(expected_event, result.event);
}
test "parse: kitty: a without text reporting" {
const input = "\x1b[97u";
const result = try parse(input);
const expected_key: Key = .{
.codepoint = 'a',
};
const expected_event: Event = .{ .key_press = expected_key };
try testing.expectEqual(5, result.n);
try testing.expectEqual(expected_event, result.event);
}