this repo has no description
13
fork

Configure Feed

Select the types of activity you want to include in your feed.

parser: handle shift+space in kkp+disambiguate

Some terminals (foot, ghostty) encode shift + space as CSI 32 ; 2 u when
using the kkp disambiguate flag. We need to handle this as a printable
character. Use the logic from vaxis (the go version), which checks if
the mods were shift only and the character is printable. Then we upper
case it, set the text and the shifted char

+49 -1
+6
src/Key.zig
··· 13 13 meta: bool = false, 14 14 caps_lock: bool = false, 15 15 num_lock: bool = false, 16 + 17 + pub fn eql(self: Modifiers, other: Modifiers) bool { 18 + const a: u8 = @bitCast(self); 19 + const b: u8 = @bitCast(other); 20 + return a == b; 21 + } 16 22 }; 17 23 18 24 /// Flags for the Kitty Protocol.
+43 -1
src/Parser.zig
··· 592 592 key.text = text_buf[0..total]; 593 593 } 594 594 595 + { 596 + // We check if we have *only* shift, no text, and a printable character. This can 597 + // happen when we have disambiguate on and a key is pressed and encoded as CSI u, 598 + // for example shift + space can produce CSI 32 ; 2 u 599 + const mod_test: Key.Modifiers = .{ 600 + .shift = true, 601 + .caps_lock = key.mods.caps_lock, 602 + .num_lock = key.mods.num_lock, 603 + }; 604 + if (key.text == null and 605 + key.mods.eql(mod_test) and 606 + key.codepoint <= std.math.maxInt(u8) and 607 + std.ascii.isPrint(@intCast(key.codepoint))) 608 + { 609 + // Encode the codepoint as upper 610 + const upper = std.ascii.toUpper(@intCast(key.codepoint)); 611 + const n = std.unicode.utf8Encode(upper, text_buf) catch unreachable; 612 + key.text = text_buf[0..n]; 613 + key.shifted_codepoint = upper; 614 + } 615 + } 616 + 595 617 const event: Event = if (is_release) 596 618 .{ .key_release = key } 597 619 else ··· 907 929 .codepoint = 'a', 908 930 .shifted_codepoint = 'A', 909 931 .mods = .{ .shift = true }, 932 + .text = "A", 910 933 }; 911 934 const expected_event: Event = .{ .key_press = expected_key }; 912 935 913 936 try testing.expectEqual(10, result.n); 914 - try testing.expectEqual(expected_event, result.event); 937 + try testing.expectEqualDeep(expected_event, result.event); 915 938 } 916 939 917 940 test "parse: kitty: alt+shift+a without text reporting" { ··· 1127 1150 try testing.expectEqual(expected.n, result.n); 1128 1151 try testing.expectEqual(expected.event, result.event); 1129 1152 } 1153 + 1154 + test "parse: disambiguate shift + space" { 1155 + const alloc = testing.allocator_instance.allocator(); 1156 + const grapheme_data = try grapheme.GraphemeData.init(alloc); 1157 + defer grapheme_data.deinit(); 1158 + const input = "\x1b[32;2u"; 1159 + var parser: Parser = .{ .grapheme_data = &grapheme_data }; 1160 + const result = try parser.parse(input, alloc); 1161 + const expected_key: Key = .{ 1162 + .codepoint = ' ', 1163 + .shifted_codepoint = ' ', 1164 + .mods = .{ .shift = true }, 1165 + .text = " ", 1166 + }; 1167 + const expected_event: Event = .{ .key_press = expected_key }; 1168 + 1169 + try testing.expectEqual(7, result.n); 1170 + try testing.expectEqualDeep(expected_event, result.event); 1171 + }