feat: add kitty query response filter and extend useInput Key interface
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -19,6 +19,11 @@ export interface Key {
|
|||||||
backspace: boolean;
|
backspace: boolean;
|
||||||
delete: boolean;
|
delete: boolean;
|
||||||
meta: boolean;
|
meta: boolean;
|
||||||
|
super: boolean;
|
||||||
|
hyper: boolean;
|
||||||
|
capsLock: boolean;
|
||||||
|
numLock: boolean;
|
||||||
|
eventType?: "press" | "repeat" | "release";
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UseInputOptions {
|
export interface UseInputOptions {
|
||||||
@@ -37,6 +42,7 @@ export function useInput(
|
|||||||
|
|
||||||
function listener(data: string) {
|
function listener(data: string) {
|
||||||
const keypress = parseKeypress(data);
|
const keypress = parseKeypress(data);
|
||||||
|
if (keypress.ignore) return;
|
||||||
|
|
||||||
const key: Key = {
|
const key: Key = {
|
||||||
upArrow: keypress.name === "up",
|
upArrow: keypress.name === "up",
|
||||||
@@ -55,20 +61,32 @@ export function useInput(
|
|||||||
backspace: keypress.name === "backspace",
|
backspace: keypress.name === "backspace",
|
||||||
delete: keypress.name === "delete",
|
delete: keypress.name === "delete",
|
||||||
meta: keypress.meta,
|
meta: keypress.meta,
|
||||||
|
super: keypress.super ?? false,
|
||||||
|
hyper: keypress.hyper ?? false,
|
||||||
|
capsLock: keypress.capsLock ?? false,
|
||||||
|
numLock: keypress.numLock ?? false,
|
||||||
|
eventType: keypress.eventType,
|
||||||
};
|
};
|
||||||
|
|
||||||
let input: string;
|
let input: string;
|
||||||
if (keypress.ctrl) {
|
if (keypress.isKittyProtocol) {
|
||||||
|
if (keypress.isPrintable) {
|
||||||
|
input = keypress.text ?? keypress.name;
|
||||||
|
} else if (keypress.ctrl && keypress.name.length === 1) {
|
||||||
|
input = keypress.name;
|
||||||
|
} else {
|
||||||
|
input = "";
|
||||||
|
}
|
||||||
|
} else if (keypress.ctrl) {
|
||||||
input = keypress.name ?? "";
|
input = keypress.name ?? "";
|
||||||
} else {
|
} else {
|
||||||
input = keypress.sequence;
|
input = keypress.sequence;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nonAlphanumericKeys.includes(keypress.name)) {
|
if (!keypress.isKittyProtocol && nonAlphanumericKeys.includes(keypress.name)) {
|
||||||
input = "";
|
input = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Strip escape prefix from incomplete sequences
|
|
||||||
if (input.startsWith("\x1b")) {
|
if (input.startsWith("\x1b")) {
|
||||||
input = input.slice(1);
|
input = input.slice(1);
|
||||||
}
|
}
|
||||||
@@ -77,8 +95,10 @@ export function useInput(
|
|||||||
key.shift = true;
|
key.shift = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// exitOnCtrlC skip: don't call user handler for Ctrl+C when intercepted
|
// exitOnCtrlC: intercept kitty Ctrl+C (\x1b[3;5u). Legacy \x03 is caught
|
||||||
|
// by emitInput in createStdinController and never reaches useInput.
|
||||||
if (input === "c" && key.ctrl && stdin?.internal_exitOnCtrlC) {
|
if (input === "c" && key.ctrl && stdin?.internal_exitOnCtrlC) {
|
||||||
|
app!.exit();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ const metaKeyCodeRe = /^(?:\x1b)([a-zA-Z0-9])$/;
|
|||||||
|
|
||||||
const fnKeyRe = /^(?:\x1b+)(O|N|\[|\[\[)(?:(\d+)(?:;(\d+))?([~^$])|(?:1;)?(\d+)?([a-zA-Z]))/;
|
const fnKeyRe = /^(?:\x1b+)(O|N|\[|\[\[)(?:(\d+)(?:;(\d+))?([~^$])|(?:1;)?(\d+)?([a-zA-Z]))/;
|
||||||
|
|
||||||
|
const kittyQueryResponseRe = /^\x1b\[\?\d+u$/;
|
||||||
|
|
||||||
const keyName: Record<string, string> = {
|
const keyName: Record<string, string> = {
|
||||||
/* xterm/gnome ESC O letter */
|
/* xterm/gnome ESC O letter */
|
||||||
OP: "f1",
|
OP: "f1",
|
||||||
@@ -131,6 +133,7 @@ export interface Keypress {
|
|||||||
* Only set by the kitty protocol parser.
|
* Only set by the kitty protocol parser.
|
||||||
*/
|
*/
|
||||||
isPrintable?: boolean;
|
isPrintable?: boolean;
|
||||||
|
ignore?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kitty keyboard protocol modifier bits.
|
// Kitty keyboard protocol modifier bits.
|
||||||
@@ -421,6 +424,10 @@ export function parseKeypress(s: Uint8Array | string = ""): Keypress {
|
|||||||
s = "";
|
s = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (kittyQueryResponseRe.test(s)) {
|
||||||
|
return { name: "", ctrl: false, meta: false, shift: false, sequence: s, raw: s, ignore: true };
|
||||||
|
}
|
||||||
|
|
||||||
// Try kitty keyboard protocol parsers first
|
// Try kitty keyboard protocol parsers first
|
||||||
const kittyResult = parseKittyKeypress(s);
|
const kittyResult = parseKittyKeypress(s);
|
||||||
if (kittyResult) return kittyResult;
|
if (kittyResult) return kittyResult;
|
||||||
|
|||||||
Reference in New Issue
Block a user