@mariozechner/pi-tui 0.24.0 → 0.24.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/editor.d.ts.map +1 -1
- package/dist/components/editor.js +46 -37
- package/dist/components/editor.js.map +1 -1
- package/dist/components/input.d.ts.map +1 -1
- package/dist/components/input.js +31 -15
- package/dist/components/input.js.map +1 -1
- package/dist/components/select-list.d.ts.map +1 -1
- package/dist/components/select-list.js +4 -4
- package/dist/components/select-list.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/keys.d.ts +104 -1
- package/dist/keys.d.ts.map +1 -1
- package/dist/keys.js +253 -16
- package/dist/keys.js.map +1 -1
- package/package.json +1 -1
package/dist/keys.js
CHANGED
|
@@ -4,13 +4,21 @@
|
|
|
4
4
|
* The Kitty keyboard protocol sends enhanced escape sequences in the format:
|
|
5
5
|
* \x1b[<codepoint>;<modifier>u
|
|
6
6
|
*
|
|
7
|
-
* Modifier
|
|
7
|
+
* Modifier bits (before adding 1 for transmission):
|
|
8
8
|
* - Shift: 1 (value 2)
|
|
9
9
|
* - Alt: 2 (value 3)
|
|
10
10
|
* - Ctrl: 4 (value 5)
|
|
11
11
|
* - Super: 8 (value 9)
|
|
12
|
+
* - Hyper: 16
|
|
13
|
+
* - Meta: 32
|
|
14
|
+
* - Caps_Lock: 64
|
|
15
|
+
* - Num_Lock: 128
|
|
12
16
|
*
|
|
13
17
|
* See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/
|
|
18
|
+
*
|
|
19
|
+
* NOTE: Some terminals (e.g., Ghostty on Linux) include lock key states
|
|
20
|
+
* (Caps Lock, Num Lock) in the modifier field. We mask these out when
|
|
21
|
+
* checking for key combinations since they shouldn't affect behavior.
|
|
14
22
|
*/
|
|
15
23
|
// Common codepoints
|
|
16
24
|
const CODEPOINTS = {
|
|
@@ -31,6 +39,8 @@ const CODEPOINTS = {
|
|
|
31
39
|
enter: 13,
|
|
32
40
|
backspace: 127,
|
|
33
41
|
};
|
|
42
|
+
// Lock key bits to ignore when matching (Caps Lock + Num Lock)
|
|
43
|
+
const LOCK_MASK = 64 + 128; // 192
|
|
34
44
|
// Modifier bits (before adding 1)
|
|
35
45
|
const MODIFIERS = {
|
|
36
46
|
shift: 1,
|
|
@@ -44,6 +54,83 @@ const MODIFIERS = {
|
|
|
44
54
|
function kittySequence(codepoint, modifier) {
|
|
45
55
|
return `\x1b[${codepoint};${modifier + 1}u`;
|
|
46
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Parse a Kitty keyboard protocol sequence.
|
|
59
|
+
* Handles formats:
|
|
60
|
+
* - \x1b[<codepoint>u (no modifier)
|
|
61
|
+
* - \x1b[<codepoint>;<modifier>u (with modifier)
|
|
62
|
+
* - \x1b[1;<modifier>A/B/C/D (arrow keys with modifier)
|
|
63
|
+
*
|
|
64
|
+
* Returns null if not a valid Kitty sequence.
|
|
65
|
+
*/
|
|
66
|
+
// Virtual codepoints for functional keys (negative to avoid conflicts)
|
|
67
|
+
const FUNCTIONAL_CODEPOINTS = {
|
|
68
|
+
delete: -10,
|
|
69
|
+
insert: -11,
|
|
70
|
+
pageUp: -12,
|
|
71
|
+
pageDown: -13,
|
|
72
|
+
home: -14,
|
|
73
|
+
end: -15,
|
|
74
|
+
};
|
|
75
|
+
function parseKittySequence(data) {
|
|
76
|
+
// Match CSI u format: \x1b[<num>u or \x1b[<num>;<mod>u
|
|
77
|
+
const csiUMatch = data.match(/^\x1b\[(\d+)(?:;(\d+))?u$/);
|
|
78
|
+
if (csiUMatch) {
|
|
79
|
+
const codepoint = parseInt(csiUMatch[1], 10);
|
|
80
|
+
const modValue = csiUMatch[2] ? parseInt(csiUMatch[2], 10) : 1;
|
|
81
|
+
return { codepoint, modifier: modValue - 1 };
|
|
82
|
+
}
|
|
83
|
+
// Match arrow keys with modifier: \x1b[1;<mod>A/B/C/D
|
|
84
|
+
const arrowMatch = data.match(/^\x1b\[1;(\d+)([ABCD])$/);
|
|
85
|
+
if (arrowMatch) {
|
|
86
|
+
const modValue = parseInt(arrowMatch[1], 10);
|
|
87
|
+
// Map arrow letters to virtual codepoints for easier matching
|
|
88
|
+
const arrowCodes = { A: -1, B: -2, C: -3, D: -4 };
|
|
89
|
+
const codepoint = arrowCodes[arrowMatch[2]];
|
|
90
|
+
return { codepoint, modifier: modValue - 1 };
|
|
91
|
+
}
|
|
92
|
+
// Match functional keys with ~ terminator: \x1b[<num>~ or \x1b[<num>;<mod>~
|
|
93
|
+
// DELETE=3, INSERT=2, PAGEUP=5, PAGEDOWN=6, etc.
|
|
94
|
+
const funcMatch = data.match(/^\x1b\[(\d+)(?:;(\d+))?~$/);
|
|
95
|
+
if (funcMatch) {
|
|
96
|
+
const keyNum = parseInt(funcMatch[1], 10);
|
|
97
|
+
const modValue = funcMatch[2] ? parseInt(funcMatch[2], 10) : 1;
|
|
98
|
+
// Map functional key numbers to virtual codepoints
|
|
99
|
+
const funcCodes = {
|
|
100
|
+
2: FUNCTIONAL_CODEPOINTS.insert,
|
|
101
|
+
3: FUNCTIONAL_CODEPOINTS.delete,
|
|
102
|
+
5: FUNCTIONAL_CODEPOINTS.pageUp,
|
|
103
|
+
6: FUNCTIONAL_CODEPOINTS.pageDown,
|
|
104
|
+
7: FUNCTIONAL_CODEPOINTS.home, // Alternative home
|
|
105
|
+
8: FUNCTIONAL_CODEPOINTS.end, // Alternative end
|
|
106
|
+
};
|
|
107
|
+
const codepoint = funcCodes[keyNum];
|
|
108
|
+
if (codepoint !== undefined) {
|
|
109
|
+
return { codepoint, modifier: modValue - 1 };
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// Match Home/End with modifier: \x1b[1;<mod>H/F
|
|
113
|
+
const homeEndMatch = data.match(/^\x1b\[1;(\d+)([HF])$/);
|
|
114
|
+
if (homeEndMatch) {
|
|
115
|
+
const modValue = parseInt(homeEndMatch[1], 10);
|
|
116
|
+
const codepoint = homeEndMatch[2] === "H" ? FUNCTIONAL_CODEPOINTS.home : FUNCTIONAL_CODEPOINTS.end;
|
|
117
|
+
return { codepoint, modifier: modValue - 1 };
|
|
118
|
+
}
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Check if a Kitty sequence matches the expected codepoint and modifier,
|
|
123
|
+
* ignoring lock key bits (Caps Lock, Num Lock).
|
|
124
|
+
*/
|
|
125
|
+
function matchesKittySequence(data, expectedCodepoint, expectedModifier) {
|
|
126
|
+
const parsed = parseKittySequence(data);
|
|
127
|
+
if (!parsed)
|
|
128
|
+
return false;
|
|
129
|
+
// Mask out lock bits from both sides for comparison
|
|
130
|
+
const actualMod = parsed.modifier & ~LOCK_MASK;
|
|
131
|
+
const expectedMod = expectedModifier & ~LOCK_MASK;
|
|
132
|
+
return parsed.codepoint === expectedCodepoint && actualMod === expectedMod;
|
|
133
|
+
}
|
|
47
134
|
// Pre-built sequences for common key combinations
|
|
48
135
|
export const Keys = {
|
|
49
136
|
// Ctrl+<letter> combinations
|
|
@@ -68,6 +155,7 @@ export const Keys = {
|
|
|
68
155
|
};
|
|
69
156
|
/**
|
|
70
157
|
* Check if input matches a Kitty protocol Ctrl+<key> sequence.
|
|
158
|
+
* Ignores lock key bits (Caps Lock, Num Lock).
|
|
71
159
|
* @param data - The input data to check
|
|
72
160
|
* @param key - Single lowercase letter (e.g., 'c' for Ctrl+C)
|
|
73
161
|
*/
|
|
@@ -75,16 +163,25 @@ export function isKittyCtrl(data, key) {
|
|
|
75
163
|
if (key.length !== 1)
|
|
76
164
|
return false;
|
|
77
165
|
const codepoint = key.charCodeAt(0);
|
|
78
|
-
|
|
166
|
+
// Check exact match first (fast path)
|
|
167
|
+
if (data === kittySequence(codepoint, MODIFIERS.ctrl))
|
|
168
|
+
return true;
|
|
169
|
+
// Check with lock bits masked out
|
|
170
|
+
return matchesKittySequence(data, codepoint, MODIFIERS.ctrl);
|
|
79
171
|
}
|
|
80
172
|
/**
|
|
81
173
|
* Check if input matches a Kitty protocol key sequence with specific modifier.
|
|
174
|
+
* Ignores lock key bits (Caps Lock, Num Lock).
|
|
82
175
|
* @param data - The input data to check
|
|
83
176
|
* @param codepoint - ASCII codepoint of the key
|
|
84
177
|
* @param modifier - Modifier value (use MODIFIERS constants)
|
|
85
178
|
*/
|
|
86
179
|
export function isKittyKey(data, codepoint, modifier) {
|
|
87
|
-
|
|
180
|
+
// Check exact match first (fast path)
|
|
181
|
+
if (data === kittySequence(codepoint, modifier))
|
|
182
|
+
return true;
|
|
183
|
+
// Check with lock bits masked out
|
|
184
|
+
return matchesKittySequence(data, codepoint, modifier);
|
|
88
185
|
}
|
|
89
186
|
// Raw control character codes
|
|
90
187
|
const RAW = {
|
|
@@ -103,82 +200,222 @@ const RAW = {
|
|
|
103
200
|
};
|
|
104
201
|
/**
|
|
105
202
|
* Check if input matches Ctrl+A (raw byte or Kitty protocol).
|
|
203
|
+
* Ignores lock key bits.
|
|
106
204
|
*/
|
|
107
205
|
export function isCtrlA(data) {
|
|
108
|
-
return data === RAW.CTRL_A || data === Keys.CTRL_A;
|
|
206
|
+
return data === RAW.CTRL_A || data === Keys.CTRL_A || matchesKittySequence(data, CODEPOINTS.a, MODIFIERS.ctrl);
|
|
109
207
|
}
|
|
110
208
|
/**
|
|
111
209
|
* Check if input matches Ctrl+C (raw byte or Kitty protocol).
|
|
210
|
+
* Ignores lock key bits.
|
|
112
211
|
*/
|
|
113
212
|
export function isCtrlC(data) {
|
|
114
|
-
return data === RAW.CTRL_C || data === Keys.CTRL_C;
|
|
213
|
+
return data === RAW.CTRL_C || data === Keys.CTRL_C || matchesKittySequence(data, CODEPOINTS.c, MODIFIERS.ctrl);
|
|
115
214
|
}
|
|
116
215
|
/**
|
|
117
216
|
* Check if input matches Ctrl+D (raw byte or Kitty protocol).
|
|
217
|
+
* Ignores lock key bits.
|
|
118
218
|
*/
|
|
119
219
|
export function isCtrlD(data) {
|
|
120
|
-
return data === RAW.CTRL_D || data === Keys.CTRL_D;
|
|
220
|
+
return data === RAW.CTRL_D || data === Keys.CTRL_D || matchesKittySequence(data, CODEPOINTS.d, MODIFIERS.ctrl);
|
|
121
221
|
}
|
|
122
222
|
/**
|
|
123
223
|
* Check if input matches Ctrl+E (raw byte or Kitty protocol).
|
|
224
|
+
* Ignores lock key bits.
|
|
124
225
|
*/
|
|
125
226
|
export function isCtrlE(data) {
|
|
126
|
-
return data === RAW.CTRL_E || data === Keys.CTRL_E;
|
|
227
|
+
return data === RAW.CTRL_E || data === Keys.CTRL_E || matchesKittySequence(data, CODEPOINTS.e, MODIFIERS.ctrl);
|
|
127
228
|
}
|
|
128
229
|
/**
|
|
129
230
|
* Check if input matches Ctrl+K (raw byte or Kitty protocol).
|
|
231
|
+
* Ignores lock key bits.
|
|
130
232
|
*/
|
|
131
233
|
export function isCtrlK(data) {
|
|
132
|
-
return data === RAW.CTRL_K || data === Keys.CTRL_K;
|
|
234
|
+
return data === RAW.CTRL_K || data === Keys.CTRL_K || matchesKittySequence(data, CODEPOINTS.k, MODIFIERS.ctrl);
|
|
133
235
|
}
|
|
134
236
|
/**
|
|
135
237
|
* Check if input matches Ctrl+O (raw byte or Kitty protocol).
|
|
238
|
+
* Ignores lock key bits.
|
|
136
239
|
*/
|
|
137
240
|
export function isCtrlO(data) {
|
|
138
|
-
return data === RAW.CTRL_O || data === Keys.CTRL_O;
|
|
241
|
+
return data === RAW.CTRL_O || data === Keys.CTRL_O || matchesKittySequence(data, CODEPOINTS.o, MODIFIERS.ctrl);
|
|
139
242
|
}
|
|
140
243
|
/**
|
|
141
244
|
* Check if input matches Ctrl+P (raw byte or Kitty protocol).
|
|
245
|
+
* Ignores lock key bits.
|
|
142
246
|
*/
|
|
143
247
|
export function isCtrlP(data) {
|
|
144
|
-
return data === RAW.CTRL_P || data === Keys.CTRL_P;
|
|
248
|
+
return data === RAW.CTRL_P || data === Keys.CTRL_P || matchesKittySequence(data, CODEPOINTS.p, MODIFIERS.ctrl);
|
|
145
249
|
}
|
|
146
250
|
/**
|
|
147
251
|
* Check if input matches Ctrl+T (raw byte or Kitty protocol).
|
|
252
|
+
* Ignores lock key bits.
|
|
148
253
|
*/
|
|
149
254
|
export function isCtrlT(data) {
|
|
150
|
-
return data === RAW.CTRL_T || data === Keys.CTRL_T;
|
|
255
|
+
return data === RAW.CTRL_T || data === Keys.CTRL_T || matchesKittySequence(data, CODEPOINTS.t, MODIFIERS.ctrl);
|
|
151
256
|
}
|
|
152
257
|
/**
|
|
153
258
|
* Check if input matches Ctrl+U (raw byte or Kitty protocol).
|
|
259
|
+
* Ignores lock key bits.
|
|
154
260
|
*/
|
|
155
261
|
export function isCtrlU(data) {
|
|
156
|
-
return data === RAW.CTRL_U || data === Keys.CTRL_U;
|
|
262
|
+
return data === RAW.CTRL_U || data === Keys.CTRL_U || matchesKittySequence(data, CODEPOINTS.u, MODIFIERS.ctrl);
|
|
157
263
|
}
|
|
158
264
|
/**
|
|
159
265
|
* Check if input matches Ctrl+W (raw byte or Kitty protocol).
|
|
266
|
+
* Ignores lock key bits.
|
|
160
267
|
*/
|
|
161
268
|
export function isCtrlW(data) {
|
|
162
|
-
return data === RAW.CTRL_W || data === Keys.CTRL_W;
|
|
269
|
+
return data === RAW.CTRL_W || data === Keys.CTRL_W || matchesKittySequence(data, CODEPOINTS.w, MODIFIERS.ctrl);
|
|
163
270
|
}
|
|
164
271
|
/**
|
|
165
272
|
* Check if input matches Alt+Backspace (legacy or Kitty protocol).
|
|
273
|
+
* Ignores lock key bits.
|
|
166
274
|
*/
|
|
167
275
|
export function isAltBackspace(data) {
|
|
168
|
-
return data === RAW.ALT_BACKSPACE ||
|
|
276
|
+
return (data === RAW.ALT_BACKSPACE ||
|
|
277
|
+
data === Keys.ALT_BACKSPACE ||
|
|
278
|
+
matchesKittySequence(data, CODEPOINTS.backspace, MODIFIERS.alt));
|
|
169
279
|
}
|
|
170
280
|
/**
|
|
171
281
|
* Check if input matches Shift+Tab (legacy or Kitty protocol).
|
|
282
|
+
* Ignores lock key bits.
|
|
172
283
|
*/
|
|
173
284
|
export function isShiftTab(data) {
|
|
174
|
-
return data === RAW.SHIFT_TAB || data === Keys.SHIFT_TAB;
|
|
285
|
+
return (data === RAW.SHIFT_TAB || data === Keys.SHIFT_TAB || matchesKittySequence(data, CODEPOINTS.tab, MODIFIERS.shift));
|
|
175
286
|
}
|
|
176
287
|
/**
|
|
177
288
|
* Check if input matches the Escape key (raw byte or Kitty protocol).
|
|
178
289
|
* Raw: \x1b (single byte)
|
|
179
290
|
* Kitty: \x1b[27u (codepoint 27 = escape)
|
|
291
|
+
* Ignores lock key bits.
|
|
180
292
|
*/
|
|
181
293
|
export function isEscape(data) {
|
|
182
|
-
return data === "\x1b" || data === `\x1b[${CODEPOINTS.escape}u
|
|
294
|
+
return data === "\x1b" || data === `\x1b[${CODEPOINTS.escape}u` || matchesKittySequence(data, CODEPOINTS.escape, 0);
|
|
295
|
+
}
|
|
296
|
+
// Arrow key virtual codepoints (negative to avoid conflicts with real codepoints)
|
|
297
|
+
const ARROW_CODEPOINTS = {
|
|
298
|
+
up: -1,
|
|
299
|
+
down: -2,
|
|
300
|
+
right: -3,
|
|
301
|
+
left: -4,
|
|
302
|
+
};
|
|
303
|
+
/**
|
|
304
|
+
* Check if input matches Arrow Up key.
|
|
305
|
+
* Handles both legacy (\x1b[A) and Kitty protocol with modifiers.
|
|
306
|
+
*/
|
|
307
|
+
export function isArrowUp(data) {
|
|
308
|
+
return data === "\x1b[A" || matchesKittySequence(data, ARROW_CODEPOINTS.up, 0);
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Check if input matches Arrow Down key.
|
|
312
|
+
* Handles both legacy (\x1b[B) and Kitty protocol with modifiers.
|
|
313
|
+
*/
|
|
314
|
+
export function isArrowDown(data) {
|
|
315
|
+
return data === "\x1b[B" || matchesKittySequence(data, ARROW_CODEPOINTS.down, 0);
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Check if input matches Arrow Right key.
|
|
319
|
+
* Handles both legacy (\x1b[C) and Kitty protocol with modifiers.
|
|
320
|
+
*/
|
|
321
|
+
export function isArrowRight(data) {
|
|
322
|
+
return data === "\x1b[C" || matchesKittySequence(data, ARROW_CODEPOINTS.right, 0);
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Check if input matches Arrow Left key.
|
|
326
|
+
* Handles both legacy (\x1b[D) and Kitty protocol with modifiers.
|
|
327
|
+
*/
|
|
328
|
+
export function isArrowLeft(data) {
|
|
329
|
+
return data === "\x1b[D" || matchesKittySequence(data, ARROW_CODEPOINTS.left, 0);
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Check if input matches plain Tab key (no modifiers).
|
|
333
|
+
* Handles both legacy (\t) and Kitty protocol.
|
|
334
|
+
*/
|
|
335
|
+
export function isTab(data) {
|
|
336
|
+
return data === "\t" || matchesKittySequence(data, CODEPOINTS.tab, 0);
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Check if input matches plain Enter/Return key (no modifiers).
|
|
340
|
+
* Handles both legacy (\r) and Kitty protocol.
|
|
341
|
+
*/
|
|
342
|
+
export function isEnter(data) {
|
|
343
|
+
return data === "\r" || matchesKittySequence(data, CODEPOINTS.enter, 0);
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Check if input matches plain Backspace key (no modifiers).
|
|
347
|
+
* Handles both legacy (\x7f, \x08) and Kitty protocol.
|
|
348
|
+
*/
|
|
349
|
+
export function isBackspace(data) {
|
|
350
|
+
return data === "\x7f" || data === "\x08" || matchesKittySequence(data, CODEPOINTS.backspace, 0);
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Check if input matches Shift+Enter.
|
|
354
|
+
* Ignores lock key bits.
|
|
355
|
+
*/
|
|
356
|
+
export function isShiftEnter(data) {
|
|
357
|
+
return data === Keys.SHIFT_ENTER || matchesKittySequence(data, CODEPOINTS.enter, MODIFIERS.shift);
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Check if input matches Alt+Enter.
|
|
361
|
+
* Ignores lock key bits.
|
|
362
|
+
*/
|
|
363
|
+
export function isAltEnter(data) {
|
|
364
|
+
return data === Keys.ALT_ENTER || data === "\x1b\r" || matchesKittySequence(data, CODEPOINTS.enter, MODIFIERS.alt);
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Check if input matches Option/Alt+Left (word navigation).
|
|
368
|
+
* Handles multiple formats including Kitty protocol.
|
|
369
|
+
*/
|
|
370
|
+
export function isAltLeft(data) {
|
|
371
|
+
return data === "\x1b[1;3D" || data === "\x1bb" || matchesKittySequence(data, ARROW_CODEPOINTS.left, MODIFIERS.alt);
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Check if input matches Option/Alt+Right (word navigation).
|
|
375
|
+
* Handles multiple formats including Kitty protocol.
|
|
376
|
+
*/
|
|
377
|
+
export function isAltRight(data) {
|
|
378
|
+
return data === "\x1b[1;3C" || data === "\x1bf" || matchesKittySequence(data, ARROW_CODEPOINTS.right, MODIFIERS.alt);
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Check if input matches Ctrl+Left (word navigation).
|
|
382
|
+
* Handles multiple formats including Kitty protocol.
|
|
383
|
+
*/
|
|
384
|
+
export function isCtrlLeft(data) {
|
|
385
|
+
return data === "\x1b[1;5D" || matchesKittySequence(data, ARROW_CODEPOINTS.left, MODIFIERS.ctrl);
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Check if input matches Ctrl+Right (word navigation).
|
|
389
|
+
* Handles multiple formats including Kitty protocol.
|
|
390
|
+
*/
|
|
391
|
+
export function isCtrlRight(data) {
|
|
392
|
+
return data === "\x1b[1;5C" || matchesKittySequence(data, ARROW_CODEPOINTS.right, MODIFIERS.ctrl);
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Check if input matches Home key.
|
|
396
|
+
* Handles legacy formats and Kitty protocol with lock key modifiers.
|
|
397
|
+
*/
|
|
398
|
+
export function isHome(data) {
|
|
399
|
+
return (data === "\x1b[H" ||
|
|
400
|
+
data === "\x1b[1~" ||
|
|
401
|
+
data === "\x1b[7~" ||
|
|
402
|
+
matchesKittySequence(data, FUNCTIONAL_CODEPOINTS.home, 0));
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Check if input matches End key.
|
|
406
|
+
* Handles legacy formats and Kitty protocol with lock key modifiers.
|
|
407
|
+
*/
|
|
408
|
+
export function isEnd(data) {
|
|
409
|
+
return (data === "\x1b[F" ||
|
|
410
|
+
data === "\x1b[4~" ||
|
|
411
|
+
data === "\x1b[8~" ||
|
|
412
|
+
matchesKittySequence(data, FUNCTIONAL_CODEPOINTS.end, 0));
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Check if input matches Delete key (forward delete).
|
|
416
|
+
* Handles legacy format and Kitty protocol with lock key modifiers.
|
|
417
|
+
*/
|
|
418
|
+
export function isDelete(data) {
|
|
419
|
+
return data === "\x1b[3~" || matchesKittySequence(data, FUNCTIONAL_CODEPOINTS.delete, 0);
|
|
183
420
|
}
|
|
184
421
|
//# sourceMappingURL=keys.js.map
|
package/dist/keys.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keys.js","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Kitty keyboard protocol key sequence helpers.\n *\n * The Kitty keyboard protocol sends enhanced escape sequences in the format:\n * \\x1b[<codepoint>;<modifier>u\n *\n * Modifier values (added to 1):\n * - Shift: 1 (value 2)\n * - Alt: 2 (value 3)\n * - Ctrl: 4 (value 5)\n * - Super: 8 (value 9)\n *\n * See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/\n */\n\n// Common codepoints\nconst CODEPOINTS = {\n\t// Letters (lowercase ASCII)\n\ta: 97,\n\tc: 99,\n\td: 100,\n\te: 101,\n\tk: 107,\n\to: 111,\n\tp: 112,\n\tt: 116,\n\tu: 117,\n\tw: 119,\n\n\t// Special keys\n\tescape: 27,\n\ttab: 9,\n\tenter: 13,\n\tbackspace: 127,\n} as const;\n\n// Modifier bits (before adding 1)\nconst MODIFIERS = {\n\tshift: 1,\n\talt: 2,\n\tctrl: 4,\n\tsuper: 8,\n} as const;\n\n/**\n * Build a Kitty keyboard protocol sequence for a key with modifier.\n */\nfunction kittySequence(codepoint: number, modifier: number): string {\n\treturn `\\x1b[${codepoint};${modifier + 1}u`;\n}\n\n// Pre-built sequences for common key combinations\nexport const Keys = {\n\t// Ctrl+<letter> combinations\n\tCTRL_A: kittySequence(CODEPOINTS.a, MODIFIERS.ctrl),\n\tCTRL_C: kittySequence(CODEPOINTS.c, MODIFIERS.ctrl),\n\tCTRL_D: kittySequence(CODEPOINTS.d, MODIFIERS.ctrl),\n\tCTRL_E: kittySequence(CODEPOINTS.e, MODIFIERS.ctrl),\n\tCTRL_K: kittySequence(CODEPOINTS.k, MODIFIERS.ctrl),\n\tCTRL_O: kittySequence(CODEPOINTS.o, MODIFIERS.ctrl),\n\tCTRL_P: kittySequence(CODEPOINTS.p, MODIFIERS.ctrl),\n\tCTRL_T: kittySequence(CODEPOINTS.t, MODIFIERS.ctrl),\n\tCTRL_U: kittySequence(CODEPOINTS.u, MODIFIERS.ctrl),\n\tCTRL_W: kittySequence(CODEPOINTS.w, MODIFIERS.ctrl),\n\n\t// Enter combinations\n\tSHIFT_ENTER: kittySequence(CODEPOINTS.enter, MODIFIERS.shift),\n\tALT_ENTER: kittySequence(CODEPOINTS.enter, MODIFIERS.alt),\n\tCTRL_ENTER: kittySequence(CODEPOINTS.enter, MODIFIERS.ctrl),\n\n\t// Tab combinations\n\tSHIFT_TAB: kittySequence(CODEPOINTS.tab, MODIFIERS.shift),\n\n\t// Backspace combinations\n\tALT_BACKSPACE: kittySequence(CODEPOINTS.backspace, MODIFIERS.alt),\n} as const;\n\n/**\n * Check if input matches a Kitty protocol Ctrl+<key> sequence.\n * @param data - The input data to check\n * @param key - Single lowercase letter (e.g., 'c' for Ctrl+C)\n */\nexport function isKittyCtrl(data: string, key: string): boolean {\n\tif (key.length !== 1) return false;\n\tconst codepoint = key.charCodeAt(0);\n\treturn data === kittySequence(codepoint, MODIFIERS.ctrl);\n}\n\n/**\n * Check if input matches a Kitty protocol key sequence with specific modifier.\n * @param data - The input data to check\n * @param codepoint - ASCII codepoint of the key\n * @param modifier - Modifier value (use MODIFIERS constants)\n */\nexport function isKittyKey(data: string, codepoint: number, modifier: number): boolean {\n\treturn data === kittySequence(codepoint, modifier);\n}\n\n// Raw control character codes\nconst RAW = {\n\tCTRL_A: \"\\x01\",\n\tCTRL_C: \"\\x03\",\n\tCTRL_D: \"\\x04\",\n\tCTRL_E: \"\\x05\",\n\tCTRL_K: \"\\x0b\",\n\tCTRL_O: \"\\x0f\",\n\tCTRL_P: \"\\x10\",\n\tCTRL_T: \"\\x14\",\n\tCTRL_U: \"\\x15\",\n\tCTRL_W: \"\\x17\",\n\tALT_BACKSPACE: \"\\x1b\\x7f\",\n\tSHIFT_TAB: \"\\x1b[Z\",\n} as const;\n\n/**\n * Check if input matches Ctrl+A (raw byte or Kitty protocol).\n */\nexport function isCtrlA(data: string): boolean {\n\treturn data === RAW.CTRL_A || data === Keys.CTRL_A;\n}\n\n/**\n * Check if input matches Ctrl+C (raw byte or Kitty protocol).\n */\nexport function isCtrlC(data: string): boolean {\n\treturn data === RAW.CTRL_C || data === Keys.CTRL_C;\n}\n\n/**\n * Check if input matches Ctrl+D (raw byte or Kitty protocol).\n */\nexport function isCtrlD(data: string): boolean {\n\treturn data === RAW.CTRL_D || data === Keys.CTRL_D;\n}\n\n/**\n * Check if input matches Ctrl+E (raw byte or Kitty protocol).\n */\nexport function isCtrlE(data: string): boolean {\n\treturn data === RAW.CTRL_E || data === Keys.CTRL_E;\n}\n\n/**\n * Check if input matches Ctrl+K (raw byte or Kitty protocol).\n */\nexport function isCtrlK(data: string): boolean {\n\treturn data === RAW.CTRL_K || data === Keys.CTRL_K;\n}\n\n/**\n * Check if input matches Ctrl+O (raw byte or Kitty protocol).\n */\nexport function isCtrlO(data: string): boolean {\n\treturn data === RAW.CTRL_O || data === Keys.CTRL_O;\n}\n\n/**\n * Check if input matches Ctrl+P (raw byte or Kitty protocol).\n */\nexport function isCtrlP(data: string): boolean {\n\treturn data === RAW.CTRL_P || data === Keys.CTRL_P;\n}\n\n/**\n * Check if input matches Ctrl+T (raw byte or Kitty protocol).\n */\nexport function isCtrlT(data: string): boolean {\n\treturn data === RAW.CTRL_T || data === Keys.CTRL_T;\n}\n\n/**\n * Check if input matches Ctrl+U (raw byte or Kitty protocol).\n */\nexport function isCtrlU(data: string): boolean {\n\treturn data === RAW.CTRL_U || data === Keys.CTRL_U;\n}\n\n/**\n * Check if input matches Ctrl+W (raw byte or Kitty protocol).\n */\nexport function isCtrlW(data: string): boolean {\n\treturn data === RAW.CTRL_W || data === Keys.CTRL_W;\n}\n\n/**\n * Check if input matches Alt+Backspace (legacy or Kitty protocol).\n */\nexport function isAltBackspace(data: string): boolean {\n\treturn data === RAW.ALT_BACKSPACE || data === Keys.ALT_BACKSPACE;\n}\n\n/**\n * Check if input matches Shift+Tab (legacy or Kitty protocol).\n */\nexport function isShiftTab(data: string): boolean {\n\treturn data === RAW.SHIFT_TAB || data === Keys.SHIFT_TAB;\n}\n\n/**\n * Check if input matches the Escape key (raw byte or Kitty protocol).\n * Raw: \\x1b (single byte)\n * Kitty: \\x1b[27u (codepoint 27 = escape)\n */\nexport function isEscape(data: string): boolean {\n\treturn data === \"\\x1b\" || data === `\\x1b[${CODEPOINTS.escape}u`;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"keys.js","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Kitty keyboard protocol key sequence helpers.\n *\n * The Kitty keyboard protocol sends enhanced escape sequences in the format:\n * \\x1b[<codepoint>;<modifier>u\n *\n * Modifier bits (before adding 1 for transmission):\n * - Shift: 1 (value 2)\n * - Alt: 2 (value 3)\n * - Ctrl: 4 (value 5)\n * - Super: 8 (value 9)\n * - Hyper: 16\n * - Meta: 32\n * - Caps_Lock: 64\n * - Num_Lock: 128\n *\n * See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/\n *\n * NOTE: Some terminals (e.g., Ghostty on Linux) include lock key states\n * (Caps Lock, Num Lock) in the modifier field. We mask these out when\n * checking for key combinations since they shouldn't affect behavior.\n */\n\n// Common codepoints\nconst CODEPOINTS = {\n\t// Letters (lowercase ASCII)\n\ta: 97,\n\tc: 99,\n\td: 100,\n\te: 101,\n\tk: 107,\n\to: 111,\n\tp: 112,\n\tt: 116,\n\tu: 117,\n\tw: 119,\n\n\t// Special keys\n\tescape: 27,\n\ttab: 9,\n\tenter: 13,\n\tbackspace: 127,\n} as const;\n\n// Lock key bits to ignore when matching (Caps Lock + Num Lock)\nconst LOCK_MASK = 64 + 128; // 192\n\n// Modifier bits (before adding 1)\nconst MODIFIERS = {\n\tshift: 1,\n\talt: 2,\n\tctrl: 4,\n\tsuper: 8,\n} as const;\n\n/**\n * Build a Kitty keyboard protocol sequence for a key with modifier.\n */\nfunction kittySequence(codepoint: number, modifier: number): string {\n\treturn `\\x1b[${codepoint};${modifier + 1}u`;\n}\n\n/**\n * Parsed Kitty keyboard protocol sequence.\n */\ninterface ParsedKittySequence {\n\tcodepoint: number;\n\tmodifier: number; // Actual modifier bits (after subtracting 1)\n}\n\n/**\n * Parse a Kitty keyboard protocol sequence.\n * Handles formats:\n * - \\x1b[<codepoint>u (no modifier)\n * - \\x1b[<codepoint>;<modifier>u (with modifier)\n * - \\x1b[1;<modifier>A/B/C/D (arrow keys with modifier)\n *\n * Returns null if not a valid Kitty sequence.\n */\n// Virtual codepoints for functional keys (negative to avoid conflicts)\nconst FUNCTIONAL_CODEPOINTS = {\n\tdelete: -10,\n\tinsert: -11,\n\tpageUp: -12,\n\tpageDown: -13,\n\thome: -14,\n\tend: -15,\n} as const;\n\nfunction parseKittySequence(data: string): ParsedKittySequence | null {\n\t// Match CSI u format: \\x1b[<num>u or \\x1b[<num>;<mod>u\n\tconst csiUMatch = data.match(/^\\x1b\\[(\\d+)(?:;(\\d+))?u$/);\n\tif (csiUMatch) {\n\t\tconst codepoint = parseInt(csiUMatch[1]!, 10);\n\t\tconst modValue = csiUMatch[2] ? parseInt(csiUMatch[2], 10) : 1;\n\t\treturn { codepoint, modifier: modValue - 1 };\n\t}\n\n\t// Match arrow keys with modifier: \\x1b[1;<mod>A/B/C/D\n\tconst arrowMatch = data.match(/^\\x1b\\[1;(\\d+)([ABCD])$/);\n\tif (arrowMatch) {\n\t\tconst modValue = parseInt(arrowMatch[1]!, 10);\n\t\t// Map arrow letters to virtual codepoints for easier matching\n\t\tconst arrowCodes: Record<string, number> = { A: -1, B: -2, C: -3, D: -4 };\n\t\tconst codepoint = arrowCodes[arrowMatch[2]!]!;\n\t\treturn { codepoint, modifier: modValue - 1 };\n\t}\n\n\t// Match functional keys with ~ terminator: \\x1b[<num>~ or \\x1b[<num>;<mod>~\n\t// DELETE=3, INSERT=2, PAGEUP=5, PAGEDOWN=6, etc.\n\tconst funcMatch = data.match(/^\\x1b\\[(\\d+)(?:;(\\d+))?~$/);\n\tif (funcMatch) {\n\t\tconst keyNum = parseInt(funcMatch[1]!, 10);\n\t\tconst modValue = funcMatch[2] ? parseInt(funcMatch[2], 10) : 1;\n\t\t// Map functional key numbers to virtual codepoints\n\t\tconst funcCodes: Record<number, number> = {\n\t\t\t2: FUNCTIONAL_CODEPOINTS.insert,\n\t\t\t3: FUNCTIONAL_CODEPOINTS.delete,\n\t\t\t5: FUNCTIONAL_CODEPOINTS.pageUp,\n\t\t\t6: FUNCTIONAL_CODEPOINTS.pageDown,\n\t\t\t7: FUNCTIONAL_CODEPOINTS.home, // Alternative home\n\t\t\t8: FUNCTIONAL_CODEPOINTS.end, // Alternative end\n\t\t};\n\t\tconst codepoint = funcCodes[keyNum];\n\t\tif (codepoint !== undefined) {\n\t\t\treturn { codepoint, modifier: modValue - 1 };\n\t\t}\n\t}\n\n\t// Match Home/End with modifier: \\x1b[1;<mod>H/F\n\tconst homeEndMatch = data.match(/^\\x1b\\[1;(\\d+)([HF])$/);\n\tif (homeEndMatch) {\n\t\tconst modValue = parseInt(homeEndMatch[1]!, 10);\n\t\tconst codepoint = homeEndMatch[2] === \"H\" ? FUNCTIONAL_CODEPOINTS.home : FUNCTIONAL_CODEPOINTS.end;\n\t\treturn { codepoint, modifier: modValue - 1 };\n\t}\n\n\treturn null;\n}\n\n/**\n * Check if a Kitty sequence matches the expected codepoint and modifier,\n * ignoring lock key bits (Caps Lock, Num Lock).\n */\nfunction matchesKittySequence(data: string, expectedCodepoint: number, expectedModifier: number): boolean {\n\tconst parsed = parseKittySequence(data);\n\tif (!parsed) return false;\n\n\t// Mask out lock bits from both sides for comparison\n\tconst actualMod = parsed.modifier & ~LOCK_MASK;\n\tconst expectedMod = expectedModifier & ~LOCK_MASK;\n\n\treturn parsed.codepoint === expectedCodepoint && actualMod === expectedMod;\n}\n\n// Pre-built sequences for common key combinations\nexport const Keys = {\n\t// Ctrl+<letter> combinations\n\tCTRL_A: kittySequence(CODEPOINTS.a, MODIFIERS.ctrl),\n\tCTRL_C: kittySequence(CODEPOINTS.c, MODIFIERS.ctrl),\n\tCTRL_D: kittySequence(CODEPOINTS.d, MODIFIERS.ctrl),\n\tCTRL_E: kittySequence(CODEPOINTS.e, MODIFIERS.ctrl),\n\tCTRL_K: kittySequence(CODEPOINTS.k, MODIFIERS.ctrl),\n\tCTRL_O: kittySequence(CODEPOINTS.o, MODIFIERS.ctrl),\n\tCTRL_P: kittySequence(CODEPOINTS.p, MODIFIERS.ctrl),\n\tCTRL_T: kittySequence(CODEPOINTS.t, MODIFIERS.ctrl),\n\tCTRL_U: kittySequence(CODEPOINTS.u, MODIFIERS.ctrl),\n\tCTRL_W: kittySequence(CODEPOINTS.w, MODIFIERS.ctrl),\n\n\t// Enter combinations\n\tSHIFT_ENTER: kittySequence(CODEPOINTS.enter, MODIFIERS.shift),\n\tALT_ENTER: kittySequence(CODEPOINTS.enter, MODIFIERS.alt),\n\tCTRL_ENTER: kittySequence(CODEPOINTS.enter, MODIFIERS.ctrl),\n\n\t// Tab combinations\n\tSHIFT_TAB: kittySequence(CODEPOINTS.tab, MODIFIERS.shift),\n\n\t// Backspace combinations\n\tALT_BACKSPACE: kittySequence(CODEPOINTS.backspace, MODIFIERS.alt),\n} as const;\n\n/**\n * Check if input matches a Kitty protocol Ctrl+<key> sequence.\n * Ignores lock key bits (Caps Lock, Num Lock).\n * @param data - The input data to check\n * @param key - Single lowercase letter (e.g., 'c' for Ctrl+C)\n */\nexport function isKittyCtrl(data: string, key: string): boolean {\n\tif (key.length !== 1) return false;\n\tconst codepoint = key.charCodeAt(0);\n\t// Check exact match first (fast path)\n\tif (data === kittySequence(codepoint, MODIFIERS.ctrl)) return true;\n\t// Check with lock bits masked out\n\treturn matchesKittySequence(data, codepoint, MODIFIERS.ctrl);\n}\n\n/**\n * Check if input matches a Kitty protocol key sequence with specific modifier.\n * Ignores lock key bits (Caps Lock, Num Lock).\n * @param data - The input data to check\n * @param codepoint - ASCII codepoint of the key\n * @param modifier - Modifier value (use MODIFIERS constants)\n */\nexport function isKittyKey(data: string, codepoint: number, modifier: number): boolean {\n\t// Check exact match first (fast path)\n\tif (data === kittySequence(codepoint, modifier)) return true;\n\t// Check with lock bits masked out\n\treturn matchesKittySequence(data, codepoint, modifier);\n}\n\n// Raw control character codes\nconst RAW = {\n\tCTRL_A: \"\\x01\",\n\tCTRL_C: \"\\x03\",\n\tCTRL_D: \"\\x04\",\n\tCTRL_E: \"\\x05\",\n\tCTRL_K: \"\\x0b\",\n\tCTRL_O: \"\\x0f\",\n\tCTRL_P: \"\\x10\",\n\tCTRL_T: \"\\x14\",\n\tCTRL_U: \"\\x15\",\n\tCTRL_W: \"\\x17\",\n\tALT_BACKSPACE: \"\\x1b\\x7f\",\n\tSHIFT_TAB: \"\\x1b[Z\",\n} as const;\n\n/**\n * Check if input matches Ctrl+A (raw byte or Kitty protocol).\n * Ignores lock key bits.\n */\nexport function isCtrlA(data: string): boolean {\n\treturn data === RAW.CTRL_A || data === Keys.CTRL_A || matchesKittySequence(data, CODEPOINTS.a, MODIFIERS.ctrl);\n}\n\n/**\n * Check if input matches Ctrl+C (raw byte or Kitty protocol).\n * Ignores lock key bits.\n */\nexport function isCtrlC(data: string): boolean {\n\treturn data === RAW.CTRL_C || data === Keys.CTRL_C || matchesKittySequence(data, CODEPOINTS.c, MODIFIERS.ctrl);\n}\n\n/**\n * Check if input matches Ctrl+D (raw byte or Kitty protocol).\n * Ignores lock key bits.\n */\nexport function isCtrlD(data: string): boolean {\n\treturn data === RAW.CTRL_D || data === Keys.CTRL_D || matchesKittySequence(data, CODEPOINTS.d, MODIFIERS.ctrl);\n}\n\n/**\n * Check if input matches Ctrl+E (raw byte or Kitty protocol).\n * Ignores lock key bits.\n */\nexport function isCtrlE(data: string): boolean {\n\treturn data === RAW.CTRL_E || data === Keys.CTRL_E || matchesKittySequence(data, CODEPOINTS.e, MODIFIERS.ctrl);\n}\n\n/**\n * Check if input matches Ctrl+K (raw byte or Kitty protocol).\n * Ignores lock key bits.\n */\nexport function isCtrlK(data: string): boolean {\n\treturn data === RAW.CTRL_K || data === Keys.CTRL_K || matchesKittySequence(data, CODEPOINTS.k, MODIFIERS.ctrl);\n}\n\n/**\n * Check if input matches Ctrl+O (raw byte or Kitty protocol).\n * Ignores lock key bits.\n */\nexport function isCtrlO(data: string): boolean {\n\treturn data === RAW.CTRL_O || data === Keys.CTRL_O || matchesKittySequence(data, CODEPOINTS.o, MODIFIERS.ctrl);\n}\n\n/**\n * Check if input matches Ctrl+P (raw byte or Kitty protocol).\n * Ignores lock key bits.\n */\nexport function isCtrlP(data: string): boolean {\n\treturn data === RAW.CTRL_P || data === Keys.CTRL_P || matchesKittySequence(data, CODEPOINTS.p, MODIFIERS.ctrl);\n}\n\n/**\n * Check if input matches Ctrl+T (raw byte or Kitty protocol).\n * Ignores lock key bits.\n */\nexport function isCtrlT(data: string): boolean {\n\treturn data === RAW.CTRL_T || data === Keys.CTRL_T || matchesKittySequence(data, CODEPOINTS.t, MODIFIERS.ctrl);\n}\n\n/**\n * Check if input matches Ctrl+U (raw byte or Kitty protocol).\n * Ignores lock key bits.\n */\nexport function isCtrlU(data: string): boolean {\n\treturn data === RAW.CTRL_U || data === Keys.CTRL_U || matchesKittySequence(data, CODEPOINTS.u, MODIFIERS.ctrl);\n}\n\n/**\n * Check if input matches Ctrl+W (raw byte or Kitty protocol).\n * Ignores lock key bits.\n */\nexport function isCtrlW(data: string): boolean {\n\treturn data === RAW.CTRL_W || data === Keys.CTRL_W || matchesKittySequence(data, CODEPOINTS.w, MODIFIERS.ctrl);\n}\n\n/**\n * Check if input matches Alt+Backspace (legacy or Kitty protocol).\n * Ignores lock key bits.\n */\nexport function isAltBackspace(data: string): boolean {\n\treturn (\n\t\tdata === RAW.ALT_BACKSPACE ||\n\t\tdata === Keys.ALT_BACKSPACE ||\n\t\tmatchesKittySequence(data, CODEPOINTS.backspace, MODIFIERS.alt)\n\t);\n}\n\n/**\n * Check if input matches Shift+Tab (legacy or Kitty protocol).\n * Ignores lock key bits.\n */\nexport function isShiftTab(data: string): boolean {\n\treturn (\n\t\tdata === RAW.SHIFT_TAB || data === Keys.SHIFT_TAB || matchesKittySequence(data, CODEPOINTS.tab, MODIFIERS.shift)\n\t);\n}\n\n/**\n * Check if input matches the Escape key (raw byte or Kitty protocol).\n * Raw: \\x1b (single byte)\n * Kitty: \\x1b[27u (codepoint 27 = escape)\n * Ignores lock key bits.\n */\nexport function isEscape(data: string): boolean {\n\treturn data === \"\\x1b\" || data === `\\x1b[${CODEPOINTS.escape}u` || matchesKittySequence(data, CODEPOINTS.escape, 0);\n}\n\n// Arrow key virtual codepoints (negative to avoid conflicts with real codepoints)\nconst ARROW_CODEPOINTS = {\n\tup: -1,\n\tdown: -2,\n\tright: -3,\n\tleft: -4,\n} as const;\n\n/**\n * Check if input matches Arrow Up key.\n * Handles both legacy (\\x1b[A) and Kitty protocol with modifiers.\n */\nexport function isArrowUp(data: string): boolean {\n\treturn data === \"\\x1b[A\" || matchesKittySequence(data, ARROW_CODEPOINTS.up, 0);\n}\n\n/**\n * Check if input matches Arrow Down key.\n * Handles both legacy (\\x1b[B) and Kitty protocol with modifiers.\n */\nexport function isArrowDown(data: string): boolean {\n\treturn data === \"\\x1b[B\" || matchesKittySequence(data, ARROW_CODEPOINTS.down, 0);\n}\n\n/**\n * Check if input matches Arrow Right key.\n * Handles both legacy (\\x1b[C) and Kitty protocol with modifiers.\n */\nexport function isArrowRight(data: string): boolean {\n\treturn data === \"\\x1b[C\" || matchesKittySequence(data, ARROW_CODEPOINTS.right, 0);\n}\n\n/**\n * Check if input matches Arrow Left key.\n * Handles both legacy (\\x1b[D) and Kitty protocol with modifiers.\n */\nexport function isArrowLeft(data: string): boolean {\n\treturn data === \"\\x1b[D\" || matchesKittySequence(data, ARROW_CODEPOINTS.left, 0);\n}\n\n/**\n * Check if input matches plain Tab key (no modifiers).\n * Handles both legacy (\\t) and Kitty protocol.\n */\nexport function isTab(data: string): boolean {\n\treturn data === \"\\t\" || matchesKittySequence(data, CODEPOINTS.tab, 0);\n}\n\n/**\n * Check if input matches plain Enter/Return key (no modifiers).\n * Handles both legacy (\\r) and Kitty protocol.\n */\nexport function isEnter(data: string): boolean {\n\treturn data === \"\\r\" || matchesKittySequence(data, CODEPOINTS.enter, 0);\n}\n\n/**\n * Check if input matches plain Backspace key (no modifiers).\n * Handles both legacy (\\x7f, \\x08) and Kitty protocol.\n */\nexport function isBackspace(data: string): boolean {\n\treturn data === \"\\x7f\" || data === \"\\x08\" || matchesKittySequence(data, CODEPOINTS.backspace, 0);\n}\n\n/**\n * Check if input matches Shift+Enter.\n * Ignores lock key bits.\n */\nexport function isShiftEnter(data: string): boolean {\n\treturn data === Keys.SHIFT_ENTER || matchesKittySequence(data, CODEPOINTS.enter, MODIFIERS.shift);\n}\n\n/**\n * Check if input matches Alt+Enter.\n * Ignores lock key bits.\n */\nexport function isAltEnter(data: string): boolean {\n\treturn data === Keys.ALT_ENTER || data === \"\\x1b\\r\" || matchesKittySequence(data, CODEPOINTS.enter, MODIFIERS.alt);\n}\n\n/**\n * Check if input matches Option/Alt+Left (word navigation).\n * Handles multiple formats including Kitty protocol.\n */\nexport function isAltLeft(data: string): boolean {\n\treturn data === \"\\x1b[1;3D\" || data === \"\\x1bb\" || matchesKittySequence(data, ARROW_CODEPOINTS.left, MODIFIERS.alt);\n}\n\n/**\n * Check if input matches Option/Alt+Right (word navigation).\n * Handles multiple formats including Kitty protocol.\n */\nexport function isAltRight(data: string): boolean {\n\treturn data === \"\\x1b[1;3C\" || data === \"\\x1bf\" || matchesKittySequence(data, ARROW_CODEPOINTS.right, MODIFIERS.alt);\n}\n\n/**\n * Check if input matches Ctrl+Left (word navigation).\n * Handles multiple formats including Kitty protocol.\n */\nexport function isCtrlLeft(data: string): boolean {\n\treturn data === \"\\x1b[1;5D\" || matchesKittySequence(data, ARROW_CODEPOINTS.left, MODIFIERS.ctrl);\n}\n\n/**\n * Check if input matches Ctrl+Right (word navigation).\n * Handles multiple formats including Kitty protocol.\n */\nexport function isCtrlRight(data: string): boolean {\n\treturn data === \"\\x1b[1;5C\" || matchesKittySequence(data, ARROW_CODEPOINTS.right, MODIFIERS.ctrl);\n}\n\n/**\n * Check if input matches Home key.\n * Handles legacy formats and Kitty protocol with lock key modifiers.\n */\nexport function isHome(data: string): boolean {\n\treturn (\n\t\tdata === \"\\x1b[H\" ||\n\t\tdata === \"\\x1b[1~\" ||\n\t\tdata === \"\\x1b[7~\" ||\n\t\tmatchesKittySequence(data, FUNCTIONAL_CODEPOINTS.home, 0)\n\t);\n}\n\n/**\n * Check if input matches End key.\n * Handles legacy formats and Kitty protocol with lock key modifiers.\n */\nexport function isEnd(data: string): boolean {\n\treturn (\n\t\tdata === \"\\x1b[F\" ||\n\t\tdata === \"\\x1b[4~\" ||\n\t\tdata === \"\\x1b[8~\" ||\n\t\tmatchesKittySequence(data, FUNCTIONAL_CODEPOINTS.end, 0)\n\t);\n}\n\n/**\n * Check if input matches Delete key (forward delete).\n * Handles legacy format and Kitty protocol with lock key modifiers.\n */\nexport function isDelete(data: string): boolean {\n\treturn data === \"\\x1b[3~\" || matchesKittySequence(data, FUNCTIONAL_CODEPOINTS.delete, 0);\n}\n"]}
|
package/package.json
CHANGED