fix(pi-tui): filter kitty keypad private-use input (#4026)

This commit is contained in:
mastertyko 2026-04-13 12:51:12 +02:00 committed by GitHub
parent 7a7683488f
commit 510629c8cb
3 changed files with 68 additions and 0 deletions

View file

@ -61,4 +61,22 @@ describe("Editor", () => {
assert.ok(rendered.includes(CURSOR_MARKER));
});
it("maps kitty keypad digits to plain editor text", () => {
const editor = new Editor(new TUI(makeTerminal()), theme);
editor.focused = true;
editor.handleInput("\x1b[57404;129u");
assert.equal(editor.getText(), "5");
});
it("does not insert kitty keypad navigation private-use glyphs into the editor", () => {
const editor = new Editor(new TUI(makeTerminal()), theme);
editor.focused = true;
editor.handleInput("\x1b[57419u");
assert.equal(editor.getText(), "");
});
});

View file

@ -43,4 +43,22 @@ describe("Input", () => {
assert.ok(!line.includes("secret123"), "rendered line must not expose raw secret text");
assert.ok(line.includes("*********"), "rendered line should include masked characters");
});
it("maps kitty keypad digits to text instead of inserting private-use glyphs", () => {
const input = new Input();
input.focused = true;
input.handleInput("\x1b[57400;129u");
assert.equal(input.getValue(), "1");
});
it("ignores kitty keypad navigation keys in text input", () => {
const input = new Input();
input.focused = true;
input.handleInput("\x1b[57417u");
assert.equal(input.getValue(), "");
});
});

View file

@ -309,6 +309,28 @@ const CODEPOINTS = {
kpEnter: 57414, // Numpad Enter (Kitty protocol)
} as const;
const KITTY_PRIVATE_USE_RANGE = { start: 57344, end: 63743 } as const;
const KITTY_KEYPAD_PRINTABLES = new Map<number, string>([
[57399, "0"], // KP_0
[57400, "1"], // KP_1
[57401, "2"], // KP_2
[57402, "3"], // KP_3
[57403, "4"], // KP_4
[57404, "5"], // KP_5
[57405, "6"], // KP_6
[57406, "7"], // KP_7
[57407, "8"], // KP_8
[57408, "9"], // KP_9
[57409, "."], // KP_DECIMAL
[57410, "/"], // KP_DIVIDE
[57411, "*"], // KP_MULTIPLY
[57412, "-"], // KP_SUBTRACT
[57413, "+"], // KP_ADD
[57415, "="], // KP_EQUAL
[57416, ","], // KP_SEPARATOR
]);
const ARROW_CODEPOINTS = {
up: -1,
down: -2,
@ -1168,6 +1190,16 @@ export function decodeKittyPrintable(data: string): string | undefined {
// Drop control characters or invalid codepoints.
if (!Number.isFinite(effectiveCodepoint) || effectiveCodepoint < 32) return undefined;
const keypadPrintable = KITTY_KEYPAD_PRINTABLES.get(effectiveCodepoint);
if (keypadPrintable !== undefined) return keypadPrintable;
if (
effectiveCodepoint >= KITTY_PRIVATE_USE_RANGE.start &&
effectiveCodepoint <= KITTY_PRIVATE_USE_RANGE.end
) {
return undefined;
}
try {
return String.fromCodePoint(effectiveCodepoint);
} catch {