From 8479bd84743e8889f728acb21a62794102db0529 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Krzywa=C5=BCnia?= <1815898+ribelo@users.noreply.github.com> Date: Sat, 11 Jul 2026 15:20:08 +0200 Subject: [PATCH] fix(tui): parse legacy alt-prefixed symbols (#6523) --- packages/tui/src/keys.ts | 11 ++++++----- packages/tui/test/keys.test.ts | 8 ++++++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/packages/tui/src/keys.ts b/packages/tui/src/keys.ts index 0d3c7085..8b6f8a0a 100644 --- a/packages/tui/src/keys.ts +++ b/packages/tui/src/keys.ts @@ -1159,8 +1159,8 @@ export function matchesKey(data: string, keyId: KeyId): boolean { if (data === `\x1b${rawCtrl}`) return true; } - if (modifier === MODIFIERS.alt && !_kittyProtocolActive && (isLetter || isDigit)) { - // Legacy: alt+letter/digit is ESC followed by the key + if (modifier === MODIFIERS.alt && !_kittyProtocolActive && (isLetter || isDigit || SYMBOL_KEYS.has(key))) { + // Legacy: alt+printable key is ESC followed by the key if (data === `\x1b${key}`) return true; } @@ -1296,9 +1296,10 @@ export function parseKey(data: string): string | undefined { if (code >= 1 && code <= 26) { return `ctrl+alt+${String.fromCharCode(code + 96)}`; } - // Legacy alt+letter/digit (ESC followed by the key) - if ((code >= 97 && code <= 122) || (code >= 48 && code <= 57)) { - return `alt+${String.fromCharCode(code)}`; + // Legacy alt+letter/digit/symbol (ESC followed by the key) + const key = String.fromCharCode(code); + if ((code >= 97 && code <= 122) || (code >= 48 && code <= 57) || SYMBOL_KEYS.has(key)) { + return `alt+${key}`; } } if (data === "\x1b[A") return "up"; diff --git a/packages/tui/test/keys.test.ts b/packages/tui/test/keys.test.ts index e06844e4..a5b893f2 100644 --- a/packages/tui/test/keys.test.ts +++ b/packages/tui/test/keys.test.ts @@ -431,6 +431,10 @@ describe("matchesKey", () => { assert.strictEqual(parseKey("\x1ba"), "alt+a"); assert.strictEqual(matchesKey("\x1b1", "alt+1"), true); assert.strictEqual(parseKey("\x1b1"), "alt+1"); + assert.strictEqual(matchesKey("\x1b,", "alt+,"), true); + assert.strictEqual(parseKey("\x1b,"), "alt+,"); + assert.strictEqual(matchesKey("\x1b.", "alt+."), true); + assert.strictEqual(parseKey("\x1b."), "alt+."); assert.strictEqual(matchesKey("\x1by", "alt+y"), true); assert.strictEqual(parseKey("\x1by"), "alt+y"); assert.strictEqual(matchesKey("\x1bz", "alt+z"), true); @@ -451,6 +455,10 @@ describe("matchesKey", () => { assert.strictEqual(parseKey("\x1ba"), undefined); assert.strictEqual(matchesKey("\x1b1", "alt+1"), false); assert.strictEqual(parseKey("\x1b1"), undefined); + assert.strictEqual(matchesKey("\x1b,", "alt+,"), false); + assert.strictEqual(parseKey("\x1b,"), undefined); + assert.strictEqual(matchesKey("\x1b.", "alt+."), false); + assert.strictEqual(parseKey("\x1b."), undefined); assert.strictEqual(matchesKey("\x1by", "alt+y"), false); assert.strictEqual(parseKey("\x1by"), undefined); setKittyProtocolActive(false);