@xterm/xterm 6.1.0-beta.98 → 6.1.0-beta.99

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,513 @@
1
+ /**
2
+ * Copyright (c) 2025 The xterm.js authors. All rights reserved.
3
+ * @license MIT
4
+ *
5
+ * Kitty keyboard protocol implementation.
6
+ * @see https://sw.kovidgoyal.net/kitty/keyboard-protocol/
7
+ */
8
+
9
+ import { IKeyboardEvent, IKeyboardResult, KeyboardResultType } from 'common/Types';
10
+ import { C0 } from 'common/data/EscapeSequences';
11
+
12
+ /**
13
+ * Kitty keyboard protocol enhancement flags (bitfield).
14
+ */
15
+ export const enum KittyKeyboardFlags {
16
+ NONE = 0b00000,
17
+ /** Disambiguate escape codes - fixes ambiguous legacy encodings */
18
+ DISAMBIGUATE_ESCAPE_CODES = 0b00001,
19
+ /** Report event types - press/repeat/release */
20
+ REPORT_EVENT_TYPES = 0b00010,
21
+ /** Report alternate keys - shifted key and base layout key */
22
+ REPORT_ALTERNATE_KEYS = 0b00100,
23
+ /** Report all keys as escape codes - text-producing keys as CSI u */
24
+ REPORT_ALL_KEYS_AS_ESCAPE_CODES = 0b01000,
25
+ /** Report associated text - includes text codepoints in escape code */
26
+ REPORT_ASSOCIATED_TEXT = 0b10000,
27
+ }
28
+
29
+ /**
30
+ * Kitty keyboard event types.
31
+ */
32
+ export const enum KittyKeyboardEventType {
33
+ PRESS = 1,
34
+ REPEAT = 2,
35
+ RELEASE = 3,
36
+ }
37
+
38
+ /**
39
+ * Kitty modifier bits (different from xterm modifier encoding).
40
+ * Value sent = 1 + modifier_bits
41
+ */
42
+ export const enum KittyKeyboardModifiers {
43
+ SHIFT = 0b00000001,
44
+ ALT = 0b00000010,
45
+ CTRL = 0b00000100,
46
+ SUPER = 0b00001000,
47
+ HYPER = 0b00010000,
48
+ META = 0b00100000,
49
+ CAPS_LOCK = 0b01000000,
50
+ NUM_LOCK = 0b10000000,
51
+ }
52
+
53
+ /**
54
+ * Functional key codes for Kitty protocol.
55
+ * Keys that don't produce text have specific unicode codepoint mappings.
56
+ */
57
+ const FUNCTIONAL_KEY_CODES: { [key: string]: number } = {
58
+ 'Escape': 27,
59
+ 'Enter': 13,
60
+ 'Tab': 9,
61
+ 'Backspace': 127,
62
+ 'CapsLock': 57358,
63
+ 'ScrollLock': 57359,
64
+ 'NumLock': 57360,
65
+ 'PrintScreen': 57361,
66
+ 'Pause': 57362,
67
+ 'ContextMenu': 57363,
68
+ // F13-F35 (F1-F12 use legacy encoding)
69
+ 'F13': 57376,
70
+ 'F14': 57377,
71
+ 'F15': 57378,
72
+ 'F16': 57379,
73
+ 'F17': 57380,
74
+ 'F18': 57381,
75
+ 'F19': 57382,
76
+ 'F20': 57383,
77
+ 'F21': 57384,
78
+ 'F22': 57385,
79
+ 'F23': 57386,
80
+ 'F24': 57387,
81
+ 'F25': 57388,
82
+ // Keypad keys
83
+ 'KP_0': 57399,
84
+ 'KP_1': 57400,
85
+ 'KP_2': 57401,
86
+ 'KP_3': 57402,
87
+ 'KP_4': 57403,
88
+ 'KP_5': 57404,
89
+ 'KP_6': 57405,
90
+ 'KP_7': 57406,
91
+ 'KP_8': 57407,
92
+ 'KP_9': 57408,
93
+ 'KP_Decimal': 57409,
94
+ 'KP_Divide': 57410,
95
+ 'KP_Multiply': 57411,
96
+ 'KP_Subtract': 57412,
97
+ 'KP_Add': 57413,
98
+ 'KP_Enter': 57414,
99
+ 'KP_Equal': 57415,
100
+ // Modifier keys
101
+ 'ShiftLeft': 57441,
102
+ 'ShiftRight': 57447,
103
+ 'ControlLeft': 57442,
104
+ 'ControlRight': 57448,
105
+ 'AltLeft': 57443,
106
+ 'AltRight': 57449,
107
+ 'MetaLeft': 57444,
108
+ 'MetaRight': 57450,
109
+ // Media keys
110
+ 'MediaPlayPause': 57430,
111
+ 'MediaStop': 57432,
112
+ 'MediaTrackNext': 57435,
113
+ 'MediaTrackPrevious': 57436,
114
+ 'AudioVolumeDown': 57438,
115
+ 'AudioVolumeUp': 57439,
116
+ 'AudioVolumeMute': 57440
117
+ };
118
+
119
+ /**
120
+ * Keys that use CSI ~ encoding with a number parameter.
121
+ */
122
+ const CSI_TILDE_KEYS: { [key: string]: number } = {
123
+ 'Insert': 2,
124
+ 'Delete': 3,
125
+ 'PageUp': 5,
126
+ 'PageDown': 6,
127
+ 'F5': 15,
128
+ 'F6': 17,
129
+ 'F7': 18,
130
+ 'F8': 19,
131
+ 'F9': 20,
132
+ 'F10': 21,
133
+ 'F11': 23,
134
+ 'F12': 24
135
+ };
136
+
137
+ /**
138
+ * Keys that use CSI letter encoding (arrows, Home, End).
139
+ */
140
+ const CSI_LETTER_KEYS: { [key: string]: string } = {
141
+ 'ArrowUp': 'A',
142
+ 'ArrowDown': 'B',
143
+ 'ArrowRight': 'C',
144
+ 'ArrowLeft': 'D',
145
+ 'Home': 'H',
146
+ 'End': 'F'
147
+ };
148
+
149
+ /**
150
+ * Function keys F1-F4 use SS3 encoding without modifiers.
151
+ */
152
+ const SS3_FUNCTION_KEYS: { [key: string]: string } = {
153
+ 'F1': 'P',
154
+ 'F2': 'Q',
155
+ 'F3': 'R',
156
+ 'F4': 'S'
157
+ };
158
+
159
+ /**
160
+ * Map browser key codes to Kitty numpad codes.
161
+ */
162
+ function getNumpadKeyCode(ev: IKeyboardEvent): number | undefined {
163
+ // Detect numpad via code property
164
+ if (ev.code.startsWith('Numpad')) {
165
+ const suffix = ev.code.slice(6);
166
+ if (suffix >= '0' && suffix <= '9') {
167
+ return 57399 + parseInt(suffix, 10);
168
+ }
169
+ switch (suffix) {
170
+ case 'Decimal': return 57409;
171
+ case 'Divide': return 57410;
172
+ case 'Multiply': return 57411;
173
+ case 'Subtract': return 57412;
174
+ case 'Add': return 57413;
175
+ case 'Enter': return 57414;
176
+ case 'Equal': return 57415;
177
+ }
178
+ }
179
+ return undefined;
180
+ }
181
+
182
+ /**
183
+ * Get modifier key code from code property.
184
+ */
185
+ function getModifierKeyCode(ev: IKeyboardEvent): number | undefined {
186
+ switch (ev.code) {
187
+ case 'ShiftLeft': return 57441;
188
+ case 'ShiftRight': return 57447;
189
+ case 'ControlLeft': return 57442;
190
+ case 'ControlRight': return 57448;
191
+ case 'AltLeft': return 57443;
192
+ case 'AltRight': return 57449;
193
+ case 'MetaLeft': return 57444;
194
+ case 'MetaRight': return 57450;
195
+ }
196
+ return undefined;
197
+ }
198
+
199
+ /**
200
+ * Encode modifiers for Kitty protocol.
201
+ * Returns 1 + modifier bits, or 0 if no modifiers.
202
+ */
203
+ function encodeModifiers(ev: IKeyboardEvent): number {
204
+ let mods = 0;
205
+ if (ev.shiftKey) mods |= KittyKeyboardModifiers.SHIFT;
206
+ if (ev.altKey) mods |= KittyKeyboardModifiers.ALT;
207
+ if (ev.ctrlKey) mods |= KittyKeyboardModifiers.CTRL;
208
+ if (ev.metaKey) mods |= KittyKeyboardModifiers.SUPER;
209
+ return mods > 0 ? mods + 1 : 0;
210
+ }
211
+
212
+ /**
213
+ * Get the unicode key code for a keyboard event.
214
+ * Returns the lowercase codepoint for letters.
215
+ * For shifted keys, uses the code property to get the base key.
216
+ */
217
+ function getKeyCode(ev: IKeyboardEvent): number | undefined {
218
+ // Check for numpad first
219
+ const numpadCode = getNumpadKeyCode(ev);
220
+ if (numpadCode !== undefined) {
221
+ return numpadCode;
222
+ }
223
+
224
+ // Check for modifier keys
225
+ const modifierCode = getModifierKeyCode(ev);
226
+ if (modifierCode !== undefined) {
227
+ return modifierCode;
228
+ }
229
+
230
+ // Check functional keys
231
+ const funcCode = FUNCTIONAL_KEY_CODES[ev.key];
232
+ if (funcCode !== undefined) {
233
+ return funcCode;
234
+ }
235
+
236
+ // For shifted keys, use code property to get base key
237
+ if (ev.shiftKey && ev.code) {
238
+ // Handle Digit0-Digit9
239
+ if (ev.code.startsWith('Digit') && ev.code.length === 6) {
240
+ const digit = ev.code.charAt(5);
241
+ if (digit >= '0' && digit <= '9') {
242
+ return digit.charCodeAt(0);
243
+ }
244
+ }
245
+ // Handle KeyA-KeyZ
246
+ if (ev.code.startsWith('Key') && ev.code.length === 4) {
247
+ const letter = ev.code.charAt(3).toLowerCase();
248
+ return letter.charCodeAt(0);
249
+ }
250
+ }
251
+
252
+ // For regular keys, use the key character's codepoint
253
+ // Always use lowercase for letters (per spec)
254
+ if (ev.key.length === 1) {
255
+ const code = ev.key.codePointAt(0)!;
256
+ // Convert uppercase A-Z to lowercase a-z
257
+ if (code >= 65 && code <= 90) {
258
+ return code + 32;
259
+ }
260
+ return code;
261
+ }
262
+
263
+ return undefined;
264
+ }
265
+
266
+ /**
267
+ * Check if a key is a modifier key.
268
+ */
269
+ function isModifierKey(ev: IKeyboardEvent): boolean {
270
+ return ev.key === 'Shift' || ev.key === 'Control' || ev.key === 'Alt' || ev.key === 'Meta';
271
+ }
272
+
273
+ /**
274
+ * Evaluate a keyboard event using Kitty keyboard protocol.
275
+ *
276
+ * @param ev The keyboard event.
277
+ * @param flags The active Kitty keyboard enhancement flags.
278
+ * @param eventType The event type (press, repeat, release).
279
+ * @returns The keyboard result with the encoded key sequence.
280
+ */
281
+ export function evaluateKeyboardEventKitty(
282
+ ev: IKeyboardEvent,
283
+ flags: number,
284
+ eventType: KittyKeyboardEventType = KittyKeyboardEventType.PRESS
285
+ ): IKeyboardResult {
286
+ const result: IKeyboardResult = {
287
+ type: KeyboardResultType.SEND_KEY,
288
+ cancel: false,
289
+ key: undefined
290
+ };
291
+
292
+ const modifiers = encodeModifiers(ev);
293
+ const isMod = isModifierKey(ev);
294
+ const reportEventTypes = !!(flags & KittyKeyboardFlags.REPORT_EVENT_TYPES);
295
+
296
+ // Don't report release events unless flag is set
297
+ if (!reportEventTypes && eventType === KittyKeyboardEventType.RELEASE) {
298
+ return result;
299
+ }
300
+
301
+ // Modifier-only keys require REPORT_ALL_KEYS_AS_ESCAPE_CODES or REPORT_EVENT_TYPES
302
+ if (isMod && !(flags & KittyKeyboardFlags.REPORT_ALL_KEYS_AS_ESCAPE_CODES) && !reportEventTypes) {
303
+ return result;
304
+ }
305
+
306
+ // Check for CSI letter keys (arrows, Home, End)
307
+ const csiLetter = CSI_LETTER_KEYS[ev.key];
308
+ if (csiLetter) {
309
+ result.key = buildCsiLetterSequence(csiLetter, modifiers, eventType, reportEventTypes);
310
+ result.cancel = true;
311
+ return result;
312
+ }
313
+
314
+ // Check for SS3/CSI function keys (F1-F4)
315
+ const ss3Letter = SS3_FUNCTION_KEYS[ev.key];
316
+ if (ss3Letter) {
317
+ result.key = buildSs3Sequence(ss3Letter, modifiers, eventType, reportEventTypes);
318
+ result.cancel = true;
319
+ return result;
320
+ }
321
+
322
+ // Check for CSI ~ keys (Insert, Delete, PageUp/Down, F5-F12)
323
+ const tildeCode = CSI_TILDE_KEYS[ev.key];
324
+ if (tildeCode !== undefined) {
325
+ result.key = buildCsiTildeSequence(tildeCode, modifiers, eventType, reportEventTypes);
326
+ result.cancel = true;
327
+ return result;
328
+ }
329
+
330
+ // Get the key code for CSI u encoding
331
+ const keyCode = getKeyCode(ev);
332
+ if (keyCode === undefined) {
333
+ return result;
334
+ }
335
+
336
+ const isFunc = FUNCTIONAL_KEY_CODES[ev.key] !== undefined || getNumpadKeyCode(ev) !== undefined;
337
+
338
+ // Determine if we should use CSI u encoding
339
+ let useCsiU = false;
340
+
341
+ if (flags & KittyKeyboardFlags.REPORT_ALL_KEYS_AS_ESCAPE_CODES) {
342
+ useCsiU = true;
343
+ } else if (reportEventTypes) {
344
+ useCsiU = true;
345
+ } else if (flags & KittyKeyboardFlags.DISAMBIGUATE_ESCAPE_CODES) {
346
+ // Modifier-only keys already handled above
347
+ // Use CSI u for keys that would be ambiguous in legacy encoding
348
+ if (keyCode === 27 || keyCode === 127 || keyCode === 13 || keyCode === 9 || keyCode === 32) {
349
+ // Escape, Backspace, Enter, Tab, Space
350
+ useCsiU = true;
351
+ } else if (isFunc) {
352
+ useCsiU = true;
353
+ } else if (modifiers > 0) {
354
+ // Any modified key
355
+ useCsiU = true;
356
+ }
357
+ }
358
+
359
+ if (useCsiU) {
360
+ result.key = buildCsiUSequence(ev, keyCode, modifiers, eventType, flags, isFunc, isMod);
361
+ result.cancel = true;
362
+ } else {
363
+ // Legacy-compatible encoding for text keys without modifiers
364
+ if (ev.key.length === 1 && !ev.ctrlKey && !ev.altKey && !ev.metaKey) {
365
+ result.key = ev.key;
366
+ }
367
+ }
368
+
369
+ return result;
370
+ }
371
+
372
+ /**
373
+ * Build CSI letter sequence for arrow keys, Home, End.
374
+ * Format: CSI [1;mod] letter
375
+ */
376
+ function buildCsiLetterSequence(
377
+ letter: string,
378
+ modifiers: number,
379
+ eventType: KittyKeyboardEventType,
380
+ reportEventTypes: boolean
381
+ ): string {
382
+ const needsEventType = reportEventTypes && eventType !== KittyKeyboardEventType.PRESS;
383
+
384
+ if (modifiers > 0 || needsEventType) {
385
+ let seq = C0.ESC + '[1;' + (modifiers > 0 ? modifiers : '1');
386
+ if (needsEventType) {
387
+ seq += ':' + eventType;
388
+ }
389
+ seq += letter;
390
+ return seq;
391
+ }
392
+ return C0.ESC + '[' + letter;
393
+ }
394
+
395
+ /**
396
+ * Build SS3 sequence for F1-F4.
397
+ * Without modifiers: SS3 letter
398
+ * With modifiers: CSI 1;mod letter
399
+ */
400
+ function buildSs3Sequence(
401
+ letter: string,
402
+ modifiers: number,
403
+ eventType: KittyKeyboardEventType,
404
+ reportEventTypes: boolean
405
+ ): string {
406
+ const needsEventType = reportEventTypes && eventType !== KittyKeyboardEventType.PRESS;
407
+
408
+ if (modifiers > 0 || needsEventType) {
409
+ let seq = C0.ESC + '[1;' + (modifiers > 0 ? modifiers : '1');
410
+ if (needsEventType) {
411
+ seq += ':' + eventType;
412
+ }
413
+ seq += letter;
414
+ return seq;
415
+ }
416
+ return C0.ESC + 'O' + letter;
417
+ }
418
+
419
+ /**
420
+ * Build CSI ~ sequence for Insert, Delete, PageUp/Down, F5-F12.
421
+ * Format: CSI number [;mod[:event]] ~
422
+ */
423
+ function buildCsiTildeSequence(
424
+ number: number,
425
+ modifiers: number,
426
+ eventType: KittyKeyboardEventType,
427
+ reportEventTypes: boolean
428
+ ): string {
429
+ const needsEventType = reportEventTypes && eventType !== KittyKeyboardEventType.PRESS;
430
+
431
+ let seq = C0.ESC + '[' + number;
432
+ if (modifiers > 0 || needsEventType) {
433
+ seq += ';' + (modifiers > 0 ? modifiers : '1');
434
+ if (needsEventType) {
435
+ seq += ':' + eventType;
436
+ }
437
+ }
438
+ seq += '~';
439
+ return seq;
440
+ }
441
+
442
+ /**
443
+ * Build CSI u sequence.
444
+ * Format: CSI keycode[:shifted[:base]] [;mod[:event][;text]] u
445
+ */
446
+ function buildCsiUSequence(
447
+ ev: IKeyboardEvent,
448
+ keyCode: number,
449
+ modifiers: number,
450
+ eventType: KittyKeyboardEventType,
451
+ flags: number,
452
+ isFunc: boolean,
453
+ isMod: boolean
454
+ ): string {
455
+ const reportEventTypes = !!(flags & KittyKeyboardFlags.REPORT_EVENT_TYPES);
456
+ const reportAlternateKeys = !!(flags & KittyKeyboardFlags.REPORT_ALTERNATE_KEYS);
457
+
458
+ let seq = C0.ESC + '[' + keyCode;
459
+
460
+ // Add shifted key alternate if REPORT_ALTERNATE_KEYS is set and shift is pressed
461
+ // Only for text-producing keys (not functional or modifier keys)
462
+ let shiftedKey: number | undefined;
463
+ if (reportAlternateKeys && ev.shiftKey && ev.key.length === 1 && !isFunc && !isMod) {
464
+ shiftedKey = ev.key.codePointAt(0);
465
+ seq += ':' + shiftedKey;
466
+ }
467
+
468
+ // Check if we need associated text (press and repeat events, not release)
469
+ // Only for text-producing keys (not functional or modifier keys)
470
+ // Also don't include text when ctrl is pressed (produces control code)
471
+ const reportAssociatedText = !!(flags & KittyKeyboardFlags.REPORT_ASSOCIATED_TEXT) &&
472
+ eventType !== KittyKeyboardEventType.RELEASE &&
473
+ ev.key.length === 1 &&
474
+ !isFunc &&
475
+ !isMod &&
476
+ !ev.ctrlKey;
477
+ const textCode = reportAssociatedText ? ev.key.codePointAt(0) : undefined;
478
+
479
+ // Determine if we need event type suffix
480
+ // For repeat: only include :2 when there's no text (text implies it's still useful input)
481
+ // For release: always include :3
482
+ const needsEventType = reportEventTypes &&
483
+ eventType !== KittyKeyboardEventType.PRESS &&
484
+ (eventType === KittyKeyboardEventType.RELEASE || textCode === undefined);
485
+
486
+ if (modifiers > 0 || needsEventType || textCode !== undefined) {
487
+ seq += ';';
488
+ if (modifiers > 0) {
489
+ seq += modifiers;
490
+ } else if (needsEventType) {
491
+ seq += '1';
492
+ }
493
+ if (needsEventType) {
494
+ seq += ':' + eventType;
495
+ }
496
+ }
497
+
498
+ // Add associated text if requested
499
+ if (textCode !== undefined) {
500
+ seq += ';' + textCode;
501
+ }
502
+
503
+ seq += 'u';
504
+ return seq;
505
+ }
506
+
507
+ /**
508
+ * Check if a keyboard event should be handled by Kitty protocol.
509
+ * Returns true if Kitty flags are active and the event should use Kitty encoding.
510
+ */
511
+ export function shouldUseKittyProtocol(flags: number): boolean {
512
+ return flags > 0;
513
+ }
@@ -5,7 +5,7 @@
5
5
 
6
6
  import { clone } from 'common/Clone';
7
7
  import { Disposable } from 'vs/base/common/lifecycle';
8
- import { IDecPrivateModes, IModes } from 'common/Types';
8
+ import { IDecPrivateModes, IKittyKeyboardState, IModes } from 'common/Types';
9
9
  import { IBufferService, ICoreService, ILogService, IOptionsService } from 'common/services/Services';
10
10
  import { Emitter } from 'vs/base/common/event';
11
11
 
@@ -26,6 +26,14 @@ const DEFAULT_DEC_PRIVATE_MODES: IDecPrivateModes = Object.freeze({
26
26
  wraparound: true // defaults: xterm - true, vt100 - false
27
27
  });
28
28
 
29
+ const DEFAULT_KITTY_KEYBOARD_STATE = (): IKittyKeyboardState => ({
30
+ flags: 0,
31
+ mainFlags: 0,
32
+ altFlags: 0,
33
+ mainStack: [],
34
+ altStack: []
35
+ });
36
+
29
37
  export class CoreService extends Disposable implements ICoreService {
30
38
  public serviceBrand: any;
31
39
 
@@ -33,6 +41,7 @@ export class CoreService extends Disposable implements ICoreService {
33
41
  public isCursorHidden: boolean = false;
34
42
  public modes: IModes;
35
43
  public decPrivateModes: IDecPrivateModes;
44
+ public kittyKeyboard: IKittyKeyboardState;
36
45
 
37
46
  private readonly _onData = this._register(new Emitter<string>());
38
47
  public readonly onData = this._onData.event;
@@ -51,11 +60,13 @@ export class CoreService extends Disposable implements ICoreService {
51
60
  super();
52
61
  this.modes = clone(DEFAULT_MODES);
53
62
  this.decPrivateModes = clone(DEFAULT_DEC_PRIVATE_MODES);
63
+ this.kittyKeyboard = DEFAULT_KITTY_KEYBOARD_STATE();
54
64
  }
55
65
 
56
66
  public reset(): void {
57
67
  this.modes = clone(DEFAULT_MODES);
58
68
  this.decPrivateModes = clone(DEFAULT_DEC_PRIVATE_MODES);
69
+ this.kittyKeyboard = DEFAULT_KITTY_KEYBOARD_STATE();
59
70
  }
60
71
 
61
72
  public triggerDataEvent(data: string, wasUserInput: boolean = false): void {
@@ -54,7 +54,8 @@ export const DEFAULT_OPTIONS: Readonly<Required<ITerminalOptions>> = {
54
54
  termName: 'xterm',
55
55
  cancelEvents: false,
56
56
  overviewRuler: {},
57
- quirks: {}
57
+ quirks: {},
58
+ vtExtensions: {}
58
59
  };
59
60
 
60
61
  const FONT_WEIGHT_OPTIONS: Extract<FontWeight, string>[] = ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'];
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  import { IDecoration, IDecorationOptions, ILinkHandler, ILogger, IWindowsPty, type IOverviewRulerOptions } from '@xterm/xterm';
7
- import { CoreMouseEncoding, CoreMouseEventType, CursorInactiveStyle, CursorStyle, IAttributeData, ICharset, IColor, ICoreMouseEvent, ICoreMouseProtocol, IDecPrivateModes, IDisposable, IModes, IOscLinkData, IWindowOptions } from 'common/Types';
7
+ import { CoreMouseEncoding, CoreMouseEventType, CursorInactiveStyle, CursorStyle, IAttributeData, ICharset, IColor, ICoreMouseEvent, ICoreMouseProtocol, IDecPrivateModes, IDisposable, IKittyKeyboardState, IModes, IOscLinkData, IWindowOptions } from 'common/Types';
8
8
  import { IBuffer, IBufferSet } from 'common/buffer/Types';
9
9
  import { createDecorator } from 'common/services/ServiceRegistry';
10
10
  import type { Emitter, Event } from 'vs/base/common/event';
@@ -85,6 +85,7 @@ export interface ICoreService {
85
85
 
86
86
  readonly modes: IModes;
87
87
  readonly decPrivateModes: IDecPrivateModes;
88
+ readonly kittyKeyboard: IKittyKeyboardState;
88
89
 
89
90
  readonly onData: Event<string>;
90
91
  readonly onUserInput: Event<void>;
@@ -265,6 +266,7 @@ export interface ITerminalOptions {
265
266
  overviewRuler?: IOverviewRulerOptions;
266
267
  quirks?: ITerminalQuirks;
267
268
  scrollOnEraseInDisplay?: boolean;
269
+ vtExtensions?: IVtExtensions;
268
270
 
269
271
  [key: string]: any;
270
272
  cancelEvents: boolean;
@@ -306,6 +308,11 @@ export interface ITerminalQuirks {
306
308
  allowSetCursorBlink?: boolean;
307
309
  }
308
310
 
311
+ export interface IVtExtensions {
312
+ kittyKeyboard?: boolean;
313
+ kittySgrBoldFaintControl?: boolean;
314
+ }
315
+
309
316
  export const IOscLinkService = createDecorator<IOscLinkService>('OscLinkService');
310
317
  export interface IOscLinkService {
311
318
  serviceBrand: undefined;
@@ -199,6 +199,12 @@ declare module '@xterm/xterm' {
199
199
  */
200
200
  minimumContrastRatio?: number;
201
201
 
202
+ /**
203
+ * Controls the visibility and style of the overview ruler which visualizes
204
+ * decorations underneath the scroll bar.
205
+ */
206
+ overviewRuler?: IOverviewRulerOptions;
207
+
202
208
  /**
203
209
  * Control various quirks features that are either non-standard or standard
204
210
  * in but generally rejected in modern terminals.
@@ -284,6 +290,11 @@ declare module '@xterm/xterm' {
284
290
  */
285
291
  theme?: ITheme;
286
292
 
293
+ /**
294
+ * Enable various VT extensions. All extensions are disabled by default.
295
+ */
296
+ vtExtensions?: IVtExtensions;
297
+
287
298
  /**
288
299
  * Compatibility information when the pty is known to be hosted on Windows.
289
300
  * Setting this will turn on certain heuristics/workarounds depending on the
@@ -313,12 +324,6 @@ declare module '@xterm/xterm' {
313
324
  * All features are disabled by default for security reasons.
314
325
  */
315
326
  windowOptions?: IWindowOptions;
316
-
317
- /**
318
- * Controls the visibility and style of the overview ruler which visualizes
319
- * decorations underneath the scroll bar.
320
- */
321
- overviewRuler?: IOverviewRulerOptions;
322
327
  }
323
328
 
324
329
  /**
@@ -430,6 +435,30 @@ declare module '@xterm/xterm' {
430
435
  allowSetCursorBlink?: boolean;
431
436
  }
432
437
 
438
+ /**
439
+ * Enable certain optional VT extensions.
440
+ */
441
+ export interface IVtExtensions {
442
+ /**
443
+ * Whether the [kitty keyboard protocol][0] (`CSI =|?|>|< u`) is enabled.
444
+ * When enabled, the terminal will respond to keyboard protocol queries and
445
+ * allow programs to enable enhanced keyboard reporting. The default is
446
+ * false.
447
+ *
448
+ * [0]: https://sw.kovidgoyal.net/kitty/keyboard-protocol/
449
+ */
450
+ kittyKeyboard?: boolean;
451
+
452
+ /**
453
+ * Whether [SGR 221 (not bold) and SGR 222 (not faint) are enabled][0].
454
+ * These are kitty extensions that allow resetting bold and faint
455
+ * independently. The default is true.
456
+ *
457
+ * [0]: https://sw.kovidgoyal.net/kitty/misc-protocol/
458
+ */
459
+ kittySgrBoldFaintControl?: boolean;
460
+ }
461
+
433
462
  /**
434
463
  * Pty information for Windows.
435
464
  */