diff --git a/src/vs/base/common/keyCodes.ts b/src/vs/base/common/keyCodes.ts index 8343795bb9c81..c31aa678c3b92 100644 --- a/src/vs/base/common/keyCodes.ts +++ b/src/vs/base/common/keyCodes.ts @@ -583,12 +583,12 @@ export abstract class ResolvedKeybinding { public abstract isChord(): boolean; /** - * Returns the firstPart, chordPart that should be used for dispatching. + * Returns the parts that should be used for dispatching. */ - public abstract getDispatchParts(): string[]; + public abstract getDispatchParts(): (string | null)[]; /** - * Returns the firstPart, chordPart of the keybinding. - * For simple keybindings, the second element will be null. + * Returns the parts that comprise of the keybinding. + * Simple keybindings return one element. */ public abstract getParts(): ResolvedKeybindingPart[]; } diff --git a/src/vs/base/common/keybindingLabels.ts b/src/vs/base/common/keybindingLabels.ts index 30344e4d7242d..486db9616a9a5 100644 --- a/src/vs/base/common/keybindingLabels.ts +++ b/src/vs/base/common/keybindingLabels.ts @@ -32,11 +32,8 @@ export class ModifierLabelProvider { this.modifierLabels[OperatingSystem.Linux] = linux; } - public toLabel(firstPartMod: Modifiers | null, firstPartKey: string | null, chordPartMod: Modifiers | null, chordPartKey: string | null, OS: OperatingSystem): string | null { - if (firstPartMod === null || firstPartKey === null) { - return null; - } - return _asString(firstPartMod, firstPartKey, chordPartMod, chordPartKey, this.modifierLabels[OS]); + public toLabel(partModifiers: Modifiers[], partKeys: string[], OS: OperatingSystem): string | null { + return _asString(partModifiers, partKeys, this.modifierLabels[OS]); } } @@ -172,13 +169,10 @@ function _simpleAsString(modifiers: Modifiers, key: string, labels: ModifierLabe return result.join(labels.separator); } -function _asString(firstPartMod: Modifiers, firstPartKey: string, chordPartMod: Modifiers | null, chordPartKey: string | null, labels: ModifierLabels): string { - let result = _simpleAsString(firstPartMod, firstPartKey, labels); - - if (chordPartMod !== null && chordPartKey !== null) { - result += ' '; - result += _simpleAsString(chordPartMod, chordPartKey, labels); +function _asString(partModifiers: Modifiers[], partKeys: string[], labels: ModifierLabels): string { + let results: string[] = []; + for (let i = 0; i < partModifiers.length; i++) { + results.push(_simpleAsString(partModifiers[i], partKeys[i], labels)); } - - return result; + return results.join(' '); } \ No newline at end of file diff --git a/src/vs/platform/keybinding/common/usLayoutResolvedKeybinding.ts b/src/vs/platform/keybinding/common/usLayoutResolvedKeybinding.ts index 338f31a295513..cf0a2ba0142f9 100644 --- a/src/vs/platform/keybinding/common/usLayoutResolvedKeybinding.ts +++ b/src/vs/platform/keybinding/common/usLayoutResolvedKeybinding.ts @@ -13,7 +13,7 @@ import { OperatingSystem } from 'vs/base/common/platform'; export class USLayoutResolvedKeybinding extends ResolvedKeybinding { private readonly _os: OperatingSystem; - private readonly _chords: SimpleKeybinding[]; + private readonly _parts: SimpleKeybinding[]; constructor(actual: Keybinding, OS: OperatingSystem) { super(); @@ -21,7 +21,7 @@ export class USLayoutResolvedKeybinding extends ResolvedKeybinding { if (!actual) { throw new Error(`Invalid USLayoutResolvedKeybinding`); } else { - this._chords = actual.parts; + this._parts = actual.parts; } } @@ -52,9 +52,15 @@ export class USLayoutResolvedKeybinding extends ResolvedKeybinding { } public getLabel(): string | null { - let firstPart = this._getUILabelForKeybinding(this._chords[0]); - let chordPart = this._getUILabelForKeybinding(this._chords[1]); - return UILabelProvider.toLabel(this._chords[0], firstPart, this._chords[1], chordPart, this._os); + let partKeys: string[] = []; + for (let part of this._parts) { + let key = this._getUILabelForKeybinding(part); + if (key === null) { + return null; + } + partKeys.push(key); + } + return UILabelProvider.toLabel(this._parts, partKeys, this._os); } private _getAriaLabelForKeybinding(keybinding: SimpleKeybinding | null): string | null { @@ -68,9 +74,15 @@ export class USLayoutResolvedKeybinding extends ResolvedKeybinding { } public getAriaLabel(): string | null { - let firstPart = this._getAriaLabelForKeybinding(this._chords[0]); - let chordPart = this._getAriaLabelForKeybinding(this._chords[1]); - return AriaLabelProvider.toLabel(this._chords[0], firstPart, this._chords[1], chordPart, this._os); + let partKeys: string[] = []; + for (let part of this._parts) { + let key = this._getAriaLabelForKeybinding(part); + if (key === null) { + return null; + } + partKeys.push(key); + } + return AriaLabelProvider.toLabel(this._parts, partKeys, this._os); } private _keyCodeToElectronAccelerator(keyCode: KeyCode): string | null { @@ -104,13 +116,16 @@ export class USLayoutResolvedKeybinding extends ResolvedKeybinding { } public getElectronAccelerator(): string | null { - if (this._chords.length > 1) { + if (this._parts.length > 1) { // Electron cannot handle chords return null; } - let firstPart = this._getElectronAcceleratorLabelForKeybinding(this._chords[0]); - return ElectronAcceleratorLabelProvider.toLabel(this._chords[0], firstPart, null, null, this._os); + let firstPart = this._getElectronAcceleratorLabelForKeybinding(this._parts[0]); + if (firstPart === null) { + return null; + } + return ElectronAcceleratorLabelProvider.toLabel(this._parts, [firstPart], this._os); } private _getUserSettingsLabelForKeybinding(keybinding: SimpleKeybinding | null): string | null { @@ -124,9 +139,15 @@ export class USLayoutResolvedKeybinding extends ResolvedKeybinding { } public getUserSettingsLabel(): string | null { - let firstPart = this._getUserSettingsLabelForKeybinding(this._chords[0]); - let chordPart = this._getUserSettingsLabelForKeybinding(this._chords[1]); - let result = UserSettingsLabelProvider.toLabel(this._chords[0], firstPart, this._chords[1], chordPart, this._os); + let partKeys: string[] = []; + for (let part of this._parts) { + let key = this._getUserSettingsLabelForKeybinding(part); + if (key === null) { + return null; + } + partKeys.push(key); + } + let result = UserSettingsLabelProvider.toLabel(this._parts, partKeys, this._os); return (result ? result.toLowerCase() : result); } @@ -135,11 +156,11 @@ export class USLayoutResolvedKeybinding extends ResolvedKeybinding { } public isChord(): boolean { - return this._chords.length > 1; + return this._parts.length > 1; } public getParts(): ResolvedKeybindingPart[] { - return this._chords.map(this._toResolvedKeybindingPart); + return this._parts.map(this._toResolvedKeybindingPart); } private _toResolvedKeybindingPart(keybinding: SimpleKeybinding): ResolvedKeybindingPart { @@ -153,8 +174,8 @@ export class USLayoutResolvedKeybinding extends ResolvedKeybinding { ); } - public getDispatchParts(): string[] { - return this._chords.map((chord) => USLayoutResolvedKeybinding.getDispatchStr(chord)); + public getDispatchParts(): (string | null)[] { + return this._parts.map((chord) => USLayoutResolvedKeybinding.getDispatchStr(chord)); } public static getDispatchStr(keybinding: SimpleKeybinding): string | null { diff --git a/src/vs/workbench/services/keybinding/common/macLinuxKeyboardMapper.ts b/src/vs/workbench/services/keybinding/common/macLinuxKeyboardMapper.ts index d4efca2649545..99d3c6db6e094 100644 --- a/src/vs/workbench/services/keybinding/common/macLinuxKeyboardMapper.ts +++ b/src/vs/workbench/services/keybinding/common/macLinuxKeyboardMapper.ts @@ -67,44 +67,65 @@ export class NativeResolvedKeybinding extends ResolvedKeybinding { private readonly _mapper: MacLinuxKeyboardMapper; private readonly _OS: OperatingSystem; - private readonly _chords: ScanCodeBinding[]; + private readonly _parts: ScanCodeBinding[]; - constructor(mapper: MacLinuxKeyboardMapper, OS: OperatingSystem, chords: ScanCodeBinding[]) { + constructor(mapper: MacLinuxKeyboardMapper, OS: OperatingSystem, parts: ScanCodeBinding[]) { super(); - if (chords.length === 0) { + if (parts.length === 0) { throw new Error(`Invalid USLayoutResolvedKeybinding`); } this._mapper = mapper; this._OS = OS; - this._chords = chords; + this._parts = parts; } public getLabel(): string | null { - let firstPart = this._mapper.getUILabelForScanCodeBinding(this._chords[0]); - let chordPart = this._mapper.getUILabelForScanCodeBinding(this._chords[1]); - return UILabelProvider.toLabel(this._chords[0], firstPart, this._chords[1], chordPart, this._OS); + let partKeys: string[] = []; + for (let part of this._parts) { + let key = this._mapper.getUILabelForScanCodeBinding(part); + if (key === null) { + return null; + } + partKeys.push(key); + } + return UILabelProvider.toLabel(this._parts, partKeys, this._OS); } public getAriaLabel(): string | null { - let firstPart = this._mapper.getAriaLabelForScanCodeBinding(this._chords[0]); - let chordPart = this._mapper.getAriaLabelForScanCodeBinding(this._chords[1]); - return AriaLabelProvider.toLabel(this._chords[0], firstPart, this._chords[1], chordPart, this._OS); + let partKeys: string[] = []; + for (let part of this._parts) { + let key = this._mapper.getAriaLabelForScanCodeBinding(part); + if (key === null) { + return null; + } + partKeys.push(key); + } + return AriaLabelProvider.toLabel(this._parts, partKeys, this._OS); } public getElectronAccelerator(): string | null { - if (this._chords.length > 1) { + if (this._parts.length > 1) { // Electron cannot handle chords return null; } - let firstPart = this._mapper.getElectronAcceleratorLabelForScanCodeBinding(this._chords[0]); - return ElectronAcceleratorLabelProvider.toLabel(this._chords[0], firstPart, null, null, this._OS); + let firstPart = this._mapper.getElectronAcceleratorLabelForScanCodeBinding(this._parts[0]); + if (firstPart === null) { + return null; + } + return ElectronAcceleratorLabelProvider.toLabel(this._parts, [firstPart], this._OS); } public getUserSettingsLabel(): string | null { - let firstPart = this._mapper.getUserSettingsLabelForScanCodeBinding(this._chords[0]); - let chordPart = this._mapper.getUserSettingsLabelForScanCodeBinding(this._chords[1]); - return UserSettingsLabelProvider.toLabel(this._chords[0], firstPart, this._chords[1], chordPart, this._OS); + let partKeys: string[] = []; + for (let part of this._parts) { + let key = this._mapper.getUserSettingsLabelForScanCodeBinding(part); + if (key === null) { + return null; + } + partKeys.push(key); + } + return UserSettingsLabelProvider.toLabel(this._parts, partKeys, this._OS); } private _isWYSIWYG(binding: ScanCodeBinding | null): boolean { @@ -127,15 +148,15 @@ export class NativeResolvedKeybinding extends ResolvedKeybinding { } public isWYSIWYG(): boolean { - return this._chords.every(this._isWYSIWYG); + return this._parts.every(this._isWYSIWYG); } public isChord(): boolean { - return this._chords.length > 1; + return this._parts.length > 1; } public getParts(): ResolvedKeybindingPart[] { - return this._chords.map(this._toResolvedKeybindingPart); + return this._parts.map(this._toResolvedKeybindingPart); } private _toResolvedKeybindingPart(binding: ScanCodeBinding): ResolvedKeybindingPart { @@ -149,8 +170,8 @@ export class NativeResolvedKeybinding extends ResolvedKeybinding { ); } - public getDispatchParts(): string[] { - return this._chords.map(this._mapper.getDispatchStrForScanCodeBinding); + public getDispatchParts(): (string | null)[] { + return this._parts.map(this._mapper.getDispatchStrForScanCodeBinding); } } @@ -1093,7 +1114,7 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper { } public resolveUserBinding(_firstPart: SimpleKeybinding | ScanCodeBinding | null, _chordPart: SimpleKeybinding | ScanCodeBinding | null): ResolvedKeybinding[] { - let chordParts = []; + let chordParts: ScanCodeBinding[][] = []; if (_firstPart) { chordParts.push(this._resolveSimpleUserBinding(_firstPart)); } diff --git a/src/vs/workbench/services/keybinding/common/windowsKeyboardMapper.ts b/src/vs/workbench/services/keybinding/common/windowsKeyboardMapper.ts index 54db9453d9767..c599156c660a9 100644 --- a/src/vs/workbench/services/keybinding/common/windowsKeyboardMapper.ts +++ b/src/vs/workbench/services/keybinding/common/windowsKeyboardMapper.ts @@ -101,9 +101,15 @@ export class WindowsNativeResolvedKeybinding extends ResolvedKeybinding { } public getLabel(): string | null { - let firstPart = this._getUILabelForKeybinding(this._parts[0]); - let chordPart = this._getUILabelForKeybinding(this._parts[1]); - return UILabelProvider.toLabel(this._parts[0], firstPart, this._parts[1], chordPart, OperatingSystem.Windows); + let partKeys: string[] = []; + for (let part of this._parts) { + let key = this._getUILabelForKeybinding(part); + if (key === null) { + return null; + } + partKeys.push(key); + } + return UILabelProvider.toLabel(this._parts, partKeys, OperatingSystem.Windows); } private _getUSLabelForKeybinding(keybinding: SimpleKeybinding | null): string | null { @@ -117,9 +123,15 @@ export class WindowsNativeResolvedKeybinding extends ResolvedKeybinding { } public getUSLabel(): string | null { - let firstPart = this._getUSLabelForKeybinding(this._parts[0]); - let chordPart = this._getUSLabelForKeybinding(this._parts[1]); - return UILabelProvider.toLabel(this._parts[0], firstPart, this._parts[1], chordPart, OperatingSystem.Windows); + let partKeys: string[] = []; + for (let part of this._parts) { + let key = this._getUSLabelForKeybinding(part); + if (key === null) { + return null; + } + partKeys.push(key); + } + return UILabelProvider.toLabel(this._parts, partKeys, OperatingSystem.Windows); } private _getAriaLabelForKeybinding(keybinding: SimpleKeybinding | null): string | null { @@ -133,9 +145,15 @@ export class WindowsNativeResolvedKeybinding extends ResolvedKeybinding { } public getAriaLabel(): string | null { - let firstPart = this._getAriaLabelForKeybinding(this._parts[0]); - let chordPart = this._getAriaLabelForKeybinding(this._parts[1]); - return AriaLabelProvider.toLabel(this._parts[0], firstPart, this._parts[1], chordPart, OperatingSystem.Windows); + let partKeys: string[] = []; + for (let part of this._parts) { + let key = this._getAriaLabelForKeybinding(part); + if (key === null) { + return null; + } + partKeys.push(key); + } + return AriaLabelProvider.toLabel(this._parts, partKeys, OperatingSystem.Windows); } private _keyCodeToElectronAccelerator(keyCode: KeyCode): string | null { @@ -176,7 +194,10 @@ export class WindowsNativeResolvedKeybinding extends ResolvedKeybinding { } let firstPart = this._getElectronAcceleratorLabelForKeybinding(this._parts[0]); - return ElectronAcceleratorLabelProvider.toLabel(this._parts[0], firstPart, null, null, OperatingSystem.Windows); + if (firstPart === null) { + return null; + } + return ElectronAcceleratorLabelProvider.toLabel(this._parts, [firstPart], OperatingSystem.Windows); } private _getUserSettingsLabelForKeybinding(keybinding: SimpleKeybinding | null): string | null { @@ -190,9 +211,15 @@ export class WindowsNativeResolvedKeybinding extends ResolvedKeybinding { } public getUserSettingsLabel(): string | null { - let firstPart = this._getUserSettingsLabelForKeybinding(this._parts[0]); - let chordPart = this._getUserSettingsLabelForKeybinding(this._parts[1]); - let result = UserSettingsLabelProvider.toLabel(this._parts[0], firstPart, this._parts[1], chordPart, OperatingSystem.Windows); + let partKeys: string[] = []; + for (let part of this._parts) { + let key = this._getUserSettingsLabelForKeybinding(part); + if (key === null) { + return null; + } + partKeys.push(key); + } + let result = UserSettingsLabelProvider.toLabel(this._parts, partKeys, OperatingSystem.Windows); return (result ? result.toLowerCase() : result); } @@ -224,11 +251,8 @@ export class WindowsNativeResolvedKeybinding extends ResolvedKeybinding { return this._parts.length > 1; } - public getParts(): [ResolvedKeybindingPart, ResolvedKeybindingPart | null] { - return [ - this._toResolvedKeybindingPart(this._parts[0]), - this._parts[1] ? this._toResolvedKeybindingPart(this._parts[1]) : null - ]; + public getParts(): ResolvedKeybindingPart[] { + return this._parts.map(this._toResolvedKeybindingPart); } private _toResolvedKeybindingPart(keybinding: SimpleKeybinding): ResolvedKeybindingPart { @@ -242,7 +266,7 @@ export class WindowsNativeResolvedKeybinding extends ResolvedKeybinding { ); } - public getDispatchParts(): string[] { + public getDispatchParts(): (string | null)[] { return this._parts.map(this._getDispatchStr); } @@ -546,7 +570,7 @@ export class WindowsKeyboardMapper implements IKeyboardMapper { public resolveUserBinding(firstPart: SimpleKeybinding | ScanCodeBinding | null, chordPart: SimpleKeybinding | ScanCodeBinding | null): ResolvedKeybinding[] { const _firstPart = this._resolveSimpleUserBinding(firstPart); const _chordPart = this._resolveSimpleUserBinding(chordPart); - let parts = []; + let parts: SimpleKeybinding[] = []; if (_firstPart) { parts.push(_firstPart); } diff --git a/src/vs/workbench/services/keybinding/test/macLinuxKeyboardMapper.test.ts b/src/vs/workbench/services/keybinding/test/macLinuxKeyboardMapper.test.ts index b6e9c6d43a969..46bf99cf9d2fc 100644 --- a/src/vs/workbench/services/keybinding/test/macLinuxKeyboardMapper.test.ts +++ b/src/vs/workbench/services/keybinding/test/macLinuxKeyboardMapper.test.ts @@ -1409,7 +1409,7 @@ suite('keyboardMapper - MAC zh_hant', () => { userSettingsLabel: 'cmd+c', isWYSIWYG: true, isChord: false, - dispatchParts: ['meta+[KeyC]', null], + dispatchParts: ['meta+[KeyC]'], }] ); }); @@ -1436,6 +1436,6 @@ function _assertKeybindingTranslation(mapper: MacLinuxKeyboardMapper, OS: Operat } const actual = actualHardwareKeypresses - .map(k => UserSettingsLabelProvider.toLabel(k, ScanCodeUtils.toString(k.scanCode), null, null, OS)); + .map(k => UserSettingsLabelProvider.toLabel([k], [ScanCodeUtils.toString(k.scanCode)], OS)); assert.deepEqual(actual, expected, `simpleKeybindingToHardwareKeypress -- "${keybindingLabel}" -- actual: "${actual}" -- expected: "${expected}"`); }