fix(tui): distinguish ctrl+backspace from backspace on Windows Terminal
0x08 (BS) was treated as plain backspace alongside 0x7f (DEL). On Windows Terminal, Backspace sends 0x7f and Ctrl+Backspace sends 0x08, making ctrl+backspace bindings unreachable. Now 0x08 matches ctrl+backspace (and ctrl+h, same byte) but not plain backspace. 0x7f remains plain backspace. fixes #2139
This commit is contained in:
@@ -2,6 +2,10 @@
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed `ctrl+backspace` being indistinguishable from plain `backspace` on Windows Terminal. `0x08` is now recognized as `ctrl+backspace` instead of `backspace`, making `ctrl+backspace` bindable on terminals where it produces a distinct byte ([#2139](https://github.com/badlogic/pi-mono/issues/2139))
|
||||
|
||||
## [0.58.0] - 2026-03-14
|
||||
|
||||
### Added
|
||||
|
||||
@@ -846,8 +846,14 @@ export function matchesKey(data: string, keyId: KeyId): boolean {
|
||||
}
|
||||
return matchesKittySequence(data, CODEPOINTS.backspace, MODIFIERS.alt);
|
||||
}
|
||||
if (ctrl && !alt && !shift) {
|
||||
// Legacy: 0x08 (BS) is sent by Windows Terminal for Ctrl+Backspace.
|
||||
// Also matches Ctrl+H (same byte, ambiguous in legacy terminals).
|
||||
if (data === "\x08") return true;
|
||||
return matchesKittySequence(data, CODEPOINTS.backspace, MODIFIERS.ctrl);
|
||||
}
|
||||
if (modifier === 0) {
|
||||
return data === "\x7f" || data === "\x08" || matchesKittySequence(data, CODEPOINTS.backspace, 0);
|
||||
return data === "\x7f" || matchesKittySequence(data, CODEPOINTS.backspace, 0);
|
||||
}
|
||||
return matchesKittySequence(data, CODEPOINTS.backspace, modifier);
|
||||
|
||||
@@ -1165,7 +1171,8 @@ export function parseKey(data: string): string | undefined {
|
||||
if (data === "\r" || (!_kittyProtocolActive && data === "\n") || data === "\x1bOM") return "enter";
|
||||
if (data === "\x00") return "ctrl+space";
|
||||
if (data === " ") return "space";
|
||||
if (data === "\x7f" || data === "\x08") return "backspace";
|
||||
if (data === "\x7f") return "backspace";
|
||||
if (data === "\x08") return "ctrl+backspace";
|
||||
if (data === "\x1b[Z") return "shift+tab";
|
||||
if (!_kittyProtocolActive && data === "\x1b\r") return "alt+enter";
|
||||
if (!_kittyProtocolActive && data === "\x1b ") return "alt+space";
|
||||
|
||||
@@ -252,6 +252,20 @@ describe("matchesKey", () => {
|
||||
assert.strictEqual(parseKey("\x1b\x1f"), "ctrl+alt+-");
|
||||
});
|
||||
|
||||
it("should distinguish backspace (0x7f) from ctrl+backspace (0x08)", () => {
|
||||
setKittyProtocolActive(false);
|
||||
// 0x7f is plain backspace
|
||||
assert.strictEqual(matchesKey("\x7f", "backspace"), true);
|
||||
assert.strictEqual(matchesKey("\x7f", "ctrl+backspace"), false);
|
||||
assert.strictEqual(parseKey("\x7f"), "backspace");
|
||||
// 0x08 is ctrl+backspace (Windows Terminal sends this for Ctrl+Backspace)
|
||||
assert.strictEqual(matchesKey("\x08", "ctrl+backspace"), true);
|
||||
assert.strictEqual(matchesKey("\x08", "backspace"), false);
|
||||
assert.strictEqual(parseKey("\x08"), "ctrl+backspace");
|
||||
// 0x08 also matches ctrl+h (same byte, ambiguous in legacy terminals)
|
||||
assert.strictEqual(matchesKey("\x08", "ctrl+h"), true);
|
||||
});
|
||||
|
||||
it("should parse legacy alt-prefixed sequences when kitty inactive", () => {
|
||||
setKittyProtocolActive(false);
|
||||
assert.strictEqual(matchesKey("\x1b ", "alt+space"), true);
|
||||
|
||||
Reference in New Issue
Block a user