macLinuxKeyboardMapper.ts ×43

Frontier kind: Code frontier

unlabeled · c_a6f64e241f95

85 tests · 8913 LOC · 41 files · introduces 0 tests · 407 LOC · 1 file

Introduces — evidence that enters the hierarchy at this concept

Code
43 ranges407 lines · 1 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
1153 ranges8913 lines · 41 files · Browse complete extent
All tests (intent)
85 testsBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

No tests are introduced at this concept. Its intent tests are introduced by other concepts.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

1 file ranked by introduced lines: 407 introduced LOC across 43 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/workbench/services/keybinding/common/macLinuxKeyboardMapper.ts 407 introduced LOC · 43 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- macLinuxKeyboardMapper.ts
2 > * Copyright (c) Microsoft Corporation. All rights reserved.
3 > * Licensed under the MIT License. See License.txt in the project root for license information.
4 > *--------------------------------------------------------------------------------------------*/
5 >
6 > import { CharCode } from '../../../../base/common/charCode.js';
7 > import { KeyCode, KeyCodeUtils, IMMUTABLE_CODE_TO_KEY_CODE, IMMUTABLE_KEY_CODE_TO_CODE, ScanCode, ScanCodeUtils, isModifierKey } from '../../../../base/common/keyCodes.js';
8 > import { ResolvedKeybinding, KeyCodeChord, SingleModifierChord, ScanCodeChord, Keybinding, Chord } from '../../../../base/common/keybindings.js';
9 > import { OperatingSystem } from '../../../../base/common/platform.js';
10 > import { IKeyboardEvent } from '../../../../platform/keybinding/common/keybinding.js';
11 > import { IKeyboardMapper } from '../../../../platform/keyboardLayout/common/keyboardMapper.js';
12 > import { BaseResolvedKeybinding } from '../../../../platform/keybinding/common/baseResolvedKeybinding.js';
13 > import { IMacLinuxKeyboardMapping, IMacLinuxKeyMapping } from '../../../../platform/keyboardLayout/common/keyboardLayout.js';
14 >
15 > /**
16 > * A map from character to key codes.
17 > * e.g. Contains entries such as:
18 > * - '/' => { keyCode: KeyCode.US_SLASH, shiftKey: false }
19 > * - '?' => { keyCode: KeyCode.US_SLASH, shiftKey: true }
20 > */
21 > const CHAR_CODE_TO_KEY_CODE: ({ keyCode: KeyCode; shiftKey: boolean } | null)[] = [];
22 >
23 > export class NativeResolvedKeybinding extends BaseResolvedKeybinding<ScanCodeChord> {
24 >
25 > private readonly _mapper: MacLinuxKeyboardMapper;
26 >
27 > constructor(mapper: MacLinuxKeyboardMapper, os: OperatingSystem, chords: ScanCodeChord[]) {
28 super(os, chords);
29 this._mapper = mapper;
30 }
32 > protected _getLabel(chord: ScanCodeChord): string | null {
33 return this._mapper.getUILabelForScanCodeChord(chord);
34 }
36 > protected _getAriaLabel(chord: ScanCodeChord): string | null {
37 return this._mapper.getAriaLabelForScanCodeChord(chord);
38 }
40 > protected _getElectronAccelerator(chord: ScanCodeChord): string | null {
41 return this._mapper.getElectronAcceleratorLabelForScanCodeChord(chord);
42 }
44 > protected _getUserSettingsLabel(chord: ScanCodeChord): string | null {
45 return this._mapper.getUserSettingsLabelForScanCodeChord(chord);
46 }
48 > protected _isWYSIWYG(binding: ScanCodeChord | null): boolean {
49 if (!binding) {
50 return true;
64 return (a.toLowerCase() === b.toLowerCase());
65 }
67 > protected _getChordDispatch(chord: ScanCodeChord): string | null {
68 return this._mapper.getDispatchStrForScanCodeChord(chord);
69 }
71 > protected _getSingleModifierChordDispatch(chord: ScanCodeChord): SingleModifierChord | null {
72 if ((chord.scanCode === ScanCode.ControlLeft || chord.scanCode === ScanCode.ControlRight) && !chord.shiftKey && !chord.altKey && !chord.metaKey) {
73 return 'ctrl';
84 return null;
85 }
87 >
88 > interface IScanCodeMapping {
89 > scanCode: ScanCode;
90 > value: number;
91 > withShift: number;
92 > withAltGr: number;
93 > withShiftAltGr: number;
94 > }
95 >
96 > class ScanCodeCombo {
97 > public readonly ctrlKey: boolean;
98 > public readonly shiftKey: boolean;
99 > public readonly altKey: boolean;
100 > public readonly scanCode: ScanCode;
101 >
102 > constructor(ctrlKey: boolean, shiftKey: boolean, altKey: boolean, scanCode: ScanCode) {
103 > this.ctrlKey = ctrlKey;
104 > this.shiftKey = shiftKey;
105 > this.altKey = altKey;
106 > this.scanCode = scanCode;
107 > }
108 >
109 > public toString(): string {
110 return `${this.ctrlKey ? 'Ctrl+' : ''}${this.shiftKey ? 'Shift+' : ''}${this.altKey ? 'Alt+' : ''}${ScanCodeUtils.toString(this.scanCode)}`;
111 }
113 > public equals(other: ScanCodeCombo): boolean {
114 return (
115 this.ctrlKey === other.ctrlKey
119 );
120 }
122 > private getProducedCharCode(mapping: IMacLinuxKeyMapping): string {
123 if (!mapping) {
124 return '';
135 return mapping.value;
136 }
138 > public getProducedChar(mapping: IMacLinuxKeyMapping): string {
139 const charCode = MacLinuxKeyboardMapper.getCharCode(this.getProducedCharCode(mapping));
140 if (charCode === 0) {
147 return ' ' + String.fromCharCode(charCode) + ' ';
148 }
150 >
151 > class KeyCodeCombo {
152 > public readonly ctrlKey: boolean;
153 > public readonly shiftKey: boolean;
154 > public readonly altKey: boolean;
155 > public readonly keyCode: KeyCode;
156 >
157 > constructor(ctrlKey: boolean, shiftKey: boolean, altKey: boolean, keyCode: KeyCode) {
158 > this.ctrlKey = ctrlKey;
159 > this.shiftKey = shiftKey;
160 > this.altKey = altKey;
161 > this.keyCode = keyCode;
162 > }
163 >
164 > public toString(): string {
165 return `${this.ctrlKey ? 'Ctrl+' : ''}${this.shiftKey ? 'Shift+' : ''}${this.altKey ? 'Alt+' : ''}${KeyCodeUtils.toString(this.keyCode)}`;
166 }
168 >
169 > class ScanCodeKeyCodeMapper {
170 >
171 > /**
172 > * ScanCode combination => KeyCode combination.
173 > * Only covers relevant modifiers ctrl, shift, alt (since meta does not influence the mappings).
174 > */
175 > private readonly _scanCodeToKeyCode: number[][] = [];
176 > /**
177 > * inverse of `_scanCodeToKeyCode`.
178 > * KeyCode combination => ScanCode combination.
179 > * Only covers relevant modifiers ctrl, shift, alt (since meta does not influence the mappings).
180 > */
181 > private readonly _keyCodeToScanCode: number[][] = [];
182 >
183 > constructor() {
184 > this._scanCodeToKeyCode = [];
185 > this._keyCodeToScanCode = [];
186 > }
187 >
188 > public registrationComplete(): void {
189 > // IntlHash and IntlBackslash are rare keys, so ensure they don't end up being the preferred...
190 > this._moveToEnd(ScanCode.IntlHash);
191 > this._moveToEnd(ScanCode.IntlBackslash);
192 > }
193 >
194 > private _moveToEnd(scanCode: ScanCode): void {
195 > for (let mod = 0; mod < 8; mod++) {
196 > const encodedKeyCodeCombos = this._scanCodeToKeyCode[(scanCode << 3) + mod];
197 > if (!encodedKeyCodeCombos) {
198 > continue;
199 > }
200 for (let i = 0, len = encodedKeyCodeCombos.length; i < len; i++) {
201 const encodedScanCodeCombos = this._keyCodeToScanCode[encodedKeyCodeCombos[i]];
216 }
217 }
219 >
220 > public registerIfUnknown(scanCodeCombo: ScanCodeCombo, keyCodeCombo: KeyCodeCombo): void {
221 > if (keyCodeCombo.keyCode === KeyCode.Unknown) {
222 > return;
223 > }
224 > const scanCodeComboEncoded = this._encodeScanCodeCombo(scanCodeCombo);
225 > const keyCodeComboEncoded = this._encodeKeyCodeCombo(keyCodeCombo);
226 >
227 > const keyCodeIsDigit = (keyCodeCombo.keyCode >= KeyCode.Digit0 && keyCodeCombo.keyCode <= KeyCode.Digit9);
228 > const keyCodeIsLetter = (keyCodeCombo.keyCode >= KeyCode.KeyA && keyCodeCombo.keyCode <= KeyCode.KeyZ);
229 >
230 > const existingKeyCodeCombos = this._scanCodeToKeyCode[scanCodeComboEncoded];
231 >
232 > // Allow a scan code to map to multiple key codes if it is a digit or a letter key code
233 > if (keyCodeIsDigit || keyCodeIsLetter) {
234 > // Only check that we don't insert the same entry twice
235 > if (existingKeyCodeCombos) {
236 for (let i = 0, len = existingKeyCodeCombos.length; i < len; i++) {
237 if (existingKeyCodeCombos[i] === keyCodeComboEncoded) {
241 }
242 }
243 > } else { macLinuxKeyboardMapper.ts
244 > // Don't allow multiples
245 > if (existingKeyCodeCombos && existingKeyCodeCombos.length !== 0) {
246 return;
247 }
249 >
250 > this._scanCodeToKeyCode[scanCodeComboEncoded] = this._scanCodeToKeyCode[scanCodeComboEncoded] || [];
251 > this._scanCodeToKeyCode[scanCodeComboEncoded].unshift(keyCodeComboEncoded);
252 >
253 > this._keyCodeToScanCode[keyCodeComboEncoded] = this._keyCodeToScanCode[keyCodeComboEncoded] || [];
254 > this._keyCodeToScanCode[keyCodeComboEncoded].unshift(scanCodeComboEncoded);
255 > }
256 >
257 > public lookupKeyCodeCombo(keyCodeCombo: KeyCodeCombo): ScanCodeCombo[] {
258 const keyCodeComboEncoded = this._encodeKeyCodeCombo(keyCodeCombo);
259 const scanCodeCombosEncoded = this._keyCodeToScanCode[keyCodeComboEncoded];
275 return result;
276 }
278 > public lookupScanCodeCombo(scanCodeCombo: ScanCodeCombo): KeyCodeCombo[] {
279 const scanCodeComboEncoded = this._encodeScanCodeCombo(scanCodeCombo);
280 const keyCodeCombosEncoded = this._scanCodeToKeyCode[scanCodeComboEncoded];
296 return result;
297 }
299 > public guessStableKeyCode(scanCode: ScanCode): KeyCode {
300 if (scanCode >= ScanCode.Digit1 && scanCode <= ScanCode.Digit0) {
301 // digits are ok
330 return KeyCode.DependsOnKbLayout;
331 }
333 > private _encodeScanCodeCombo(scanCodeCombo: ScanCodeCombo): number {
334 > return this._encode(scanCodeCombo.ctrlKey, scanCodeCombo.shiftKey, scanCodeCombo.altKey, scanCodeCombo.scanCode);
335 > }
336 >
337 > private _encodeKeyCodeCombo(keyCodeCombo: KeyCodeCombo): number {
338 > return this._encode(keyCodeCombo.ctrlKey, keyCodeCombo.shiftKey, keyCodeCombo.altKey, keyCodeCombo.keyCode);
339 > }
340 >
341 > private _encode(ctrlKey: boolean, shiftKey: boolean, altKey: boolean, principal: number): number {
342 > return (
343 > ((ctrlKey ? 1 : 0) << 0)
344 > | ((shiftKey ? 1 : 0) << 1)
345 > | ((altKey ? 1 : 0) << 2)
346 > | principal << 3
347 > ) >>> 0;
348 > }
349 > }
350 >
351 > export class MacLinuxKeyboardMapper implements IKeyboardMapper {
352 >
353 > /**
354 > * used only for debug purposes.
355 > */
356 > private readonly _codeInfo: IMacLinuxKeyMapping[];
357 > /**
358 > * Maps ScanCode combos <-> KeyCode combos.
359 > */
360 > private readonly _scanCodeKeyCodeMapper: ScanCodeKeyCodeMapper;
361 > /**
362 > * UI label for a ScanCode.
363 > */
364 > private readonly _scanCodeToLabel: Array<string | null> = [];
365 > /**
366 > * Dispatching string for a ScanCode.
367 > */
368 > private readonly _scanCodeToDispatch: Array<string | null> = [];
369 >
370 > constructor(
371 > private readonly _isUSStandard: boolean,
372 > rawMappings: IMacLinuxKeyboardMapping,
373 > private readonly _mapAltGrToCtrlAlt: boolean,
374 > private readonly _OS: OperatingSystem,
375 > ) {
376 > this._codeInfo = [];
377 > this._scanCodeKeyCodeMapper = new ScanCodeKeyCodeMapper();
378 > this._scanCodeToLabel = [];
379 > this._scanCodeToDispatch = [];
380 >
381 > const _registerIfUnknown = (
382 > hwCtrlKey: 0 | 1, hwShiftKey: 0 | 1, hwAltKey: 0 | 1, scanCode: ScanCode,
383 > kbCtrlKey: 0 | 1, kbShiftKey: 0 | 1, kbAltKey: 0 | 1, keyCode: KeyCode,
384 > ): void => {
385 > this._scanCodeKeyCodeMapper.registerIfUnknown(
386 > new ScanCodeCombo(hwCtrlKey ? true : false, hwShiftKey ? true : false, hwAltKey ? true : false, scanCode),
387 > new KeyCodeCombo(kbCtrlKey ? true : false, kbShiftKey ? true : false, kbAltKey ? true : false, keyCode)
388 > );
389 > };
390 >
391 > const _registerAllCombos = (_ctrlKey: 0 | 1, _shiftKey: 0 | 1, _altKey: 0 | 1, scanCode: ScanCode, keyCode: KeyCode): void => {
392 > for (let ctrlKey = _ctrlKey; ctrlKey <= 1; ctrlKey++) {
393 > for (let shiftKey = _shiftKey; shiftKey <= 1; shiftKey++) {
394 > for (let altKey = _altKey; altKey <= 1; altKey++) {
395 > _registerIfUnknown(
396 > ctrlKey, shiftKey, altKey, scanCode,
397 > ctrlKey, shiftKey, altKey, keyCode
398 > );
399 > }
400 > }
401 > }
402 > };
403 >
404 > // Initialize `_scanCodeToLabel`
405 > for (let scanCode = ScanCode.None; scanCode < ScanCode.MAX_VALUE; scanCode++) {
406 > this._scanCodeToLabel[scanCode] = null;
407 > }
408 >
409 > // Initialize `_scanCodeToDispatch`
410 > for (let scanCode = ScanCode.None; scanCode < ScanCode.MAX_VALUE; scanCode++) {
411 > this._scanCodeToDispatch[scanCode] = null;
412 > }
413 >
414 > // Handle immutable mappings
415 > for (let scanCode = ScanCode.None; scanCode < ScanCode.MAX_VALUE; scanCode++) {
416 > const keyCode = IMMUTABLE_CODE_TO_KEY_CODE[scanCode];
417 > if (keyCode !== KeyCode.DependsOnKbLayout) {
418 > _registerAllCombos(0, 0, 0, scanCode, keyCode);
419 > this._scanCodeToLabel[scanCode] = KeyCodeUtils.toString(keyCode);
420 >
421 > if (keyCode === KeyCode.Unknown || isModifierKey(keyCode)) {
422 > this._scanCodeToDispatch[scanCode] = null; // cannot dispatch on this ScanCode
423 > } else {
424 > this._scanCodeToDispatch[scanCode] = `[${ScanCodeUtils.toString(scanCode)}]`;
425 > }
426 > }
427 > }
428 >
429 > // Try to identify keyboard layouts where characters A-Z are missing
430 > // and forcibly map them to their corresponding scan codes if that is the case
431 > const missingLatinLettersOverride: { [scanCode: string]: IMacLinuxKeyMapping } = {};
432 >
433 > {
434 > const producesLatinLetter: boolean[] = [];
435 > for (const strScanCode in rawMappings) {
436 if (rawMappings.hasOwnProperty(strScanCode)) {
437 const scanCode = ScanCodeUtils.toEnum(strScanCode);
452 }
453 }
455 > const _registerLetterIfMissing = (charCode: CharCode, scanCode: ScanCode, value: string, withShift: string): void => {
456 > if (!producesLatinLetter[charCode]) {
457 missingLatinLettersOverride[ScanCodeUtils.toString(scanCode)] = {
458 value: value,
462 };
463 }
465 >
466 > // Ensure letters are mapped
467 > _registerLetterIfMissing(CharCode.A, ScanCode.KeyA, 'a', 'A');
468 > _registerLetterIfMissing(CharCode.B, ScanCode.KeyB, 'b', 'B');
469 > _registerLetterIfMissing(CharCode.C, ScanCode.KeyC, 'c', 'C');
470 > _registerLetterIfMissing(CharCode.D, ScanCode.KeyD, 'd', 'D');
471 > _registerLetterIfMissing(CharCode.E, ScanCode.KeyE, 'e', 'E');
472 > _registerLetterIfMissing(CharCode.F, ScanCode.KeyF, 'f', 'F');
473 > _registerLetterIfMissing(CharCode.G, ScanCode.KeyG, 'g', 'G');
474 > _registerLetterIfMissing(CharCode.H, ScanCode.KeyH, 'h', 'H');
475 > _registerLetterIfMissing(CharCode.I, ScanCode.KeyI, 'i', 'I');
476 > _registerLetterIfMissing(CharCode.J, ScanCode.KeyJ, 'j', 'J');
477 > _registerLetterIfMissing(CharCode.K, ScanCode.KeyK, 'k', 'K');
478 > _registerLetterIfMissing(CharCode.L, ScanCode.KeyL, 'l', 'L');
479 > _registerLetterIfMissing(CharCode.M, ScanCode.KeyM, 'm', 'M');
480 > _registerLetterIfMissing(CharCode.N, ScanCode.KeyN, 'n', 'N');
481 > _registerLetterIfMissing(CharCode.O, ScanCode.KeyO, 'o', 'O');
482 > _registerLetterIfMissing(CharCode.P, ScanCode.KeyP, 'p', 'P');
483 > _registerLetterIfMissing(CharCode.Q, ScanCode.KeyQ, 'q', 'Q');
484 > _registerLetterIfMissing(CharCode.R, ScanCode.KeyR, 'r', 'R');
485 > _registerLetterIfMissing(CharCode.S, ScanCode.KeyS, 's', 'S');
486 > _registerLetterIfMissing(CharCode.T, ScanCode.KeyT, 't', 'T');
487 > _registerLetterIfMissing(CharCode.U, ScanCode.KeyU, 'u', 'U');
488 > _registerLetterIfMissing(CharCode.V, ScanCode.KeyV, 'v', 'V');
489 > _registerLetterIfMissing(CharCode.W, ScanCode.KeyW, 'w', 'W');
490 > _registerLetterIfMissing(CharCode.X, ScanCode.KeyX, 'x', 'X');
491 > _registerLetterIfMissing(CharCode.Y, ScanCode.KeyY, 'y', 'Y');
492 > _registerLetterIfMissing(CharCode.Z, ScanCode.KeyZ, 'z', 'Z');
493 > }
494 >
495 > const mappings: IScanCodeMapping[] = [];
496 > let mappingsLen = 0;
497 > for (const strScanCode in rawMappings) {
498 if (rawMappings.hasOwnProperty(strScanCode)) {
499 const scanCode = ScanCodeUtils.toEnum(strScanCode);
536 }
537 }
539 > // Handle all `withShiftAltGr` entries
540 > for (let i = mappings.length - 1; i >= 0; i--) {
541 const mapping = mappings[i];
542 const scanCode = mapping.scanCode;
561 }
562 }
563 > // Handle all `withAltGr` entries macLinuxKeyboardMapper.ts
564 > for (let i = mappings.length - 1; i >= 0; i--) {
565 const mapping = mappings[i];
566 const scanCode = mapping.scanCode;
585 }
586 }
587 > // Handle all `withShift` entries macLinuxKeyboardMapper.ts
588 > for (let i = mappings.length - 1; i >= 0; i--) {
589 const mapping = mappings[i];
590 const scanCode = mapping.scanCode;
619 }
620 }
621 > // Handle all `value` entries macLinuxKeyboardMapper.ts
622 > for (let i = mappings.length - 1; i >= 0; i--) {
623 const mapping = mappings[i];
624 const scanCode = mapping.scanCode;
648 }
649 }
650 > // Handle all left-over available digits macLinuxKeyboardMapper.ts
651 > _registerAllCombos(0, 0, 0, ScanCode.Digit1, KeyCode.Digit1);
652 > _registerAllCombos(0, 0, 0, ScanCode.Digit2, KeyCode.Digit2);
653 > _registerAllCombos(0, 0, 0, ScanCode.Digit3, KeyCode.Digit3);
654 > _registerAllCombos(0, 0, 0, ScanCode.Digit4, KeyCode.Digit4);
655 > _registerAllCombos(0, 0, 0, ScanCode.Digit5, KeyCode.Digit5);
656 > _registerAllCombos(0, 0, 0, ScanCode.Digit6, KeyCode.Digit6);
657 > _registerAllCombos(0, 0, 0, ScanCode.Digit7, KeyCode.Digit7);
658 > _registerAllCombos(0, 0, 0, ScanCode.Digit8, KeyCode.Digit8);
659 > _registerAllCombos(0, 0, 0, ScanCode.Digit9, KeyCode.Digit9);
660 > _registerAllCombos(0, 0, 0, ScanCode.Digit0, KeyCode.Digit0);
661 >
662 > this._scanCodeKeyCodeMapper.registrationComplete();
663 > }
664 >
665 > public dumpDebugInfo(): string {
666 const result: string[] = [];
667
756 return result.join('\n');
757 }
759 > private _leftPad(str: string | null, cnt: number): string {
760 if (str === null) {
761 str = 'null';
766 return str;
767 }
769 > public keyCodeChordToScanCodeChord(chord: KeyCodeChord): ScanCodeChord[] {
770 // Avoid double Enter bindings (both ScanCode.NumpadEnter and ScanCode.Enter point to KeyCode.Enter)
771 if (chord.keyCode === KeyCode.Enter) {
784 return result;
785 }
787 > public getUILabelForScanCodeChord(chord: ScanCodeChord | null): string | null {
788 if (!chord) {
789 return null;
806 return this._scanCodeToLabel[chord.scanCode];
807 }
809 > public getAriaLabelForScanCodeChord(chord: ScanCodeChord | null): string | null {
810 if (!chord) {
811 return null;
816 return this._scanCodeToLabel[chord.scanCode];
817 }
819 > public getDispatchStrForScanCodeChord(chord: ScanCodeChord): string | null {
820 const codeDispatch = this._scanCodeToDispatch[chord.scanCode];
821 if (!codeDispatch) {
840 return result;
841 }
843 > public getUserSettingsLabelForScanCodeChord(chord: ScanCodeChord | null): string | null {
844 if (!chord) {
845 return null;
869 return this._scanCodeToDispatch[chord.scanCode];
870 }
872 > public getElectronAcceleratorLabelForScanCodeChord(chord: ScanCodeChord | null): string | null {
873 if (!chord) {
874 return null;
912 return null;
913 }
915 > private _toResolvedKeybinding(chordParts: ScanCodeChord[][]): NativeResolvedKeybinding[] {
916 if (chordParts.length === 0) {
917 return [];
921 return result;
922 }
924 > private _generateResolvedKeybindings(chordParts: ScanCodeChord[][], currentIndex: number, previousParts: ScanCodeChord[], result: NativeResolvedKeybinding[]) {
925 const chordPart = chordParts[currentIndex];
926 const isFinalIndex = currentIndex === chordParts.length - 1;
934 }
935 }
937 > public resolveKeyboardEvent(keyboardEvent: IKeyboardEvent): NativeResolvedKeybinding {
938 let code = ScanCodeUtils.toEnum(keyboardEvent.code);
939
995 return new NativeResolvedKeybinding(this, this._OS, [chord]);
996 }
998 > private _resolveChord(chord: Chord | null): ScanCodeChord[] {
999 if (!chord) {
1000 return [];
1005 return this.keyCodeChordToScanCodeChord(chord);
1006 }
1008 > public resolveKeybinding(keybinding: Keybinding): ResolvedKeybinding[] {
1009 const chords: ScanCodeChord[][] = keybinding.chords.map(chord => this._resolveChord(chord));
1010 return this._toResolvedKeybinding(chords);
1011 }
1013 > private static _redirectCharCode(charCode: number): number {
1014 switch (charCode) {
1015 // allow-any-unicode-next-line
1026 return charCode;
1027 }
1029 > private static _charCodeToKb(charCode: number): { keyCode: KeyCode; shiftKey: boolean } | null {
1030 charCode = this._redirectCharCode(charCode);
1031 if (charCode < CHAR_CODE_TO_KEY_CODE.length) {
1034 return null;
1035 }
1037 > /**
1038 > * Attempt to map a combining character to a regular one that renders the same way.
1039 > *
1040 > * https://www.compart.com/en/unicode/bidiclass/NSM
1041 > */
1042 > public static getCharCode(char: string): number {
1043 if (char.length === 0) {
1044 return 0;
1060 return charCode;
1061 }
1063 >
1064 > (function () {
1065 > function define(charCode: number, keyCode: KeyCode, shiftKey: boolean): void {
1066 > for (let i = CHAR_CODE_TO_KEY_CODE.length; i < charCode; i++) {
1067 > CHAR_CODE_TO_KEY_CODE[i] = null;
1068 > }
1069 > CHAR_CODE_TO_KEY_CODE[charCode] = { keyCode: keyCode, shiftKey: shiftKey };
1070 > }
1071 >
1072 > for (let chCode = CharCode.A; chCode <= CharCode.Z; chCode++) {
1073 > define(chCode, KeyCode.KeyA + (chCode - CharCode.A), true);
1074 > }
1075 >
1076 > for (let chCode = CharCode.a; chCode <= CharCode.z; chCode++) {
1077 > define(chCode, KeyCode.KeyA + (chCode - CharCode.a), false);
1078 > }
1079 >
1080 > define(CharCode.Semicolon, KeyCode.Semicolon, false);
1081 > define(CharCode.Colon, KeyCode.Semicolon, true);
1082 >
1083 > define(CharCode.Equals, KeyCode.Equal, false);
1084 > define(CharCode.Plus, KeyCode.Equal, true);
1085 >
1086 > define(CharCode.Comma, KeyCode.Comma, false);
1087 > define(CharCode.LessThan, KeyCode.Comma, true);
1088 >
1089 > define(CharCode.Dash, KeyCode.Minus, false);
1090 > define(CharCode.Underline, KeyCode.Minus, true);
1091 >
1092 > define(CharCode.Period, KeyCode.Period, false);
1093 > define(CharCode.GreaterThan, KeyCode.Period, true);
1094 >
1095 > define(CharCode.Slash, KeyCode.Slash, false);
1096 > define(CharCode.QuestionMark, KeyCode.Slash, true);
1097 >
1098 > define(CharCode.BackTick, KeyCode.Backquote, false);
1099 > define(CharCode.Tilde, KeyCode.Backquote, true);
1100 >
1101 > define(CharCode.OpenSquareBracket, KeyCode.BracketLeft, false);
1102 > define(CharCode.OpenCurlyBrace, KeyCode.BracketLeft, true);
1103 >
1104 > define(CharCode.Backslash, KeyCode.Backslash, false);
1105 > define(CharCode.Pipe, KeyCode.Backslash, true);
1106 >
1107 > define(CharCode.CloseSquareBracket, KeyCode.BracketRight, false);
1108 > define(CharCode.CloseCurlyBrace, KeyCode.BracketRight, true);
1109 >
1110 > define(CharCode.SingleQuote, KeyCode.Quote, false);
1111 > define(CharCode.DoubleQuote, KeyCode.Quote, true);
1112 > })();