this repo has no description
1const std = @import("std");
2const vaxis = @import("../../main.zig");
3
4pub fn encode(
5 writer: *std.Io.Writer,
6 key: vaxis.Key,
7 press: bool,
8 kitty_flags: vaxis.Key.KittyFlags,
9) !void {
10 const flags: u5 = @bitCast(kitty_flags);
11 switch (press) {
12 true => {
13 switch (flags) {
14 0 => try legacy(writer, key),
15 else => unreachable, // TODO: kitty encodings
16 }
17 },
18 false => {},
19 }
20}
21
22fn legacy(writer: *std.Io.Writer, key: vaxis.Key) !void {
23 // If we have text, we always write it directly
24 if (key.text) |text| {
25 try writer.writeAll(text);
26 return;
27 }
28
29 const shift = 0b00000001;
30 const alt = 0b00000010;
31 const ctrl = 0b00000100;
32
33 const effective_mods: u8 = blk: {
34 const mods: u8 = @bitCast(key.mods);
35 break :blk mods & (shift | alt | ctrl);
36 };
37
38 // If we have no mods and an ascii byte, write it directly
39 if (effective_mods == 0 and key.codepoint <= 0x7F) {
40 const b: u8 = @truncate(key.codepoint);
41 try writer.writeByte(b);
42 return;
43 }
44
45 // If we are lowercase ascii and ctrl, we map to a control byte
46 if (effective_mods == ctrl and key.codepoint >= 'a' and key.codepoint <= 'z') {
47 const b: u8 = @truncate(key.codepoint);
48 try writer.writeByte(b -| 0x60);
49 return;
50 }
51
52 // If we are printable ascii + alt
53 if (effective_mods == alt and key.codepoint >= ' ' and key.codepoint < 0x7F) {
54 const b: u8 = @truncate(key.codepoint);
55 try writer.print("\x1b{c}", .{b});
56 return;
57 }
58
59 // If we are ctrl + alt + lowercase ascii
60 if (effective_mods == (ctrl | alt) and key.codepoint >= 'a' and key.codepoint <= 'z') {
61 // convert to control sequence
62 try writer.print("\x1b{d}", .{key.codepoint - 0x60});
63 }
64
65 const def = switch (key.codepoint) {
66 vaxis.Key.escape => escape,
67 vaxis.Key.enter,
68 vaxis.Key.kp_enter,
69 => enter,
70 vaxis.Key.tab => tab,
71 vaxis.Key.backspace => backspace,
72 vaxis.Key.insert,
73 vaxis.Key.kp_insert,
74 => insert,
75 vaxis.Key.delete,
76 vaxis.Key.kp_delete,
77 => delete,
78 vaxis.Key.left,
79 vaxis.Key.kp_left,
80 => left,
81 vaxis.Key.right,
82 vaxis.Key.kp_right,
83 => right,
84 vaxis.Key.up,
85 vaxis.Key.kp_up,
86 => up,
87 vaxis.Key.down,
88 vaxis.Key.kp_down,
89 => down,
90 vaxis.Key.page_up,
91 vaxis.Key.kp_page_up,
92 => page_up,
93 vaxis.Key.page_down,
94 vaxis.Key.kp_page_down,
95 => page_down,
96 vaxis.Key.home,
97 vaxis.Key.kp_home,
98 => home,
99 vaxis.Key.end,
100 vaxis.Key.kp_end,
101 => end,
102 vaxis.Key.f1 => f1,
103 vaxis.Key.f2 => f2,
104 vaxis.Key.f3 => f3_legacy,
105 vaxis.Key.f4 => f4,
106 vaxis.Key.f5 => f5,
107 vaxis.Key.f6 => f6,
108 vaxis.Key.f7 => f7,
109 vaxis.Key.f8 => f8,
110 vaxis.Key.f9 => f9,
111 vaxis.Key.f10 => f10,
112 vaxis.Key.f11 => f11,
113 vaxis.Key.f12 => f12,
114 else => return, // TODO: more keys
115 };
116
117 switch (effective_mods) {
118 0 => {
119 if (def.number == 1)
120 switch (key.codepoint) {
121 vaxis.Key.f1,
122 vaxis.Key.f2,
123 vaxis.Key.f3,
124 vaxis.Key.f4,
125 => try writer.print("\x1bO{c}", .{def.suffix}),
126 else => try writer.print("\x1b[{c}", .{def.suffix}),
127 }
128 else
129 try writer.print("\x1b[{d}{c}", .{ def.number, def.suffix });
130 },
131 else => try writer.print("\x1b[{d};{d}{c}", .{ def.number, effective_mods + 1, def.suffix }),
132 }
133}
134
135const Definition = struct {
136 number: u21,
137 suffix: u8,
138};
139
140const escape: Definition = .{ .number = 27, .suffix = 'u' };
141const enter: Definition = .{ .number = 13, .suffix = 'u' };
142const tab: Definition = .{ .number = 9, .suffix = 'u' };
143const backspace: Definition = .{ .number = 127, .suffix = 'u' };
144const insert: Definition = .{ .number = 2, .suffix = '~' };
145const delete: Definition = .{ .number = 3, .suffix = '~' };
146const left: Definition = .{ .number = 1, .suffix = 'D' };
147const right: Definition = .{ .number = 1, .suffix = 'C' };
148const up: Definition = .{ .number = 1, .suffix = 'A' };
149const down: Definition = .{ .number = 1, .suffix = 'B' };
150const page_up: Definition = .{ .number = 5, .suffix = '~' };
151const page_down: Definition = .{ .number = 6, .suffix = '~' };
152const home: Definition = .{ .number = 1, .suffix = 'H' };
153const end: Definition = .{ .number = 1, .suffix = 'F' };
154const caps_lock: Definition = .{ .number = 57358, .suffix = 'u' };
155const scroll_lock: Definition = .{ .number = 57359, .suffix = 'u' };
156const num_lock: Definition = .{ .number = 57360, .suffix = 'u' };
157const print_screen: Definition = .{ .number = 57361, .suffix = 'u' };
158const pause: Definition = .{ .number = 57362, .suffix = 'u' };
159const menu: Definition = .{ .number = 57363, .suffix = 'u' };
160const f1: Definition = .{ .number = 1, .suffix = 'P' };
161const f2: Definition = .{ .number = 1, .suffix = 'Q' };
162const f3: Definition = .{ .number = 13, .suffix = '~' };
163const f3_legacy: Definition = .{ .number = 1, .suffix = 'R' };
164const f4: Definition = .{ .number = 1, .suffix = 'S' };
165const f5: Definition = .{ .number = 15, .suffix = '~' };
166const f6: Definition = .{ .number = 17, .suffix = '~' };
167const f7: Definition = .{ .number = 18, .suffix = '~' };
168const f8: Definition = .{ .number = 19, .suffix = '~' };
169const f9: Definition = .{ .number = 20, .suffix = '~' };
170const f10: Definition = .{ .number = 21, .suffix = '~' };
171const f11: Definition = .{ .number = 23, .suffix = '~' };
172const f12: Definition = .{ .number = 24, .suffix = '~' };