Add kitty support for function keys. (#12415)

This commit is contained in:
Tommaso Sciortino
2025-10-31 16:19:55 -07:00
committed by GitHub
parent f8ce3585eb
commit caf2ca1438
2 changed files with 49 additions and 45 deletions

View File

@@ -469,6 +469,10 @@ describe('KeypressContext - Kitty Protocol', () => {
{ sequence: `\x1b[1~`, expected: { name: 'home' } },
{ sequence: `\x1b[4~`, expected: { name: 'end' } },
{ sequence: `\x1b[2~`, expected: { name: 'insert' } },
{ sequence: `\x1b[11~`, expected: { name: 'f1' } },
{ sequence: `\x1b[17~`, expected: { name: 'f6' } },
{ sequence: `\x1b[23~`, expected: { name: 'f11' } },
{ sequence: `\x1b[24~`, expected: { name: 'f12' } },
// Reverse tabs
{ sequence: `\x1b[Z`, expected: { name: 'tab', shift: true } },
{ sequence: `\x1b[1;2Z`, expected: { name: 'tab', shift: true } },

View File

@@ -56,6 +56,48 @@ const MAC_ALT_KEY_CHARACTER_MAP: Record<string, string> = {
'\u00B5': 'm', // "µ" toggle markup view
};
/**
* Maps symbols from parameterized functional keys `\x1b[1;1<letter>`
* to their corresponding key names (e.g., 'up', 'f1').
*/
const LEGACY_FUNC_TO_NAME: { [k: string]: string } = {
A: 'up',
B: 'down',
C: 'right',
D: 'left',
H: 'home',
F: 'end',
P: 'f1',
Q: 'f2',
R: 'f3',
S: 'f4',
};
/**
* Maps key codes from tilde-coded functional keys `\x1b[<code>~`
* to their corresponding key names.
*/
const TILDE_KEYCODE_TO_NAME: Record<number, string> = {
1: 'home',
2: 'insert',
3: 'delete',
4: 'end',
5: 'pageup',
6: 'pagedown',
11: 'f1',
12: 'f2',
13: 'f3',
14: 'f4',
15: 'f5',
17: 'f6', // skipping 16 is intentional
18: 'f7',
19: 'f8',
20: 'f9',
21: 'f10',
23: 'f11', // skipping 22 is intentional
24: 'f12',
};
/**
* Check if a buffer could potentially be a valid kitty sequence or its prefix.
*/
@@ -169,19 +211,7 @@ function parseKittyPrefix(buffer: string): { key: Key; length: number } | null {
const alt = (bits & MODIFIER_ALT_BIT) === MODIFIER_ALT_BIT;
const ctrl = (bits & MODIFIER_CTRL_BIT) === MODIFIER_CTRL_BIT;
const sym = m[2];
const symbolToName: { [k: string]: string } = {
A: 'up',
B: 'down',
C: 'right',
D: 'left',
H: 'home',
F: 'end',
P: 'f1',
Q: 'f2',
R: 'f3',
S: 'f4',
};
const name = symbolToName[sym] || '';
const name = LEGACY_FUNC_TO_NAME[sym] || '';
if (!name) return null;
return {
key: {
@@ -216,29 +246,7 @@ function parseKittyPrefix(buffer: string): { key: Key; length: number } | null {
// Tilde-coded functional keys (Delete, Insert, PageUp/Down, Home/End)
if (terminator === '~') {
let name: string | null = null;
switch (keyCode) {
case 1:
name = 'home';
break;
case 2:
name = 'insert';
break;
case 3:
name = 'delete';
break;
case 4:
name = 'end';
break;
case 5:
name = 'pageup';
break;
case 6:
name = 'pagedown';
break;
default:
break;
}
const name = TILDE_KEYCODE_TO_NAME[keyCode];
if (name) {
return {
key: {
@@ -307,15 +315,7 @@ function parseKittyPrefix(buffer: string): { key: Key; length: number } | null {
m = buffer.match(legacyFuncKey);
if (m) {
const sym = m[1];
const nameMap: { [key: string]: string } = {
A: 'up',
B: 'down',
C: 'right',
D: 'left',
H: 'home',
F: 'end',
};
const name = nameMap[sym]!;
const name = LEGACY_FUNC_TO_NAME[sym]!;
return {
key: {
name,