ink 6.5.1 → 6.7.0

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.
Files changed (46) hide show
  1. package/build/components/App.d.ts +7 -48
  2. package/build/components/App.js +259 -225
  3. package/build/components/App.js.map +1 -1
  4. package/build/components/CursorContext.d.ts +11 -0
  5. package/build/components/CursorContext.js +8 -0
  6. package/build/components/CursorContext.js.map +1 -0
  7. package/build/components/ErrorBoundary.d.ts +18 -0
  8. package/build/components/ErrorBoundary.js +23 -0
  9. package/build/components/ErrorBoundary.js.map +1 -0
  10. package/build/cursor-helpers.d.ts +38 -0
  11. package/build/cursor-helpers.js +56 -0
  12. package/build/cursor-helpers.js.map +1 -0
  13. package/build/hooks/use-cursor.d.ts +12 -0
  14. package/build/hooks/use-cursor.js +29 -0
  15. package/build/hooks/use-cursor.js.map +1 -0
  16. package/build/hooks/use-focus-manager.d.ts +1 -1
  17. package/build/hooks/use-focus-manager.js +1 -1
  18. package/build/hooks/use-input.d.ts +38 -0
  19. package/build/hooks/use-input.js +33 -2
  20. package/build/hooks/use-input.js.map +1 -1
  21. package/build/index.d.ts +4 -0
  22. package/build/index.js +2 -0
  23. package/build/index.js.map +1 -1
  24. package/build/ink.d.ts +32 -0
  25. package/build/ink.js +258 -31
  26. package/build/ink.js.map +1 -1
  27. package/build/kitty-keyboard.d.ts +23 -0
  28. package/build/kitty-keyboard.js +32 -0
  29. package/build/kitty-keyboard.js.map +1 -0
  30. package/build/log-update.d.ts +6 -1
  31. package/build/log-update.js +166 -40
  32. package/build/log-update.js.map +1 -1
  33. package/build/parse-keypress.d.ts +8 -0
  34. package/build/parse-keypress.js +270 -2
  35. package/build/parse-keypress.js.map +1 -1
  36. package/build/reconciler.js +11 -1
  37. package/build/reconciler.js.map +1 -1
  38. package/build/render.d.ts +23 -1
  39. package/build/render.js +7 -2
  40. package/build/render.js.map +1 -1
  41. package/build/styles.d.ts +8 -8
  42. package/build/write-synchronized.d.ts +4 -0
  43. package/build/write-synchronized.js +7 -0
  44. package/build/write-synchronized.js.map +1 -0
  45. package/package.json +18 -15
  46. package/readme.md +180 -12
@@ -1,108 +1,234 @@
1
1
  import ansiEscapes from 'ansi-escapes';
2
2
  import cliCursor from 'cli-cursor';
3
+ import { cursorPositionChanged, buildCursorSuffix, buildCursorOnlySequence, buildReturnToBottomPrefix, hideCursorEscape, } from './cursor-helpers.js';
4
+ // Count visible lines in a string, ignoring the trailing empty element
5
+ // that `split('\n')` produces when the string ends with '\n'.
6
+ const visibleLineCount = (lines, str) => str.endsWith('\n') ? lines.length - 1 : lines.length;
3
7
  const createStandard = (stream, { showCursor = false } = {}) => {
4
8
  let previousLineCount = 0;
5
9
  let previousOutput = '';
6
10
  let hasHiddenCursor = false;
11
+ let cursorPosition;
12
+ let cursorDirty = false;
13
+ let previousCursorPosition;
14
+ let cursorWasShown = false;
15
+ const getActiveCursor = () => (cursorDirty ? cursorPosition : undefined);
16
+ const hasChanges = (str, activeCursor) => {
17
+ const cursorChanged = cursorPositionChanged(activeCursor, previousCursorPosition);
18
+ return str !== previousOutput || cursorChanged;
19
+ };
7
20
  const render = (str) => {
8
21
  if (!showCursor && !hasHiddenCursor) {
9
- cliCursor.hide();
22
+ cliCursor.hide(stream);
10
23
  hasHiddenCursor = true;
11
24
  }
12
- const output = str + '\n';
13
- if (output === previousOutput) {
14
- return;
25
+ // Only use cursor if setCursorPosition was called since last render.
26
+ // This ensures stale positions don't persist after component unmount.
27
+ const activeCursor = getActiveCursor();
28
+ cursorDirty = false;
29
+ const cursorChanged = cursorPositionChanged(activeCursor, previousCursorPosition);
30
+ if (!hasChanges(str, activeCursor)) {
31
+ return false;
32
+ }
33
+ const lines = str.split('\n');
34
+ const visibleCount = visibleLineCount(lines, str);
35
+ const cursorSuffix = buildCursorSuffix(visibleCount, activeCursor);
36
+ if (str === previousOutput && cursorChanged) {
37
+ stream.write(buildCursorOnlySequence({
38
+ cursorWasShown,
39
+ previousLineCount,
40
+ previousCursorPosition,
41
+ visibleLineCount: visibleCount,
42
+ cursorPosition: activeCursor,
43
+ }));
44
+ }
45
+ else {
46
+ previousOutput = str;
47
+ const returnPrefix = buildReturnToBottomPrefix(cursorWasShown, previousLineCount, previousCursorPosition);
48
+ stream.write(returnPrefix +
49
+ ansiEscapes.eraseLines(previousLineCount) +
50
+ str +
51
+ cursorSuffix);
52
+ previousLineCount = lines.length;
15
53
  }
16
- previousOutput = output;
17
- stream.write(ansiEscapes.eraseLines(previousLineCount) + output);
18
- previousLineCount = output.split('\n').length;
54
+ previousCursorPosition = activeCursor ? { ...activeCursor } : undefined;
55
+ cursorWasShown = activeCursor !== undefined;
56
+ return true;
19
57
  };
20
58
  render.clear = () => {
21
- stream.write(ansiEscapes.eraseLines(previousLineCount));
59
+ const prefix = buildReturnToBottomPrefix(cursorWasShown, previousLineCount, previousCursorPosition);
60
+ stream.write(prefix + ansiEscapes.eraseLines(previousLineCount));
22
61
  previousOutput = '';
23
62
  previousLineCount = 0;
63
+ previousCursorPosition = undefined;
64
+ cursorWasShown = false;
24
65
  };
25
66
  render.done = () => {
26
67
  previousOutput = '';
27
68
  previousLineCount = 0;
69
+ previousCursorPosition = undefined;
70
+ cursorWasShown = false;
28
71
  if (!showCursor) {
29
- cliCursor.show();
72
+ cliCursor.show(stream);
30
73
  hasHiddenCursor = false;
31
74
  }
32
75
  };
33
76
  render.sync = (str) => {
34
- const output = str + '\n';
35
- previousOutput = output;
36
- previousLineCount = output.split('\n').length;
77
+ const activeCursor = cursorDirty ? cursorPosition : undefined;
78
+ cursorDirty = false;
79
+ const lines = str.split('\n');
80
+ previousOutput = str;
81
+ previousLineCount = lines.length;
82
+ if (!activeCursor && cursorWasShown) {
83
+ stream.write(hideCursorEscape);
84
+ }
85
+ if (activeCursor) {
86
+ stream.write(buildCursorSuffix(visibleLineCount(lines, str), activeCursor));
87
+ }
88
+ previousCursorPosition = activeCursor ? { ...activeCursor } : undefined;
89
+ cursorWasShown = activeCursor !== undefined;
90
+ };
91
+ render.setCursorPosition = (position) => {
92
+ cursorPosition = position;
93
+ cursorDirty = true;
37
94
  };
95
+ render.isCursorDirty = () => cursorDirty;
96
+ render.willRender = (str) => hasChanges(str, getActiveCursor());
38
97
  return render;
39
98
  };
40
99
  const createIncremental = (stream, { showCursor = false } = {}) => {
41
100
  let previousLines = [];
42
101
  let previousOutput = '';
43
102
  let hasHiddenCursor = false;
103
+ let cursorPosition;
104
+ let cursorDirty = false;
105
+ let previousCursorPosition;
106
+ let cursorWasShown = false;
107
+ const getActiveCursor = () => (cursorDirty ? cursorPosition : undefined);
108
+ const hasChanges = (str, activeCursor) => {
109
+ const cursorChanged = cursorPositionChanged(activeCursor, previousCursorPosition);
110
+ return str !== previousOutput || cursorChanged;
111
+ };
44
112
  const render = (str) => {
45
113
  if (!showCursor && !hasHiddenCursor) {
46
- cliCursor.hide();
114
+ cliCursor.hide(stream);
47
115
  hasHiddenCursor = true;
48
116
  }
49
- const output = str + '\n';
50
- if (output === previousOutput) {
51
- return;
52
- }
53
- const previousCount = previousLines.length;
54
- const nextLines = output.split('\n');
55
- const nextCount = nextLines.length;
56
- const visibleCount = nextCount - 1;
57
- if (output === '\n' || previousOutput.length === 0) {
58
- stream.write(ansiEscapes.eraseLines(previousCount) + output);
59
- previousOutput = output;
117
+ // Only use cursor if setCursorPosition was called since last render.
118
+ // This ensures stale positions don't persist after component unmount.
119
+ const activeCursor = getActiveCursor();
120
+ cursorDirty = false;
121
+ const cursorChanged = cursorPositionChanged(activeCursor, previousCursorPosition);
122
+ if (!hasChanges(str, activeCursor)) {
123
+ return false;
124
+ }
125
+ const nextLines = str.split('\n');
126
+ const visibleCount = visibleLineCount(nextLines, str);
127
+ const previousVisible = visibleLineCount(previousLines, previousOutput);
128
+ if (str === previousOutput && cursorChanged) {
129
+ stream.write(buildCursorOnlySequence({
130
+ cursorWasShown,
131
+ previousLineCount: previousLines.length,
132
+ previousCursorPosition,
133
+ visibleLineCount: visibleCount,
134
+ cursorPosition: activeCursor,
135
+ }));
136
+ previousCursorPosition = activeCursor ? { ...activeCursor } : undefined;
137
+ cursorWasShown = activeCursor !== undefined;
138
+ return true;
139
+ }
140
+ const returnPrefix = buildReturnToBottomPrefix(cursorWasShown, previousLines.length, previousCursorPosition);
141
+ if (str === '\n' || previousOutput.length === 0) {
142
+ const cursorSuffix = buildCursorSuffix(visibleCount, activeCursor);
143
+ stream.write(returnPrefix +
144
+ ansiEscapes.eraseLines(previousLines.length) +
145
+ str +
146
+ cursorSuffix);
147
+ cursorWasShown = activeCursor !== undefined;
148
+ previousCursorPosition = activeCursor ? { ...activeCursor } : undefined;
149
+ previousOutput = str;
60
150
  previousLines = nextLines;
61
- return;
151
+ return true;
62
152
  }
153
+ const hasTrailingNewline = str.endsWith('\n');
63
154
  // We aggregate all chunks for incremental rendering into a buffer, and then write them to stdout at the end.
64
155
  const buffer = [];
156
+ buffer.push(returnPrefix);
65
157
  // Clear extra lines if the current content's line count is lower than the previous.
66
- if (nextCount < previousCount) {
67
- buffer.push(
68
- // Erases the trailing lines and the final newline slot.
69
- ansiEscapes.eraseLines(previousCount - nextCount + 1),
70
- // Positions cursor to the top of the rendered output.
71
- ansiEscapes.cursorUp(visibleCount));
158
+ if (visibleCount < previousVisible) {
159
+ const previousHadTrailingNewline = previousOutput.endsWith('\n');
160
+ const extraSlot = previousHadTrailingNewline ? 1 : 0;
161
+ buffer.push(ansiEscapes.eraseLines(previousVisible - visibleCount + extraSlot), ansiEscapes.cursorUp(visibleCount));
72
162
  }
73
163
  else {
74
- buffer.push(ansiEscapes.cursorUp(previousCount - 1));
164
+ buffer.push(ansiEscapes.cursorUp(previousVisible - 1));
75
165
  }
76
166
  for (let i = 0; i < visibleCount; i++) {
167
+ const isLastLine = i === visibleCount - 1;
77
168
  // We do not write lines if the contents are the same. This prevents flickering during renders.
78
169
  if (nextLines[i] === previousLines[i]) {
79
- buffer.push(ansiEscapes.cursorNextLine);
170
+ // Don't move past the last line when there's no trailing newline,
171
+ // otherwise the cursor overshoots the rendered block.
172
+ if (!isLastLine || hasTrailingNewline) {
173
+ buffer.push(ansiEscapes.cursorNextLine);
174
+ }
80
175
  continue;
81
176
  }
82
- buffer.push(ansiEscapes.eraseLine + nextLines[i] + '\n');
177
+ buffer.push(ansiEscapes.cursorTo(0) +
178
+ nextLines[i] +
179
+ ansiEscapes.eraseEndLine +
180
+ // Don't append newline after the last line when the input
181
+ // has no trailing newline (fullscreen mode).
182
+ (isLastLine && !hasTrailingNewline ? '' : '\n'));
83
183
  }
184
+ const cursorSuffix = buildCursorSuffix(visibleCount, activeCursor);
185
+ buffer.push(cursorSuffix);
84
186
  stream.write(buffer.join(''));
85
- previousOutput = output;
187
+ cursorWasShown = activeCursor !== undefined;
188
+ previousCursorPosition = activeCursor ? { ...activeCursor } : undefined;
189
+ previousOutput = str;
86
190
  previousLines = nextLines;
191
+ return true;
87
192
  };
88
193
  render.clear = () => {
89
- stream.write(ansiEscapes.eraseLines(previousLines.length));
194
+ const prefix = buildReturnToBottomPrefix(cursorWasShown, previousLines.length, previousCursorPosition);
195
+ stream.write(prefix + ansiEscapes.eraseLines(previousLines.length));
90
196
  previousOutput = '';
91
197
  previousLines = [];
198
+ previousCursorPosition = undefined;
199
+ cursorWasShown = false;
92
200
  };
93
201
  render.done = () => {
94
202
  previousOutput = '';
95
203
  previousLines = [];
204
+ previousCursorPosition = undefined;
205
+ cursorWasShown = false;
96
206
  if (!showCursor) {
97
- cliCursor.show();
207
+ cliCursor.show(stream);
98
208
  hasHiddenCursor = false;
99
209
  }
100
210
  };
101
211
  render.sync = (str) => {
102
- const output = str + '\n';
103
- previousOutput = output;
104
- previousLines = output.split('\n');
212
+ const activeCursor = cursorDirty ? cursorPosition : undefined;
213
+ cursorDirty = false;
214
+ const lines = str.split('\n');
215
+ previousOutput = str;
216
+ previousLines = lines;
217
+ if (!activeCursor && cursorWasShown) {
218
+ stream.write(hideCursorEscape);
219
+ }
220
+ if (activeCursor) {
221
+ stream.write(buildCursorSuffix(visibleLineCount(lines, str), activeCursor));
222
+ }
223
+ previousCursorPosition = activeCursor ? { ...activeCursor } : undefined;
224
+ cursorWasShown = activeCursor !== undefined;
225
+ };
226
+ render.setCursorPosition = (position) => {
227
+ cursorPosition = position;
228
+ cursorDirty = true;
105
229
  };
230
+ render.isCursorDirty = () => cursorDirty;
231
+ render.willRender = (str) => hasChanges(str, getActiveCursor());
106
232
  return render;
107
233
  };
108
234
  const create = (stream, { showCursor = false, incremental = false } = {}) => {
@@ -1 +1 @@
1
- {"version":3,"file":"log-update.js","sourceRoot":"","sources":["../src/log-update.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"log-update.js","sourceRoot":"","sources":["../src/log-update.ts"],"names":[],"mappings":"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"}
@@ -9,6 +9,14 @@ type ParsedKey = {
9
9
  sequence: string;
10
10
  raw: string | undefined;
11
11
  code?: string;
12
+ super?: boolean;
13
+ hyper?: boolean;
14
+ capsLock?: boolean;
15
+ numLock?: boolean;
16
+ eventType?: 'press' | 'repeat' | 'release';
17
+ isKittyProtocol?: boolean;
18
+ text?: string;
19
+ isPrintable?: boolean;
12
20
  };
13
21
  declare const parseKeypress: (s?: Buffer | string) => ParsedKey;
14
22
  export default parseKeypress;
@@ -1,5 +1,6 @@
1
1
  // Copied from https://github.com/enquirer/enquirer/blob/36785f3399a41cd61e9d28d1eb9c2fcd73d69b4c/lib/keypress.js
2
2
  import { Buffer } from 'node:buffer';
3
+ import { kittyModifiers } from './kitty-keyboard.js';
3
4
  const metaKeyCodeRe = /^(?:\x1b)([a-zA-Z0-9])$/;
4
5
  const fnKeyRe = /^(?:\x1b+)(O|N|\[|\[\[)(?:(\d+)(?:;(\d+))?([~^$])|(?:1;)?(\d+)?([a-zA-Z]))/;
5
6
  const keyName = {
@@ -115,6 +116,249 @@ const isCtrlKey = (code) => {
115
116
  '[8^',
116
117
  ].includes(code);
117
118
  };
119
+ // Kitty keyboard protocol: CSI codepoint ; modifiers [: eventType] [; text-as-codepoints] u
120
+ const kittyKeyRe = /^\x1b\[(\d+)(?:;(\d+)(?::(\d+))?(?:;([\d:]+))?)?u$/;
121
+ // Kitty-enhanced special keys: CSI number ; modifiers : eventType {letter|~}
122
+ // These are legacy CSI sequences enhanced with the :eventType field.
123
+ // Examples: \x1b[1;1:1A (up arrow press), \x1b[3;1:3~ (delete release)
124
+ const kittySpecialKeyRe = /^\x1b\[(\d+);(\d+):(\d+)([A-Za-z~])$/;
125
+ // Letter-terminated special key names (CSI 1 ; mods letter)
126
+ const kittySpecialLetterKeys = {
127
+ A: 'up',
128
+ B: 'down',
129
+ C: 'right',
130
+ D: 'left',
131
+ E: 'clear',
132
+ F: 'end',
133
+ H: 'home',
134
+ P: 'f1',
135
+ Q: 'f2',
136
+ R: 'f3',
137
+ S: 'f4',
138
+ };
139
+ // Number-terminated special key names (CSI number ; mods ~)
140
+ const kittySpecialNumberKeys = {
141
+ 2: 'insert',
142
+ 3: 'delete',
143
+ 5: 'pageup',
144
+ 6: 'pagedown',
145
+ 7: 'home',
146
+ 8: 'end',
147
+ 11: 'f1',
148
+ 12: 'f2',
149
+ 13: 'f3',
150
+ 14: 'f4',
151
+ 15: 'f5',
152
+ 17: 'f6',
153
+ 18: 'f7',
154
+ 19: 'f8',
155
+ 20: 'f9',
156
+ 21: 'f10',
157
+ 23: 'f11',
158
+ 24: 'f12',
159
+ };
160
+ // Map of special codepoints to key names in kitty protocol
161
+ const kittyCodepointNames = {
162
+ 27: 'escape',
163
+ // 13 (return) and 32 (space) are handled before this lookup
164
+ // in parseKittyKeypress so they can be marked as printable.
165
+ 9: 'tab',
166
+ 127: 'delete',
167
+ 8: 'backspace',
168
+ 57358: 'capslock',
169
+ 57359: 'scrolllock',
170
+ 57360: 'numlock',
171
+ 57361: 'printscreen',
172
+ 57362: 'pause',
173
+ 57363: 'menu',
174
+ 57376: 'f13',
175
+ 57377: 'f14',
176
+ 57378: 'f15',
177
+ 57379: 'f16',
178
+ 57380: 'f17',
179
+ 57381: 'f18',
180
+ 57382: 'f19',
181
+ 57383: 'f20',
182
+ 57384: 'f21',
183
+ 57385: 'f22',
184
+ 57386: 'f23',
185
+ 57387: 'f24',
186
+ 57388: 'f25',
187
+ 57389: 'f26',
188
+ 57390: 'f27',
189
+ 57391: 'f28',
190
+ 57392: 'f29',
191
+ 57393: 'f30',
192
+ 57394: 'f31',
193
+ 57395: 'f32',
194
+ 57396: 'f33',
195
+ 57397: 'f34',
196
+ 57398: 'f35',
197
+ 57399: 'kp0',
198
+ 57400: 'kp1',
199
+ 57401: 'kp2',
200
+ 57402: 'kp3',
201
+ 57403: 'kp4',
202
+ 57404: 'kp5',
203
+ 57405: 'kp6',
204
+ 57406: 'kp7',
205
+ 57407: 'kp8',
206
+ 57408: 'kp9',
207
+ 57409: 'kpdecimal',
208
+ 57410: 'kpdivide',
209
+ 57411: 'kpmultiply',
210
+ 57412: 'kpsubtract',
211
+ 57413: 'kpadd',
212
+ 57414: 'kpenter',
213
+ 57415: 'kpequal',
214
+ 57416: 'kpseparator',
215
+ 57417: 'kpleft',
216
+ 57418: 'kpright',
217
+ 57419: 'kpup',
218
+ 57420: 'kpdown',
219
+ 57421: 'kppageup',
220
+ 57422: 'kppagedown',
221
+ 57423: 'kphome',
222
+ 57424: 'kpend',
223
+ 57425: 'kpinsert',
224
+ 57426: 'kpdelete',
225
+ 57427: 'kpbegin',
226
+ 57428: 'mediaplay',
227
+ 57429: 'mediapause',
228
+ 57430: 'mediaplaypause',
229
+ 57431: 'mediareverse',
230
+ 57432: 'mediastop',
231
+ 57433: 'mediafastforward',
232
+ 57434: 'mediarewind',
233
+ 57435: 'mediatracknext',
234
+ 57436: 'mediatrackprevious',
235
+ 57437: 'mediarecord',
236
+ 57438: 'lowervolume',
237
+ 57439: 'raisevolume',
238
+ 57440: 'mutevolume',
239
+ 57441: 'leftshift',
240
+ 57442: 'leftcontrol',
241
+ 57443: 'leftalt',
242
+ 57444: 'leftsuper',
243
+ 57445: 'lefthyper',
244
+ 57446: 'leftmeta',
245
+ 57447: 'rightshift',
246
+ 57448: 'rightcontrol',
247
+ 57449: 'rightalt',
248
+ 57450: 'rightsuper',
249
+ 57451: 'righthyper',
250
+ 57452: 'rightmeta',
251
+ 57453: 'isoLevel3Shift',
252
+ 57454: 'isoLevel5Shift',
253
+ };
254
+ // Valid Unicode codepoint range, excluding surrogates
255
+ const isValidCodepoint = (cp) => cp >= 0 && cp <= 0x10_ffff && !(cp >= 0xd8_00 && cp <= 0xdf_ff);
256
+ const safeFromCodePoint = (cp) => isValidCodepoint(cp) ? String.fromCodePoint(cp) : '?';
257
+ function resolveEventType(value) {
258
+ if (value === 3)
259
+ return 'release';
260
+ if (value === 2)
261
+ return 'repeat';
262
+ return 'press';
263
+ }
264
+ function parseKittyModifiers(modifiers) {
265
+ return {
266
+ ctrl: !!(modifiers & kittyModifiers.ctrl),
267
+ shift: !!(modifiers & kittyModifiers.shift),
268
+ meta: !!(modifiers & kittyModifiers.meta),
269
+ option: !!(modifiers & kittyModifiers.alt),
270
+ super: !!(modifiers & kittyModifiers.super),
271
+ hyper: !!(modifiers & kittyModifiers.hyper),
272
+ capsLock: !!(modifiers & kittyModifiers.capsLock),
273
+ numLock: !!(modifiers & kittyModifiers.numLock),
274
+ };
275
+ }
276
+ const parseKittyKeypress = (s) => {
277
+ const match = kittyKeyRe.exec(s);
278
+ if (!match)
279
+ return null;
280
+ const codepoint = parseInt(match[1], 10);
281
+ const modifiers = match[2] ? Math.max(0, parseInt(match[2], 10) - 1) : 0;
282
+ const eventType = match[3] ? parseInt(match[3], 10) : 1;
283
+ const textField = match[4];
284
+ // Bail on invalid primary codepoint
285
+ if (!isValidCodepoint(codepoint)) {
286
+ return null;
287
+ }
288
+ // Parse text-as-codepoints field (colon-separated Unicode codepoints)
289
+ let text;
290
+ if (textField) {
291
+ text = textField
292
+ .split(':')
293
+ .map(cp => safeFromCodePoint(parseInt(cp, 10)))
294
+ .join('');
295
+ }
296
+ // Determine key name from codepoint
297
+ let name;
298
+ let isPrintable;
299
+ if (codepoint === 32) {
300
+ name = 'space';
301
+ isPrintable = true;
302
+ }
303
+ else if (codepoint === 13) {
304
+ name = 'return';
305
+ isPrintable = true;
306
+ }
307
+ else if (kittyCodepointNames[codepoint]) {
308
+ name = kittyCodepointNames[codepoint];
309
+ isPrintable = false;
310
+ }
311
+ else if (codepoint >= 1 && codepoint <= 26) {
312
+ // Ctrl+letter comes as codepoint 1-26
313
+ name = String.fromCodePoint(codepoint + 96); // 'a' is 97
314
+ isPrintable = false;
315
+ }
316
+ else {
317
+ name = safeFromCodePoint(codepoint).toLowerCase();
318
+ isPrintable = true;
319
+ }
320
+ // Default text to the character from the codepoint when not explicitly
321
+ // provided by the protocol, so keys like space and return produce their
322
+ // expected text input (' ' and '\r' respectively).
323
+ if (isPrintable && !text) {
324
+ text = safeFromCodePoint(codepoint);
325
+ }
326
+ return {
327
+ name,
328
+ ...parseKittyModifiers(modifiers),
329
+ eventType: resolveEventType(eventType),
330
+ sequence: s,
331
+ raw: s,
332
+ isKittyProtocol: true,
333
+ isPrintable,
334
+ text,
335
+ };
336
+ };
337
+ // Parse kitty-enhanced special key sequences (arrow keys, function keys, etc.)
338
+ // These use the legacy CSI format but with an added :eventType field.
339
+ const parseKittySpecialKey = (s) => {
340
+ const match = kittySpecialKeyRe.exec(s);
341
+ if (!match)
342
+ return null;
343
+ const number = parseInt(match[1], 10);
344
+ const modifiers = Math.max(0, parseInt(match[2], 10) - 1);
345
+ const eventType = parseInt(match[3], 10);
346
+ const terminator = match[4];
347
+ const name = terminator === '~'
348
+ ? kittySpecialNumberKeys[number]
349
+ : kittySpecialLetterKeys[terminator];
350
+ if (!name)
351
+ return null;
352
+ return {
353
+ name,
354
+ ...parseKittyModifiers(modifiers),
355
+ eventType: resolveEventType(eventType),
356
+ sequence: s,
357
+ raw: s,
358
+ isKittyProtocol: true,
359
+ isPrintable: false,
360
+ };
361
+ };
118
362
  const parseKeypress = (s = '') => {
119
363
  let parts;
120
364
  if (Buffer.isBuffer(s)) {
@@ -132,6 +376,29 @@ const parseKeypress = (s = '') => {
132
376
  else if (!s) {
133
377
  s = '';
134
378
  }
379
+ // Try kitty keyboard protocol parsers first
380
+ const kittyResult = parseKittyKeypress(s);
381
+ if (kittyResult)
382
+ return kittyResult;
383
+ const kittySpecialResult = parseKittySpecialKey(s);
384
+ if (kittySpecialResult)
385
+ return kittySpecialResult;
386
+ // If the input matched the kitty CSI-u pattern but was rejected (e.g.,
387
+ // invalid codepoint), return a safe empty keypress instead of falling
388
+ // through to legacy parsing which can produce unsafe states (undefined name)
389
+ if (kittyKeyRe.test(s)) {
390
+ return {
391
+ name: '',
392
+ ctrl: false,
393
+ meta: false,
394
+ shift: false,
395
+ option: false,
396
+ sequence: s,
397
+ raw: s,
398
+ isKittyProtocol: true,
399
+ isPrintable: false,
400
+ };
401
+ }
135
402
  const key = {
136
403
  name: '',
137
404
  ctrl: false,
@@ -142,10 +409,11 @@ const parseKeypress = (s = '') => {
142
409
  raw: s,
143
410
  };
144
411
  key.sequence = key.sequence || s || key.name;
145
- if (s === '\r') {
146
- // carriage return
412
+ if (s === '\r' || s === '\x1b\r') {
413
+ // carriage return (or option+return on macOS)
147
414
  key.raw = undefined;
148
415
  key.name = 'return';
416
+ key.option = s.length === 2;
149
417
  }
150
418
  else if (s === '\n') {
151
419
  // enter, should have been called linefeed