@mariozechner/pi-tui 0.23.4 → 0.23.5

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 ADDED
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Kitty keyboard protocol key sequence helpers.
3
+ *
4
+ * The Kitty keyboard protocol sends enhanced escape sequences in the format:
5
+ * \x1b[<codepoint>;<modifier>u
6
+ *
7
+ * Modifier values (added to 1):
8
+ * - Shift: 1 (value 2)
9
+ * - Alt: 2 (value 3)
10
+ * - Ctrl: 4 (value 5)
11
+ * - Super: 8 (value 9)
12
+ *
13
+ * See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/
14
+ */
15
+ export declare const Keys: {
16
+ readonly CTRL_A: string;
17
+ readonly CTRL_C: string;
18
+ readonly CTRL_D: string;
19
+ readonly CTRL_E: string;
20
+ readonly CTRL_K: string;
21
+ readonly CTRL_O: string;
22
+ readonly CTRL_P: string;
23
+ readonly CTRL_T: string;
24
+ readonly CTRL_U: string;
25
+ readonly CTRL_W: string;
26
+ readonly SHIFT_ENTER: string;
27
+ readonly ALT_ENTER: string;
28
+ readonly CTRL_ENTER: string;
29
+ readonly SHIFT_TAB: string;
30
+ readonly ALT_BACKSPACE: string;
31
+ };
32
+ /**
33
+ * Check if input matches a Kitty protocol Ctrl+<key> sequence.
34
+ * @param data - The input data to check
35
+ * @param key - Single lowercase letter (e.g., 'c' for Ctrl+C)
36
+ */
37
+ export declare function isKittyCtrl(data: string, key: string): boolean;
38
+ /**
39
+ * Check if input matches a Kitty protocol key sequence with specific modifier.
40
+ * @param data - The input data to check
41
+ * @param codepoint - ASCII codepoint of the key
42
+ * @param modifier - Modifier value (use MODIFIERS constants)
43
+ */
44
+ export declare function isKittyKey(data: string, codepoint: number, modifier: number): boolean;
45
+ /**
46
+ * Check if input matches Ctrl+A (raw byte or Kitty protocol).
47
+ */
48
+ export declare function isCtrlA(data: string): boolean;
49
+ /**
50
+ * Check if input matches Ctrl+C (raw byte or Kitty protocol).
51
+ */
52
+ export declare function isCtrlC(data: string): boolean;
53
+ /**
54
+ * Check if input matches Ctrl+D (raw byte or Kitty protocol).
55
+ */
56
+ export declare function isCtrlD(data: string): boolean;
57
+ /**
58
+ * Check if input matches Ctrl+E (raw byte or Kitty protocol).
59
+ */
60
+ export declare function isCtrlE(data: string): boolean;
61
+ /**
62
+ * Check if input matches Ctrl+K (raw byte or Kitty protocol).
63
+ */
64
+ export declare function isCtrlK(data: string): boolean;
65
+ /**
66
+ * Check if input matches Ctrl+O (raw byte or Kitty protocol).
67
+ */
68
+ export declare function isCtrlO(data: string): boolean;
69
+ /**
70
+ * Check if input matches Ctrl+P (raw byte or Kitty protocol).
71
+ */
72
+ export declare function isCtrlP(data: string): boolean;
73
+ /**
74
+ * Check if input matches Ctrl+T (raw byte or Kitty protocol).
75
+ */
76
+ export declare function isCtrlT(data: string): boolean;
77
+ /**
78
+ * Check if input matches Ctrl+U (raw byte or Kitty protocol).
79
+ */
80
+ export declare function isCtrlU(data: string): boolean;
81
+ /**
82
+ * Check if input matches Ctrl+W (raw byte or Kitty protocol).
83
+ */
84
+ export declare function isCtrlW(data: string): boolean;
85
+ /**
86
+ * Check if input matches Alt+Backspace (legacy or Kitty protocol).
87
+ */
88
+ export declare function isAltBackspace(data: string): boolean;
89
+ /**
90
+ * Check if input matches Shift+Tab (legacy or Kitty protocol).
91
+ */
92
+ export declare function isShiftTab(data: string): boolean;
93
+ /**
94
+ * Check if input matches the Escape key (raw byte or Kitty protocol).
95
+ * Raw: \x1b (single byte)
96
+ * Kitty: \x1b[27u (codepoint 27 = escape)
97
+ */
98
+ export declare function isEscape(data: string): boolean;
99
+ //# sourceMappingURL=keys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAuCH,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;CAuBP,CAAC;AAEX;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAI9D;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAErF;AAkBD;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7C;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7C;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7C;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7C;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7C;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7C;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7C;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7C;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7C;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7C;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEhD;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE9C","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"]}
package/dist/keys.js ADDED
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Kitty keyboard protocol key sequence helpers.
3
+ *
4
+ * The Kitty keyboard protocol sends enhanced escape sequences in the format:
5
+ * \x1b[<codepoint>;<modifier>u
6
+ *
7
+ * Modifier values (added to 1):
8
+ * - Shift: 1 (value 2)
9
+ * - Alt: 2 (value 3)
10
+ * - Ctrl: 4 (value 5)
11
+ * - Super: 8 (value 9)
12
+ *
13
+ * See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/
14
+ */
15
+ // Common codepoints
16
+ const CODEPOINTS = {
17
+ // Letters (lowercase ASCII)
18
+ a: 97,
19
+ c: 99,
20
+ d: 100,
21
+ e: 101,
22
+ k: 107,
23
+ o: 111,
24
+ p: 112,
25
+ t: 116,
26
+ u: 117,
27
+ w: 119,
28
+ // Special keys
29
+ escape: 27,
30
+ tab: 9,
31
+ enter: 13,
32
+ backspace: 127,
33
+ };
34
+ // Modifier bits (before adding 1)
35
+ const MODIFIERS = {
36
+ shift: 1,
37
+ alt: 2,
38
+ ctrl: 4,
39
+ super: 8,
40
+ };
41
+ /**
42
+ * Build a Kitty keyboard protocol sequence for a key with modifier.
43
+ */
44
+ function kittySequence(codepoint, modifier) {
45
+ return `\x1b[${codepoint};${modifier + 1}u`;
46
+ }
47
+ // Pre-built sequences for common key combinations
48
+ export const Keys = {
49
+ // Ctrl+<letter> combinations
50
+ CTRL_A: kittySequence(CODEPOINTS.a, MODIFIERS.ctrl),
51
+ CTRL_C: kittySequence(CODEPOINTS.c, MODIFIERS.ctrl),
52
+ CTRL_D: kittySequence(CODEPOINTS.d, MODIFIERS.ctrl),
53
+ CTRL_E: kittySequence(CODEPOINTS.e, MODIFIERS.ctrl),
54
+ CTRL_K: kittySequence(CODEPOINTS.k, MODIFIERS.ctrl),
55
+ CTRL_O: kittySequence(CODEPOINTS.o, MODIFIERS.ctrl),
56
+ CTRL_P: kittySequence(CODEPOINTS.p, MODIFIERS.ctrl),
57
+ CTRL_T: kittySequence(CODEPOINTS.t, MODIFIERS.ctrl),
58
+ CTRL_U: kittySequence(CODEPOINTS.u, MODIFIERS.ctrl),
59
+ CTRL_W: kittySequence(CODEPOINTS.w, MODIFIERS.ctrl),
60
+ // Enter combinations
61
+ SHIFT_ENTER: kittySequence(CODEPOINTS.enter, MODIFIERS.shift),
62
+ ALT_ENTER: kittySequence(CODEPOINTS.enter, MODIFIERS.alt),
63
+ CTRL_ENTER: kittySequence(CODEPOINTS.enter, MODIFIERS.ctrl),
64
+ // Tab combinations
65
+ SHIFT_TAB: kittySequence(CODEPOINTS.tab, MODIFIERS.shift),
66
+ // Backspace combinations
67
+ ALT_BACKSPACE: kittySequence(CODEPOINTS.backspace, MODIFIERS.alt),
68
+ };
69
+ /**
70
+ * Check if input matches a Kitty protocol Ctrl+<key> sequence.
71
+ * @param data - The input data to check
72
+ * @param key - Single lowercase letter (e.g., 'c' for Ctrl+C)
73
+ */
74
+ export function isKittyCtrl(data, key) {
75
+ if (key.length !== 1)
76
+ return false;
77
+ const codepoint = key.charCodeAt(0);
78
+ return data === kittySequence(codepoint, MODIFIERS.ctrl);
79
+ }
80
+ /**
81
+ * Check if input matches a Kitty protocol key sequence with specific modifier.
82
+ * @param data - The input data to check
83
+ * @param codepoint - ASCII codepoint of the key
84
+ * @param modifier - Modifier value (use MODIFIERS constants)
85
+ */
86
+ export function isKittyKey(data, codepoint, modifier) {
87
+ return data === kittySequence(codepoint, modifier);
88
+ }
89
+ // Raw control character codes
90
+ const RAW = {
91
+ CTRL_A: "\x01",
92
+ CTRL_C: "\x03",
93
+ CTRL_D: "\x04",
94
+ CTRL_E: "\x05",
95
+ CTRL_K: "\x0b",
96
+ CTRL_O: "\x0f",
97
+ CTRL_P: "\x10",
98
+ CTRL_T: "\x14",
99
+ CTRL_U: "\x15",
100
+ CTRL_W: "\x17",
101
+ ALT_BACKSPACE: "\x1b\x7f",
102
+ SHIFT_TAB: "\x1b[Z",
103
+ };
104
+ /**
105
+ * Check if input matches Ctrl+A (raw byte or Kitty protocol).
106
+ */
107
+ export function isCtrlA(data) {
108
+ return data === RAW.CTRL_A || data === Keys.CTRL_A;
109
+ }
110
+ /**
111
+ * Check if input matches Ctrl+C (raw byte or Kitty protocol).
112
+ */
113
+ export function isCtrlC(data) {
114
+ return data === RAW.CTRL_C || data === Keys.CTRL_C;
115
+ }
116
+ /**
117
+ * Check if input matches Ctrl+D (raw byte or Kitty protocol).
118
+ */
119
+ export function isCtrlD(data) {
120
+ return data === RAW.CTRL_D || data === Keys.CTRL_D;
121
+ }
122
+ /**
123
+ * Check if input matches Ctrl+E (raw byte or Kitty protocol).
124
+ */
125
+ export function isCtrlE(data) {
126
+ return data === RAW.CTRL_E || data === Keys.CTRL_E;
127
+ }
128
+ /**
129
+ * Check if input matches Ctrl+K (raw byte or Kitty protocol).
130
+ */
131
+ export function isCtrlK(data) {
132
+ return data === RAW.CTRL_K || data === Keys.CTRL_K;
133
+ }
134
+ /**
135
+ * Check if input matches Ctrl+O (raw byte or Kitty protocol).
136
+ */
137
+ export function isCtrlO(data) {
138
+ return data === RAW.CTRL_O || data === Keys.CTRL_O;
139
+ }
140
+ /**
141
+ * Check if input matches Ctrl+P (raw byte or Kitty protocol).
142
+ */
143
+ export function isCtrlP(data) {
144
+ return data === RAW.CTRL_P || data === Keys.CTRL_P;
145
+ }
146
+ /**
147
+ * Check if input matches Ctrl+T (raw byte or Kitty protocol).
148
+ */
149
+ export function isCtrlT(data) {
150
+ return data === RAW.CTRL_T || data === Keys.CTRL_T;
151
+ }
152
+ /**
153
+ * Check if input matches Ctrl+U (raw byte or Kitty protocol).
154
+ */
155
+ export function isCtrlU(data) {
156
+ return data === RAW.CTRL_U || data === Keys.CTRL_U;
157
+ }
158
+ /**
159
+ * Check if input matches Ctrl+W (raw byte or Kitty protocol).
160
+ */
161
+ export function isCtrlW(data) {
162
+ return data === RAW.CTRL_W || data === Keys.CTRL_W;
163
+ }
164
+ /**
165
+ * Check if input matches Alt+Backspace (legacy or Kitty protocol).
166
+ */
167
+ export function isAltBackspace(data) {
168
+ return data === RAW.ALT_BACKSPACE || data === Keys.ALT_BACKSPACE;
169
+ }
170
+ /**
171
+ * Check if input matches Shift+Tab (legacy or Kitty protocol).
172
+ */
173
+ export function isShiftTab(data) {
174
+ return data === RAW.SHIFT_TAB || data === Keys.SHIFT_TAB;
175
+ }
176
+ /**
177
+ * Check if input matches the Escape key (raw byte or Kitty protocol).
178
+ * Raw: \x1b (single byte)
179
+ * Kitty: \x1b[27u (codepoint 27 = escape)
180
+ */
181
+ export function isEscape(data) {
182
+ return data === "\x1b" || data === `\x1b[${CODEPOINTS.escape}u`;
183
+ }
184
+ //# sourceMappingURL=keys.js.map
@@ -0,0 +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 +1 @@
1
- {"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../src/terminal.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,QAAQ;IAExB,KAAK,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IAGnE,IAAI,IAAI,IAAI,CAAC;IAGb,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAG1B,IAAI,OAAO,IAAI,MAAM,CAAC;IACtB,IAAI,IAAI,IAAI,MAAM,CAAC;IAGnB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAG5B,UAAU,IAAI,IAAI,CAAC;IACnB,UAAU,IAAI,IAAI,CAAC;IAGnB,SAAS,IAAI,IAAI,CAAC;IAClB,eAAe,IAAI,IAAI,CAAC;IACxB,WAAW,IAAI,IAAI,CAAC;CACpB;AAED;;GAEG;AACH,qBAAa,eAAgB,YAAW,QAAQ;IAC/C,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,YAAY,CAAC,CAAyB;IAC9C,OAAO,CAAC,aAAa,CAAC,CAAa;IAEnC,KAAK,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAkBjE;IAED,IAAI,IAAI,IAAI,CAkBX;IAED,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAExB;IAED,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAS1B;IAED,UAAU,IAAI,IAAI,CAEjB;IAED,UAAU,IAAI,IAAI,CAEjB;IAED,SAAS,IAAI,IAAI,CAEhB;IAED,eAAe,IAAI,IAAI,CAEtB;IAED,WAAW,IAAI,IAAI,CAElB;CACD","sourcesContent":["/**\n * Minimal terminal interface for TUI\n */\nexport interface Terminal {\n\t// Start the terminal with input and resize handlers\n\tstart(onInput: (data: string) => void, onResize: () => void): void;\n\n\t// Stop the terminal and restore state\n\tstop(): void;\n\n\t// Write output to terminal\n\twrite(data: string): void;\n\n\t// Get terminal dimensions\n\tget columns(): number;\n\tget rows(): number;\n\n\t// Cursor positioning (relative to current position)\n\tmoveBy(lines: number): void; // Move cursor up (negative) or down (positive) by N lines\n\n\t// Cursor visibility\n\thideCursor(): void; // Hide the cursor\n\tshowCursor(): void; // Show the cursor\n\n\t// Clear operations\n\tclearLine(): void; // Clear current line\n\tclearFromCursor(): void; // Clear from cursor to end of screen\n\tclearScreen(): void; // Clear entire screen and move cursor to (0,0)\n}\n\n/**\n * Real terminal using process.stdin/stdout\n */\nexport class ProcessTerminal implements Terminal {\n\tprivate wasRaw = false;\n\tprivate inputHandler?: (data: string) => void;\n\tprivate resizeHandler?: () => void;\n\n\tstart(onInput: (data: string) => void, onResize: () => void): void {\n\t\tthis.inputHandler = onInput;\n\t\tthis.resizeHandler = onResize;\n\n\t\t// Save previous state and enable raw mode\n\t\tthis.wasRaw = process.stdin.isRaw || false;\n\t\tif (process.stdin.setRawMode) {\n\t\t\tprocess.stdin.setRawMode(true);\n\t\t}\n\t\tprocess.stdin.setEncoding(\"utf8\");\n\t\tprocess.stdin.resume();\n\n\t\t// Enable bracketed paste mode - terminal will wrap pastes in \\x1b[200~ ... \\x1b[201~\n\t\tprocess.stdout.write(\"\\x1b[?2004h\");\n\n\t\t// Set up event handlers\n\t\tprocess.stdin.on(\"data\", this.inputHandler);\n\t\tprocess.stdout.on(\"resize\", this.resizeHandler);\n\t}\n\n\tstop(): void {\n\t\t// Disable bracketed paste mode\n\t\tprocess.stdout.write(\"\\x1b[?2004l\");\n\n\t\t// Remove event handlers\n\t\tif (this.inputHandler) {\n\t\t\tprocess.stdin.removeListener(\"data\", this.inputHandler);\n\t\t\tthis.inputHandler = undefined;\n\t\t}\n\t\tif (this.resizeHandler) {\n\t\t\tprocess.stdout.removeListener(\"resize\", this.resizeHandler);\n\t\t\tthis.resizeHandler = undefined;\n\t\t}\n\n\t\t// Restore raw mode state\n\t\tif (process.stdin.setRawMode) {\n\t\t\tprocess.stdin.setRawMode(this.wasRaw);\n\t\t}\n\t}\n\n\twrite(data: string): void {\n\t\tprocess.stdout.write(data);\n\t}\n\n\tget columns(): number {\n\t\treturn process.stdout.columns || 80;\n\t}\n\n\tget rows(): number {\n\t\treturn process.stdout.rows || 24;\n\t}\n\n\tmoveBy(lines: number): void {\n\t\tif (lines > 0) {\n\t\t\t// Move down\n\t\t\tprocess.stdout.write(`\\x1b[${lines}B`);\n\t\t} else if (lines < 0) {\n\t\t\t// Move up\n\t\t\tprocess.stdout.write(`\\x1b[${-lines}A`);\n\t\t}\n\t\t// lines === 0: no movement\n\t}\n\n\thideCursor(): void {\n\t\tprocess.stdout.write(\"\\x1b[?25l\");\n\t}\n\n\tshowCursor(): void {\n\t\tprocess.stdout.write(\"\\x1b[?25h\");\n\t}\n\n\tclearLine(): void {\n\t\tprocess.stdout.write(\"\\x1b[K\");\n\t}\n\n\tclearFromCursor(): void {\n\t\tprocess.stdout.write(\"\\x1b[J\");\n\t}\n\n\tclearScreen(): void {\n\t\tprocess.stdout.write(\"\\x1b[2J\\x1b[H\"); // Clear screen and move to home (1,1)\n\t}\n}\n"]}
1
+ {"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../src/terminal.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,QAAQ;IAExB,KAAK,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IAGnE,IAAI,IAAI,IAAI,CAAC;IAGb,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAG1B,IAAI,OAAO,IAAI,MAAM,CAAC;IACtB,IAAI,IAAI,IAAI,MAAM,CAAC;IAGnB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAG5B,UAAU,IAAI,IAAI,CAAC;IACnB,UAAU,IAAI,IAAI,CAAC;IAGnB,SAAS,IAAI,IAAI,CAAC;IAClB,eAAe,IAAI,IAAI,CAAC;IACxB,WAAW,IAAI,IAAI,CAAC;CACpB;AAED;;GAEG;AACH,qBAAa,eAAgB,YAAW,QAAQ;IAC/C,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,YAAY,CAAC,CAAyB;IAC9C,OAAO,CAAC,aAAa,CAAC,CAAa;IAEnC,KAAK,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAwBjE;IAED,IAAI,IAAI,IAAI,CAqBX;IAED,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAExB;IAED,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAS1B;IAED,UAAU,IAAI,IAAI,CAEjB;IAED,UAAU,IAAI,IAAI,CAEjB;IAED,SAAS,IAAI,IAAI,CAEhB;IAED,eAAe,IAAI,IAAI,CAEtB;IAED,WAAW,IAAI,IAAI,CAElB;CACD","sourcesContent":["/**\n * Minimal terminal interface for TUI\n */\nexport interface Terminal {\n\t// Start the terminal with input and resize handlers\n\tstart(onInput: (data: string) => void, onResize: () => void): void;\n\n\t// Stop the terminal and restore state\n\tstop(): void;\n\n\t// Write output to terminal\n\twrite(data: string): void;\n\n\t// Get terminal dimensions\n\tget columns(): number;\n\tget rows(): number;\n\n\t// Cursor positioning (relative to current position)\n\tmoveBy(lines: number): void; // Move cursor up (negative) or down (positive) by N lines\n\n\t// Cursor visibility\n\thideCursor(): void; // Hide the cursor\n\tshowCursor(): void; // Show the cursor\n\n\t// Clear operations\n\tclearLine(): void; // Clear current line\n\tclearFromCursor(): void; // Clear from cursor to end of screen\n\tclearScreen(): void; // Clear entire screen and move cursor to (0,0)\n}\n\n/**\n * Real terminal using process.stdin/stdout\n */\nexport class ProcessTerminal implements Terminal {\n\tprivate wasRaw = false;\n\tprivate inputHandler?: (data: string) => void;\n\tprivate resizeHandler?: () => void;\n\n\tstart(onInput: (data: string) => void, onResize: () => void): void {\n\t\tthis.inputHandler = onInput;\n\t\tthis.resizeHandler = onResize;\n\n\t\t// Save previous state and enable raw mode\n\t\tthis.wasRaw = process.stdin.isRaw || false;\n\t\tif (process.stdin.setRawMode) {\n\t\t\tprocess.stdin.setRawMode(true);\n\t\t}\n\t\tprocess.stdin.setEncoding(\"utf8\");\n\t\tprocess.stdin.resume();\n\n\t\t// Enable bracketed paste mode - terminal will wrap pastes in \\x1b[200~ ... \\x1b[201~\n\t\tprocess.stdout.write(\"\\x1b[?2004h\");\n\n\t\t// Enable Kitty keyboard protocol (disambiguate escape codes)\n\t\t// This makes terminals like Ghostty, Kitty, WezTerm send enhanced key sequences\n\t\t// e.g., Shift+Enter becomes \\x1b[13;2u instead of just \\r\n\t\t// See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/\n\t\tprocess.stdout.write(\"\\x1b[>1u\");\n\n\t\t// Set up event handlers\n\t\tprocess.stdin.on(\"data\", this.inputHandler);\n\t\tprocess.stdout.on(\"resize\", this.resizeHandler);\n\t}\n\n\tstop(): void {\n\t\t// Disable bracketed paste mode\n\t\tprocess.stdout.write(\"\\x1b[?2004l\");\n\n\t\t// Disable Kitty keyboard protocol (pop the flags we pushed)\n\t\tprocess.stdout.write(\"\\x1b[<u\");\n\n\t\t// Remove event handlers\n\t\tif (this.inputHandler) {\n\t\t\tprocess.stdin.removeListener(\"data\", this.inputHandler);\n\t\t\tthis.inputHandler = undefined;\n\t\t}\n\t\tif (this.resizeHandler) {\n\t\t\tprocess.stdout.removeListener(\"resize\", this.resizeHandler);\n\t\t\tthis.resizeHandler = undefined;\n\t\t}\n\n\t\t// Restore raw mode state\n\t\tif (process.stdin.setRawMode) {\n\t\t\tprocess.stdin.setRawMode(this.wasRaw);\n\t\t}\n\t}\n\n\twrite(data: string): void {\n\t\tprocess.stdout.write(data);\n\t}\n\n\tget columns(): number {\n\t\treturn process.stdout.columns || 80;\n\t}\n\n\tget rows(): number {\n\t\treturn process.stdout.rows || 24;\n\t}\n\n\tmoveBy(lines: number): void {\n\t\tif (lines > 0) {\n\t\t\t// Move down\n\t\t\tprocess.stdout.write(`\\x1b[${lines}B`);\n\t\t} else if (lines < 0) {\n\t\t\t// Move up\n\t\t\tprocess.stdout.write(`\\x1b[${-lines}A`);\n\t\t}\n\t\t// lines === 0: no movement\n\t}\n\n\thideCursor(): void {\n\t\tprocess.stdout.write(\"\\x1b[?25l\");\n\t}\n\n\tshowCursor(): void {\n\t\tprocess.stdout.write(\"\\x1b[?25h\");\n\t}\n\n\tclearLine(): void {\n\t\tprocess.stdout.write(\"\\x1b[K\");\n\t}\n\n\tclearFromCursor(): void {\n\t\tprocess.stdout.write(\"\\x1b[J\");\n\t}\n\n\tclearScreen(): void {\n\t\tprocess.stdout.write(\"\\x1b[2J\\x1b[H\"); // Clear screen and move to home (1,1)\n\t}\n}\n"]}
package/dist/terminal.js CHANGED
@@ -17,6 +17,11 @@ export class ProcessTerminal {
17
17
  process.stdin.resume();
18
18
  // Enable bracketed paste mode - terminal will wrap pastes in \x1b[200~ ... \x1b[201~
19
19
  process.stdout.write("\x1b[?2004h");
20
+ // Enable Kitty keyboard protocol (disambiguate escape codes)
21
+ // This makes terminals like Ghostty, Kitty, WezTerm send enhanced key sequences
22
+ // e.g., Shift+Enter becomes \x1b[13;2u instead of just \r
23
+ // See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/
24
+ process.stdout.write("\x1b[>1u");
20
25
  // Set up event handlers
21
26
  process.stdin.on("data", this.inputHandler);
22
27
  process.stdout.on("resize", this.resizeHandler);
@@ -24,6 +29,8 @@ export class ProcessTerminal {
24
29
  stop() {
25
30
  // Disable bracketed paste mode
26
31
  process.stdout.write("\x1b[?2004l");
32
+ // Disable Kitty keyboard protocol (pop the flags we pushed)
33
+ process.stdout.write("\x1b[<u");
27
34
  // Remove event handlers
28
35
  if (this.inputHandler) {
29
36
  process.stdin.removeListener("data", this.inputHandler);
@@ -1 +1 @@
1
- {"version":3,"file":"terminal.js","sourceRoot":"","sources":["../src/terminal.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Minimal terminal interface for TUI\n */\nexport interface Terminal {\n\t// Start the terminal with input and resize handlers\n\tstart(onInput: (data: string) => void, onResize: () => void): void;\n\n\t// Stop the terminal and restore state\n\tstop(): void;\n\n\t// Write output to terminal\n\twrite(data: string): void;\n\n\t// Get terminal dimensions\n\tget columns(): number;\n\tget rows(): number;\n\n\t// Cursor positioning (relative to current position)\n\tmoveBy(lines: number): void; // Move cursor up (negative) or down (positive) by N lines\n\n\t// Cursor visibility\n\thideCursor(): void; // Hide the cursor\n\tshowCursor(): void; // Show the cursor\n\n\t// Clear operations\n\tclearLine(): void; // Clear current line\n\tclearFromCursor(): void; // Clear from cursor to end of screen\n\tclearScreen(): void; // Clear entire screen and move cursor to (0,0)\n}\n\n/**\n * Real terminal using process.stdin/stdout\n */\nexport class ProcessTerminal implements Terminal {\n\tprivate wasRaw = false;\n\tprivate inputHandler?: (data: string) => void;\n\tprivate resizeHandler?: () => void;\n\n\tstart(onInput: (data: string) => void, onResize: () => void): void {\n\t\tthis.inputHandler = onInput;\n\t\tthis.resizeHandler = onResize;\n\n\t\t// Save previous state and enable raw mode\n\t\tthis.wasRaw = process.stdin.isRaw || false;\n\t\tif (process.stdin.setRawMode) {\n\t\t\tprocess.stdin.setRawMode(true);\n\t\t}\n\t\tprocess.stdin.setEncoding(\"utf8\");\n\t\tprocess.stdin.resume();\n\n\t\t// Enable bracketed paste mode - terminal will wrap pastes in \\x1b[200~ ... \\x1b[201~\n\t\tprocess.stdout.write(\"\\x1b[?2004h\");\n\n\t\t// Set up event handlers\n\t\tprocess.stdin.on(\"data\", this.inputHandler);\n\t\tprocess.stdout.on(\"resize\", this.resizeHandler);\n\t}\n\n\tstop(): void {\n\t\t// Disable bracketed paste mode\n\t\tprocess.stdout.write(\"\\x1b[?2004l\");\n\n\t\t// Remove event handlers\n\t\tif (this.inputHandler) {\n\t\t\tprocess.stdin.removeListener(\"data\", this.inputHandler);\n\t\t\tthis.inputHandler = undefined;\n\t\t}\n\t\tif (this.resizeHandler) {\n\t\t\tprocess.stdout.removeListener(\"resize\", this.resizeHandler);\n\t\t\tthis.resizeHandler = undefined;\n\t\t}\n\n\t\t// Restore raw mode state\n\t\tif (process.stdin.setRawMode) {\n\t\t\tprocess.stdin.setRawMode(this.wasRaw);\n\t\t}\n\t}\n\n\twrite(data: string): void {\n\t\tprocess.stdout.write(data);\n\t}\n\n\tget columns(): number {\n\t\treturn process.stdout.columns || 80;\n\t}\n\n\tget rows(): number {\n\t\treturn process.stdout.rows || 24;\n\t}\n\n\tmoveBy(lines: number): void {\n\t\tif (lines > 0) {\n\t\t\t// Move down\n\t\t\tprocess.stdout.write(`\\x1b[${lines}B`);\n\t\t} else if (lines < 0) {\n\t\t\t// Move up\n\t\t\tprocess.stdout.write(`\\x1b[${-lines}A`);\n\t\t}\n\t\t// lines === 0: no movement\n\t}\n\n\thideCursor(): void {\n\t\tprocess.stdout.write(\"\\x1b[?25l\");\n\t}\n\n\tshowCursor(): void {\n\t\tprocess.stdout.write(\"\\x1b[?25h\");\n\t}\n\n\tclearLine(): void {\n\t\tprocess.stdout.write(\"\\x1b[K\");\n\t}\n\n\tclearFromCursor(): void {\n\t\tprocess.stdout.write(\"\\x1b[J\");\n\t}\n\n\tclearScreen(): void {\n\t\tprocess.stdout.write(\"\\x1b[2J\\x1b[H\"); // Clear screen and move to home (1,1)\n\t}\n}\n"]}
1
+ {"version":3,"file":"terminal.js","sourceRoot":"","sources":["../src/terminal.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Minimal terminal interface for TUI\n */\nexport interface Terminal {\n\t// Start the terminal with input and resize handlers\n\tstart(onInput: (data: string) => void, onResize: () => void): void;\n\n\t// Stop the terminal and restore state\n\tstop(): void;\n\n\t// Write output to terminal\n\twrite(data: string): void;\n\n\t// Get terminal dimensions\n\tget columns(): number;\n\tget rows(): number;\n\n\t// Cursor positioning (relative to current position)\n\tmoveBy(lines: number): void; // Move cursor up (negative) or down (positive) by N lines\n\n\t// Cursor visibility\n\thideCursor(): void; // Hide the cursor\n\tshowCursor(): void; // Show the cursor\n\n\t// Clear operations\n\tclearLine(): void; // Clear current line\n\tclearFromCursor(): void; // Clear from cursor to end of screen\n\tclearScreen(): void; // Clear entire screen and move cursor to (0,0)\n}\n\n/**\n * Real terminal using process.stdin/stdout\n */\nexport class ProcessTerminal implements Terminal {\n\tprivate wasRaw = false;\n\tprivate inputHandler?: (data: string) => void;\n\tprivate resizeHandler?: () => void;\n\n\tstart(onInput: (data: string) => void, onResize: () => void): void {\n\t\tthis.inputHandler = onInput;\n\t\tthis.resizeHandler = onResize;\n\n\t\t// Save previous state and enable raw mode\n\t\tthis.wasRaw = process.stdin.isRaw || false;\n\t\tif (process.stdin.setRawMode) {\n\t\t\tprocess.stdin.setRawMode(true);\n\t\t}\n\t\tprocess.stdin.setEncoding(\"utf8\");\n\t\tprocess.stdin.resume();\n\n\t\t// Enable bracketed paste mode - terminal will wrap pastes in \\x1b[200~ ... \\x1b[201~\n\t\tprocess.stdout.write(\"\\x1b[?2004h\");\n\n\t\t// Enable Kitty keyboard protocol (disambiguate escape codes)\n\t\t// This makes terminals like Ghostty, Kitty, WezTerm send enhanced key sequences\n\t\t// e.g., Shift+Enter becomes \\x1b[13;2u instead of just \\r\n\t\t// See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/\n\t\tprocess.stdout.write(\"\\x1b[>1u\");\n\n\t\t// Set up event handlers\n\t\tprocess.stdin.on(\"data\", this.inputHandler);\n\t\tprocess.stdout.on(\"resize\", this.resizeHandler);\n\t}\n\n\tstop(): void {\n\t\t// Disable bracketed paste mode\n\t\tprocess.stdout.write(\"\\x1b[?2004l\");\n\n\t\t// Disable Kitty keyboard protocol (pop the flags we pushed)\n\t\tprocess.stdout.write(\"\\x1b[<u\");\n\n\t\t// Remove event handlers\n\t\tif (this.inputHandler) {\n\t\t\tprocess.stdin.removeListener(\"data\", this.inputHandler);\n\t\t\tthis.inputHandler = undefined;\n\t\t}\n\t\tif (this.resizeHandler) {\n\t\t\tprocess.stdout.removeListener(\"resize\", this.resizeHandler);\n\t\t\tthis.resizeHandler = undefined;\n\t\t}\n\n\t\t// Restore raw mode state\n\t\tif (process.stdin.setRawMode) {\n\t\t\tprocess.stdin.setRawMode(this.wasRaw);\n\t\t}\n\t}\n\n\twrite(data: string): void {\n\t\tprocess.stdout.write(data);\n\t}\n\n\tget columns(): number {\n\t\treturn process.stdout.columns || 80;\n\t}\n\n\tget rows(): number {\n\t\treturn process.stdout.rows || 24;\n\t}\n\n\tmoveBy(lines: number): void {\n\t\tif (lines > 0) {\n\t\t\t// Move down\n\t\t\tprocess.stdout.write(`\\x1b[${lines}B`);\n\t\t} else if (lines < 0) {\n\t\t\t// Move up\n\t\t\tprocess.stdout.write(`\\x1b[${-lines}A`);\n\t\t}\n\t\t// lines === 0: no movement\n\t}\n\n\thideCursor(): void {\n\t\tprocess.stdout.write(\"\\x1b[?25l\");\n\t}\n\n\tshowCursor(): void {\n\t\tprocess.stdout.write(\"\\x1b[?25h\");\n\t}\n\n\tclearLine(): void {\n\t\tprocess.stdout.write(\"\\x1b[K\");\n\t}\n\n\tclearFromCursor(): void {\n\t\tprocess.stdout.write(\"\\x1b[J\");\n\t}\n\n\tclearScreen(): void {\n\t\tprocess.stdout.write(\"\\x1b[2J\\x1b[H\"); // Clear screen and move to home (1,1)\n\t}\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mariozechner/pi-tui",
3
- "version": "0.23.4",
3
+ "version": "0.23.5",
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",