diff --git a/src/tests/promptInputKeys.test.ts b/src/tests/promptInputKeys.test.ts index 69d2075..8952a3d 100644 --- a/src/tests/promptInputKeys.test.ts +++ b/src/tests/promptInputKeys.test.ts @@ -80,7 +80,7 @@ test("parseTerminalInput keeps BS payload for meta+backspace", () => { test("parseTerminalInput recognizes shifted return sequences", () => { const { input, key } = parseTerminalInput("\u001B\r"); - assert.equal(input, "\r"); + assert.equal(input, ""); assert.equal(key.return, true); assert.equal(key.shift, true); assert.equal(key.meta, false); @@ -108,8 +108,8 @@ test("parseTerminalInput recognizes alternate shifted return sequences", () => { }); test("terminal extended key helpers request and restore modifyOtherKeys mode", () => { - assert.equal(enableTerminalExtendedKeys(), "\u001B[>4;1m"); - assert.equal(disableTerminalExtendedKeys(), "\u001B[>4;0m"); + assert.equal(enableTerminalExtendedKeys(), "\u001B[>4;1m\u001B[>1u"); + assert.equal(disableTerminalExtendedKeys(), "\u001B[>4;0m\u001B[ { diff --git a/src/ui/prompt/cursor.ts b/src/ui/prompt/cursor.ts index 2668470..5eff1de 100644 --- a/src/ui/prompt/cursor.ts +++ b/src/ui/prompt/cursor.ts @@ -40,12 +40,14 @@ function disableTerminalFocusReporting(): string { return "\u001B[?1004l"; } +// xterm modifyOtherKeys + Kitty progressive enhancement. +// Both are needed: some terminals (incl. Windows Terminal) only respond to Kitty. export function enableTerminalExtendedKeys(): string { - return "\u001B[>4;1m"; + return "\u001B[>4;1m\u001B[>1u"; } export function disableTerminalExtendedKeys(): string { - return "\u001B[>4;0m"; + return "\u001B[>4;0m\u001B[1u) sends plain Enter as ESC[13u +// or ESC[13;NUMBERu with extra flags; xterm sends ESC[13;2u for Shift. +const CSI_RETURN_RE = /^\u001B\[13;(\d+)[u~]$/; +const CSI_EXTENDED_RETURN_RE = /^\u001B\[27;(\d+);13~$/; + +function isReturn(raw: string): boolean { + if (raw === "\r") return true; + if (SHIFT_RETURN_SEQUENCES.has(raw)) return true; + if (META_RETURN_SEQUENCES.has(raw)) return true; + return CSI_RETURN_RE.test(raw) || CSI_EXTENDED_RETURN_RE.test(raw); +} const META_RETURN_SEQUENCES = new Set(["\u001B[13;3u", "\u001B[13;4u"]); const CTRL_LEFT_SEQUENCES = new Set(["\u001B[1;5D", "\u001B[5D"]); const CTRL_RIGHT_SEQUENCES = new Set(["\u001B[1;5C", "\u001B[5C"]); @@ -113,10 +161,10 @@ export function parseTerminalInput(data: Buffer | string): { input: string; key: end: END_SEQUENCES.has(raw), pageDown: raw === "\u001B[6~", pageUp: raw === "\u001B[5~", - return: raw === "\r" || SHIFT_RETURN_SEQUENCES.has(raw) || META_RETURN_SEQUENCES.has(raw), + return: isReturn(raw), escape: raw === "\u001B", ctrl: CTRL_LEFT_SEQUENCES.has(raw) || CTRL_RIGHT_SEQUENCES.has(raw), - shift: SHIFT_RETURN_SEQUENCES.has(raw), + shift: isShiftReturn(raw), tab: raw === "\t" || raw === "\u001B[Z", backspace: BACKSPACE_BYTES.has(raw), delete: FORWARD_DELETE_SEQUENCES.has(raw), @@ -162,7 +210,7 @@ export function parseTerminalInput(data: Buffer | string): { input: string; key: key.shift = true; } - if (key.tab || key.backspace || key.delete) { + if (key.tab || key.backspace || key.delete || key.return) { input = ""; }