Merge VS Code 1.21 source code (#1067)

* Initial VS Code 1.21 file copy with patches

* A few more merges

* Post npm install

* Fix batch of build breaks

* Fix more build breaks

* Fix more build errors

* Fix more build breaks

* Runtime fixes 1

* Get connection dialog working with some todos

* Fix a few packaging issues

* Copy several node_modules to package build to fix loader issues

* Fix breaks from master

* A few more fixes

* Make tests pass

* First pass of license header updates

* Second pass of license header updates

* Fix restore dialog issues

* Remove add additional themes menu items

* fix select box issues where the list doesn't show up

* formatting

* Fix editor dispose issue

* Copy over node modules to correct location on all platforms
This commit is contained in:
Karl Burtram
2018-04-04 15:27:51 -07:00
committed by GitHub
parent 5fba3e31b4
commit dafb780987
9412 changed files with 141255 additions and 98813 deletions

View File

@@ -14,7 +14,6 @@ import { Edit } from 'vs/base/common/jsonFormatter';
import { setProperty } from 'vs/base/common/jsonEdit';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { EditOperation } from 'vs/editor/common/core/editOperation';
import { Range } from 'vs/editor/common/core/range';
import { Selection } from 'vs/editor/common/core/selection';
@@ -25,6 +24,7 @@ import { ITextFileService } from 'vs/workbench/services/textfile/common/textfile
import { IFileService } from 'vs/platform/files/common/files';
import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem';
import { ITextModel } from 'vs/editor/common/model';
export const IKeybindingEditingService = createDecorator<IKeybindingEditingService>('keybindingEditingService');
@@ -112,7 +112,7 @@ export class KeybindingsEditingService extends Disposable implements IKeybinding
return this.textFileService.save(this.resource);
}
private updateUserKeybinding(newKey: string, keybindingItem: ResolvedKeybindingItem, model: editorCommon.IModel): void {
private updateUserKeybinding(newKey: string, keybindingItem: ResolvedKeybindingItem, model: ITextModel): void {
const { tabSize, insertSpaces } = model.getOptions();
const eol = model.getEOL();
const userKeybindingEntries = <IUserFriendlyKeybinding[]>json.parse(model.getValue());
@@ -122,7 +122,7 @@ export class KeybindingsEditingService extends Disposable implements IKeybinding
}
}
private updateDefaultKeybinding(newKey: string, keybindingItem: ResolvedKeybindingItem, model: editorCommon.IModel): void {
private updateDefaultKeybinding(newKey: string, keybindingItem: ResolvedKeybindingItem, model: ITextModel): void {
const { tabSize, insertSpaces } = model.getOptions();
const eol = model.getEOL();
const userKeybindingEntries = <IUserFriendlyKeybinding[]>json.parse(model.getValue());
@@ -140,7 +140,7 @@ export class KeybindingsEditingService extends Disposable implements IKeybinding
}
}
private removeUserKeybinding(keybindingItem: ResolvedKeybindingItem, model: editorCommon.IModel): void {
private removeUserKeybinding(keybindingItem: ResolvedKeybindingItem, model: ITextModel): void {
const { tabSize, insertSpaces } = model.getOptions();
const eol = model.getEOL();
const userKeybindingEntries = <IUserFriendlyKeybinding[]>json.parse(model.getValue());
@@ -150,13 +150,13 @@ export class KeybindingsEditingService extends Disposable implements IKeybinding
}
}
private removeDefaultKeybinding(keybindingItem: ResolvedKeybindingItem, model: editorCommon.IModel): void {
private removeDefaultKeybinding(keybindingItem: ResolvedKeybindingItem, model: ITextModel): void {
const { tabSize, insertSpaces } = model.getOptions();
const eol = model.getEOL();
this.applyEditsToBuffer(setProperty(model.getValue(), [-1], this.asObject(keybindingItem.resolvedKeybinding.getUserSettingsLabel(), keybindingItem.command, keybindingItem.when, true), { tabSize, insertSpaces, eol })[0], model);
}
private removeUnassignedDefaultKeybinding(keybindingItem: ResolvedKeybindingItem, model: editorCommon.IModel): void {
private removeUnassignedDefaultKeybinding(keybindingItem: ResolvedKeybindingItem, model: ITextModel): void {
const { tabSize, insertSpaces } = model.getOptions();
const eol = model.getEOL();
const userKeybindingEntries = <IUserFriendlyKeybinding[]>json.parse(model.getValue());
@@ -202,7 +202,7 @@ export class KeybindingsEditingService extends Disposable implements IKeybinding
}
private applyEditsToBuffer(edit: Edit, model: editorCommon.IModel): void {
private applyEditsToBuffer(edit: Edit, model: ITextModel): void {
const startPosition = model.getPositionAt(edit.offset);
const endPosition = model.getPositionAt(edit.offset + edit.length);
const range = new Range(startPosition.lineNumber, startPosition.column, endPosition.lineNumber, endPosition.column);
@@ -225,7 +225,7 @@ export class KeybindingsEditingService extends Disposable implements IKeybinding
// Target cannot be dirty if not writing into buffer
if (this.textFileService.isDirty(this.resource)) {
return TPromise.wrapError<IReference<ITextEditorModel>>(new Error(localize('errorKeybindingsFileDirty', "Unable to write because the file is dirty. Please save the **Keybindings** file and try again.")));
return TPromise.wrapError<IReference<ITextEditorModel>>(new Error(localize('errorKeybindingsFileDirty', "Unable to write because the keybindings configuration file is dirty. Please save it first and then try again.")));
}
return this.resolveModelReference()
@@ -235,11 +235,11 @@ export class KeybindingsEditingService extends Disposable implements IKeybinding
if (model.getValue()) {
const parsed = this.parse(model);
if (parsed.parseErrors.length) {
return TPromise.wrapError<IReference<ITextEditorModel>>(new Error(localize('parseErrors', "Unable to write keybindings. Please open **Keybindings file** to correct errors/warnings in the file and try again.")));
return TPromise.wrapError<IReference<ITextEditorModel>>(new Error(localize('parseErrors', "Unable to write to the keybindings configuration file. Please open it to correct errors/warnings in the file and try again.")));
}
if (parsed.result) {
if (!isArray(parsed.result)) {
return TPromise.wrapError<IReference<ITextEditorModel>>(new Error(localize('errorInvalidConfiguration', "Unable to write keybindings. **Keybindings file** has an object which is not of type Array. Please open the file to clean up and try again.")));
return TPromise.wrapError<IReference<ITextEditorModel>>(new Error(localize('errorInvalidConfiguration', "Unable to write to the keybindings configuration file. It has an object which is not of type Array. Please open the file to clean up and try again.")));
}
} else {
const content = EOL + '[]';
@@ -253,7 +253,7 @@ export class KeybindingsEditingService extends Disposable implements IKeybinding
});
}
private parse(model: editorCommon.IModel): { result: IUserFriendlyKeybinding[], parseErrors: json.ParseError[] } {
private parse(model: ITextModel): { result: IUserFriendlyKeybinding[], parseErrors: json.ParseError[] } {
const parseErrors: json.ParseError[] = [];
const result = json.parse(model.getValue(), parseErrors, { allowTrailingComma: true });
return { result, parseErrors };

View File

@@ -8,7 +8,7 @@ import * as nls from 'vs/nls';
import { IJSONSchema } from 'vs/base/common/jsonSchema';
import { ResolvedKeybinding, Keybinding } from 'vs/base/common/keyCodes';
import { OS, OperatingSystem } from 'vs/base/common/platform';
import { ExtensionMessageCollector, ExtensionsRegistry } from 'vs/platform/extensions/common/extensionsRegistry';
import { ExtensionMessageCollector, ExtensionsRegistry } from 'vs/workbench/services/extensions/common/extensionsRegistry';
import { Extensions, IJSONContributionRegistry } from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
import { AbstractKeybindingService } from 'vs/platform/keybinding/common/abstractKeybindingService';
import { IStatusbarService } from 'vs/platform/statusbar/common/statusbar';
@@ -16,11 +16,10 @@ import { KeybindingResolver } from 'vs/platform/keybinding/common/keybindingReso
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IKeybindingEvent, IUserFriendlyKeybinding, KeybindingSource, IKeyboardEvent } from 'vs/platform/keybinding/common/keybinding';
import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IKeybindingItem, KeybindingsRegistry, IKeybindingRule2 } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { IKeybindingItem, KeybindingsRegistry, IKeybindingRule2, KeybindingRuleSource } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { Registry } from 'vs/platform/registry/common/platform';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { keybindingsTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
import { IMessageService } from 'vs/platform/message/common/message';
import { ConfigWatcher } from 'vs/base/node/config';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import * as dom from 'vs/base/browser/dom';
@@ -36,6 +35,8 @@ import Event, { Emitter } from 'vs/base/common/event';
import { Extensions as ConfigExtensions, IConfigurationRegistry, IConfigurationNode } from 'vs/platform/configuration/common/configurationRegistry';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { onUnexpectedError } from 'vs/base/common/errors';
import { release } from 'os';
import { INotificationService } from 'vs/platform/notification/common/notification';
export class KeyboardMapperFactory {
public static readonly INSTANCE = new KeyboardMapperFactory();
@@ -262,12 +263,12 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService {
@IContextKeyService contextKeyService: IContextKeyService,
@ICommandService commandService: ICommandService,
@ITelemetryService telemetryService: ITelemetryService,
@IMessageService messageService: IMessageService,
@INotificationService notificationService: INotificationService,
@IEnvironmentService environmentService: IEnvironmentService,
@IStatusbarService statusBarService: IStatusbarService,
@IConfigurationService configurationService: IConfigurationService
) {
super(contextKeyService, commandService, telemetryService, messageService, statusBarService);
super(contextKeyService, commandService, telemetryService, notificationService, statusBarService);
let dispatchConfig = getDispatchConfig(configurationService);
configurationService.onDidChangeConfiguration((e) => {
@@ -458,7 +459,7 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService {
if (isValidContributedKeyBinding(keybindings, rejects)) {
let rule = this._asCommandRule(isBuiltin, idx++, keybindings);
if (rule) {
KeybindingsRegistry.registerKeybindingRule2(rule);
KeybindingsRegistry.registerKeybindingRule2(rule, KeybindingRuleSource.Extension);
commandAdded = true;
}
}
@@ -583,6 +584,12 @@ const keyboardConfiguration: IConfigurationNode = {
'default': 'code',
'description': nls.localize('dispatch', "Controls the dispatching logic for key presses to use either `code` (recommended) or `keyCode`."),
'included': OS === OperatingSystem.Macintosh || OS === OperatingSystem.Linux
},
'keyboard.touchbar.enabled': {
'type': 'boolean',
'default': true,
'description': nls.localize('touchbar.enabled', "Enables the macOS touchbar buttons on the keyboard if available."),
'included': OS === OperatingSystem.Macintosh && parseFloat(release()) >= 16 // Minimum: macOS Sierra (10.12.x = darwin 16.x)
}
}
};

View File

@@ -13,6 +13,151 @@ import { USLayoutResolvedKeybinding } from 'vs/platform/keybinding/common/usLayo
import { ScanCodeBinding, ScanCode } from 'vs/workbench/services/keybinding/common/scanCode';
suite('keybindingIO', () => {
test('serialize/deserialize', function () {
function testOneSerialization(keybinding: number, expected: string, msg: string, OS: OperatingSystem): void {
let usLayoutResolvedKeybinding = new USLayoutResolvedKeybinding(createKeybinding(keybinding, OS), OS);
let actualSerialized = usLayoutResolvedKeybinding.getUserSettingsLabel();
assert.equal(actualSerialized, expected, expected + ' - ' + msg);
}
function testSerialization(keybinding: number, expectedWin: string, expectedMac: string, expectedLinux: string): void {
testOneSerialization(keybinding, expectedWin, 'win', OperatingSystem.Windows);
testOneSerialization(keybinding, expectedMac, 'mac', OperatingSystem.Macintosh);
testOneSerialization(keybinding, expectedLinux, 'linux', OperatingSystem.Linux);
}
function testOneDeserialization(keybinding: string, _expected: number, msg: string, OS: OperatingSystem): void {
let actualDeserialized = KeybindingIO.readKeybinding(keybinding, OS);
let expected = createKeybinding(_expected, OS);
assert.deepEqual(actualDeserialized, expected, keybinding + ' - ' + msg);
}
function testDeserialization(inWin: string, inMac: string, inLinux: string, expected: number): void {
testOneDeserialization(inWin, expected, 'win', OperatingSystem.Windows);
testOneDeserialization(inMac, expected, 'mac', OperatingSystem.Macintosh);
testOneDeserialization(inLinux, expected, 'linux', OperatingSystem.Linux);
}
function testRoundtrip(keybinding: number, expectedWin: string, expectedMac: string, expectedLinux: string): void {
testSerialization(keybinding, expectedWin, expectedMac, expectedLinux);
testDeserialization(expectedWin, expectedMac, expectedLinux, keybinding);
}
testRoundtrip(KeyCode.KEY_0, '0', '0', '0');
testRoundtrip(KeyCode.KEY_A, 'a', 'a', 'a');
testRoundtrip(KeyCode.UpArrow, 'up', 'up', 'up');
testRoundtrip(KeyCode.RightArrow, 'right', 'right', 'right');
testRoundtrip(KeyCode.DownArrow, 'down', 'down', 'down');
testRoundtrip(KeyCode.LeftArrow, 'left', 'left', 'left');
// one modifier
testRoundtrip(KeyMod.Alt | KeyCode.KEY_A, 'alt+a', 'alt+a', 'alt+a');
testRoundtrip(KeyMod.CtrlCmd | KeyCode.KEY_A, 'ctrl+a', 'cmd+a', 'ctrl+a');
testRoundtrip(KeyMod.Shift | KeyCode.KEY_A, 'shift+a', 'shift+a', 'shift+a');
testRoundtrip(KeyMod.WinCtrl | KeyCode.KEY_A, 'win+a', 'ctrl+a', 'meta+a');
// two modifiers
testRoundtrip(KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_A, 'ctrl+alt+a', 'alt+cmd+a', 'ctrl+alt+a');
testRoundtrip(KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_A, 'ctrl+shift+a', 'shift+cmd+a', 'ctrl+shift+a');
testRoundtrip(KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.KEY_A, 'ctrl+win+a', 'ctrl+cmd+a', 'ctrl+meta+a');
testRoundtrip(KeyMod.Shift | KeyMod.Alt | KeyCode.KEY_A, 'shift+alt+a', 'shift+alt+a', 'shift+alt+a');
testRoundtrip(KeyMod.Shift | KeyMod.WinCtrl | KeyCode.KEY_A, 'shift+win+a', 'ctrl+shift+a', 'shift+meta+a');
testRoundtrip(KeyMod.Alt | KeyMod.WinCtrl | KeyCode.KEY_A, 'alt+win+a', 'ctrl+alt+a', 'alt+meta+a');
// three modifiers
testRoundtrip(KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyCode.KEY_A, 'ctrl+shift+alt+a', 'shift+alt+cmd+a', 'ctrl+shift+alt+a');
testRoundtrip(KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.WinCtrl | KeyCode.KEY_A, 'ctrl+shift+win+a', 'ctrl+shift+cmd+a', 'ctrl+shift+meta+a');
testRoundtrip(KeyMod.Shift | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.KEY_A, 'shift+alt+win+a', 'ctrl+shift+alt+a', 'shift+alt+meta+a');
// all modifiers
testRoundtrip(KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.KEY_A, 'ctrl+shift+alt+win+a', 'ctrl+shift+alt+cmd+a', 'ctrl+shift+alt+meta+a');
// chords
testRoundtrip(KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_A, KeyMod.CtrlCmd | KeyCode.KEY_A), 'ctrl+a ctrl+a', 'cmd+a cmd+a', 'ctrl+a ctrl+a');
testRoundtrip(KeyChord(KeyMod.CtrlCmd | KeyCode.UpArrow, KeyMod.CtrlCmd | KeyCode.UpArrow), 'ctrl+up ctrl+up', 'cmd+up cmd+up', 'ctrl+up ctrl+up');
// OEM keys
testRoundtrip(KeyCode.US_SEMICOLON, ';', ';', ';');
testRoundtrip(KeyCode.US_EQUAL, '=', '=', '=');
testRoundtrip(KeyCode.US_COMMA, ',', ',', ',');
testRoundtrip(KeyCode.US_MINUS, '-', '-', '-');
testRoundtrip(KeyCode.US_DOT, '.', '.', '.');
testRoundtrip(KeyCode.US_SLASH, '/', '/', '/');
testRoundtrip(KeyCode.US_BACKTICK, '`', '`', '`');
testRoundtrip(KeyCode.ABNT_C1, 'abnt_c1', 'abnt_c1', 'abnt_c1');
testRoundtrip(KeyCode.ABNT_C2, 'abnt_c2', 'abnt_c2', 'abnt_c2');
testRoundtrip(KeyCode.US_OPEN_SQUARE_BRACKET, '[', '[', '[');
testRoundtrip(KeyCode.US_BACKSLASH, '\\', '\\', '\\');
testRoundtrip(KeyCode.US_CLOSE_SQUARE_BRACKET, ']', ']', ']');
testRoundtrip(KeyCode.US_QUOTE, '\'', '\'', '\'');
testRoundtrip(KeyCode.OEM_8, 'oem_8', 'oem_8', 'oem_8');
testRoundtrip(KeyCode.OEM_102, 'oem_102', 'oem_102', 'oem_102');
// OEM aliases
testDeserialization('OEM_1', 'OEM_1', 'OEM_1', KeyCode.US_SEMICOLON);
testDeserialization('OEM_PLUS', 'OEM_PLUS', 'OEM_PLUS', KeyCode.US_EQUAL);
testDeserialization('OEM_COMMA', 'OEM_COMMA', 'OEM_COMMA', KeyCode.US_COMMA);
testDeserialization('OEM_MINUS', 'OEM_MINUS', 'OEM_MINUS', KeyCode.US_MINUS);
testDeserialization('OEM_PERIOD', 'OEM_PERIOD', 'OEM_PERIOD', KeyCode.US_DOT);
testDeserialization('OEM_2', 'OEM_2', 'OEM_2', KeyCode.US_SLASH);
testDeserialization('OEM_3', 'OEM_3', 'OEM_3', KeyCode.US_BACKTICK);
testDeserialization('ABNT_C1', 'ABNT_C1', 'ABNT_C1', KeyCode.ABNT_C1);
testDeserialization('ABNT_C2', 'ABNT_C2', 'ABNT_C2', KeyCode.ABNT_C2);
testDeserialization('OEM_4', 'OEM_4', 'OEM_4', KeyCode.US_OPEN_SQUARE_BRACKET);
testDeserialization('OEM_5', 'OEM_5', 'OEM_5', KeyCode.US_BACKSLASH);
testDeserialization('OEM_6', 'OEM_6', 'OEM_6', KeyCode.US_CLOSE_SQUARE_BRACKET);
testDeserialization('OEM_7', 'OEM_7', 'OEM_7', KeyCode.US_QUOTE);
testDeserialization('OEM_8', 'OEM_8', 'OEM_8', KeyCode.OEM_8);
testDeserialization('OEM_102', 'OEM_102', 'OEM_102', KeyCode.OEM_102);
// accepts '-' as separator
testDeserialization('ctrl-shift-alt-win-a', 'ctrl-shift-alt-cmd-a', 'ctrl-shift-alt-meta-a', KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.KEY_A);
// various input mistakes
testDeserialization(' ctrl-shift-alt-win-A ', ' shift-alt-cmd-Ctrl-A ', ' ctrl-shift-alt-META-A ', KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.KEY_A);
});
test('deserialize scan codes', () => {
assert.deepEqual(
KeybindingIO._readUserBinding('ctrl+shift+[comma] ctrl+/'),
[new ScanCodeBinding(true, true, false, false, ScanCode.Comma), new SimpleKeybinding(true, false, false, false, KeyCode.US_SLASH)]
);
});
test('issue #10452 - invalid command', () => {
let strJSON = `[{ "key": "ctrl+k ctrl+f", "command": ["firstcommand", "seccondcommand"] }]`;
let userKeybinding = <IUserFriendlyKeybinding>JSON.parse(strJSON)[0];
let keybindingItem = KeybindingIO.readUserKeybindingItem(userKeybinding, OS);
assert.equal(keybindingItem.command, null);
});
test('issue #10452 - invalid when', () => {
let strJSON = `[{ "key": "ctrl+k ctrl+f", "command": "firstcommand", "when": [] }]`;
let userKeybinding = <IUserFriendlyKeybinding>JSON.parse(strJSON)[0];
let keybindingItem = KeybindingIO.readUserKeybindingItem(userKeybinding, OS);
assert.equal(keybindingItem.when, null);
});
test('issue #10452 - invalid key', () => {
let strJSON = `[{ "key": [], "command": "firstcommand" }]`;
let userKeybinding = <IUserFriendlyKeybinding>JSON.parse(strJSON)[0];
let keybindingItem = KeybindingIO.readUserKeybindingItem(userKeybinding, OS);
assert.equal(keybindingItem.firstPart, null);
assert.equal(keybindingItem.chordPart, null);
});
test('issue #10452 - invalid key 2', () => {
let strJSON = `[{ "key": "", "command": "firstcommand" }]`;
let userKeybinding = <IUserFriendlyKeybinding>JSON.parse(strJSON)[0];
let keybindingItem = KeybindingIO.readUserKeybindingItem(userKeybinding, OS);
assert.equal(keybindingItem.firstPart, null);
assert.equal(keybindingItem.chordPart, null);
});
test('test commands args', () => {
let strJSON = `[{ "key": "ctrl+k ctrl+f", "command": "firstcommand", "when": [], "args": { "text": "theText" } }]`;
let userKeybinding = <IUserFriendlyKeybinding>JSON.parse(strJSON)[0];
let keybindingItem = KeybindingIO.readUserKeybindingItem(userKeybinding, OS);
assert.equal(keybindingItem.commandArgs.text, 'theText');
});
});

View File

@@ -72,7 +72,7 @@ export function assertMapping(writeFileIfDifferent: boolean, mapper: IKeyboardMa
writeFile(filePath, actual);
}
try {
assert.deepEqual(actual, expected);
assert.deepEqual(actual.split(/\r\n|\n/), expected.split(/\r\n|\n/));
} catch (err) {
return done(err);
}

View File

@@ -12,6 +12,222 @@ import { MacLinuxFallbackKeyboardMapper } from 'vs/workbench/services/keybinding
import { ScanCodeBinding, ScanCode } from 'vs/workbench/services/keybinding/common/scanCode';
suite('keyboardMapper - MAC fallback', () => {
let mapper = new MacLinuxFallbackKeyboardMapper(OperatingSystem.Macintosh);
function _assertResolveKeybinding(k: number, expected: IResolvedKeybinding[]): void {
assertResolveKeybinding(mapper, createKeybinding(k, OperatingSystem.Macintosh), expected);
}
test('resolveKeybinding Cmd+Z', () => {
_assertResolveKeybinding(
KeyMod.CtrlCmd | KeyCode.KEY_Z,
[{
label: '⌘Z',
ariaLabel: 'Command+Z',
electronAccelerator: 'Cmd+Z',
userSettingsLabel: 'cmd+z',
isWYSIWYG: true,
isChord: false,
dispatchParts: ['meta+Z', null],
}]
);
});
test('resolveKeybinding Cmd+K Cmd+=', () => {
_assertResolveKeybinding(
KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.US_EQUAL),
[{
label: '⌘K ⌘=',
ariaLabel: 'Command+K Command+=',
electronAccelerator: null,
userSettingsLabel: 'cmd+k cmd+=',
isWYSIWYG: true,
isChord: true,
dispatchParts: ['meta+K', 'meta+='],
}]
);
});
test('resolveKeyboardEvent Cmd+Z', () => {
assertResolveKeyboardEvent(
mapper,
{
ctrlKey: false,
shiftKey: false,
altKey: false,
metaKey: true,
keyCode: KeyCode.KEY_Z,
code: null
},
{
label: '⌘Z',
ariaLabel: 'Command+Z',
electronAccelerator: 'Cmd+Z',
userSettingsLabel: 'cmd+z',
isWYSIWYG: true,
isChord: false,
dispatchParts: ['meta+Z', null],
}
);
});
test('resolveUserBinding Cmd+[Comma] Cmd+/', () => {
assertResolveUserBinding(
mapper,
new ScanCodeBinding(false, false, false, true, ScanCode.Comma),
new SimpleKeybinding(false, false, false, true, KeyCode.US_SLASH),
[{
label: '⌘, ⌘/',
ariaLabel: 'Command+, Command+/',
electronAccelerator: null,
userSettingsLabel: 'cmd+, cmd+/',
isWYSIWYG: true,
isChord: true,
dispatchParts: ['meta+,', 'meta+/'],
}]
);
});
test('resolveKeyboardEvent Modifier only Meta+', () => {
assertResolveKeyboardEvent(
mapper,
{
ctrlKey: false,
shiftKey: false,
altKey: false,
metaKey: true,
keyCode: KeyCode.Meta,
code: null
},
{
label: '⌘',
ariaLabel: 'Command+',
electronAccelerator: null,
userSettingsLabel: 'cmd+',
isWYSIWYG: true,
isChord: false,
dispatchParts: [null, null],
}
);
});
});
suite('keyboardMapper - LINUX fallback', () => {
let mapper = new MacLinuxFallbackKeyboardMapper(OperatingSystem.Linux);
function _assertResolveKeybinding(k: number, expected: IResolvedKeybinding[]): void {
assertResolveKeybinding(mapper, createKeybinding(k, OperatingSystem.Linux), expected);
}
test('resolveKeybinding Ctrl+Z', () => {
_assertResolveKeybinding(
KeyMod.CtrlCmd | KeyCode.KEY_Z,
[{
label: 'Ctrl+Z',
ariaLabel: 'Control+Z',
electronAccelerator: 'Ctrl+Z',
userSettingsLabel: 'ctrl+z',
isWYSIWYG: true,
isChord: false,
dispatchParts: ['ctrl+Z', null],
}]
);
});
test('resolveKeybinding Ctrl+K Ctrl+=', () => {
_assertResolveKeybinding(
KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.US_EQUAL),
[{
label: 'Ctrl+K Ctrl+=',
ariaLabel: 'Control+K Control+=',
electronAccelerator: null,
userSettingsLabel: 'ctrl+k ctrl+=',
isWYSIWYG: true,
isChord: true,
dispatchParts: ['ctrl+K', 'ctrl+='],
}]
);
});
test('resolveKeyboardEvent Ctrl+Z', () => {
assertResolveKeyboardEvent(
mapper,
{
ctrlKey: true,
shiftKey: false,
altKey: false,
metaKey: false,
keyCode: KeyCode.KEY_Z,
code: null
},
{
label: 'Ctrl+Z',
ariaLabel: 'Control+Z',
electronAccelerator: 'Ctrl+Z',
userSettingsLabel: 'ctrl+z',
isWYSIWYG: true,
isChord: false,
dispatchParts: ['ctrl+Z', null],
}
);
});
test('resolveUserBinding Ctrl+[Comma] Ctrl+/', () => {
assertResolveUserBinding(
mapper,
new ScanCodeBinding(true, false, false, false, ScanCode.Comma),
new SimpleKeybinding(true, false, false, false, KeyCode.US_SLASH),
[{
label: 'Ctrl+, Ctrl+/',
ariaLabel: 'Control+, Control+/',
electronAccelerator: null,
userSettingsLabel: 'ctrl+, ctrl+/',
isWYSIWYG: true,
isChord: true,
dispatchParts: ['ctrl+,', 'ctrl+/'],
}]
);
});
test('resolveUserBinding Ctrl+[Comma]', () => {
assertResolveUserBinding(
mapper,
new ScanCodeBinding(true, false, false, false, ScanCode.Comma),
null,
[{
label: 'Ctrl+,',
ariaLabel: 'Control+,',
electronAccelerator: 'Ctrl+,',
userSettingsLabel: 'ctrl+,',
isWYSIWYG: true,
isChord: false,
dispatchParts: ['ctrl+,', null],
}]
);
});
test('resolveKeyboardEvent Modifier only Ctrl+', () => {
assertResolveKeyboardEvent(
mapper,
{
ctrlKey: true,
shiftKey: false,
altKey: false,
metaKey: false,
keyCode: KeyCode.Ctrl,
code: null
},
{
label: 'Ctrl+',
ariaLabel: 'Control+',
electronAccelerator: null,
userSettingsLabel: 'ctrl+',
isWYSIWYG: true,
isChord: false,
dispatchParts: [null, null],
}
);
});
});

View File

@@ -16,7 +16,7 @@ import { TPromise } from 'vs/base/common/winjs.base';
import { KeyCode, SimpleKeybinding, ChordKeybinding } from 'vs/base/common/keyCodes';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import extfs = require('vs/base/node/extfs');
import { TestTextFileService, TestEditorGroupService, TestLifecycleService, TestBackupFileService, TestContextService, TestTextResourceConfigurationService, TestHashService } from 'vs/workbench/test/workbenchTestServices';
import { TestTextFileService, TestEditorGroupService, TestLifecycleService, TestBackupFileService, TestContextService, TestTextResourceConfigurationService, TestHashService, TestEnvironmentService } from 'vs/workbench/test/workbenchTestServices';
import { IWorkspaceContextService, Workspace, toWorkspaceFolders } from 'vs/platform/workspace/common/workspace';
import uuid = require('vs/base/common/uuid');
import { ConfigurationService } from 'vs/platform/configuration/node/configurationService';
@@ -37,13 +37,14 @@ import { IModeService } from 'vs/editor/common/services/modeService';
import { ModeServiceImpl } from 'vs/editor/common/services/modeServiceImpl';
import { IModelService } from 'vs/editor/common/services/modelService';
import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { KeybindingsEditingService } from 'vs/workbench/services/keybinding/common/keybindingEditing';
import { IUserFriendlyKeybinding } from 'vs/platform/keybinding/common/keybinding';
import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
import { IHashService } from 'vs/workbench/services/hash/common/hashService';
import { mkdirp } from 'vs/base/node/pfs';
import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService';
interface Modifiers {
metaKey?: boolean;
@@ -53,6 +54,175 @@ interface Modifiers {
}
suite('Keybindings Editing', () => {
test('errors cases - parse errors', () => {
let instantiationService: TestInstantiationService;
let testObject: KeybindingsEditingService;
let testDir: string;
let keybindingsFile: string;
setup(() => {
return setUpWorkspace().then(() => {
keybindingsFile = path.join(testDir, 'keybindings.json');
instantiationService = new TestInstantiationService();
instantiationService.stub(IEnvironmentService, { appKeybindingsPath: keybindingsFile });
instantiationService.stub(IConfigurationService, ConfigurationService);
instantiationService.stub(IConfigurationService, 'getValue', { 'eol': '\n' });
instantiationService.stub(IConfigurationService, 'onDidUpdateConfiguration', () => { });
instantiationService.stub(IConfigurationService, 'onDidChangeConfiguration', () => { });
instantiationService.stub(IWorkspaceContextService, new TestContextService());
const lifecycleService = new TestLifecycleService();
instantiationService.stub(ILifecycleService, lifecycleService);
instantiationService.stub(IContextKeyService, <IContextKeyService>instantiationService.createInstance(MockContextKeyService));
instantiationService.stub(IHashService, new TestHashService());
instantiationService.stub(IEditorGroupService, new TestEditorGroupService());
instantiationService.stub(ITelemetryService, NullTelemetryService);
instantiationService.stub(IModeService, ModeServiceImpl);
instantiationService.stub(IModelService, instantiationService.createInstance(ModelServiceImpl));
instantiationService.stub(IFileService, new FileService(new TestContextService(new Workspace(testDir, testDir, toWorkspaceFolders([{ path: testDir }]))), TestEnvironmentService, new TestTextResourceConfigurationService(), new TestConfigurationService(), lifecycleService, { disableWatcher: true }));
instantiationService.stub(IUntitledEditorService, instantiationService.createInstance(UntitledEditorService));
instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService));
instantiationService.stub(ITextModelService, <ITextModelService>instantiationService.createInstance(TextModelResolverService));
instantiationService.stub(IBackupFileService, new TestBackupFileService());
testObject = instantiationService.createInstance(KeybindingsEditingService);
});
});
function setUpWorkspace(): TPromise<boolean> {
testDir = path.join(os.tmpdir(), 'vsctests', uuid.generateUuid());
return mkdirp(testDir, 493);
}
teardown(() => {
return new TPromise<void>((c, e) => {
if (testDir) {
extfs.del(testDir, os.tmpdir(), () => c(null), () => c(null));
} else {
c(null);
}
}).then(() => testDir = null);
});
test('errors cases - parse errors', () => {
fs.writeFileSync(keybindingsFile, ',,,,,,,,,,,,,,');
return testObject.editKeybinding('alt+c', aResolvedKeybindingItem({ firstPart: { keyCode: KeyCode.Escape } }))
.then(() => assert.fail('Should fail with parse errors'),
error => assert.equal(error.message, 'Unable to write to the keybindings configuration file. Please open it to correct errors/warnings in the file and try again.'));
});
test('errors cases - parse errors 2', () => {
fs.writeFileSync(keybindingsFile, '[{"key": }]');
return testObject.editKeybinding('alt+c', aResolvedKeybindingItem({ firstPart: { keyCode: KeyCode.Escape } }))
.then(() => assert.fail('Should fail with parse errors'),
error => assert.equal(error.message, 'Unable to write to the keybindings configuration file. Please open it to correct errors/warnings in the file and try again.'));
});
test('errors cases - dirty', () => {
instantiationService.stub(ITextFileService, 'isDirty', true);
return testObject.editKeybinding('alt+c', aResolvedKeybindingItem({ firstPart: { keyCode: KeyCode.Escape } }))
.then(() => assert.fail('Should fail with dirty error'),
error => assert.equal(error.message, 'Unable to write because the keybindings configuration file is dirty. Please save it first and then try again.'));
});
test('errors cases - did not find an array', () => {
fs.writeFileSync(keybindingsFile, '{"key": "alt+c", "command": "hello"}');
return testObject.editKeybinding('alt+c', aResolvedKeybindingItem({ firstPart: { keyCode: KeyCode.Escape } }))
.then(() => assert.fail('Should fail with dirty error'),
error => assert.equal(error.message, 'Unable to write to the keybindings configuration file. It has an object which is not of type Array. Please open the file to clean up and try again.'));
});
test('edit a default keybinding to an empty file', () => {
fs.writeFileSync(keybindingsFile, '');
const expected: IUserFriendlyKeybinding[] = [{ key: 'alt+c', command: 'a' }, { key: 'escape', command: '-a' }];
return testObject.editKeybinding('alt+c', aResolvedKeybindingItem({ firstPart: { keyCode: KeyCode.Escape }, command: 'a' }))
.then(() => assert.deepEqual(getUserKeybindings(), expected));
});
test('edit a default keybinding to a non existing keybindings file', () => {
keybindingsFile = path.join(testDir, 'nonExistingFile.json');
instantiationService.get(IEnvironmentService).appKeybindingsPath = keybindingsFile;
testObject = instantiationService.createInstance(KeybindingsEditingService);
const expected: IUserFriendlyKeybinding[] = [{ key: 'alt+c', command: 'a' }, { key: 'escape', command: '-a' }];
return testObject.editKeybinding('alt+c', aResolvedKeybindingItem({ firstPart: { keyCode: KeyCode.Escape }, command: 'a' }))
.then(() => assert.deepEqual(getUserKeybindings(), expected));
});
test('edit a default keybinding to an empty array', () => {
writeToKeybindingsFile();
const expected: IUserFriendlyKeybinding[] = [{ key: 'alt+c', command: 'a' }, { key: 'escape', command: '-a' }];
return testObject.editKeybinding('alt+c', aResolvedKeybindingItem({ firstPart: { keyCode: KeyCode.Escape }, command: 'a' }))
.then(() => assert.deepEqual(getUserKeybindings(), expected));
});
test('edit a default keybinding in an existing array', () => {
writeToKeybindingsFile({ command: 'b', key: 'shift+c' });
const expected: IUserFriendlyKeybinding[] = [{ key: 'shift+c', command: 'b' }, { key: 'alt+c', command: 'a' }, { key: 'escape', command: '-a' }];
return testObject.editKeybinding('alt+c', aResolvedKeybindingItem({ firstPart: { keyCode: KeyCode.Escape }, command: 'a' }))
.then(() => assert.deepEqual(getUserKeybindings(), expected));
});
test('add a new default keybinding', () => {
const expected: IUserFriendlyKeybinding[] = [{ key: 'alt+c', command: 'a' }];
return testObject.editKeybinding('alt+c', aResolvedKeybindingItem({ command: 'a' }))
.then(() => assert.deepEqual(getUserKeybindings(), expected));
});
test('edit an user keybinding', () => {
writeToKeybindingsFile({ key: 'escape', command: 'b' });
const expected: IUserFriendlyKeybinding[] = [{ key: 'alt+c', command: 'b' }];
return testObject.editKeybinding('alt+c', aResolvedKeybindingItem({ firstPart: { keyCode: KeyCode.Escape }, command: 'b', isDefault: false }))
.then(() => assert.deepEqual(getUserKeybindings(), expected));
});
test('edit an user keybinding with more than one element', () => {
writeToKeybindingsFile({ key: 'escape', command: 'b' }, { key: 'alt+shift+g', command: 'c' });
const expected: IUserFriendlyKeybinding[] = [{ key: 'alt+c', command: 'b' }, { key: 'alt+shift+g', command: 'c' }];
return testObject.editKeybinding('alt+c', aResolvedKeybindingItem({ firstPart: { keyCode: KeyCode.Escape }, command: 'b', isDefault: false }))
.then(() => assert.deepEqual(getUserKeybindings(), expected));
});
test('remove a default keybinding', () => {
const expected: IUserFriendlyKeybinding[] = [{ key: 'alt+c', command: '-a' }];
return testObject.removeKeybinding(aResolvedKeybindingItem({ command: 'a', firstPart: { keyCode: KeyCode.KEY_C, modifiers: { altKey: true } } }))
.then(() => assert.deepEqual(getUserKeybindings(), expected));
});
test('remove a user keybinding', () => {
writeToKeybindingsFile({ key: 'alt+c', command: 'b' });
return testObject.removeKeybinding(aResolvedKeybindingItem({ command: 'b', firstPart: { keyCode: KeyCode.KEY_C, modifiers: { altKey: true } }, isDefault: false }))
.then(() => assert.deepEqual(getUserKeybindings(), []));
});
test('reset an edited keybinding', () => {
writeToKeybindingsFile({ key: 'alt+c', command: 'b' });
return testObject.resetKeybinding(aResolvedKeybindingItem({ command: 'b', firstPart: { keyCode: KeyCode.KEY_C, modifiers: { altKey: true } }, isDefault: false }))
.then(() => assert.deepEqual(getUserKeybindings(), []));
});
test('reset a removed keybinding', () => {
writeToKeybindingsFile({ key: 'alt+c', command: '-b' });
return testObject.resetKeybinding(aResolvedKeybindingItem({ command: 'b', isDefault: false }))
.then(() => assert.deepEqual(getUserKeybindings(), []));
});
function writeToKeybindingsFile(...keybindings: IUserFriendlyKeybinding[]) {
fs.writeFileSync(keybindingsFile, JSON.stringify(keybindings || []));
}
function getUserKeybindings(): IUserFriendlyKeybinding[] {
return json.parse(fs.readFileSync(keybindingsFile).toString('utf8'));
}
function aResolvedKeybindingItem({ command, when, isDefault, firstPart, chordPart }: { command?: string, when?: string, isDefault?: boolean, firstPart?: { keyCode: KeyCode, modifiers?: Modifiers }, chordPart?: { keyCode: KeyCode, modifiers?: Modifiers } }): ResolvedKeybindingItem {
const aSimpleKeybinding = function (part: { keyCode: KeyCode, modifiers?: Modifiers }): SimpleKeybinding {
const { ctrlKey, shiftKey, altKey, metaKey } = part.modifiers || { ctrlKey: false, shiftKey: false, altKey: false, metaKey: false };
return new SimpleKeybinding(ctrlKey, shiftKey, altKey, metaKey, part.keyCode);
};
const keybinding = firstPart ? chordPart ? new ChordKeybinding(aSimpleKeybinding(firstPart), aSimpleKeybinding(chordPart)) : aSimpleKeybinding(firstPart) : null;
return new ResolvedKeybindingItem(keybinding ? new USLayoutResolvedKeybinding(keybinding, OS) : null, command || 'some command', null, when ? ContextKeyExpr.deserialize(when) : null, isDefault === void 0 ? true : isDefault);
}
});

View File

@@ -14,8 +14,523 @@ import { ScanCodeBinding, ScanCode } from 'vs/workbench/services/keybinding/comm
const WRITE_FILE_IF_DIFFERENT = false;
function createKeyboardMapper(isUSStandard: boolean, file: string): TPromise<WindowsKeyboardMapper> {
return readRawMapping<IWindowsKeyboardMapping>(file).then((rawMappings) => {
return new WindowsKeyboardMapper(isUSStandard, rawMappings);
});
}
function _assertResolveKeybinding(mapper: WindowsKeyboardMapper, k: number, expected: IResolvedKeybinding[]): void {
assertResolveKeybinding(mapper, createKeybinding(k, OperatingSystem.Windows), expected);
}
suite('keyboardMapper - WINDOWS de_ch', () => {
let mapper: WindowsKeyboardMapper;
suiteSetup((done) => {
createKeyboardMapper(false, 'win_de_ch').then((_mapper) => {
mapper = _mapper;
done();
}, done);
});
test('mapping', (done) => {
done();
assertMapping(WRITE_FILE_IF_DIFFERENT, mapper, 'win_de_ch.txt', done);
});
test('resolveKeybinding Ctrl+A', () => {
_assertResolveKeybinding(
mapper,
KeyMod.CtrlCmd | KeyCode.KEY_A,
[{
label: 'Ctrl+A',
ariaLabel: 'Control+A',
electronAccelerator: 'Ctrl+A',
userSettingsLabel: 'ctrl+a',
isWYSIWYG: true,
isChord: false,
dispatchParts: ['ctrl+A', null],
}]
);
});
test('resolveKeybinding Ctrl+Z', () => {
_assertResolveKeybinding(
mapper,
KeyMod.CtrlCmd | KeyCode.KEY_Z,
[{
label: 'Ctrl+Z',
ariaLabel: 'Control+Z',
electronAccelerator: 'Ctrl+Z',
userSettingsLabel: 'ctrl+z',
isWYSIWYG: true,
isChord: false,
dispatchParts: ['ctrl+Z', null],
}]
);
});
test('resolveKeyboardEvent Ctrl+Z', () => {
assertResolveKeyboardEvent(
mapper,
{
ctrlKey: true,
shiftKey: false,
altKey: false,
metaKey: false,
keyCode: KeyCode.KEY_Z,
code: null
},
{
label: 'Ctrl+Z',
ariaLabel: 'Control+Z',
electronAccelerator: 'Ctrl+Z',
userSettingsLabel: 'ctrl+z',
isWYSIWYG: true,
isChord: false,
dispatchParts: ['ctrl+Z', null],
}
);
});
test('resolveKeybinding Ctrl+]', () => {
_assertResolveKeybinding(
mapper,
KeyMod.CtrlCmd | KeyCode.US_CLOSE_SQUARE_BRACKET,
[{
label: 'Ctrl+^',
ariaLabel: 'Control+^',
electronAccelerator: 'Ctrl+]',
userSettingsLabel: 'ctrl+oem_6',
isWYSIWYG: false,
isChord: false,
dispatchParts: ['ctrl+]', null],
}]
);
});
test('resolveKeyboardEvent Ctrl+]', () => {
assertResolveKeyboardEvent(
mapper,
{
ctrlKey: true,
shiftKey: false,
altKey: false,
metaKey: false,
keyCode: KeyCode.US_CLOSE_SQUARE_BRACKET,
code: null
},
{
label: 'Ctrl+^',
ariaLabel: 'Control+^',
electronAccelerator: 'Ctrl+]',
userSettingsLabel: 'ctrl+oem_6',
isWYSIWYG: false,
isChord: false,
dispatchParts: ['ctrl+]', null],
}
);
});
test('resolveKeybinding Shift+]', () => {
_assertResolveKeybinding(
mapper,
KeyMod.Shift | KeyCode.US_CLOSE_SQUARE_BRACKET,
[{
label: 'Shift+^',
ariaLabel: 'Shift+^',
electronAccelerator: 'Shift+]',
userSettingsLabel: 'shift+oem_6',
isWYSIWYG: false,
isChord: false,
dispatchParts: ['shift+]', null],
}]
);
});
test('resolveKeybinding Ctrl+/', () => {
_assertResolveKeybinding(
mapper,
KeyMod.CtrlCmd | KeyCode.US_SLASH,
[{
label: 'Ctrl+§',
ariaLabel: 'Control+§',
electronAccelerator: 'Ctrl+/',
userSettingsLabel: 'ctrl+oem_2',
isWYSIWYG: false,
isChord: false,
dispatchParts: ['ctrl+/', null],
}]
);
});
test('resolveKeybinding Ctrl+Shift+/', () => {
_assertResolveKeybinding(
mapper,
KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.US_SLASH,
[{
label: 'Ctrl+Shift+§',
ariaLabel: 'Control+Shift+§',
electronAccelerator: 'Ctrl+Shift+/',
userSettingsLabel: 'ctrl+shift+oem_2',
isWYSIWYG: false,
isChord: false,
dispatchParts: ['ctrl+shift+/', null],
}]
);
});
test('resolveKeybinding Ctrl+K Ctrl+\\', () => {
_assertResolveKeybinding(
mapper,
KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.US_BACKSLASH),
[{
label: 'Ctrl+K Ctrl+ä',
ariaLabel: 'Control+K Control+ä',
electronAccelerator: null,
userSettingsLabel: 'ctrl+k ctrl+oem_5',
isWYSIWYG: false,
isChord: true,
dispatchParts: ['ctrl+K', 'ctrl+\\'],
}]
);
});
test('resolveKeybinding Ctrl+K Ctrl+=', () => {
_assertResolveKeybinding(
mapper,
KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.US_EQUAL),
[]
);
});
test('resolveKeybinding Ctrl+DownArrow', () => {
_assertResolveKeybinding(
mapper,
KeyMod.CtrlCmd | KeyCode.DownArrow,
[{
label: 'Ctrl+DownArrow',
ariaLabel: 'Control+DownArrow',
electronAccelerator: 'Ctrl+Down',
userSettingsLabel: 'ctrl+down',
isWYSIWYG: true,
isChord: false,
dispatchParts: ['ctrl+DownArrow', null],
}]
);
});
test('resolveKeybinding Ctrl+NUMPAD_0', () => {
_assertResolveKeybinding(
mapper,
KeyMod.CtrlCmd | KeyCode.NUMPAD_0,
[{
label: 'Ctrl+NumPad0',
ariaLabel: 'Control+NumPad0',
electronAccelerator: null,
userSettingsLabel: 'ctrl+numpad0',
isWYSIWYG: true,
isChord: false,
dispatchParts: ['ctrl+NumPad0', null],
}]
);
});
test('resolveKeybinding Ctrl+Home', () => {
_assertResolveKeybinding(
mapper,
KeyMod.CtrlCmd | KeyCode.Home,
[{
label: 'Ctrl+Home',
ariaLabel: 'Control+Home',
electronAccelerator: 'Ctrl+Home',
userSettingsLabel: 'ctrl+home',
isWYSIWYG: true,
isChord: false,
dispatchParts: ['ctrl+Home', null],
}]
);
});
test('resolveKeyboardEvent Ctrl+Home', () => {
assertResolveKeyboardEvent(
mapper,
{
ctrlKey: true,
shiftKey: false,
altKey: false,
metaKey: false,
keyCode: KeyCode.Home,
code: null
},
{
label: 'Ctrl+Home',
ariaLabel: 'Control+Home',
electronAccelerator: 'Ctrl+Home',
userSettingsLabel: 'ctrl+home',
isWYSIWYG: true,
isChord: false,
dispatchParts: ['ctrl+Home', null],
}
);
});
test('resolveUserBinding Ctrl+[Comma] Ctrl+/', () => {
assertResolveUserBinding(
mapper,
new ScanCodeBinding(true, false, false, false, ScanCode.Comma),
new SimpleKeybinding(true, false, false, false, KeyCode.US_SLASH),
[{
label: 'Ctrl+, Ctrl+§',
ariaLabel: 'Control+, Control+§',
electronAccelerator: null,
userSettingsLabel: 'ctrl+oem_comma ctrl+oem_2',
isWYSIWYG: false,
isChord: true,
dispatchParts: ['ctrl+,', 'ctrl+/'],
}]
);
});
test('resolveKeyboardEvent Modifier only Ctrl+', () => {
assertResolveKeyboardEvent(
mapper,
{
ctrlKey: true,
shiftKey: false,
altKey: false,
metaKey: false,
keyCode: KeyCode.Ctrl,
code: null
},
{
label: 'Ctrl+',
ariaLabel: 'Control+',
electronAccelerator: null,
userSettingsLabel: 'ctrl+',
isWYSIWYG: true,
isChord: false,
dispatchParts: [null, null],
}
);
});
});
suite('keyboardMapper - WINDOWS en_us', () => {
let mapper: WindowsKeyboardMapper;
suiteSetup((done) => {
createKeyboardMapper(true, 'win_en_us').then((_mapper) => {
mapper = _mapper;
done();
}, done);
});
test('mapping', (done) => {
assertMapping(WRITE_FILE_IF_DIFFERENT, mapper, 'win_en_us.txt', done);
});
test('resolveKeybinding Ctrl+K Ctrl+\\', () => {
_assertResolveKeybinding(
mapper,
KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.US_BACKSLASH),
[{
label: 'Ctrl+K Ctrl+\\',
ariaLabel: 'Control+K Control+\\',
electronAccelerator: null,
userSettingsLabel: 'ctrl+k ctrl+\\',
isWYSIWYG: true,
isChord: true,
dispatchParts: ['ctrl+K', 'ctrl+\\'],
}]
);
});
test('resolveUserBinding Ctrl+[Comma] Ctrl+/', () => {
assertResolveUserBinding(
mapper,
new ScanCodeBinding(true, false, false, false, ScanCode.Comma),
new SimpleKeybinding(true, false, false, false, KeyCode.US_SLASH),
[{
label: 'Ctrl+, Ctrl+/',
ariaLabel: 'Control+, Control+/',
electronAccelerator: null,
userSettingsLabel: 'ctrl+, ctrl+/',
isWYSIWYG: true,
isChord: true,
dispatchParts: ['ctrl+,', 'ctrl+/'],
}]
);
});
test('resolveUserBinding Ctrl+[Comma]', () => {
assertResolveUserBinding(
mapper,
new ScanCodeBinding(true, false, false, false, ScanCode.Comma),
null,
[{
label: 'Ctrl+,',
ariaLabel: 'Control+,',
electronAccelerator: 'Ctrl+,',
userSettingsLabel: 'ctrl+,',
isWYSIWYG: true,
isChord: false,
dispatchParts: ['ctrl+,', null],
}]
);
});
test('resolveKeyboardEvent Modifier only Ctrl+', () => {
assertResolveKeyboardEvent(
mapper,
{
ctrlKey: true,
shiftKey: false,
altKey: false,
metaKey: false,
keyCode: KeyCode.Ctrl,
code: null
},
{
label: 'Ctrl+',
ariaLabel: 'Control+',
electronAccelerator: null,
userSettingsLabel: 'ctrl+',
isWYSIWYG: true,
isChord: false,
dispatchParts: [null, null],
}
);
});
});
suite('keyboardMapper - WINDOWS por_ptb', () => {
let mapper: WindowsKeyboardMapper;
suiteSetup((done) => {
createKeyboardMapper(false, 'win_por_ptb').then((_mapper) => {
mapper = _mapper;
done();
}, done);
});
test('mapping', (done) => {
assertMapping(WRITE_FILE_IF_DIFFERENT, mapper, 'win_por_ptb.txt', done);
});
test('resolveKeyboardEvent Ctrl+[IntlRo]', () => {
assertResolveKeyboardEvent(
mapper,
{
ctrlKey: true,
shiftKey: false,
altKey: false,
metaKey: false,
keyCode: KeyCode.ABNT_C1,
code: null
},
{
label: 'Ctrl+/',
ariaLabel: 'Control+/',
electronAccelerator: 'Ctrl+ABNT_C1',
userSettingsLabel: 'ctrl+abnt_c1',
isWYSIWYG: false,
isChord: false,
dispatchParts: ['ctrl+ABNT_C1', null],
}
);
});
test('resolveKeyboardEvent Ctrl+[NumpadComma]', () => {
assertResolveKeyboardEvent(
mapper,
{
ctrlKey: true,
shiftKey: false,
altKey: false,
metaKey: false,
keyCode: KeyCode.ABNT_C2,
code: null
},
{
label: 'Ctrl+.',
ariaLabel: 'Control+.',
electronAccelerator: 'Ctrl+ABNT_C2',
userSettingsLabel: 'ctrl+abnt_c2',
isWYSIWYG: false,
isChord: false,
dispatchParts: ['ctrl+ABNT_C2', null],
}
);
});
});
suite('keyboardMapper - WINDOWS ru', () => {
let mapper: WindowsKeyboardMapper;
suiteSetup((done) => {
createKeyboardMapper(false, 'win_ru').then((_mapper) => {
mapper = _mapper;
done();
}, done);
});
test('mapping', (done) => {
assertMapping(WRITE_FILE_IF_DIFFERENT, mapper, 'win_ru.txt', done);
});
test('issue ##24361: resolveKeybinding Ctrl+K Ctrl+K', () => {
_assertResolveKeybinding(
mapper,
KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_K),
[{
label: 'Ctrl+K Ctrl+K',
ariaLabel: 'Control+K Control+K',
electronAccelerator: null,
userSettingsLabel: 'ctrl+k ctrl+k',
isWYSIWYG: true,
isChord: true,
dispatchParts: ['ctrl+K', 'ctrl+K'],
}]
);
});
});
suite('keyboardMapper - misc', () => {
test('issue #23513: Toggle Sidebar Visibility and Go to Line display same key mapping in Arabic keyboard', () => {
const mapper = new WindowsKeyboardMapper(false, {
'KeyB': {
'vkey': 'VK_B',
'value': 'لا',
'withShift': 'لآ',
'withAltGr': '',
'withShiftAltGr': ''
},
'KeyG': {
'vkey': 'VK_G',
'value': 'ل',
'withShift': 'لأ',
'withAltGr': '',
'withShiftAltGr': ''
}
});
_assertResolveKeybinding(
mapper,
KeyMod.CtrlCmd | KeyCode.KEY_B,
[{
label: 'Ctrl+B',
ariaLabel: 'Control+B',
electronAccelerator: 'Ctrl+B',
userSettingsLabel: 'ctrl+b',
isWYSIWYG: true,
isChord: false,
dispatchParts: ['ctrl+B', null],
}]
);
});
});