@mariozechner/pi-tui 0.34.0 → 0.34.1

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/keys.d.ts CHANGED
@@ -4,14 +4,20 @@
4
4
  * Supports both legacy terminal sequences and Kitty keyboard protocol.
5
5
  * See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/
6
6
  *
7
+ * Symbol keys are also supported, however some ctrl+symbol combos
8
+ * overlap with ASCII codes, e.g. ctrl+[ = ESC.
9
+ * See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/#legacy-ctrl-mapping-of-ascii-keys
10
+ * Those can still be * used for ctrl+shift combos
11
+ *
7
12
  * API:
8
13
  * - matchesKey(data, keyId) - Check if input matches a key identifier
9
14
  * - parseKey(data) - Parse input and return the key identifier
10
15
  * - Key - Helper object for creating typed key identifiers
11
16
  */
12
17
  type Letter = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z";
18
+ type SymbolKey = "`" | "-" | "=" | "[" | "]" | "\\" | ";" | "'" | "," | "." | "/" | "!" | "@" | "#" | "$" | "%" | "^" | "&" | "*" | "(" | ")" | "_" | "+" | "|" | "~" | "{" | "}" | ":" | "<" | ">" | "?";
13
19
  type SpecialKey = "escape" | "esc" | "enter" | "return" | "tab" | "space" | "backspace" | "delete" | "home" | "end" | "up" | "down" | "left" | "right";
14
- type BaseKey = Letter | SpecialKey;
20
+ type BaseKey = Letter | SymbolKey | SpecialKey;
15
21
  /**
16
22
  * Union type of all valid key identifiers.
17
23
  * Provides autocomplete and catches typos at compile time.
@@ -22,6 +28,7 @@ export type KeyId = BaseKey | `ctrl+${BaseKey}` | `shift+${BaseKey}` | `alt+${Ba
22
28
  *
23
29
  * Usage:
24
30
  * - Key.escape, Key.enter, Key.tab, etc. for special keys
31
+ * - Key.backtick, Key.comma, Key.period, etc. for symbol keys
25
32
  * - Key.ctrl("c"), Key.alt("x") for single modifier
26
33
  * - Key.ctrlShift("p"), Key.ctrlAlt("x") for combined modifiers
27
34
  */
@@ -40,6 +47,37 @@ export declare const Key: {
40
47
  readonly down: "down";
41
48
  readonly left: "left";
42
49
  readonly right: "right";
50
+ readonly backtick: "`";
51
+ readonly hyphen: "-";
52
+ readonly equals: "=";
53
+ readonly leftbracket: "[";
54
+ readonly rightbracket: "]";
55
+ readonly backslash: "\\";
56
+ readonly semicolon: ";";
57
+ readonly quote: "'";
58
+ readonly comma: ",";
59
+ readonly period: ".";
60
+ readonly slash: "/";
61
+ readonly exclamation: "!";
62
+ readonly at: "@";
63
+ readonly hash: "#";
64
+ readonly dollar: "$";
65
+ readonly percent: "%";
66
+ readonly caret: "^";
67
+ readonly ampersand: "&";
68
+ readonly asterisk: "*";
69
+ readonly leftparen: "(";
70
+ readonly rightparen: ")";
71
+ readonly underscore: "_";
72
+ readonly plus: "+";
73
+ readonly pipe: "|";
74
+ readonly tilde: "~";
75
+ readonly leftbrace: "{";
76
+ readonly rightbrace: "}";
77
+ readonly colon: ":";
78
+ readonly lessthan: "<";
79
+ readonly greaterthan: ">";
80
+ readonly question: "?";
43
81
  readonly ctrl: <K extends BaseKey>(key: K) => `ctrl+${K}`;
44
82
  readonly shift: <K extends BaseKey>(key: K) => `shift+${K}`;
45
83
  readonly alt: <K extends BaseKey>(key: K) => `alt+${K}`;
@@ -1 +1 @@
1
- {"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH,KAAK,MAAM,GACR,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,CAAC;AAEP,KAAK,UAAU,GACZ,QAAQ,GACR,KAAK,GACL,OAAO,GACP,QAAQ,GACR,KAAK,GACL,OAAO,GACP,WAAW,GACX,QAAQ,GACR,MAAM,GACN,KAAK,GACL,IAAI,GACJ,MAAM,GACN,MAAM,GACN,OAAO,CAAC;AAEX,KAAK,OAAO,GAAG,MAAM,GAAG,UAAU,CAAC;AAEnC;;;GAGG;AACH,MAAM,MAAM,KAAK,GACd,OAAO,GACP,QAAQ,OAAO,EAAE,GACjB,SAAS,OAAO,EAAE,GAClB,OAAO,OAAO,EAAE,GAChB,cAAc,OAAO,EAAE,GACvB,cAAc,OAAO,EAAE,GACvB,YAAY,OAAO,EAAE,GACrB,YAAY,OAAO,EAAE,GACrB,aAAa,OAAO,EAAE,GACtB,aAAa,OAAO,EAAE,GACtB,kBAAkB,OAAO,EAAE,GAC3B,kBAAkB,OAAO,EAAE,GAC3B,kBAAkB,OAAO,EAAE,GAC3B,kBAAkB,OAAO,EAAE,GAC3B,kBAAkB,OAAO,EAAE,GAC3B,kBAAkB,OAAO,EAAE,CAAC;AAE/B;;;;;;;GAOG;AACH,eAAO,MAAM,GAAG;;;;;;;;;;;;;;;oBAkBR,CAAC;qBACA,CAAC;mBACH,CAAC;yBAGK,CAAC;yBACD,CAAC;uBACH,CAAC;uBACD,CAAC;wBACA,CAAC;wBACD,CAAC;4BAGG,CAAC;CACP,CAAC;AA4HX;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CA0K9D;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CA2DzD","sourcesContent":["/**\n * Keyboard input handling for terminal applications.\n *\n * Supports both legacy terminal sequences and Kitty keyboard protocol.\n * See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/\n *\n * API:\n * - matchesKey(data, keyId) - Check if input matches a key identifier\n * - parseKey(data) - Parse input and return the key identifier\n * - Key - Helper object for creating typed key identifiers\n */\n\n// =============================================================================\n// Type-Safe Key Identifiers\n// =============================================================================\n\ntype Letter =\n\t| \"a\"\n\t| \"b\"\n\t| \"c\"\n\t| \"d\"\n\t| \"e\"\n\t| \"f\"\n\t| \"g\"\n\t| \"h\"\n\t| \"i\"\n\t| \"j\"\n\t| \"k\"\n\t| \"l\"\n\t| \"m\"\n\t| \"n\"\n\t| \"o\"\n\t| \"p\"\n\t| \"q\"\n\t| \"r\"\n\t| \"s\"\n\t| \"t\"\n\t| \"u\"\n\t| \"v\"\n\t| \"w\"\n\t| \"x\"\n\t| \"y\"\n\t| \"z\";\n\ntype SpecialKey =\n\t| \"escape\"\n\t| \"esc\"\n\t| \"enter\"\n\t| \"return\"\n\t| \"tab\"\n\t| \"space\"\n\t| \"backspace\"\n\t| \"delete\"\n\t| \"home\"\n\t| \"end\"\n\t| \"up\"\n\t| \"down\"\n\t| \"left\"\n\t| \"right\";\n\ntype BaseKey = Letter | SpecialKey;\n\n/**\n * Union type of all valid key identifiers.\n * Provides autocomplete and catches typos at compile time.\n */\nexport type KeyId =\n\t| BaseKey\n\t| `ctrl+${BaseKey}`\n\t| `shift+${BaseKey}`\n\t| `alt+${BaseKey}`\n\t| `ctrl+shift+${BaseKey}`\n\t| `shift+ctrl+${BaseKey}`\n\t| `ctrl+alt+${BaseKey}`\n\t| `alt+ctrl+${BaseKey}`\n\t| `shift+alt+${BaseKey}`\n\t| `alt+shift+${BaseKey}`\n\t| `ctrl+shift+alt+${BaseKey}`\n\t| `ctrl+alt+shift+${BaseKey}`\n\t| `shift+ctrl+alt+${BaseKey}`\n\t| `shift+alt+ctrl+${BaseKey}`\n\t| `alt+ctrl+shift+${BaseKey}`\n\t| `alt+shift+ctrl+${BaseKey}`;\n\n/**\n * Helper object for creating typed key identifiers with autocomplete.\n *\n * Usage:\n * - Key.escape, Key.enter, Key.tab, etc. for special keys\n * - Key.ctrl(\"c\"), Key.alt(\"x\") for single modifier\n * - Key.ctrlShift(\"p\"), Key.ctrlAlt(\"x\") for combined modifiers\n */\nexport const Key = {\n\t// Special keys\n\tescape: \"escape\" as const,\n\tesc: \"esc\" as const,\n\tenter: \"enter\" as const,\n\treturn: \"return\" as const,\n\ttab: \"tab\" as const,\n\tspace: \"space\" as const,\n\tbackspace: \"backspace\" as const,\n\tdelete: \"delete\" as const,\n\thome: \"home\" as const,\n\tend: \"end\" as const,\n\tup: \"up\" as const,\n\tdown: \"down\" as const,\n\tleft: \"left\" as const,\n\tright: \"right\" as const,\n\n\t// Single modifiers\n\tctrl: <K extends BaseKey>(key: K): `ctrl+${K}` => `ctrl+${key}`,\n\tshift: <K extends BaseKey>(key: K): `shift+${K}` => `shift+${key}`,\n\talt: <K extends BaseKey>(key: K): `alt+${K}` => `alt+${key}`,\n\n\t// Combined modifiers\n\tctrlShift: <K extends BaseKey>(key: K): `ctrl+shift+${K}` => `ctrl+shift+${key}`,\n\tshiftCtrl: <K extends BaseKey>(key: K): `shift+ctrl+${K}` => `shift+ctrl+${key}`,\n\tctrlAlt: <K extends BaseKey>(key: K): `ctrl+alt+${K}` => `ctrl+alt+${key}`,\n\taltCtrl: <K extends BaseKey>(key: K): `alt+ctrl+${K}` => `alt+ctrl+${key}`,\n\tshiftAlt: <K extends BaseKey>(key: K): `shift+alt+${K}` => `shift+alt+${key}`,\n\taltShift: <K extends BaseKey>(key: K): `alt+shift+${K}` => `alt+shift+${key}`,\n\n\t// Triple modifiers\n\tctrlShiftAlt: <K extends BaseKey>(key: K): `ctrl+shift+alt+${K}` => `ctrl+shift+alt+${key}`,\n} as const;\n\n// =============================================================================\n// Constants\n// =============================================================================\n\nconst MODIFIERS = {\n\tshift: 1,\n\talt: 2,\n\tctrl: 4,\n} as const;\n\nconst LOCK_MASK = 64 + 128; // Caps Lock + Num Lock\n\nconst CODEPOINTS = {\n\tescape: 27,\n\ttab: 9,\n\tenter: 13,\n\tspace: 32,\n\tbackspace: 127,\n\tkpEnter: 57414, // Numpad Enter (Kitty protocol)\n} as const;\n\nconst ARROW_CODEPOINTS = {\n\tup: -1,\n\tdown: -2,\n\tright: -3,\n\tleft: -4,\n} as const;\n\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\n// =============================================================================\n// Kitty Protocol Parsing\n// =============================================================================\n\ninterface ParsedKittySequence {\n\tcodepoint: number;\n\tmodifier: number;\n}\n\nfunction parseKittySequence(data: string): ParsedKittySequence | null {\n\t// 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// 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\tconst arrowCodes: Record<string, number> = { A: -1, B: -2, C: -3, D: -4 };\n\t\treturn { codepoint: arrowCodes[arrowMatch[2]!]!, modifier: modValue - 1 };\n\t}\n\n\t// Functional keys: \\x1b[<num>~ or \\x1b[<num>;<mod>~\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\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,\n\t\t\t8: FUNCTIONAL_CODEPOINTS.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// 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\nfunction matchesKittySequence(data: string, expectedCodepoint: number, expectedModifier: number): boolean {\n\tconst parsed = parseKittySequence(data);\n\tif (!parsed) return false;\n\tconst actualMod = parsed.modifier & ~LOCK_MASK;\n\tconst expectedMod = expectedModifier & ~LOCK_MASK;\n\treturn parsed.codepoint === expectedCodepoint && actualMod === expectedMod;\n}\n\n// =============================================================================\n// Generic Key Matching\n// =============================================================================\n\nfunction rawCtrlChar(letter: string): string {\n\tconst code = letter.toLowerCase().charCodeAt(0) - 96;\n\treturn String.fromCharCode(code);\n}\n\nfunction parseKeyId(keyId: string): { key: string; ctrl: boolean; shift: boolean; alt: boolean } | null {\n\tconst parts = keyId.toLowerCase().split(\"+\");\n\tconst key = parts[parts.length - 1];\n\tif (!key) return null;\n\treturn {\n\t\tkey,\n\t\tctrl: parts.includes(\"ctrl\"),\n\t\tshift: parts.includes(\"shift\"),\n\t\talt: parts.includes(\"alt\"),\n\t};\n}\n\n/**\n * Match input data against a key identifier string.\n *\n * Supported key identifiers:\n * - Single keys: \"escape\", \"tab\", \"enter\", \"backspace\", \"delete\", \"home\", \"end\", \"space\"\n * - Arrow keys: \"up\", \"down\", \"left\", \"right\"\n * - Ctrl combinations: \"ctrl+c\", \"ctrl+z\", etc.\n * - Shift combinations: \"shift+tab\", \"shift+enter\"\n * - Alt combinations: \"alt+enter\", \"alt+backspace\"\n * - Combined modifiers: \"shift+ctrl+p\", \"ctrl+alt+x\"\n *\n * Use the Key helper for autocomplete: Key.ctrl(\"c\"), Key.escape, Key.ctrlShift(\"p\")\n *\n * @param data - Raw input data from terminal\n * @param keyId - Key identifier (e.g., \"ctrl+c\", \"escape\", Key.ctrl(\"c\"))\n */\nexport function matchesKey(data: string, keyId: KeyId): boolean {\n\tconst parsed = parseKeyId(keyId);\n\tif (!parsed) return false;\n\n\tconst { key, ctrl, shift, alt } = parsed;\n\tlet modifier = 0;\n\tif (shift) modifier |= MODIFIERS.shift;\n\tif (alt) modifier |= MODIFIERS.alt;\n\tif (ctrl) modifier |= MODIFIERS.ctrl;\n\n\tswitch (key) {\n\t\tcase \"escape\":\n\t\tcase \"esc\":\n\t\t\tif (modifier !== 0) return false;\n\t\t\treturn data === \"\\x1b\" || matchesKittySequence(data, CODEPOINTS.escape, 0);\n\n\t\tcase \"space\":\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn data === \" \" || matchesKittySequence(data, CODEPOINTS.space, 0);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, CODEPOINTS.space, modifier);\n\n\t\tcase \"tab\":\n\t\t\tif (shift && !ctrl && !alt) {\n\t\t\t\treturn data === \"\\x1b[Z\" || matchesKittySequence(data, CODEPOINTS.tab, MODIFIERS.shift);\n\t\t\t}\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn data === \"\\t\" || matchesKittySequence(data, CODEPOINTS.tab, 0);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, CODEPOINTS.tab, modifier);\n\n\t\tcase \"enter\":\n\t\tcase \"return\":\n\t\t\tif (shift && !ctrl && !alt) {\n\t\t\t\treturn (\n\t\t\t\t\tmatchesKittySequence(data, CODEPOINTS.enter, MODIFIERS.shift) ||\n\t\t\t\t\tmatchesKittySequence(data, CODEPOINTS.kpEnter, MODIFIERS.shift)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (alt && !ctrl && !shift) {\n\t\t\t\treturn (\n\t\t\t\t\tdata === \"\\x1b\\r\" ||\n\t\t\t\t\tmatchesKittySequence(data, CODEPOINTS.enter, MODIFIERS.alt) ||\n\t\t\t\t\tmatchesKittySequence(data, CODEPOINTS.kpEnter, MODIFIERS.alt)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn (\n\t\t\t\t\tdata === \"\\r\" ||\n\t\t\t\t\tdata === \"\\x1bOM\" || // SS3 M (numpad enter in some terminals)\n\t\t\t\t\tmatchesKittySequence(data, CODEPOINTS.enter, 0) ||\n\t\t\t\t\tmatchesKittySequence(data, CODEPOINTS.kpEnter, 0)\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn (\n\t\t\t\tmatchesKittySequence(data, CODEPOINTS.enter, modifier) ||\n\t\t\t\tmatchesKittySequence(data, CODEPOINTS.kpEnter, modifier)\n\t\t\t);\n\n\t\tcase \"backspace\":\n\t\t\tif (alt && !ctrl && !shift) {\n\t\t\t\treturn data === \"\\x1b\\x7f\" || matchesKittySequence(data, CODEPOINTS.backspace, MODIFIERS.alt);\n\t\t\t}\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn data === \"\\x7f\" || data === \"\\x08\" || matchesKittySequence(data, CODEPOINTS.backspace, 0);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, CODEPOINTS.backspace, modifier);\n\n\t\tcase \"delete\":\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn data === \"\\x1b[3~\" || matchesKittySequence(data, FUNCTIONAL_CODEPOINTS.delete, 0);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, FUNCTIONAL_CODEPOINTS.delete, modifier);\n\n\t\tcase \"home\":\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn (\n\t\t\t\t\tdata === \"\\x1b[H\" ||\n\t\t\t\t\tdata === \"\\x1b[1~\" ||\n\t\t\t\t\tdata === \"\\x1b[7~\" ||\n\t\t\t\t\tmatchesKittySequence(data, FUNCTIONAL_CODEPOINTS.home, 0)\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, FUNCTIONAL_CODEPOINTS.home, modifier);\n\n\t\tcase \"end\":\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn (\n\t\t\t\t\tdata === \"\\x1b[F\" ||\n\t\t\t\t\tdata === \"\\x1b[4~\" ||\n\t\t\t\t\tdata === \"\\x1b[8~\" ||\n\t\t\t\t\tmatchesKittySequence(data, FUNCTIONAL_CODEPOINTS.end, 0)\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, FUNCTIONAL_CODEPOINTS.end, modifier);\n\n\t\tcase \"up\":\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn data === \"\\x1b[A\" || matchesKittySequence(data, ARROW_CODEPOINTS.up, 0);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, ARROW_CODEPOINTS.up, modifier);\n\n\t\tcase \"down\":\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn data === \"\\x1b[B\" || matchesKittySequence(data, ARROW_CODEPOINTS.down, 0);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, ARROW_CODEPOINTS.down, modifier);\n\n\t\tcase \"left\":\n\t\t\tif (alt && !ctrl && !shift) {\n\t\t\t\treturn (\n\t\t\t\t\tdata === \"\\x1b[1;3D\" ||\n\t\t\t\t\tdata === \"\\x1bb\" ||\n\t\t\t\t\tmatchesKittySequence(data, ARROW_CODEPOINTS.left, MODIFIERS.alt)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (ctrl && !alt && !shift) {\n\t\t\t\treturn data === \"\\x1b[1;5D\" || matchesKittySequence(data, ARROW_CODEPOINTS.left, MODIFIERS.ctrl);\n\t\t\t}\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn data === \"\\x1b[D\" || matchesKittySequence(data, ARROW_CODEPOINTS.left, 0);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, ARROW_CODEPOINTS.left, modifier);\n\n\t\tcase \"right\":\n\t\t\tif (alt && !ctrl && !shift) {\n\t\t\t\treturn (\n\t\t\t\t\tdata === \"\\x1b[1;3C\" ||\n\t\t\t\t\tdata === \"\\x1bf\" ||\n\t\t\t\t\tmatchesKittySequence(data, ARROW_CODEPOINTS.right, MODIFIERS.alt)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (ctrl && !alt && !shift) {\n\t\t\t\treturn data === \"\\x1b[1;5C\" || matchesKittySequence(data, ARROW_CODEPOINTS.right, MODIFIERS.ctrl);\n\t\t\t}\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn data === \"\\x1b[C\" || matchesKittySequence(data, ARROW_CODEPOINTS.right, 0);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, ARROW_CODEPOINTS.right, modifier);\n\t}\n\n\t// Handle single letter keys (a-z)\n\tif (key.length === 1 && key >= \"a\" && key <= \"z\") {\n\t\tconst codepoint = key.charCodeAt(0);\n\n\t\tif (ctrl && !shift && !alt) {\n\t\t\tconst raw = rawCtrlChar(key);\n\t\t\tif (data === raw) return true;\n\t\t\tif (data.length > 0 && data.charCodeAt(0) === raw.charCodeAt(0)) return true;\n\t\t\treturn matchesKittySequence(data, codepoint, MODIFIERS.ctrl);\n\t\t}\n\n\t\tif (ctrl && shift && !alt) {\n\t\t\treturn matchesKittySequence(data, codepoint, MODIFIERS.shift + MODIFIERS.ctrl);\n\t\t}\n\n\t\tif (shift && !ctrl && !alt) {\n\t\t\t// Legacy: shift+letter produces uppercase\n\t\t\tif (data === key.toUpperCase()) return true;\n\t\t\treturn matchesKittySequence(data, codepoint, MODIFIERS.shift);\n\t\t}\n\n\t\tif (modifier !== 0) {\n\t\t\treturn matchesKittySequence(data, codepoint, modifier);\n\t\t}\n\n\t\treturn data === key;\n\t}\n\n\treturn false;\n}\n\n/**\n * Parse input data and return the key identifier if recognized.\n *\n * @param data - Raw input data from terminal\n * @returns Key identifier string (e.g., \"ctrl+c\") or undefined\n */\nexport function parseKey(data: string): string | undefined {\n\tconst kitty = parseKittySequence(data);\n\tif (kitty) {\n\t\tconst { codepoint, modifier } = kitty;\n\t\tconst mods: string[] = [];\n\t\tconst effectiveMod = modifier & ~LOCK_MASK;\n\t\tif (effectiveMod & MODIFIERS.shift) mods.push(\"shift\");\n\t\tif (effectiveMod & MODIFIERS.ctrl) mods.push(\"ctrl\");\n\t\tif (effectiveMod & MODIFIERS.alt) mods.push(\"alt\");\n\n\t\tlet keyName: string | undefined;\n\t\tif (codepoint === CODEPOINTS.escape) keyName = \"escape\";\n\t\telse if (codepoint === CODEPOINTS.tab) keyName = \"tab\";\n\t\telse if (codepoint === CODEPOINTS.enter || codepoint === CODEPOINTS.kpEnter) keyName = \"enter\";\n\t\telse if (codepoint === CODEPOINTS.space) keyName = \"space\";\n\t\telse if (codepoint === CODEPOINTS.backspace) keyName = \"backspace\";\n\t\telse if (codepoint === FUNCTIONAL_CODEPOINTS.delete) keyName = \"delete\";\n\t\telse if (codepoint === FUNCTIONAL_CODEPOINTS.home) keyName = \"home\";\n\t\telse if (codepoint === FUNCTIONAL_CODEPOINTS.end) keyName = \"end\";\n\t\telse if (codepoint === ARROW_CODEPOINTS.up) keyName = \"up\";\n\t\telse if (codepoint === ARROW_CODEPOINTS.down) keyName = \"down\";\n\t\telse if (codepoint === ARROW_CODEPOINTS.left) keyName = \"left\";\n\t\telse if (codepoint === ARROW_CODEPOINTS.right) keyName = \"right\";\n\t\telse if (codepoint >= 97 && codepoint <= 122) keyName = String.fromCharCode(codepoint);\n\n\t\tif (keyName) {\n\t\t\treturn mods.length > 0 ? `${mods.join(\"+\")}+${keyName}` : keyName;\n\t\t}\n\t}\n\n\t// Legacy sequences\n\tif (data === \"\\x1b\") return \"escape\";\n\tif (data === \"\\t\") return \"tab\";\n\tif (data === \"\\r\" || data === \"\\x1bOM\") return \"enter\";\n\tif (data === \" \") return \"space\";\n\tif (data === \"\\x7f\" || data === \"\\x08\") return \"backspace\";\n\tif (data === \"\\x1b[Z\") return \"shift+tab\";\n\tif (data === \"\\x1b\\r\") return \"alt+enter\";\n\tif (data === \"\\x1b\\x7f\") return \"alt+backspace\";\n\tif (data === \"\\x1b[A\") return \"up\";\n\tif (data === \"\\x1b[B\") return \"down\";\n\tif (data === \"\\x1b[C\") return \"right\";\n\tif (data === \"\\x1b[D\") return \"left\";\n\tif (data === \"\\x1b[H\") return \"home\";\n\tif (data === \"\\x1b[F\") return \"end\";\n\tif (data === \"\\x1b[3~\") return \"delete\";\n\n\t// Raw Ctrl+letter\n\tif (data.length === 1) {\n\t\tconst code = data.charCodeAt(0);\n\t\tif (code >= 1 && code <= 26) {\n\t\t\treturn `ctrl+${String.fromCharCode(code + 96)}`;\n\t\t}\n\t\tif (code >= 32 && code <= 126) {\n\t\t\treturn data;\n\t\t}\n\t}\n\n\treturn undefined;\n}\n"]}
1
+ {"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAMH,KAAK,MAAM,GACR,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,CAAC;AAEP,KAAK,SAAS,GACX,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,IAAI,GACJ,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,CAAC;AAEP,KAAK,UAAU,GACZ,QAAQ,GACR,KAAK,GACL,OAAO,GACP,QAAQ,GACR,KAAK,GACL,OAAO,GACP,WAAW,GACX,QAAQ,GACR,MAAM,GACN,KAAK,GACL,IAAI,GACJ,MAAM,GACN,MAAM,GACN,OAAO,CAAC;AAEX,KAAK,OAAO,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,CAAC;AAE/C;;;GAGG;AACH,MAAM,MAAM,KAAK,GACd,OAAO,GACP,QAAQ,OAAO,EAAE,GACjB,SAAS,OAAO,EAAE,GAClB,OAAO,OAAO,EAAE,GAChB,cAAc,OAAO,EAAE,GACvB,cAAc,OAAO,EAAE,GACvB,YAAY,OAAO,EAAE,GACrB,YAAY,OAAO,EAAE,GACrB,aAAa,OAAO,EAAE,GACtB,aAAa,OAAO,EAAE,GACtB,kBAAkB,OAAO,EAAE,GAC3B,kBAAkB,OAAO,EAAE,GAC3B,kBAAkB,OAAO,EAAE,GAC3B,kBAAkB,OAAO,EAAE,GAC3B,kBAAkB,OAAO,EAAE,GAC3B,kBAAkB,OAAO,EAAE,CAAC;AAE/B;;;;;;;;GAQG;AACH,eAAO,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oBAmDR,CAAC;qBACA,CAAC;mBACH,CAAC;yBAGK,CAAC;yBACD,CAAC;uBACH,CAAC;uBACD,CAAC;wBACA,CAAC;wBACD,CAAC;4BAGG,CAAC;CACP,CAAC;AA8JX;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CA0K9D;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CA4DzD","sourcesContent":["/**\n * Keyboard input handling for terminal applications.\n *\n * Supports both legacy terminal sequences and Kitty keyboard protocol.\n * See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/\n *\n * Symbol keys are also supported, however some ctrl+symbol combos\n * overlap with ASCII codes, e.g. ctrl+[ = ESC.\n * See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/#legacy-ctrl-mapping-of-ascii-keys\n * Those can still be * used for ctrl+shift combos\n *\n * API:\n * - matchesKey(data, keyId) - Check if input matches a key identifier\n * - parseKey(data) - Parse input and return the key identifier\n * - Key - Helper object for creating typed key identifiers\n */\n\n// =============================================================================\n// Type-Safe Key Identifiers\n// =============================================================================\n\ntype Letter =\n\t| \"a\"\n\t| \"b\"\n\t| \"c\"\n\t| \"d\"\n\t| \"e\"\n\t| \"f\"\n\t| \"g\"\n\t| \"h\"\n\t| \"i\"\n\t| \"j\"\n\t| \"k\"\n\t| \"l\"\n\t| \"m\"\n\t| \"n\"\n\t| \"o\"\n\t| \"p\"\n\t| \"q\"\n\t| \"r\"\n\t| \"s\"\n\t| \"t\"\n\t| \"u\"\n\t| \"v\"\n\t| \"w\"\n\t| \"x\"\n\t| \"y\"\n\t| \"z\";\n\ntype SymbolKey =\n\t| \"`\"\n\t| \"-\"\n\t| \"=\"\n\t| \"[\"\n\t| \"]\"\n\t| \"\\\\\"\n\t| \";\"\n\t| \"'\"\n\t| \",\"\n\t| \".\"\n\t| \"/\"\n\t| \"!\"\n\t| \"@\"\n\t| \"#\"\n\t| \"$\"\n\t| \"%\"\n\t| \"^\"\n\t| \"&\"\n\t| \"*\"\n\t| \"(\"\n\t| \")\"\n\t| \"_\"\n\t| \"+\"\n\t| \"|\"\n\t| \"~\"\n\t| \"{\"\n\t| \"}\"\n\t| \":\"\n\t| \"<\"\n\t| \">\"\n\t| \"?\";\n\ntype SpecialKey =\n\t| \"escape\"\n\t| \"esc\"\n\t| \"enter\"\n\t| \"return\"\n\t| \"tab\"\n\t| \"space\"\n\t| \"backspace\"\n\t| \"delete\"\n\t| \"home\"\n\t| \"end\"\n\t| \"up\"\n\t| \"down\"\n\t| \"left\"\n\t| \"right\";\n\ntype BaseKey = Letter | SymbolKey | SpecialKey;\n\n/**\n * Union type of all valid key identifiers.\n * Provides autocomplete and catches typos at compile time.\n */\nexport type KeyId =\n\t| BaseKey\n\t| `ctrl+${BaseKey}`\n\t| `shift+${BaseKey}`\n\t| `alt+${BaseKey}`\n\t| `ctrl+shift+${BaseKey}`\n\t| `shift+ctrl+${BaseKey}`\n\t| `ctrl+alt+${BaseKey}`\n\t| `alt+ctrl+${BaseKey}`\n\t| `shift+alt+${BaseKey}`\n\t| `alt+shift+${BaseKey}`\n\t| `ctrl+shift+alt+${BaseKey}`\n\t| `ctrl+alt+shift+${BaseKey}`\n\t| `shift+ctrl+alt+${BaseKey}`\n\t| `shift+alt+ctrl+${BaseKey}`\n\t| `alt+ctrl+shift+${BaseKey}`\n\t| `alt+shift+ctrl+${BaseKey}`;\n\n/**\n * Helper object for creating typed key identifiers with autocomplete.\n *\n * Usage:\n * - Key.escape, Key.enter, Key.tab, etc. for special keys\n * - Key.backtick, Key.comma, Key.period, etc. for symbol keys\n * - Key.ctrl(\"c\"), Key.alt(\"x\") for single modifier\n * - Key.ctrlShift(\"p\"), Key.ctrlAlt(\"x\") for combined modifiers\n */\nexport const Key = {\n\t// Special keys\n\tescape: \"escape\" as const,\n\tesc: \"esc\" as const,\n\tenter: \"enter\" as const,\n\treturn: \"return\" as const,\n\ttab: \"tab\" as const,\n\tspace: \"space\" as const,\n\tbackspace: \"backspace\" as const,\n\tdelete: \"delete\" as const,\n\thome: \"home\" as const,\n\tend: \"end\" as const,\n\tup: \"up\" as const,\n\tdown: \"down\" as const,\n\tleft: \"left\" as const,\n\tright: \"right\" as const,\n\n\t// Symbol keys\n\tbacktick: \"`\" as const,\n\thyphen: \"-\" as const,\n\tequals: \"=\" as const,\n\tleftbracket: \"[\" as const,\n\trightbracket: \"]\" as const,\n\tbackslash: \"\\\\\" as const,\n\tsemicolon: \";\" as const,\n\tquote: \"'\" as const,\n\tcomma: \",\" as const,\n\tperiod: \".\" as const,\n\tslash: \"/\" as const,\n\texclamation: \"!\" as const,\n\tat: \"@\" as const,\n\thash: \"#\" as const,\n\tdollar: \"$\" as const,\n\tpercent: \"%\" as const,\n\tcaret: \"^\" as const,\n\tampersand: \"&\" as const,\n\tasterisk: \"*\" as const,\n\tleftparen: \"(\" as const,\n\trightparen: \")\" as const,\n\tunderscore: \"_\" as const,\n\tplus: \"+\" as const,\n\tpipe: \"|\" as const,\n\ttilde: \"~\" as const,\n\tleftbrace: \"{\" as const,\n\trightbrace: \"}\" as const,\n\tcolon: \":\" as const,\n\tlessthan: \"<\" as const,\n\tgreaterthan: \">\" as const,\n\tquestion: \"?\" as const,\n\n\t// Single modifiers\n\tctrl: <K extends BaseKey>(key: K): `ctrl+${K}` => `ctrl+${key}`,\n\tshift: <K extends BaseKey>(key: K): `shift+${K}` => `shift+${key}`,\n\talt: <K extends BaseKey>(key: K): `alt+${K}` => `alt+${key}`,\n\n\t// Combined modifiers\n\tctrlShift: <K extends BaseKey>(key: K): `ctrl+shift+${K}` => `ctrl+shift+${key}`,\n\tshiftCtrl: <K extends BaseKey>(key: K): `shift+ctrl+${K}` => `shift+ctrl+${key}`,\n\tctrlAlt: <K extends BaseKey>(key: K): `ctrl+alt+${K}` => `ctrl+alt+${key}`,\n\taltCtrl: <K extends BaseKey>(key: K): `alt+ctrl+${K}` => `alt+ctrl+${key}`,\n\tshiftAlt: <K extends BaseKey>(key: K): `shift+alt+${K}` => `shift+alt+${key}`,\n\taltShift: <K extends BaseKey>(key: K): `alt+shift+${K}` => `alt+shift+${key}`,\n\n\t// Triple modifiers\n\tctrlShiftAlt: <K extends BaseKey>(key: K): `ctrl+shift+alt+${K}` => `ctrl+shift+alt+${key}`,\n} as const;\n\n// =============================================================================\n// Constants\n// =============================================================================\n\nconst SYMBOL_KEYS = new Set([\n\t\"`\",\n\t\"-\",\n\t\"=\",\n\t\"[\",\n\t\"]\",\n\t\"\\\\\",\n\t\";\",\n\t\"'\",\n\t\",\",\n\t\".\",\n\t\"/\",\n\t\"!\",\n\t\"@\",\n\t\"#\",\n\t\"$\",\n\t\"%\",\n\t\"^\",\n\t\"&\",\n\t\"*\",\n\t\"(\",\n\t\")\",\n\t\"_\",\n\t\"+\",\n\t\"|\",\n\t\"~\",\n\t\"{\",\n\t\"}\",\n\t\":\",\n\t\"<\",\n\t\">\",\n\t\"?\",\n]);\n\nconst MODIFIERS = {\n\tshift: 1,\n\talt: 2,\n\tctrl: 4,\n} as const;\n\nconst LOCK_MASK = 64 + 128; // Caps Lock + Num Lock\n\nconst CODEPOINTS = {\n\tescape: 27,\n\ttab: 9,\n\tenter: 13,\n\tspace: 32,\n\tbackspace: 127,\n\tkpEnter: 57414, // Numpad Enter (Kitty protocol)\n} as const;\n\nconst ARROW_CODEPOINTS = {\n\tup: -1,\n\tdown: -2,\n\tright: -3,\n\tleft: -4,\n} as const;\n\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\n// =============================================================================\n// Kitty Protocol Parsing\n// =============================================================================\n\ninterface ParsedKittySequence {\n\tcodepoint: number;\n\tmodifier: number;\n}\n\nfunction parseKittySequence(data: string): ParsedKittySequence | null {\n\t// 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// 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\tconst arrowCodes: Record<string, number> = { A: -1, B: -2, C: -3, D: -4 };\n\t\treturn { codepoint: arrowCodes[arrowMatch[2]!]!, modifier: modValue - 1 };\n\t}\n\n\t// Functional keys: \\x1b[<num>~ or \\x1b[<num>;<mod>~\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\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,\n\t\t\t8: FUNCTIONAL_CODEPOINTS.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// 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\nfunction matchesKittySequence(data: string, expectedCodepoint: number, expectedModifier: number): boolean {\n\tconst parsed = parseKittySequence(data);\n\tif (!parsed) return false;\n\tconst actualMod = parsed.modifier & ~LOCK_MASK;\n\tconst expectedMod = expectedModifier & ~LOCK_MASK;\n\treturn parsed.codepoint === expectedCodepoint && actualMod === expectedMod;\n}\n\n// =============================================================================\n// Generic Key Matching\n// =============================================================================\n\nfunction rawCtrlChar(letter: string): string {\n\tconst code = letter.toLowerCase().charCodeAt(0) - 96;\n\treturn String.fromCharCode(code);\n}\n\nfunction parseKeyId(keyId: string): { key: string; ctrl: boolean; shift: boolean; alt: boolean } | null {\n\tconst parts = keyId.toLowerCase().split(\"+\");\n\tconst key = parts[parts.length - 1];\n\tif (!key) return null;\n\treturn {\n\t\tkey,\n\t\tctrl: parts.includes(\"ctrl\"),\n\t\tshift: parts.includes(\"shift\"),\n\t\talt: parts.includes(\"alt\"),\n\t};\n}\n\n/**\n * Match input data against a key identifier string.\n *\n * Supported key identifiers:\n * - Single keys: \"escape\", \"tab\", \"enter\", \"backspace\", \"delete\", \"home\", \"end\", \"space\"\n * - Arrow keys: \"up\", \"down\", \"left\", \"right\"\n * - Ctrl combinations: \"ctrl+c\", \"ctrl+z\", etc.\n * - Shift combinations: \"shift+tab\", \"shift+enter\"\n * - Alt combinations: \"alt+enter\", \"alt+backspace\"\n * - Combined modifiers: \"shift+ctrl+p\", \"ctrl+alt+x\"\n *\n * Use the Key helper for autocomplete: Key.ctrl(\"c\"), Key.escape, Key.ctrlShift(\"p\")\n *\n * @param data - Raw input data from terminal\n * @param keyId - Key identifier (e.g., \"ctrl+c\", \"escape\", Key.ctrl(\"c\"))\n */\nexport function matchesKey(data: string, keyId: KeyId): boolean {\n\tconst parsed = parseKeyId(keyId);\n\tif (!parsed) return false;\n\n\tconst { key, ctrl, shift, alt } = parsed;\n\tlet modifier = 0;\n\tif (shift) modifier |= MODIFIERS.shift;\n\tif (alt) modifier |= MODIFIERS.alt;\n\tif (ctrl) modifier |= MODIFIERS.ctrl;\n\n\tswitch (key) {\n\t\tcase \"escape\":\n\t\tcase \"esc\":\n\t\t\tif (modifier !== 0) return false;\n\t\t\treturn data === \"\\x1b\" || matchesKittySequence(data, CODEPOINTS.escape, 0);\n\n\t\tcase \"space\":\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn data === \" \" || matchesKittySequence(data, CODEPOINTS.space, 0);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, CODEPOINTS.space, modifier);\n\n\t\tcase \"tab\":\n\t\t\tif (shift && !ctrl && !alt) {\n\t\t\t\treturn data === \"\\x1b[Z\" || matchesKittySequence(data, CODEPOINTS.tab, MODIFIERS.shift);\n\t\t\t}\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn data === \"\\t\" || matchesKittySequence(data, CODEPOINTS.tab, 0);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, CODEPOINTS.tab, modifier);\n\n\t\tcase \"enter\":\n\t\tcase \"return\":\n\t\t\tif (shift && !ctrl && !alt) {\n\t\t\t\treturn (\n\t\t\t\t\tmatchesKittySequence(data, CODEPOINTS.enter, MODIFIERS.shift) ||\n\t\t\t\t\tmatchesKittySequence(data, CODEPOINTS.kpEnter, MODIFIERS.shift)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (alt && !ctrl && !shift) {\n\t\t\t\treturn (\n\t\t\t\t\tdata === \"\\x1b\\r\" ||\n\t\t\t\t\tmatchesKittySequence(data, CODEPOINTS.enter, MODIFIERS.alt) ||\n\t\t\t\t\tmatchesKittySequence(data, CODEPOINTS.kpEnter, MODIFIERS.alt)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn (\n\t\t\t\t\tdata === \"\\r\" ||\n\t\t\t\t\tdata === \"\\x1bOM\" || // SS3 M (numpad enter in some terminals)\n\t\t\t\t\tmatchesKittySequence(data, CODEPOINTS.enter, 0) ||\n\t\t\t\t\tmatchesKittySequence(data, CODEPOINTS.kpEnter, 0)\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn (\n\t\t\t\tmatchesKittySequence(data, CODEPOINTS.enter, modifier) ||\n\t\t\t\tmatchesKittySequence(data, CODEPOINTS.kpEnter, modifier)\n\t\t\t);\n\n\t\tcase \"backspace\":\n\t\t\tif (alt && !ctrl && !shift) {\n\t\t\t\treturn data === \"\\x1b\\x7f\" || matchesKittySequence(data, CODEPOINTS.backspace, MODIFIERS.alt);\n\t\t\t}\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn data === \"\\x7f\" || data === \"\\x08\" || matchesKittySequence(data, CODEPOINTS.backspace, 0);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, CODEPOINTS.backspace, modifier);\n\n\t\tcase \"delete\":\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn data === \"\\x1b[3~\" || matchesKittySequence(data, FUNCTIONAL_CODEPOINTS.delete, 0);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, FUNCTIONAL_CODEPOINTS.delete, modifier);\n\n\t\tcase \"home\":\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn (\n\t\t\t\t\tdata === \"\\x1b[H\" ||\n\t\t\t\t\tdata === \"\\x1b[1~\" ||\n\t\t\t\t\tdata === \"\\x1b[7~\" ||\n\t\t\t\t\tmatchesKittySequence(data, FUNCTIONAL_CODEPOINTS.home, 0)\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, FUNCTIONAL_CODEPOINTS.home, modifier);\n\n\t\tcase \"end\":\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn (\n\t\t\t\t\tdata === \"\\x1b[F\" ||\n\t\t\t\t\tdata === \"\\x1b[4~\" ||\n\t\t\t\t\tdata === \"\\x1b[8~\" ||\n\t\t\t\t\tmatchesKittySequence(data, FUNCTIONAL_CODEPOINTS.end, 0)\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, FUNCTIONAL_CODEPOINTS.end, modifier);\n\n\t\tcase \"up\":\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn data === \"\\x1b[A\" || matchesKittySequence(data, ARROW_CODEPOINTS.up, 0);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, ARROW_CODEPOINTS.up, modifier);\n\n\t\tcase \"down\":\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn data === \"\\x1b[B\" || matchesKittySequence(data, ARROW_CODEPOINTS.down, 0);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, ARROW_CODEPOINTS.down, modifier);\n\n\t\tcase \"left\":\n\t\t\tif (alt && !ctrl && !shift) {\n\t\t\t\treturn (\n\t\t\t\t\tdata === \"\\x1b[1;3D\" ||\n\t\t\t\t\tdata === \"\\x1bb\" ||\n\t\t\t\t\tmatchesKittySequence(data, ARROW_CODEPOINTS.left, MODIFIERS.alt)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (ctrl && !alt && !shift) {\n\t\t\t\treturn data === \"\\x1b[1;5D\" || matchesKittySequence(data, ARROW_CODEPOINTS.left, MODIFIERS.ctrl);\n\t\t\t}\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn data === \"\\x1b[D\" || matchesKittySequence(data, ARROW_CODEPOINTS.left, 0);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, ARROW_CODEPOINTS.left, modifier);\n\n\t\tcase \"right\":\n\t\t\tif (alt && !ctrl && !shift) {\n\t\t\t\treturn (\n\t\t\t\t\tdata === \"\\x1b[1;3C\" ||\n\t\t\t\t\tdata === \"\\x1bf\" ||\n\t\t\t\t\tmatchesKittySequence(data, ARROW_CODEPOINTS.right, MODIFIERS.alt)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (ctrl && !alt && !shift) {\n\t\t\t\treturn data === \"\\x1b[1;5C\" || matchesKittySequence(data, ARROW_CODEPOINTS.right, MODIFIERS.ctrl);\n\t\t\t}\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn data === \"\\x1b[C\" || matchesKittySequence(data, ARROW_CODEPOINTS.right, 0);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, ARROW_CODEPOINTS.right, modifier);\n\t}\n\n\t// Handle single letter keys (a-z) and some symbols\n\tif (key.length === 1 && ((key >= \"a\" && key <= \"z\") || SYMBOL_KEYS.has(key))) {\n\t\tconst codepoint = key.charCodeAt(0);\n\n\t\tif (ctrl && !shift && !alt) {\n\t\t\tconst raw = rawCtrlChar(key);\n\t\t\tif (data === raw) return true;\n\t\t\tif (data.length > 0 && data.charCodeAt(0) === raw.charCodeAt(0)) return true;\n\t\t\treturn matchesKittySequence(data, codepoint, MODIFIERS.ctrl);\n\t\t}\n\n\t\tif (ctrl && shift && !alt) {\n\t\t\treturn matchesKittySequence(data, codepoint, MODIFIERS.shift + MODIFIERS.ctrl);\n\t\t}\n\n\t\tif (shift && !ctrl && !alt) {\n\t\t\t// Legacy: shift+letter produces uppercase\n\t\t\tif (data === key.toUpperCase()) return true;\n\t\t\treturn matchesKittySequence(data, codepoint, MODIFIERS.shift);\n\t\t}\n\n\t\tif (modifier !== 0) {\n\t\t\treturn matchesKittySequence(data, codepoint, modifier);\n\t\t}\n\n\t\treturn data === key;\n\t}\n\n\treturn false;\n}\n\n/**\n * Parse input data and return the key identifier if recognized.\n *\n * @param data - Raw input data from terminal\n * @returns Key identifier string (e.g., \"ctrl+c\") or undefined\n */\nexport function parseKey(data: string): string | undefined {\n\tconst kitty = parseKittySequence(data);\n\tif (kitty) {\n\t\tconst { codepoint, modifier } = kitty;\n\t\tconst mods: string[] = [];\n\t\tconst effectiveMod = modifier & ~LOCK_MASK;\n\t\tif (effectiveMod & MODIFIERS.shift) mods.push(\"shift\");\n\t\tif (effectiveMod & MODIFIERS.ctrl) mods.push(\"ctrl\");\n\t\tif (effectiveMod & MODIFIERS.alt) mods.push(\"alt\");\n\n\t\tlet keyName: string | undefined;\n\t\tif (codepoint === CODEPOINTS.escape) keyName = \"escape\";\n\t\telse if (codepoint === CODEPOINTS.tab) keyName = \"tab\";\n\t\telse if (codepoint === CODEPOINTS.enter || codepoint === CODEPOINTS.kpEnter) keyName = \"enter\";\n\t\telse if (codepoint === CODEPOINTS.space) keyName = \"space\";\n\t\telse if (codepoint === CODEPOINTS.backspace) keyName = \"backspace\";\n\t\telse if (codepoint === FUNCTIONAL_CODEPOINTS.delete) keyName = \"delete\";\n\t\telse if (codepoint === FUNCTIONAL_CODEPOINTS.home) keyName = \"home\";\n\t\telse if (codepoint === FUNCTIONAL_CODEPOINTS.end) keyName = \"end\";\n\t\telse if (codepoint === ARROW_CODEPOINTS.up) keyName = \"up\";\n\t\telse if (codepoint === ARROW_CODEPOINTS.down) keyName = \"down\";\n\t\telse if (codepoint === ARROW_CODEPOINTS.left) keyName = \"left\";\n\t\telse if (codepoint === ARROW_CODEPOINTS.right) keyName = \"right\";\n\t\telse if (codepoint >= 97 && codepoint <= 122) keyName = String.fromCharCode(codepoint);\n\t\telse if (SYMBOL_KEYS.has(String.fromCharCode(codepoint))) keyName = String.fromCharCode(codepoint);\n\n\t\tif (keyName) {\n\t\t\treturn mods.length > 0 ? `${mods.join(\"+\")}+${keyName}` : keyName;\n\t\t}\n\t}\n\n\t// Legacy sequences\n\tif (data === \"\\x1b\") return \"escape\";\n\tif (data === \"\\t\") return \"tab\";\n\tif (data === \"\\r\" || data === \"\\x1bOM\") return \"enter\";\n\tif (data === \" \") return \"space\";\n\tif (data === \"\\x7f\" || data === \"\\x08\") return \"backspace\";\n\tif (data === \"\\x1b[Z\") return \"shift+tab\";\n\tif (data === \"\\x1b\\r\") return \"alt+enter\";\n\tif (data === \"\\x1b\\x7f\") return \"alt+backspace\";\n\tif (data === \"\\x1b[A\") return \"up\";\n\tif (data === \"\\x1b[B\") return \"down\";\n\tif (data === \"\\x1b[C\") return \"right\";\n\tif (data === \"\\x1b[D\") return \"left\";\n\tif (data === \"\\x1b[H\") return \"home\";\n\tif (data === \"\\x1b[F\") return \"end\";\n\tif (data === \"\\x1b[3~\") return \"delete\";\n\n\t// Raw Ctrl+letter\n\tif (data.length === 1) {\n\t\tconst code = data.charCodeAt(0);\n\t\tif (code >= 1 && code <= 26) {\n\t\t\treturn `ctrl+${String.fromCharCode(code + 96)}`;\n\t\t}\n\t\tif (code >= 32 && code <= 126) {\n\t\t\treturn data;\n\t\t}\n\t}\n\n\treturn undefined;\n}\n"]}
package/dist/keys.js CHANGED
@@ -4,6 +4,11 @@
4
4
  * Supports both legacy terminal sequences and Kitty keyboard protocol.
5
5
  * See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/
6
6
  *
7
+ * Symbol keys are also supported, however some ctrl+symbol combos
8
+ * overlap with ASCII codes, e.g. ctrl+[ = ESC.
9
+ * See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/#legacy-ctrl-mapping-of-ascii-keys
10
+ * Those can still be * used for ctrl+shift combos
11
+ *
7
12
  * API:
8
13
  * - matchesKey(data, keyId) - Check if input matches a key identifier
9
14
  * - parseKey(data) - Parse input and return the key identifier
@@ -14,6 +19,7 @@
14
19
  *
15
20
  * Usage:
16
21
  * - Key.escape, Key.enter, Key.tab, etc. for special keys
22
+ * - Key.backtick, Key.comma, Key.period, etc. for symbol keys
17
23
  * - Key.ctrl("c"), Key.alt("x") for single modifier
18
24
  * - Key.ctrlShift("p"), Key.ctrlAlt("x") for combined modifiers
19
25
  */
@@ -33,6 +39,38 @@ export const Key = {
33
39
  down: "down",
34
40
  left: "left",
35
41
  right: "right",
42
+ // Symbol keys
43
+ backtick: "`",
44
+ hyphen: "-",
45
+ equals: "=",
46
+ leftbracket: "[",
47
+ rightbracket: "]",
48
+ backslash: "\\",
49
+ semicolon: ";",
50
+ quote: "'",
51
+ comma: ",",
52
+ period: ".",
53
+ slash: "/",
54
+ exclamation: "!",
55
+ at: "@",
56
+ hash: "#",
57
+ dollar: "$",
58
+ percent: "%",
59
+ caret: "^",
60
+ ampersand: "&",
61
+ asterisk: "*",
62
+ leftparen: "(",
63
+ rightparen: ")",
64
+ underscore: "_",
65
+ plus: "+",
66
+ pipe: "|",
67
+ tilde: "~",
68
+ leftbrace: "{",
69
+ rightbrace: "}",
70
+ colon: ":",
71
+ lessthan: "<",
72
+ greaterthan: ">",
73
+ question: "?",
36
74
  // Single modifiers
37
75
  ctrl: (key) => `ctrl+${key}`,
38
76
  shift: (key) => `shift+${key}`,
@@ -50,6 +88,39 @@ export const Key = {
50
88
  // =============================================================================
51
89
  // Constants
52
90
  // =============================================================================
91
+ const SYMBOL_KEYS = new Set([
92
+ "`",
93
+ "-",
94
+ "=",
95
+ "[",
96
+ "]",
97
+ "\\",
98
+ ";",
99
+ "'",
100
+ ",",
101
+ ".",
102
+ "/",
103
+ "!",
104
+ "@",
105
+ "#",
106
+ "$",
107
+ "%",
108
+ "^",
109
+ "&",
110
+ "*",
111
+ "(",
112
+ ")",
113
+ "_",
114
+ "+",
115
+ "|",
116
+ "~",
117
+ "{",
118
+ "}",
119
+ ":",
120
+ "<",
121
+ ">",
122
+ "?",
123
+ ]);
53
124
  const MODIFIERS = {
54
125
  shift: 1,
55
126
  alt: 2,
@@ -279,8 +350,8 @@ export function matchesKey(data, keyId) {
279
350
  }
280
351
  return matchesKittySequence(data, ARROW_CODEPOINTS.right, modifier);
281
352
  }
282
- // Handle single letter keys (a-z)
283
- if (key.length === 1 && key >= "a" && key <= "z") {
353
+ // Handle single letter keys (a-z) and some symbols
354
+ if (key.length === 1 && ((key >= "a" && key <= "z") || SYMBOL_KEYS.has(key))) {
284
355
  const codepoint = key.charCodeAt(0);
285
356
  if (ctrl && !shift && !alt) {
286
357
  const raw = rawCtrlChar(key);
@@ -351,6 +422,8 @@ export function parseKey(data) {
351
422
  keyName = "right";
352
423
  else if (codepoint >= 97 && codepoint <= 122)
353
424
  keyName = String.fromCharCode(codepoint);
425
+ else if (SYMBOL_KEYS.has(String.fromCharCode(codepoint)))
426
+ keyName = String.fromCharCode(codepoint);
354
427
  if (keyName) {
355
428
  return mods.length > 0 ? `${mods.join("+")}+${keyName}` : keyName;
356
429
  }
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 * Keyboard input handling for terminal applications.\n *\n * Supports both legacy terminal sequences and Kitty keyboard protocol.\n * See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/\n *\n * API:\n * - matchesKey(data, keyId) - Check if input matches a key identifier\n * - parseKey(data) - Parse input and return the key identifier\n * - Key - Helper object for creating typed key identifiers\n */\n\n// =============================================================================\n// Type-Safe Key Identifiers\n// =============================================================================\n\ntype Letter =\n\t| \"a\"\n\t| \"b\"\n\t| \"c\"\n\t| \"d\"\n\t| \"e\"\n\t| \"f\"\n\t| \"g\"\n\t| \"h\"\n\t| \"i\"\n\t| \"j\"\n\t| \"k\"\n\t| \"l\"\n\t| \"m\"\n\t| \"n\"\n\t| \"o\"\n\t| \"p\"\n\t| \"q\"\n\t| \"r\"\n\t| \"s\"\n\t| \"t\"\n\t| \"u\"\n\t| \"v\"\n\t| \"w\"\n\t| \"x\"\n\t| \"y\"\n\t| \"z\";\n\ntype SpecialKey =\n\t| \"escape\"\n\t| \"esc\"\n\t| \"enter\"\n\t| \"return\"\n\t| \"tab\"\n\t| \"space\"\n\t| \"backspace\"\n\t| \"delete\"\n\t| \"home\"\n\t| \"end\"\n\t| \"up\"\n\t| \"down\"\n\t| \"left\"\n\t| \"right\";\n\ntype BaseKey = Letter | SpecialKey;\n\n/**\n * Union type of all valid key identifiers.\n * Provides autocomplete and catches typos at compile time.\n */\nexport type KeyId =\n\t| BaseKey\n\t| `ctrl+${BaseKey}`\n\t| `shift+${BaseKey}`\n\t| `alt+${BaseKey}`\n\t| `ctrl+shift+${BaseKey}`\n\t| `shift+ctrl+${BaseKey}`\n\t| `ctrl+alt+${BaseKey}`\n\t| `alt+ctrl+${BaseKey}`\n\t| `shift+alt+${BaseKey}`\n\t| `alt+shift+${BaseKey}`\n\t| `ctrl+shift+alt+${BaseKey}`\n\t| `ctrl+alt+shift+${BaseKey}`\n\t| `shift+ctrl+alt+${BaseKey}`\n\t| `shift+alt+ctrl+${BaseKey}`\n\t| `alt+ctrl+shift+${BaseKey}`\n\t| `alt+shift+ctrl+${BaseKey}`;\n\n/**\n * Helper object for creating typed key identifiers with autocomplete.\n *\n * Usage:\n * - Key.escape, Key.enter, Key.tab, etc. for special keys\n * - Key.ctrl(\"c\"), Key.alt(\"x\") for single modifier\n * - Key.ctrlShift(\"p\"), Key.ctrlAlt(\"x\") for combined modifiers\n */\nexport const Key = {\n\t// Special keys\n\tescape: \"escape\" as const,\n\tesc: \"esc\" as const,\n\tenter: \"enter\" as const,\n\treturn: \"return\" as const,\n\ttab: \"tab\" as const,\n\tspace: \"space\" as const,\n\tbackspace: \"backspace\" as const,\n\tdelete: \"delete\" as const,\n\thome: \"home\" as const,\n\tend: \"end\" as const,\n\tup: \"up\" as const,\n\tdown: \"down\" as const,\n\tleft: \"left\" as const,\n\tright: \"right\" as const,\n\n\t// Single modifiers\n\tctrl: <K extends BaseKey>(key: K): `ctrl+${K}` => `ctrl+${key}`,\n\tshift: <K extends BaseKey>(key: K): `shift+${K}` => `shift+${key}`,\n\talt: <K extends BaseKey>(key: K): `alt+${K}` => `alt+${key}`,\n\n\t// Combined modifiers\n\tctrlShift: <K extends BaseKey>(key: K): `ctrl+shift+${K}` => `ctrl+shift+${key}`,\n\tshiftCtrl: <K extends BaseKey>(key: K): `shift+ctrl+${K}` => `shift+ctrl+${key}`,\n\tctrlAlt: <K extends BaseKey>(key: K): `ctrl+alt+${K}` => `ctrl+alt+${key}`,\n\taltCtrl: <K extends BaseKey>(key: K): `alt+ctrl+${K}` => `alt+ctrl+${key}`,\n\tshiftAlt: <K extends BaseKey>(key: K): `shift+alt+${K}` => `shift+alt+${key}`,\n\taltShift: <K extends BaseKey>(key: K): `alt+shift+${K}` => `alt+shift+${key}`,\n\n\t// Triple modifiers\n\tctrlShiftAlt: <K extends BaseKey>(key: K): `ctrl+shift+alt+${K}` => `ctrl+shift+alt+${key}`,\n} as const;\n\n// =============================================================================\n// Constants\n// =============================================================================\n\nconst MODIFIERS = {\n\tshift: 1,\n\talt: 2,\n\tctrl: 4,\n} as const;\n\nconst LOCK_MASK = 64 + 128; // Caps Lock + Num Lock\n\nconst CODEPOINTS = {\n\tescape: 27,\n\ttab: 9,\n\tenter: 13,\n\tspace: 32,\n\tbackspace: 127,\n\tkpEnter: 57414, // Numpad Enter (Kitty protocol)\n} as const;\n\nconst ARROW_CODEPOINTS = {\n\tup: -1,\n\tdown: -2,\n\tright: -3,\n\tleft: -4,\n} as const;\n\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\n// =============================================================================\n// Kitty Protocol Parsing\n// =============================================================================\n\ninterface ParsedKittySequence {\n\tcodepoint: number;\n\tmodifier: number;\n}\n\nfunction parseKittySequence(data: string): ParsedKittySequence | null {\n\t// 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// 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\tconst arrowCodes: Record<string, number> = { A: -1, B: -2, C: -3, D: -4 };\n\t\treturn { codepoint: arrowCodes[arrowMatch[2]!]!, modifier: modValue - 1 };\n\t}\n\n\t// Functional keys: \\x1b[<num>~ or \\x1b[<num>;<mod>~\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\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,\n\t\t\t8: FUNCTIONAL_CODEPOINTS.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// 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\nfunction matchesKittySequence(data: string, expectedCodepoint: number, expectedModifier: number): boolean {\n\tconst parsed = parseKittySequence(data);\n\tif (!parsed) return false;\n\tconst actualMod = parsed.modifier & ~LOCK_MASK;\n\tconst expectedMod = expectedModifier & ~LOCK_MASK;\n\treturn parsed.codepoint === expectedCodepoint && actualMod === expectedMod;\n}\n\n// =============================================================================\n// Generic Key Matching\n// =============================================================================\n\nfunction rawCtrlChar(letter: string): string {\n\tconst code = letter.toLowerCase().charCodeAt(0) - 96;\n\treturn String.fromCharCode(code);\n}\n\nfunction parseKeyId(keyId: string): { key: string; ctrl: boolean; shift: boolean; alt: boolean } | null {\n\tconst parts = keyId.toLowerCase().split(\"+\");\n\tconst key = parts[parts.length - 1];\n\tif (!key) return null;\n\treturn {\n\t\tkey,\n\t\tctrl: parts.includes(\"ctrl\"),\n\t\tshift: parts.includes(\"shift\"),\n\t\talt: parts.includes(\"alt\"),\n\t};\n}\n\n/**\n * Match input data against a key identifier string.\n *\n * Supported key identifiers:\n * - Single keys: \"escape\", \"tab\", \"enter\", \"backspace\", \"delete\", \"home\", \"end\", \"space\"\n * - Arrow keys: \"up\", \"down\", \"left\", \"right\"\n * - Ctrl combinations: \"ctrl+c\", \"ctrl+z\", etc.\n * - Shift combinations: \"shift+tab\", \"shift+enter\"\n * - Alt combinations: \"alt+enter\", \"alt+backspace\"\n * - Combined modifiers: \"shift+ctrl+p\", \"ctrl+alt+x\"\n *\n * Use the Key helper for autocomplete: Key.ctrl(\"c\"), Key.escape, Key.ctrlShift(\"p\")\n *\n * @param data - Raw input data from terminal\n * @param keyId - Key identifier (e.g., \"ctrl+c\", \"escape\", Key.ctrl(\"c\"))\n */\nexport function matchesKey(data: string, keyId: KeyId): boolean {\n\tconst parsed = parseKeyId(keyId);\n\tif (!parsed) return false;\n\n\tconst { key, ctrl, shift, alt } = parsed;\n\tlet modifier = 0;\n\tif (shift) modifier |= MODIFIERS.shift;\n\tif (alt) modifier |= MODIFIERS.alt;\n\tif (ctrl) modifier |= MODIFIERS.ctrl;\n\n\tswitch (key) {\n\t\tcase \"escape\":\n\t\tcase \"esc\":\n\t\t\tif (modifier !== 0) return false;\n\t\t\treturn data === \"\\x1b\" || matchesKittySequence(data, CODEPOINTS.escape, 0);\n\n\t\tcase \"space\":\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn data === \" \" || matchesKittySequence(data, CODEPOINTS.space, 0);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, CODEPOINTS.space, modifier);\n\n\t\tcase \"tab\":\n\t\t\tif (shift && !ctrl && !alt) {\n\t\t\t\treturn data === \"\\x1b[Z\" || matchesKittySequence(data, CODEPOINTS.tab, MODIFIERS.shift);\n\t\t\t}\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn data === \"\\t\" || matchesKittySequence(data, CODEPOINTS.tab, 0);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, CODEPOINTS.tab, modifier);\n\n\t\tcase \"enter\":\n\t\tcase \"return\":\n\t\t\tif (shift && !ctrl && !alt) {\n\t\t\t\treturn (\n\t\t\t\t\tmatchesKittySequence(data, CODEPOINTS.enter, MODIFIERS.shift) ||\n\t\t\t\t\tmatchesKittySequence(data, CODEPOINTS.kpEnter, MODIFIERS.shift)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (alt && !ctrl && !shift) {\n\t\t\t\treturn (\n\t\t\t\t\tdata === \"\\x1b\\r\" ||\n\t\t\t\t\tmatchesKittySequence(data, CODEPOINTS.enter, MODIFIERS.alt) ||\n\t\t\t\t\tmatchesKittySequence(data, CODEPOINTS.kpEnter, MODIFIERS.alt)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn (\n\t\t\t\t\tdata === \"\\r\" ||\n\t\t\t\t\tdata === \"\\x1bOM\" || // SS3 M (numpad enter in some terminals)\n\t\t\t\t\tmatchesKittySequence(data, CODEPOINTS.enter, 0) ||\n\t\t\t\t\tmatchesKittySequence(data, CODEPOINTS.kpEnter, 0)\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn (\n\t\t\t\tmatchesKittySequence(data, CODEPOINTS.enter, modifier) ||\n\t\t\t\tmatchesKittySequence(data, CODEPOINTS.kpEnter, modifier)\n\t\t\t);\n\n\t\tcase \"backspace\":\n\t\t\tif (alt && !ctrl && !shift) {\n\t\t\t\treturn data === \"\\x1b\\x7f\" || matchesKittySequence(data, CODEPOINTS.backspace, MODIFIERS.alt);\n\t\t\t}\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn data === \"\\x7f\" || data === \"\\x08\" || matchesKittySequence(data, CODEPOINTS.backspace, 0);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, CODEPOINTS.backspace, modifier);\n\n\t\tcase \"delete\":\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn data === \"\\x1b[3~\" || matchesKittySequence(data, FUNCTIONAL_CODEPOINTS.delete, 0);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, FUNCTIONAL_CODEPOINTS.delete, modifier);\n\n\t\tcase \"home\":\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn (\n\t\t\t\t\tdata === \"\\x1b[H\" ||\n\t\t\t\t\tdata === \"\\x1b[1~\" ||\n\t\t\t\t\tdata === \"\\x1b[7~\" ||\n\t\t\t\t\tmatchesKittySequence(data, FUNCTIONAL_CODEPOINTS.home, 0)\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, FUNCTIONAL_CODEPOINTS.home, modifier);\n\n\t\tcase \"end\":\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn (\n\t\t\t\t\tdata === \"\\x1b[F\" ||\n\t\t\t\t\tdata === \"\\x1b[4~\" ||\n\t\t\t\t\tdata === \"\\x1b[8~\" ||\n\t\t\t\t\tmatchesKittySequence(data, FUNCTIONAL_CODEPOINTS.end, 0)\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, FUNCTIONAL_CODEPOINTS.end, modifier);\n\n\t\tcase \"up\":\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn data === \"\\x1b[A\" || matchesKittySequence(data, ARROW_CODEPOINTS.up, 0);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, ARROW_CODEPOINTS.up, modifier);\n\n\t\tcase \"down\":\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn data === \"\\x1b[B\" || matchesKittySequence(data, ARROW_CODEPOINTS.down, 0);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, ARROW_CODEPOINTS.down, modifier);\n\n\t\tcase \"left\":\n\t\t\tif (alt && !ctrl && !shift) {\n\t\t\t\treturn (\n\t\t\t\t\tdata === \"\\x1b[1;3D\" ||\n\t\t\t\t\tdata === \"\\x1bb\" ||\n\t\t\t\t\tmatchesKittySequence(data, ARROW_CODEPOINTS.left, MODIFIERS.alt)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (ctrl && !alt && !shift) {\n\t\t\t\treturn data === \"\\x1b[1;5D\" || matchesKittySequence(data, ARROW_CODEPOINTS.left, MODIFIERS.ctrl);\n\t\t\t}\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn data === \"\\x1b[D\" || matchesKittySequence(data, ARROW_CODEPOINTS.left, 0);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, ARROW_CODEPOINTS.left, modifier);\n\n\t\tcase \"right\":\n\t\t\tif (alt && !ctrl && !shift) {\n\t\t\t\treturn (\n\t\t\t\t\tdata === \"\\x1b[1;3C\" ||\n\t\t\t\t\tdata === \"\\x1bf\" ||\n\t\t\t\t\tmatchesKittySequence(data, ARROW_CODEPOINTS.right, MODIFIERS.alt)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (ctrl && !alt && !shift) {\n\t\t\t\treturn data === \"\\x1b[1;5C\" || matchesKittySequence(data, ARROW_CODEPOINTS.right, MODIFIERS.ctrl);\n\t\t\t}\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn data === \"\\x1b[C\" || matchesKittySequence(data, ARROW_CODEPOINTS.right, 0);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, ARROW_CODEPOINTS.right, modifier);\n\t}\n\n\t// Handle single letter keys (a-z)\n\tif (key.length === 1 && key >= \"a\" && key <= \"z\") {\n\t\tconst codepoint = key.charCodeAt(0);\n\n\t\tif (ctrl && !shift && !alt) {\n\t\t\tconst raw = rawCtrlChar(key);\n\t\t\tif (data === raw) return true;\n\t\t\tif (data.length > 0 && data.charCodeAt(0) === raw.charCodeAt(0)) return true;\n\t\t\treturn matchesKittySequence(data, codepoint, MODIFIERS.ctrl);\n\t\t}\n\n\t\tif (ctrl && shift && !alt) {\n\t\t\treturn matchesKittySequence(data, codepoint, MODIFIERS.shift + MODIFIERS.ctrl);\n\t\t}\n\n\t\tif (shift && !ctrl && !alt) {\n\t\t\t// Legacy: shift+letter produces uppercase\n\t\t\tif (data === key.toUpperCase()) return true;\n\t\t\treturn matchesKittySequence(data, codepoint, MODIFIERS.shift);\n\t\t}\n\n\t\tif (modifier !== 0) {\n\t\t\treturn matchesKittySequence(data, codepoint, modifier);\n\t\t}\n\n\t\treturn data === key;\n\t}\n\n\treturn false;\n}\n\n/**\n * Parse input data and return the key identifier if recognized.\n *\n * @param data - Raw input data from terminal\n * @returns Key identifier string (e.g., \"ctrl+c\") or undefined\n */\nexport function parseKey(data: string): string | undefined {\n\tconst kitty = parseKittySequence(data);\n\tif (kitty) {\n\t\tconst { codepoint, modifier } = kitty;\n\t\tconst mods: string[] = [];\n\t\tconst effectiveMod = modifier & ~LOCK_MASK;\n\t\tif (effectiveMod & MODIFIERS.shift) mods.push(\"shift\");\n\t\tif (effectiveMod & MODIFIERS.ctrl) mods.push(\"ctrl\");\n\t\tif (effectiveMod & MODIFIERS.alt) mods.push(\"alt\");\n\n\t\tlet keyName: string | undefined;\n\t\tif (codepoint === CODEPOINTS.escape) keyName = \"escape\";\n\t\telse if (codepoint === CODEPOINTS.tab) keyName = \"tab\";\n\t\telse if (codepoint === CODEPOINTS.enter || codepoint === CODEPOINTS.kpEnter) keyName = \"enter\";\n\t\telse if (codepoint === CODEPOINTS.space) keyName = \"space\";\n\t\telse if (codepoint === CODEPOINTS.backspace) keyName = \"backspace\";\n\t\telse if (codepoint === FUNCTIONAL_CODEPOINTS.delete) keyName = \"delete\";\n\t\telse if (codepoint === FUNCTIONAL_CODEPOINTS.home) keyName = \"home\";\n\t\telse if (codepoint === FUNCTIONAL_CODEPOINTS.end) keyName = \"end\";\n\t\telse if (codepoint === ARROW_CODEPOINTS.up) keyName = \"up\";\n\t\telse if (codepoint === ARROW_CODEPOINTS.down) keyName = \"down\";\n\t\telse if (codepoint === ARROW_CODEPOINTS.left) keyName = \"left\";\n\t\telse if (codepoint === ARROW_CODEPOINTS.right) keyName = \"right\";\n\t\telse if (codepoint >= 97 && codepoint <= 122) keyName = String.fromCharCode(codepoint);\n\n\t\tif (keyName) {\n\t\t\treturn mods.length > 0 ? `${mods.join(\"+\")}+${keyName}` : keyName;\n\t\t}\n\t}\n\n\t// Legacy sequences\n\tif (data === \"\\x1b\") return \"escape\";\n\tif (data === \"\\t\") return \"tab\";\n\tif (data === \"\\r\" || data === \"\\x1bOM\") return \"enter\";\n\tif (data === \" \") return \"space\";\n\tif (data === \"\\x7f\" || data === \"\\x08\") return \"backspace\";\n\tif (data === \"\\x1b[Z\") return \"shift+tab\";\n\tif (data === \"\\x1b\\r\") return \"alt+enter\";\n\tif (data === \"\\x1b\\x7f\") return \"alt+backspace\";\n\tif (data === \"\\x1b[A\") return \"up\";\n\tif (data === \"\\x1b[B\") return \"down\";\n\tif (data === \"\\x1b[C\") return \"right\";\n\tif (data === \"\\x1b[D\") return \"left\";\n\tif (data === \"\\x1b[H\") return \"home\";\n\tif (data === \"\\x1b[F\") return \"end\";\n\tif (data === \"\\x1b[3~\") return \"delete\";\n\n\t// Raw Ctrl+letter\n\tif (data.length === 1) {\n\t\tconst code = data.charCodeAt(0);\n\t\tif (code >= 1 && code <= 26) {\n\t\t\treturn `ctrl+${String.fromCharCode(code + 96)}`;\n\t\t}\n\t\tif (code >= 32 && code <= 126) {\n\t\t\treturn data;\n\t\t}\n\t}\n\n\treturn undefined;\n}\n"]}
1
+ {"version":3,"file":"keys.js","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Keyboard input handling for terminal applications.\n *\n * Supports both legacy terminal sequences and Kitty keyboard protocol.\n * See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/\n *\n * Symbol keys are also supported, however some ctrl+symbol combos\n * overlap with ASCII codes, e.g. ctrl+[ = ESC.\n * See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/#legacy-ctrl-mapping-of-ascii-keys\n * Those can still be * used for ctrl+shift combos\n *\n * API:\n * - matchesKey(data, keyId) - Check if input matches a key identifier\n * - parseKey(data) - Parse input and return the key identifier\n * - Key - Helper object for creating typed key identifiers\n */\n\n// =============================================================================\n// Type-Safe Key Identifiers\n// =============================================================================\n\ntype Letter =\n\t| \"a\"\n\t| \"b\"\n\t| \"c\"\n\t| \"d\"\n\t| \"e\"\n\t| \"f\"\n\t| \"g\"\n\t| \"h\"\n\t| \"i\"\n\t| \"j\"\n\t| \"k\"\n\t| \"l\"\n\t| \"m\"\n\t| \"n\"\n\t| \"o\"\n\t| \"p\"\n\t| \"q\"\n\t| \"r\"\n\t| \"s\"\n\t| \"t\"\n\t| \"u\"\n\t| \"v\"\n\t| \"w\"\n\t| \"x\"\n\t| \"y\"\n\t| \"z\";\n\ntype SymbolKey =\n\t| \"`\"\n\t| \"-\"\n\t| \"=\"\n\t| \"[\"\n\t| \"]\"\n\t| \"\\\\\"\n\t| \";\"\n\t| \"'\"\n\t| \",\"\n\t| \".\"\n\t| \"/\"\n\t| \"!\"\n\t| \"@\"\n\t| \"#\"\n\t| \"$\"\n\t| \"%\"\n\t| \"^\"\n\t| \"&\"\n\t| \"*\"\n\t| \"(\"\n\t| \")\"\n\t| \"_\"\n\t| \"+\"\n\t| \"|\"\n\t| \"~\"\n\t| \"{\"\n\t| \"}\"\n\t| \":\"\n\t| \"<\"\n\t| \">\"\n\t| \"?\";\n\ntype SpecialKey =\n\t| \"escape\"\n\t| \"esc\"\n\t| \"enter\"\n\t| \"return\"\n\t| \"tab\"\n\t| \"space\"\n\t| \"backspace\"\n\t| \"delete\"\n\t| \"home\"\n\t| \"end\"\n\t| \"up\"\n\t| \"down\"\n\t| \"left\"\n\t| \"right\";\n\ntype BaseKey = Letter | SymbolKey | SpecialKey;\n\n/**\n * Union type of all valid key identifiers.\n * Provides autocomplete and catches typos at compile time.\n */\nexport type KeyId =\n\t| BaseKey\n\t| `ctrl+${BaseKey}`\n\t| `shift+${BaseKey}`\n\t| `alt+${BaseKey}`\n\t| `ctrl+shift+${BaseKey}`\n\t| `shift+ctrl+${BaseKey}`\n\t| `ctrl+alt+${BaseKey}`\n\t| `alt+ctrl+${BaseKey}`\n\t| `shift+alt+${BaseKey}`\n\t| `alt+shift+${BaseKey}`\n\t| `ctrl+shift+alt+${BaseKey}`\n\t| `ctrl+alt+shift+${BaseKey}`\n\t| `shift+ctrl+alt+${BaseKey}`\n\t| `shift+alt+ctrl+${BaseKey}`\n\t| `alt+ctrl+shift+${BaseKey}`\n\t| `alt+shift+ctrl+${BaseKey}`;\n\n/**\n * Helper object for creating typed key identifiers with autocomplete.\n *\n * Usage:\n * - Key.escape, Key.enter, Key.tab, etc. for special keys\n * - Key.backtick, Key.comma, Key.period, etc. for symbol keys\n * - Key.ctrl(\"c\"), Key.alt(\"x\") for single modifier\n * - Key.ctrlShift(\"p\"), Key.ctrlAlt(\"x\") for combined modifiers\n */\nexport const Key = {\n\t// Special keys\n\tescape: \"escape\" as const,\n\tesc: \"esc\" as const,\n\tenter: \"enter\" as const,\n\treturn: \"return\" as const,\n\ttab: \"tab\" as const,\n\tspace: \"space\" as const,\n\tbackspace: \"backspace\" as const,\n\tdelete: \"delete\" as const,\n\thome: \"home\" as const,\n\tend: \"end\" as const,\n\tup: \"up\" as const,\n\tdown: \"down\" as const,\n\tleft: \"left\" as const,\n\tright: \"right\" as const,\n\n\t// Symbol keys\n\tbacktick: \"`\" as const,\n\thyphen: \"-\" as const,\n\tequals: \"=\" as const,\n\tleftbracket: \"[\" as const,\n\trightbracket: \"]\" as const,\n\tbackslash: \"\\\\\" as const,\n\tsemicolon: \";\" as const,\n\tquote: \"'\" as const,\n\tcomma: \",\" as const,\n\tperiod: \".\" as const,\n\tslash: \"/\" as const,\n\texclamation: \"!\" as const,\n\tat: \"@\" as const,\n\thash: \"#\" as const,\n\tdollar: \"$\" as const,\n\tpercent: \"%\" as const,\n\tcaret: \"^\" as const,\n\tampersand: \"&\" as const,\n\tasterisk: \"*\" as const,\n\tleftparen: \"(\" as const,\n\trightparen: \")\" as const,\n\tunderscore: \"_\" as const,\n\tplus: \"+\" as const,\n\tpipe: \"|\" as const,\n\ttilde: \"~\" as const,\n\tleftbrace: \"{\" as const,\n\trightbrace: \"}\" as const,\n\tcolon: \":\" as const,\n\tlessthan: \"<\" as const,\n\tgreaterthan: \">\" as const,\n\tquestion: \"?\" as const,\n\n\t// Single modifiers\n\tctrl: <K extends BaseKey>(key: K): `ctrl+${K}` => `ctrl+${key}`,\n\tshift: <K extends BaseKey>(key: K): `shift+${K}` => `shift+${key}`,\n\talt: <K extends BaseKey>(key: K): `alt+${K}` => `alt+${key}`,\n\n\t// Combined modifiers\n\tctrlShift: <K extends BaseKey>(key: K): `ctrl+shift+${K}` => `ctrl+shift+${key}`,\n\tshiftCtrl: <K extends BaseKey>(key: K): `shift+ctrl+${K}` => `shift+ctrl+${key}`,\n\tctrlAlt: <K extends BaseKey>(key: K): `ctrl+alt+${K}` => `ctrl+alt+${key}`,\n\taltCtrl: <K extends BaseKey>(key: K): `alt+ctrl+${K}` => `alt+ctrl+${key}`,\n\tshiftAlt: <K extends BaseKey>(key: K): `shift+alt+${K}` => `shift+alt+${key}`,\n\taltShift: <K extends BaseKey>(key: K): `alt+shift+${K}` => `alt+shift+${key}`,\n\n\t// Triple modifiers\n\tctrlShiftAlt: <K extends BaseKey>(key: K): `ctrl+shift+alt+${K}` => `ctrl+shift+alt+${key}`,\n} as const;\n\n// =============================================================================\n// Constants\n// =============================================================================\n\nconst SYMBOL_KEYS = new Set([\n\t\"`\",\n\t\"-\",\n\t\"=\",\n\t\"[\",\n\t\"]\",\n\t\"\\\\\",\n\t\";\",\n\t\"'\",\n\t\",\",\n\t\".\",\n\t\"/\",\n\t\"!\",\n\t\"@\",\n\t\"#\",\n\t\"$\",\n\t\"%\",\n\t\"^\",\n\t\"&\",\n\t\"*\",\n\t\"(\",\n\t\")\",\n\t\"_\",\n\t\"+\",\n\t\"|\",\n\t\"~\",\n\t\"{\",\n\t\"}\",\n\t\":\",\n\t\"<\",\n\t\">\",\n\t\"?\",\n]);\n\nconst MODIFIERS = {\n\tshift: 1,\n\talt: 2,\n\tctrl: 4,\n} as const;\n\nconst LOCK_MASK = 64 + 128; // Caps Lock + Num Lock\n\nconst CODEPOINTS = {\n\tescape: 27,\n\ttab: 9,\n\tenter: 13,\n\tspace: 32,\n\tbackspace: 127,\n\tkpEnter: 57414, // Numpad Enter (Kitty protocol)\n} as const;\n\nconst ARROW_CODEPOINTS = {\n\tup: -1,\n\tdown: -2,\n\tright: -3,\n\tleft: -4,\n} as const;\n\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\n// =============================================================================\n// Kitty Protocol Parsing\n// =============================================================================\n\ninterface ParsedKittySequence {\n\tcodepoint: number;\n\tmodifier: number;\n}\n\nfunction parseKittySequence(data: string): ParsedKittySequence | null {\n\t// 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// 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\tconst arrowCodes: Record<string, number> = { A: -1, B: -2, C: -3, D: -4 };\n\t\treturn { codepoint: arrowCodes[arrowMatch[2]!]!, modifier: modValue - 1 };\n\t}\n\n\t// Functional keys: \\x1b[<num>~ or \\x1b[<num>;<mod>~\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\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,\n\t\t\t8: FUNCTIONAL_CODEPOINTS.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// 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\nfunction matchesKittySequence(data: string, expectedCodepoint: number, expectedModifier: number): boolean {\n\tconst parsed = parseKittySequence(data);\n\tif (!parsed) return false;\n\tconst actualMod = parsed.modifier & ~LOCK_MASK;\n\tconst expectedMod = expectedModifier & ~LOCK_MASK;\n\treturn parsed.codepoint === expectedCodepoint && actualMod === expectedMod;\n}\n\n// =============================================================================\n// Generic Key Matching\n// =============================================================================\n\nfunction rawCtrlChar(letter: string): string {\n\tconst code = letter.toLowerCase().charCodeAt(0) - 96;\n\treturn String.fromCharCode(code);\n}\n\nfunction parseKeyId(keyId: string): { key: string; ctrl: boolean; shift: boolean; alt: boolean } | null {\n\tconst parts = keyId.toLowerCase().split(\"+\");\n\tconst key = parts[parts.length - 1];\n\tif (!key) return null;\n\treturn {\n\t\tkey,\n\t\tctrl: parts.includes(\"ctrl\"),\n\t\tshift: parts.includes(\"shift\"),\n\t\talt: parts.includes(\"alt\"),\n\t};\n}\n\n/**\n * Match input data against a key identifier string.\n *\n * Supported key identifiers:\n * - Single keys: \"escape\", \"tab\", \"enter\", \"backspace\", \"delete\", \"home\", \"end\", \"space\"\n * - Arrow keys: \"up\", \"down\", \"left\", \"right\"\n * - Ctrl combinations: \"ctrl+c\", \"ctrl+z\", etc.\n * - Shift combinations: \"shift+tab\", \"shift+enter\"\n * - Alt combinations: \"alt+enter\", \"alt+backspace\"\n * - Combined modifiers: \"shift+ctrl+p\", \"ctrl+alt+x\"\n *\n * Use the Key helper for autocomplete: Key.ctrl(\"c\"), Key.escape, Key.ctrlShift(\"p\")\n *\n * @param data - Raw input data from terminal\n * @param keyId - Key identifier (e.g., \"ctrl+c\", \"escape\", Key.ctrl(\"c\"))\n */\nexport function matchesKey(data: string, keyId: KeyId): boolean {\n\tconst parsed = parseKeyId(keyId);\n\tif (!parsed) return false;\n\n\tconst { key, ctrl, shift, alt } = parsed;\n\tlet modifier = 0;\n\tif (shift) modifier |= MODIFIERS.shift;\n\tif (alt) modifier |= MODIFIERS.alt;\n\tif (ctrl) modifier |= MODIFIERS.ctrl;\n\n\tswitch (key) {\n\t\tcase \"escape\":\n\t\tcase \"esc\":\n\t\t\tif (modifier !== 0) return false;\n\t\t\treturn data === \"\\x1b\" || matchesKittySequence(data, CODEPOINTS.escape, 0);\n\n\t\tcase \"space\":\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn data === \" \" || matchesKittySequence(data, CODEPOINTS.space, 0);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, CODEPOINTS.space, modifier);\n\n\t\tcase \"tab\":\n\t\t\tif (shift && !ctrl && !alt) {\n\t\t\t\treturn data === \"\\x1b[Z\" || matchesKittySequence(data, CODEPOINTS.tab, MODIFIERS.shift);\n\t\t\t}\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn data === \"\\t\" || matchesKittySequence(data, CODEPOINTS.tab, 0);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, CODEPOINTS.tab, modifier);\n\n\t\tcase \"enter\":\n\t\tcase \"return\":\n\t\t\tif (shift && !ctrl && !alt) {\n\t\t\t\treturn (\n\t\t\t\t\tmatchesKittySequence(data, CODEPOINTS.enter, MODIFIERS.shift) ||\n\t\t\t\t\tmatchesKittySequence(data, CODEPOINTS.kpEnter, MODIFIERS.shift)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (alt && !ctrl && !shift) {\n\t\t\t\treturn (\n\t\t\t\t\tdata === \"\\x1b\\r\" ||\n\t\t\t\t\tmatchesKittySequence(data, CODEPOINTS.enter, MODIFIERS.alt) ||\n\t\t\t\t\tmatchesKittySequence(data, CODEPOINTS.kpEnter, MODIFIERS.alt)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn (\n\t\t\t\t\tdata === \"\\r\" ||\n\t\t\t\t\tdata === \"\\x1bOM\" || // SS3 M (numpad enter in some terminals)\n\t\t\t\t\tmatchesKittySequence(data, CODEPOINTS.enter, 0) ||\n\t\t\t\t\tmatchesKittySequence(data, CODEPOINTS.kpEnter, 0)\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn (\n\t\t\t\tmatchesKittySequence(data, CODEPOINTS.enter, modifier) ||\n\t\t\t\tmatchesKittySequence(data, CODEPOINTS.kpEnter, modifier)\n\t\t\t);\n\n\t\tcase \"backspace\":\n\t\t\tif (alt && !ctrl && !shift) {\n\t\t\t\treturn data === \"\\x1b\\x7f\" || matchesKittySequence(data, CODEPOINTS.backspace, MODIFIERS.alt);\n\t\t\t}\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn data === \"\\x7f\" || data === \"\\x08\" || matchesKittySequence(data, CODEPOINTS.backspace, 0);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, CODEPOINTS.backspace, modifier);\n\n\t\tcase \"delete\":\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn data === \"\\x1b[3~\" || matchesKittySequence(data, FUNCTIONAL_CODEPOINTS.delete, 0);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, FUNCTIONAL_CODEPOINTS.delete, modifier);\n\n\t\tcase \"home\":\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn (\n\t\t\t\t\tdata === \"\\x1b[H\" ||\n\t\t\t\t\tdata === \"\\x1b[1~\" ||\n\t\t\t\t\tdata === \"\\x1b[7~\" ||\n\t\t\t\t\tmatchesKittySequence(data, FUNCTIONAL_CODEPOINTS.home, 0)\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, FUNCTIONAL_CODEPOINTS.home, modifier);\n\n\t\tcase \"end\":\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn (\n\t\t\t\t\tdata === \"\\x1b[F\" ||\n\t\t\t\t\tdata === \"\\x1b[4~\" ||\n\t\t\t\t\tdata === \"\\x1b[8~\" ||\n\t\t\t\t\tmatchesKittySequence(data, FUNCTIONAL_CODEPOINTS.end, 0)\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, FUNCTIONAL_CODEPOINTS.end, modifier);\n\n\t\tcase \"up\":\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn data === \"\\x1b[A\" || matchesKittySequence(data, ARROW_CODEPOINTS.up, 0);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, ARROW_CODEPOINTS.up, modifier);\n\n\t\tcase \"down\":\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn data === \"\\x1b[B\" || matchesKittySequence(data, ARROW_CODEPOINTS.down, 0);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, ARROW_CODEPOINTS.down, modifier);\n\n\t\tcase \"left\":\n\t\t\tif (alt && !ctrl && !shift) {\n\t\t\t\treturn (\n\t\t\t\t\tdata === \"\\x1b[1;3D\" ||\n\t\t\t\t\tdata === \"\\x1bb\" ||\n\t\t\t\t\tmatchesKittySequence(data, ARROW_CODEPOINTS.left, MODIFIERS.alt)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (ctrl && !alt && !shift) {\n\t\t\t\treturn data === \"\\x1b[1;5D\" || matchesKittySequence(data, ARROW_CODEPOINTS.left, MODIFIERS.ctrl);\n\t\t\t}\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn data === \"\\x1b[D\" || matchesKittySequence(data, ARROW_CODEPOINTS.left, 0);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, ARROW_CODEPOINTS.left, modifier);\n\n\t\tcase \"right\":\n\t\t\tif (alt && !ctrl && !shift) {\n\t\t\t\treturn (\n\t\t\t\t\tdata === \"\\x1b[1;3C\" ||\n\t\t\t\t\tdata === \"\\x1bf\" ||\n\t\t\t\t\tmatchesKittySequence(data, ARROW_CODEPOINTS.right, MODIFIERS.alt)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (ctrl && !alt && !shift) {\n\t\t\t\treturn data === \"\\x1b[1;5C\" || matchesKittySequence(data, ARROW_CODEPOINTS.right, MODIFIERS.ctrl);\n\t\t\t}\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn data === \"\\x1b[C\" || matchesKittySequence(data, ARROW_CODEPOINTS.right, 0);\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, ARROW_CODEPOINTS.right, modifier);\n\t}\n\n\t// Handle single letter keys (a-z) and some symbols\n\tif (key.length === 1 && ((key >= \"a\" && key <= \"z\") || SYMBOL_KEYS.has(key))) {\n\t\tconst codepoint = key.charCodeAt(0);\n\n\t\tif (ctrl && !shift && !alt) {\n\t\t\tconst raw = rawCtrlChar(key);\n\t\t\tif (data === raw) return true;\n\t\t\tif (data.length > 0 && data.charCodeAt(0) === raw.charCodeAt(0)) return true;\n\t\t\treturn matchesKittySequence(data, codepoint, MODIFIERS.ctrl);\n\t\t}\n\n\t\tif (ctrl && shift && !alt) {\n\t\t\treturn matchesKittySequence(data, codepoint, MODIFIERS.shift + MODIFIERS.ctrl);\n\t\t}\n\n\t\tif (shift && !ctrl && !alt) {\n\t\t\t// Legacy: shift+letter produces uppercase\n\t\t\tif (data === key.toUpperCase()) return true;\n\t\t\treturn matchesKittySequence(data, codepoint, MODIFIERS.shift);\n\t\t}\n\n\t\tif (modifier !== 0) {\n\t\t\treturn matchesKittySequence(data, codepoint, modifier);\n\t\t}\n\n\t\treturn data === key;\n\t}\n\n\treturn false;\n}\n\n/**\n * Parse input data and return the key identifier if recognized.\n *\n * @param data - Raw input data from terminal\n * @returns Key identifier string (e.g., \"ctrl+c\") or undefined\n */\nexport function parseKey(data: string): string | undefined {\n\tconst kitty = parseKittySequence(data);\n\tif (kitty) {\n\t\tconst { codepoint, modifier } = kitty;\n\t\tconst mods: string[] = [];\n\t\tconst effectiveMod = modifier & ~LOCK_MASK;\n\t\tif (effectiveMod & MODIFIERS.shift) mods.push(\"shift\");\n\t\tif (effectiveMod & MODIFIERS.ctrl) mods.push(\"ctrl\");\n\t\tif (effectiveMod & MODIFIERS.alt) mods.push(\"alt\");\n\n\t\tlet keyName: string | undefined;\n\t\tif (codepoint === CODEPOINTS.escape) keyName = \"escape\";\n\t\telse if (codepoint === CODEPOINTS.tab) keyName = \"tab\";\n\t\telse if (codepoint === CODEPOINTS.enter || codepoint === CODEPOINTS.kpEnter) keyName = \"enter\";\n\t\telse if (codepoint === CODEPOINTS.space) keyName = \"space\";\n\t\telse if (codepoint === CODEPOINTS.backspace) keyName = \"backspace\";\n\t\telse if (codepoint === FUNCTIONAL_CODEPOINTS.delete) keyName = \"delete\";\n\t\telse if (codepoint === FUNCTIONAL_CODEPOINTS.home) keyName = \"home\";\n\t\telse if (codepoint === FUNCTIONAL_CODEPOINTS.end) keyName = \"end\";\n\t\telse if (codepoint === ARROW_CODEPOINTS.up) keyName = \"up\";\n\t\telse if (codepoint === ARROW_CODEPOINTS.down) keyName = \"down\";\n\t\telse if (codepoint === ARROW_CODEPOINTS.left) keyName = \"left\";\n\t\telse if (codepoint === ARROW_CODEPOINTS.right) keyName = \"right\";\n\t\telse if (codepoint >= 97 && codepoint <= 122) keyName = String.fromCharCode(codepoint);\n\t\telse if (SYMBOL_KEYS.has(String.fromCharCode(codepoint))) keyName = String.fromCharCode(codepoint);\n\n\t\tif (keyName) {\n\t\t\treturn mods.length > 0 ? `${mods.join(\"+\")}+${keyName}` : keyName;\n\t\t}\n\t}\n\n\t// Legacy sequences\n\tif (data === \"\\x1b\") return \"escape\";\n\tif (data === \"\\t\") return \"tab\";\n\tif (data === \"\\r\" || data === \"\\x1bOM\") return \"enter\";\n\tif (data === \" \") return \"space\";\n\tif (data === \"\\x7f\" || data === \"\\x08\") return \"backspace\";\n\tif (data === \"\\x1b[Z\") return \"shift+tab\";\n\tif (data === \"\\x1b\\r\") return \"alt+enter\";\n\tif (data === \"\\x1b\\x7f\") return \"alt+backspace\";\n\tif (data === \"\\x1b[A\") return \"up\";\n\tif (data === \"\\x1b[B\") return \"down\";\n\tif (data === \"\\x1b[C\") return \"right\";\n\tif (data === \"\\x1b[D\") return \"left\";\n\tif (data === \"\\x1b[H\") return \"home\";\n\tif (data === \"\\x1b[F\") return \"end\";\n\tif (data === \"\\x1b[3~\") return \"delete\";\n\n\t// Raw Ctrl+letter\n\tif (data.length === 1) {\n\t\tconst code = data.charCodeAt(0);\n\t\tif (code >= 1 && code <= 26) {\n\t\t\treturn `ctrl+${String.fromCharCode(code + 96)}`;\n\t\t}\n\t\tif (code >= 32 && code <= 126) {\n\t\t\treturn data;\n\t\t}\n\t}\n\n\treturn undefined;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mariozechner/pi-tui",
3
- "version": "0.34.0",
3
+ "version": "0.34.1",
4
4
  "description": "Terminal User Interface library with differential rendering for efficient text-based applications",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",