Skip to content

Commit fdb7346

Browse files
committed
Fix kitty keyboard disambiguate mode for space, enter, tab, backspace
1 parent 783c4a3 commit fdb7346

File tree

2 files changed

+32
-12
lines changed

2 files changed

+32
-12
lines changed

src/common/input/KittyKeyboard.test.ts

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -100,24 +100,24 @@ describe('KittyKeyboard', () => {
100100
assert.strictEqual(result.key, '\x1b[27u');
101101
});
102102

103-
it('Enter → CSI 13 u', () => {
103+
it('Enter → legacy \\r', () => {
104104
const result = kitty.evaluate(createEvent({ key: 'Enter' }), flags);
105-
assert.strictEqual(result.key, '\x1b[13u');
105+
assert.strictEqual(result.key, '\r');
106106
});
107107

108-
it('Tab → CSI 9 u', () => {
108+
it('Tab → legacy \\t', () => {
109109
const result = kitty.evaluate(createEvent({ key: 'Tab' }), flags);
110-
assert.strictEqual(result.key, '\x1b[9u');
110+
assert.strictEqual(result.key, '\t');
111111
});
112112

113-
it('Backspace → CSI 127 u', () => {
113+
it('Backspace → legacy \\x7f', () => {
114114
const result = kitty.evaluate(createEvent({ key: 'Backspace' }), flags);
115-
assert.strictEqual(result.key, '\x1b[127u');
115+
assert.strictEqual(result.key, '\x7f');
116116
});
117117

118-
it('Space → CSI 32 u', () => {
118+
it('Space → plain space (text-generating key)', () => {
119119
const result = kitty.evaluate(createEvent({ key: ' ' }), flags);
120-
assert.strictEqual(result.key, '\x1b[32u');
120+
assert.strictEqual(result.key, ' ');
121121
});
122122

123123
it('Shift+Tab → CSI 9;2 u', () => {
@@ -134,6 +134,21 @@ describe('KittyKeyboard', () => {
134134
const result = kitty.evaluate(createEvent({ key: 'Escape', altKey: true }), flags);
135135
assert.strictEqual(result.key, '\x1b[27;3u');
136136
});
137+
138+
it('Ctrl+Backspace → CSI 127;5 u', () => {
139+
const result = kitty.evaluate(createEvent({ key: 'Backspace', ctrlKey: true }), flags);
140+
assert.strictEqual(result.key, '\x1b[127;5u');
141+
});
142+
143+
it('Ctrl+Space → CSI 32;5 u', () => {
144+
const result = kitty.evaluate(createEvent({ key: ' ', ctrlKey: true }), flags);
145+
assert.strictEqual(result.key, '\x1b[32;5u');
146+
});
147+
148+
it('Alt+Space → CSI 32;3 u', () => {
149+
const result = kitty.evaluate(createEvent({ key: ' ', altKey: true }), flags);
150+
assert.strictEqual(result.key, '\x1b[32;3u');
151+
});
137152
});
138153

139154
describe('navigation keys', () => {

src/common/input/KittyKeyboard.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -457,9 +457,11 @@ export class KittyKeyboard {
457457
} else if (reportEventTypes) {
458458
useCsiU = true;
459459
} else if (flags & KittyKeyboardFlags.DISAMBIGUATE_ESCAPE_CODES) {
460-
if (keyCode === 27 || keyCode === 127 || keyCode === 13 || keyCode === 9 || keyCode === 32) {
461-
useCsiU = true;
462-
} else if (isFunc) {
460+
// Per spec, Enter/Tab/Backspace "still generate the same bytes as in legacy
461+
// mode" and Space is a text-generating key, so these skip the isFunc fast-path
462+
// and only get CSI u when modifiers are present (handled below).
463+
const isDisambiguateLegacy = keyCode === 13 || keyCode === 9 || keyCode === 127;
464+
if (isFunc && !isDisambiguateLegacy) {
463465
useCsiU = true;
464466
} else if (modifiers > 0) {
465467
if (ev.shiftKey && !ev.ctrlKey && !ev.altKey && !ev.metaKey && ev.key.length === 1) {
@@ -474,7 +476,10 @@ export class KittyKeyboard {
474476
result.key = this._buildCsiUSequence(ev, keyCode, modifiers, eventType, flags, isFunc, isMod);
475477
result.cancel = true;
476478
} else {
477-
if (ev.key.length === 1 && !ev.ctrlKey && !ev.altKey && !ev.metaKey) {
479+
const legacyByte = keyCode === 13 ? '\r' : keyCode === 9 ? '\t' : keyCode === 127 ? '\x7f' : undefined;
480+
if (legacyByte) {
481+
result.key = legacyByte;
482+
} else if (ev.key.length === 1 && !ev.ctrlKey && !ev.altKey && !ev.metaKey) {
478483
result.key = ev.key;
479484
}
480485
}

0 commit comments

Comments
 (0)