a modern tui library written in zig

feat: add detection of kitty multi cursor protocol support (cap_multi_cursor)

authored by neurocyte.flow-control.dev and committed by rockorager.dev 551e7cd6 f6be46db

+4
src/Loop.zig
··· 362 362 log.info("color_scheme_updates capability detected", .{}); 363 363 vx.caps.color_scheme_updates = true; 364 364 }, 365 + .cap_multi_cursor => { 366 + log.info("multi cursor capability detected", .{}); 367 + vx.caps.multi_cursor = true; 368 + }, 365 369 .cap_da1 => { 366 370 std.Thread.Futex.wake(&vx.query_futex, 10); 367 371 vx.queries_done.store(true, .unordered);
+37
src/Parser.zig
··· 646 646 else => return null_event, 647 647 } 648 648 }, 649 + 'q' => { 650 + // kitty multi cursor cap (CSI > 1;2;3;29;30;40;100;101 TRAILER) (TRAILER is " q") 651 + const second_final = sequence[sequence.len - 2]; 652 + if (second_final != ' ') return null_event; 653 + // check for any digits. we're not too picky about checking the supported cursor types here 654 + for (sequence[0 .. sequence.len - 2]) |c| switch (c) { 655 + '0'...'9' => return .{ .event = .cap_multi_cursor, .n = sequence.len }, 656 + else => continue, 657 + }; 658 + return null_event; 659 + }, 649 660 else => return null_event, 650 661 } 651 662 } ··· 1075 1086 const actual = result.event.?.key_press; 1076 1087 try testing.expectEqualStrings(expected_key.text.?, actual.text.?); 1077 1088 try testing.expectEqual(expected_key.codepoint, actual.codepoint); 1089 + } 1090 + 1091 + test "parse(csi): kitty multi cursor" { 1092 + var buf: [1]u8 = undefined; 1093 + { 1094 + const input = "\x1b[>1;2;3;29;30;40;100;101 q"; 1095 + const result = parseCsi(input, &buf); 1096 + const expected: Result = .{ 1097 + .event = .cap_multi_cursor, 1098 + .n = input.len, 1099 + }; 1100 + 1101 + try testing.expectEqual(expected.n, result.n); 1102 + try testing.expectEqual(expected.event, result.event); 1103 + } 1104 + { 1105 + const input = "\x1b[> q"; 1106 + const result = parseCsi(input, &buf); 1107 + const expected: Result = .{ 1108 + .event = null, 1109 + .n = input.len, 1110 + }; 1111 + 1112 + try testing.expectEqual(expected.n, result.n); 1113 + try testing.expectEqual(expected.event, result.event); 1114 + } 1078 1115 } 1079 1116 1080 1117 test "parse(csi): decrpm" {
+2
src/Vaxis.zig
··· 38 38 color_scheme_updates: bool = false, 39 39 explicit_width: bool = false, 40 40 scaled_text: bool = false, 41 + multi_cursor: bool = false, 41 42 }; 42 43 43 44 pub const Options = struct { ··· 300 301 // why we see a Shift modifier 301 302 ctlseqs.home ++ 302 303 ctlseqs.scaled_text_query ++ 304 + ctlseqs.multi_cursor_query ++ 303 305 ctlseqs.cursor_position_request ++ 304 306 ctlseqs.xtversion ++ 305 307 ctlseqs.csi_u_query ++
+1
src/ctlseqs.zig
··· 14 14 pub const cursor_position_request = "\x1b[6n"; 15 15 pub const explicit_width_query = "\x1b]66;w=1; \x1b\\"; 16 16 pub const scaled_text_query = "\x1b]66;s=2; \x1b\\"; 17 + pub const multi_cursor_query = "\x1b[> q"; 17 18 18 19 // mouse. We try for button motion and any motion. terminals will enable the 19 20 // last one we tried (any motion). This was added because zellij doesn't
+1
src/event.zig
··· 26 26 cap_unicode, 27 27 cap_da1, 28 28 cap_color_scheme_updates, 29 + cap_multi_cursor, 29 30 };