mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-07 01:25:38 -05:00
SQL Operations Studio Public Preview 1 (0.23) release source code
This commit is contained in:
@@ -0,0 +1,421 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { ResolvedKeybinding, KeyCode, KeyMod, KeyChord, Keybinding, createKeybinding, createSimpleKeybinding, SimpleKeybinding } from 'vs/base/common/keyCodes';
|
||||
import { AbstractKeybindingService } from 'vs/platform/keybinding/common/abstractKeybindingService';
|
||||
import { USLayoutResolvedKeybinding } from 'vs/platform/keybinding/common/usLayoutResolvedKeybinding';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { KeybindingResolver } from 'vs/platform/keybinding/common/keybindingResolver';
|
||||
import { IContext, ContextKeyExpr, IContextKeyService, IContextKeyServiceTarget } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IStatusbarService } from 'vs/platform/statusbar/common/statusbar';
|
||||
import { IMessageService } from 'vs/platform/message/common/message';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem';
|
||||
import { OS } from 'vs/base/common/platform';
|
||||
import { IKeyboardEvent } from 'vs/platform/keybinding/common/keybinding';
|
||||
|
||||
function createContext(ctx: any) {
|
||||
return {
|
||||
getValue: (key: string) => {
|
||||
return ctx[key];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
suite('AbstractKeybindingService', () => {
|
||||
|
||||
class TestKeybindingService extends AbstractKeybindingService {
|
||||
private _resolver: KeybindingResolver;
|
||||
|
||||
constructor(
|
||||
resolver: KeybindingResolver,
|
||||
contextKeyService: IContextKeyService,
|
||||
commandService: ICommandService,
|
||||
messageService: IMessageService,
|
||||
statusService?: IStatusbarService
|
||||
) {
|
||||
super(contextKeyService, commandService, messageService, statusService);
|
||||
this._resolver = resolver;
|
||||
}
|
||||
|
||||
protected _getResolver(): KeybindingResolver {
|
||||
return this._resolver;
|
||||
}
|
||||
|
||||
public resolveKeybinding(kb: Keybinding): ResolvedKeybinding[] {
|
||||
return [new USLayoutResolvedKeybinding(kb, OS)];
|
||||
}
|
||||
|
||||
public resolveKeyboardEvent(keyboardEvent: IKeyboardEvent): ResolvedKeybinding {
|
||||
let keybinding = new SimpleKeybinding(
|
||||
keyboardEvent.ctrlKey,
|
||||
keyboardEvent.shiftKey,
|
||||
keyboardEvent.altKey,
|
||||
keyboardEvent.metaKey,
|
||||
keyboardEvent.keyCode
|
||||
);
|
||||
return this.resolveKeybinding(keybinding)[0];
|
||||
}
|
||||
|
||||
public resolveUserBinding(userBinding: string): ResolvedKeybinding[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
public testDispatch(kb: number): boolean {
|
||||
const keybinding = createSimpleKeybinding(kb, OS);
|
||||
return this._dispatch({
|
||||
ctrlKey: keybinding.ctrlKey,
|
||||
shiftKey: keybinding.shiftKey,
|
||||
altKey: keybinding.altKey,
|
||||
metaKey: keybinding.metaKey,
|
||||
keyCode: keybinding.keyCode,
|
||||
code: null
|
||||
}, null);
|
||||
}
|
||||
}
|
||||
|
||||
let createTestKeybindingService: (items: ResolvedKeybindingItem[], contextValue?: any) => TestKeybindingService = null;
|
||||
let currentContextValue: IContext = null;
|
||||
let executeCommandCalls: { commandId: string; args: any[]; }[] = null;
|
||||
let showMessageCalls: { sev: Severity, message: any; }[] = null;
|
||||
let statusMessageCalls: string[] = null;
|
||||
let statusMessageCallsDisposed: string[] = null;
|
||||
|
||||
setup(() => {
|
||||
executeCommandCalls = [];
|
||||
showMessageCalls = [];
|
||||
statusMessageCalls = [];
|
||||
statusMessageCallsDisposed = [];
|
||||
|
||||
createTestKeybindingService = (items: ResolvedKeybindingItem[]): TestKeybindingService => {
|
||||
|
||||
let contextKeyService: IContextKeyService = {
|
||||
_serviceBrand: undefined,
|
||||
dispose: undefined,
|
||||
onDidChangeContext: undefined,
|
||||
createKey: undefined,
|
||||
contextMatchesRules: undefined,
|
||||
getContextKeyValue: undefined,
|
||||
createScoped: undefined,
|
||||
getContext: (target: IContextKeyServiceTarget): any => {
|
||||
return currentContextValue;
|
||||
}
|
||||
};
|
||||
|
||||
let commandService: ICommandService = {
|
||||
_serviceBrand: undefined,
|
||||
onWillExecuteCommand: () => ({ dispose: () => { } }),
|
||||
executeCommand: (commandId: string, ...args: any[]): TPromise<any> => {
|
||||
executeCommandCalls.push({
|
||||
commandId: commandId,
|
||||
args: args
|
||||
});
|
||||
return TPromise.as(void 0);
|
||||
}
|
||||
};
|
||||
|
||||
let messageService: IMessageService = {
|
||||
_serviceBrand: undefined,
|
||||
hideAll: undefined,
|
||||
confirm: undefined,
|
||||
show: (sev: Severity, message: any): () => void => {
|
||||
showMessageCalls.push({
|
||||
sev: sev,
|
||||
message: message
|
||||
});
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
let statusbarService: IStatusbarService = {
|
||||
_serviceBrand: undefined,
|
||||
addEntry: undefined,
|
||||
setStatusMessage: (message: string, autoDisposeAfter?: number, delayBy?: number): IDisposable => {
|
||||
statusMessageCalls.push(message);
|
||||
return {
|
||||
dispose: () => {
|
||||
statusMessageCallsDisposed.push(message);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
let resolver = new KeybindingResolver(items, []);
|
||||
|
||||
return new TestKeybindingService(resolver, contextKeyService, commandService, messageService, statusbarService);
|
||||
};
|
||||
});
|
||||
|
||||
teardown(() => {
|
||||
currentContextValue = null;
|
||||
executeCommandCalls = null;
|
||||
showMessageCalls = null;
|
||||
createTestKeybindingService = null;
|
||||
statusMessageCalls = null;
|
||||
statusMessageCallsDisposed = null;
|
||||
});
|
||||
|
||||
function kbItem(keybinding: number, command: string, when: ContextKeyExpr = null): ResolvedKeybindingItem {
|
||||
const resolvedKeybinding = (keybinding !== 0 ? new USLayoutResolvedKeybinding(createKeybinding(keybinding, OS), OS) : null);
|
||||
return new ResolvedKeybindingItem(
|
||||
resolvedKeybinding,
|
||||
command,
|
||||
null,
|
||||
when,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
function toUsLabel(keybinding: number): string {
|
||||
const usResolvedKeybinding = new USLayoutResolvedKeybinding(createKeybinding(keybinding, OS), OS);
|
||||
return usResolvedKeybinding.getLabel();
|
||||
}
|
||||
|
||||
test('issue #16498: chord mode is quit for invalid chords', () => {
|
||||
|
||||
let kbService = createTestKeybindingService([
|
||||
kbItem(KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_X), 'chordCommand'),
|
||||
kbItem(KeyCode.Backspace, 'simpleCommand'),
|
||||
]);
|
||||
|
||||
// send Ctrl/Cmd + K
|
||||
let shouldPreventDefault = kbService.testDispatch(KeyMod.CtrlCmd | KeyCode.KEY_K);
|
||||
assert.equal(shouldPreventDefault, true);
|
||||
assert.deepEqual(executeCommandCalls, []);
|
||||
assert.deepEqual(showMessageCalls, []);
|
||||
assert.deepEqual(statusMessageCalls, [
|
||||
`(${toUsLabel(KeyMod.CtrlCmd | KeyCode.KEY_K)}) was pressed. Waiting for second key of chord...`
|
||||
]);
|
||||
assert.deepEqual(statusMessageCallsDisposed, []);
|
||||
executeCommandCalls = [];
|
||||
showMessageCalls = [];
|
||||
statusMessageCalls = [];
|
||||
statusMessageCallsDisposed = [];
|
||||
|
||||
// send backspace
|
||||
shouldPreventDefault = kbService.testDispatch(KeyCode.Backspace);
|
||||
assert.equal(shouldPreventDefault, true);
|
||||
assert.deepEqual(executeCommandCalls, []);
|
||||
assert.deepEqual(showMessageCalls, []);
|
||||
assert.deepEqual(statusMessageCalls, [
|
||||
`The key combination (${toUsLabel(KeyMod.CtrlCmd | KeyCode.KEY_K)}, ${toUsLabel(KeyCode.Backspace)}) is not a command.`
|
||||
]);
|
||||
assert.deepEqual(statusMessageCallsDisposed, [
|
||||
`(${toUsLabel(KeyMod.CtrlCmd | KeyCode.KEY_K)}) was pressed. Waiting for second key of chord...`
|
||||
]);
|
||||
executeCommandCalls = [];
|
||||
showMessageCalls = [];
|
||||
statusMessageCalls = [];
|
||||
statusMessageCallsDisposed = [];
|
||||
|
||||
// send backspace
|
||||
shouldPreventDefault = kbService.testDispatch(KeyCode.Backspace);
|
||||
assert.equal(shouldPreventDefault, true);
|
||||
assert.deepEqual(executeCommandCalls, [{
|
||||
commandId: 'simpleCommand',
|
||||
args: [{}]
|
||||
}]);
|
||||
assert.deepEqual(showMessageCalls, []);
|
||||
assert.deepEqual(statusMessageCalls, []);
|
||||
assert.deepEqual(statusMessageCallsDisposed, []);
|
||||
executeCommandCalls = [];
|
||||
showMessageCalls = [];
|
||||
statusMessageCalls = [];
|
||||
statusMessageCallsDisposed = [];
|
||||
|
||||
kbService.dispose();
|
||||
});
|
||||
|
||||
test('issue #16833: Keybinding service should not testDispatch on modifier keys', () => {
|
||||
|
||||
let kbService = createTestKeybindingService([
|
||||
kbItem(KeyCode.Ctrl, 'nope'),
|
||||
kbItem(KeyCode.Meta, 'nope'),
|
||||
kbItem(KeyCode.Alt, 'nope'),
|
||||
kbItem(KeyCode.Shift, 'nope'),
|
||||
|
||||
kbItem(KeyMod.CtrlCmd, 'nope'),
|
||||
kbItem(KeyMod.WinCtrl, 'nope'),
|
||||
kbItem(KeyMod.Alt, 'nope'),
|
||||
kbItem(KeyMod.Shift, 'nope'),
|
||||
]);
|
||||
|
||||
function assertIsIgnored(keybinding: number): void {
|
||||
let shouldPreventDefault = kbService.testDispatch(keybinding);
|
||||
assert.equal(shouldPreventDefault, false);
|
||||
assert.deepEqual(executeCommandCalls, []);
|
||||
assert.deepEqual(showMessageCalls, []);
|
||||
assert.deepEqual(statusMessageCalls, []);
|
||||
assert.deepEqual(statusMessageCallsDisposed, []);
|
||||
executeCommandCalls = [];
|
||||
showMessageCalls = [];
|
||||
statusMessageCalls = [];
|
||||
statusMessageCallsDisposed = [];
|
||||
}
|
||||
|
||||
assertIsIgnored(KeyCode.Ctrl);
|
||||
assertIsIgnored(KeyCode.Meta);
|
||||
assertIsIgnored(KeyCode.Alt);
|
||||
assertIsIgnored(KeyCode.Shift);
|
||||
|
||||
assertIsIgnored(KeyMod.CtrlCmd);
|
||||
assertIsIgnored(KeyMod.WinCtrl);
|
||||
assertIsIgnored(KeyMod.Alt);
|
||||
assertIsIgnored(KeyMod.Shift);
|
||||
|
||||
kbService.dispose();
|
||||
});
|
||||
|
||||
test('can trigger command that is sharing keybinding with chord', () => {
|
||||
|
||||
let kbService = createTestKeybindingService([
|
||||
kbItem(KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_X), 'chordCommand'),
|
||||
kbItem(KeyMod.CtrlCmd | KeyCode.KEY_K, 'simpleCommand', ContextKeyExpr.has('key1')),
|
||||
]);
|
||||
|
||||
|
||||
// send Ctrl/Cmd + K
|
||||
currentContextValue = createContext({
|
||||
key1: true
|
||||
});
|
||||
let shouldPreventDefault = kbService.testDispatch(KeyMod.CtrlCmd | KeyCode.KEY_K);
|
||||
assert.equal(shouldPreventDefault, true);
|
||||
assert.deepEqual(executeCommandCalls, [{
|
||||
commandId: 'simpleCommand',
|
||||
args: [{}]
|
||||
}]);
|
||||
assert.deepEqual(showMessageCalls, []);
|
||||
assert.deepEqual(statusMessageCalls, []);
|
||||
assert.deepEqual(statusMessageCallsDisposed, []);
|
||||
executeCommandCalls = [];
|
||||
showMessageCalls = [];
|
||||
statusMessageCalls = [];
|
||||
statusMessageCallsDisposed = [];
|
||||
|
||||
// send Ctrl/Cmd + K
|
||||
currentContextValue = createContext({});
|
||||
shouldPreventDefault = kbService.testDispatch(KeyMod.CtrlCmd | KeyCode.KEY_K);
|
||||
assert.equal(shouldPreventDefault, true);
|
||||
assert.deepEqual(executeCommandCalls, []);
|
||||
assert.deepEqual(showMessageCalls, []);
|
||||
assert.deepEqual(statusMessageCalls, [
|
||||
`(${toUsLabel(KeyMod.CtrlCmd | KeyCode.KEY_K)}) was pressed. Waiting for second key of chord...`
|
||||
]);
|
||||
assert.deepEqual(statusMessageCallsDisposed, []);
|
||||
executeCommandCalls = [];
|
||||
showMessageCalls = [];
|
||||
statusMessageCalls = [];
|
||||
statusMessageCallsDisposed = [];
|
||||
|
||||
// send Ctrl/Cmd + X
|
||||
currentContextValue = createContext({});
|
||||
shouldPreventDefault = kbService.testDispatch(KeyMod.CtrlCmd | KeyCode.KEY_X);
|
||||
assert.equal(shouldPreventDefault, true);
|
||||
assert.deepEqual(executeCommandCalls, [{
|
||||
commandId: 'chordCommand',
|
||||
args: [{}]
|
||||
}]);
|
||||
assert.deepEqual(showMessageCalls, []);
|
||||
assert.deepEqual(statusMessageCalls, []);
|
||||
assert.deepEqual(statusMessageCallsDisposed, [
|
||||
`(${toUsLabel(KeyMod.CtrlCmd | KeyCode.KEY_K)}) was pressed. Waiting for second key of chord...`
|
||||
]);
|
||||
executeCommandCalls = [];
|
||||
showMessageCalls = [];
|
||||
statusMessageCalls = [];
|
||||
statusMessageCallsDisposed = [];
|
||||
|
||||
kbService.dispose();
|
||||
});
|
||||
|
||||
test('cannot trigger chord if command is overwriting', () => {
|
||||
|
||||
let kbService = createTestKeybindingService([
|
||||
kbItem(KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_X), 'chordCommand', ContextKeyExpr.has('key1')),
|
||||
kbItem(KeyMod.CtrlCmd | KeyCode.KEY_K, 'simpleCommand'),
|
||||
]);
|
||||
|
||||
|
||||
// send Ctrl/Cmd + K
|
||||
currentContextValue = createContext({});
|
||||
let shouldPreventDefault = kbService.testDispatch(KeyMod.CtrlCmd | KeyCode.KEY_K);
|
||||
assert.equal(shouldPreventDefault, true);
|
||||
assert.deepEqual(executeCommandCalls, [{
|
||||
commandId: 'simpleCommand',
|
||||
args: [{}]
|
||||
}]);
|
||||
assert.deepEqual(showMessageCalls, []);
|
||||
assert.deepEqual(statusMessageCalls, []);
|
||||
assert.deepEqual(statusMessageCallsDisposed, []);
|
||||
executeCommandCalls = [];
|
||||
showMessageCalls = [];
|
||||
statusMessageCalls = [];
|
||||
statusMessageCallsDisposed = [];
|
||||
|
||||
// send Ctrl/Cmd + K
|
||||
currentContextValue = createContext({
|
||||
key1: true
|
||||
});
|
||||
shouldPreventDefault = kbService.testDispatch(KeyMod.CtrlCmd | KeyCode.KEY_K);
|
||||
assert.equal(shouldPreventDefault, true);
|
||||
assert.deepEqual(executeCommandCalls, [{
|
||||
commandId: 'simpleCommand',
|
||||
args: [{}]
|
||||
}]);
|
||||
assert.deepEqual(showMessageCalls, []);
|
||||
assert.deepEqual(statusMessageCalls, []);
|
||||
assert.deepEqual(statusMessageCallsDisposed, []);
|
||||
executeCommandCalls = [];
|
||||
showMessageCalls = [];
|
||||
statusMessageCalls = [];
|
||||
statusMessageCallsDisposed = [];
|
||||
|
||||
// send Ctrl/Cmd + X
|
||||
currentContextValue = createContext({
|
||||
key1: true
|
||||
});
|
||||
shouldPreventDefault = kbService.testDispatch(KeyMod.CtrlCmd | KeyCode.KEY_X);
|
||||
assert.equal(shouldPreventDefault, false);
|
||||
assert.deepEqual(executeCommandCalls, []);
|
||||
assert.deepEqual(showMessageCalls, []);
|
||||
assert.deepEqual(statusMessageCalls, []);
|
||||
assert.deepEqual(statusMessageCallsDisposed, []);
|
||||
executeCommandCalls = [];
|
||||
showMessageCalls = [];
|
||||
statusMessageCalls = [];
|
||||
statusMessageCallsDisposed = [];
|
||||
|
||||
kbService.dispose();
|
||||
});
|
||||
|
||||
test('can have spying command', () => {
|
||||
|
||||
let kbService = createTestKeybindingService([
|
||||
kbItem(KeyMod.CtrlCmd | KeyCode.KEY_K, '^simpleCommand'),
|
||||
]);
|
||||
|
||||
// send Ctrl/Cmd + K
|
||||
currentContextValue = createContext({});
|
||||
let shouldPreventDefault = kbService.testDispatch(KeyMod.CtrlCmd | KeyCode.KEY_K);
|
||||
assert.equal(shouldPreventDefault, false);
|
||||
assert.deepEqual(executeCommandCalls, [{
|
||||
commandId: 'simpleCommand',
|
||||
args: [{}]
|
||||
}]);
|
||||
assert.deepEqual(showMessageCalls, []);
|
||||
assert.deepEqual(statusMessageCalls, []);
|
||||
assert.deepEqual(statusMessageCallsDisposed, []);
|
||||
executeCommandCalls = [];
|
||||
showMessageCalls = [];
|
||||
statusMessageCalls = [];
|
||||
statusMessageCallsDisposed = [];
|
||||
|
||||
kbService.dispose();
|
||||
});
|
||||
});
|
||||
172
src/vs/platform/keybinding/test/common/keybindingLabels.test.ts
Normal file
172
src/vs/platform/keybinding/test/common/keybindingLabels.test.ts
Normal file
@@ -0,0 +1,172 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { KeyCode, KeyMod, KeyChord, createKeybinding } from 'vs/base/common/keyCodes';
|
||||
import { USLayoutResolvedKeybinding } from 'vs/platform/keybinding/common/usLayoutResolvedKeybinding';
|
||||
import { OperatingSystem } from 'vs/base/common/platform';
|
||||
|
||||
suite('KeybindingLabels', () => {
|
||||
|
||||
function assertUSLabel(OS: OperatingSystem, keybinding: number, expected: string): void {
|
||||
const usResolvedKeybinding = new USLayoutResolvedKeybinding(createKeybinding(keybinding, OS), OS);
|
||||
assert.equal(usResolvedKeybinding.getLabel(), expected);
|
||||
}
|
||||
|
||||
test('Windows US label', () => {
|
||||
// no modifier
|
||||
assertUSLabel(OperatingSystem.Windows, KeyCode.KEY_A, 'A');
|
||||
|
||||
// one modifier
|
||||
assertUSLabel(OperatingSystem.Windows, KeyMod.CtrlCmd | KeyCode.KEY_A, 'Ctrl+A');
|
||||
assertUSLabel(OperatingSystem.Windows, KeyMod.Shift | KeyCode.KEY_A, 'Shift+A');
|
||||
assertUSLabel(OperatingSystem.Windows, KeyMod.Alt | KeyCode.KEY_A, 'Alt+A');
|
||||
assertUSLabel(OperatingSystem.Windows, KeyMod.WinCtrl | KeyCode.KEY_A, 'Windows+A');
|
||||
|
||||
// two modifiers
|
||||
assertUSLabel(OperatingSystem.Windows, KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_A, 'Ctrl+Shift+A');
|
||||
assertUSLabel(OperatingSystem.Windows, KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_A, 'Ctrl+Alt+A');
|
||||
assertUSLabel(OperatingSystem.Windows, KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.KEY_A, 'Ctrl+Windows+A');
|
||||
assertUSLabel(OperatingSystem.Windows, KeyMod.Shift | KeyMod.Alt | KeyCode.KEY_A, 'Shift+Alt+A');
|
||||
assertUSLabel(OperatingSystem.Windows, KeyMod.Shift | KeyMod.WinCtrl | KeyCode.KEY_A, 'Shift+Windows+A');
|
||||
assertUSLabel(OperatingSystem.Windows, KeyMod.Alt | KeyMod.WinCtrl | KeyCode.KEY_A, 'Alt+Windows+A');
|
||||
|
||||
// three modifiers
|
||||
assertUSLabel(OperatingSystem.Windows, KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyCode.KEY_A, 'Ctrl+Shift+Alt+A');
|
||||
assertUSLabel(OperatingSystem.Windows, KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.WinCtrl | KeyCode.KEY_A, 'Ctrl+Shift+Windows+A');
|
||||
assertUSLabel(OperatingSystem.Windows, KeyMod.CtrlCmd | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.KEY_A, 'Ctrl+Alt+Windows+A');
|
||||
assertUSLabel(OperatingSystem.Windows, KeyMod.Shift | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.KEY_A, 'Shift+Alt+Windows+A');
|
||||
|
||||
// four modifiers
|
||||
assertUSLabel(OperatingSystem.Windows, KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.KEY_A, 'Ctrl+Shift+Alt+Windows+A');
|
||||
|
||||
// chord
|
||||
assertUSLabel(OperatingSystem.Windows, KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_A, KeyMod.CtrlCmd | KeyCode.KEY_B), 'Ctrl+A Ctrl+B');
|
||||
});
|
||||
|
||||
test('Linux US label', () => {
|
||||
// no modifier
|
||||
assertUSLabel(OperatingSystem.Linux, KeyCode.KEY_A, 'A');
|
||||
|
||||
// one modifier
|
||||
assertUSLabel(OperatingSystem.Linux, KeyMod.CtrlCmd | KeyCode.KEY_A, 'Ctrl+A');
|
||||
assertUSLabel(OperatingSystem.Linux, KeyMod.Shift | KeyCode.KEY_A, 'Shift+A');
|
||||
assertUSLabel(OperatingSystem.Linux, KeyMod.Alt | KeyCode.KEY_A, 'Alt+A');
|
||||
assertUSLabel(OperatingSystem.Linux, KeyMod.WinCtrl | KeyCode.KEY_A, 'Windows+A');
|
||||
|
||||
// two modifiers
|
||||
assertUSLabel(OperatingSystem.Linux, KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_A, 'Ctrl+Shift+A');
|
||||
assertUSLabel(OperatingSystem.Linux, KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_A, 'Ctrl+Alt+A');
|
||||
assertUSLabel(OperatingSystem.Linux, KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.KEY_A, 'Ctrl+Windows+A');
|
||||
assertUSLabel(OperatingSystem.Linux, KeyMod.Shift | KeyMod.Alt | KeyCode.KEY_A, 'Shift+Alt+A');
|
||||
assertUSLabel(OperatingSystem.Linux, KeyMod.Shift | KeyMod.WinCtrl | KeyCode.KEY_A, 'Shift+Windows+A');
|
||||
assertUSLabel(OperatingSystem.Linux, KeyMod.Alt | KeyMod.WinCtrl | KeyCode.KEY_A, 'Alt+Windows+A');
|
||||
|
||||
// three modifiers
|
||||
assertUSLabel(OperatingSystem.Linux, KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyCode.KEY_A, 'Ctrl+Shift+Alt+A');
|
||||
assertUSLabel(OperatingSystem.Linux, KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.WinCtrl | KeyCode.KEY_A, 'Ctrl+Shift+Windows+A');
|
||||
assertUSLabel(OperatingSystem.Linux, KeyMod.CtrlCmd | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.KEY_A, 'Ctrl+Alt+Windows+A');
|
||||
assertUSLabel(OperatingSystem.Linux, KeyMod.Shift | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.KEY_A, 'Shift+Alt+Windows+A');
|
||||
|
||||
// four modifiers
|
||||
assertUSLabel(OperatingSystem.Linux, KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.KEY_A, 'Ctrl+Shift+Alt+Windows+A');
|
||||
|
||||
// chord
|
||||
assertUSLabel(OperatingSystem.Linux, KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_A, KeyMod.CtrlCmd | KeyCode.KEY_B), 'Ctrl+A Ctrl+B');
|
||||
});
|
||||
|
||||
test('Mac US label', () => {
|
||||
// no modifier
|
||||
assertUSLabel(OperatingSystem.Macintosh, KeyCode.KEY_A, 'A');
|
||||
|
||||
// one modifier
|
||||
assertUSLabel(OperatingSystem.Macintosh, KeyMod.CtrlCmd | KeyCode.KEY_A, '⌘A');
|
||||
assertUSLabel(OperatingSystem.Macintosh, KeyMod.Shift | KeyCode.KEY_A, '⇧A');
|
||||
assertUSLabel(OperatingSystem.Macintosh, KeyMod.Alt | KeyCode.KEY_A, '⌥A');
|
||||
assertUSLabel(OperatingSystem.Macintosh, KeyMod.WinCtrl | KeyCode.KEY_A, '⌃A');
|
||||
|
||||
// two modifiers
|
||||
assertUSLabel(OperatingSystem.Macintosh, KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_A, '⇧⌘A');
|
||||
assertUSLabel(OperatingSystem.Macintosh, KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_A, '⌥⌘A');
|
||||
assertUSLabel(OperatingSystem.Macintosh, KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.KEY_A, '⌃⌘A');
|
||||
assertUSLabel(OperatingSystem.Macintosh, KeyMod.Shift | KeyMod.Alt | KeyCode.KEY_A, '⇧⌥A');
|
||||
assertUSLabel(OperatingSystem.Macintosh, KeyMod.Shift | KeyMod.WinCtrl | KeyCode.KEY_A, '⌃⇧A');
|
||||
assertUSLabel(OperatingSystem.Macintosh, KeyMod.Alt | KeyMod.WinCtrl | KeyCode.KEY_A, '⌃⌥A');
|
||||
|
||||
// three modifiers
|
||||
assertUSLabel(OperatingSystem.Macintosh, KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyCode.KEY_A, '⇧⌥⌘A');
|
||||
assertUSLabel(OperatingSystem.Macintosh, KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.WinCtrl | KeyCode.KEY_A, '⌃⇧⌘A');
|
||||
assertUSLabel(OperatingSystem.Macintosh, KeyMod.CtrlCmd | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.KEY_A, '⌃⌥⌘A');
|
||||
assertUSLabel(OperatingSystem.Macintosh, KeyMod.Shift | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.KEY_A, '⌃⇧⌥A');
|
||||
|
||||
// four modifiers
|
||||
assertUSLabel(OperatingSystem.Macintosh, KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.KEY_A, '⌃⇧⌥⌘A');
|
||||
|
||||
// chord
|
||||
assertUSLabel(OperatingSystem.Macintosh, KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_A, KeyMod.CtrlCmd | KeyCode.KEY_B), '⌘A ⌘B');
|
||||
|
||||
// special keys
|
||||
assertUSLabel(OperatingSystem.Macintosh, KeyCode.LeftArrow, '←');
|
||||
assertUSLabel(OperatingSystem.Macintosh, KeyCode.UpArrow, '↑');
|
||||
assertUSLabel(OperatingSystem.Macintosh, KeyCode.RightArrow, '→');
|
||||
assertUSLabel(OperatingSystem.Macintosh, KeyCode.DownArrow, '↓');
|
||||
});
|
||||
|
||||
test('Aria label', () => {
|
||||
function assertAriaLabel(OS: OperatingSystem, keybinding: number, expected: string): void {
|
||||
const usResolvedKeybinding = new USLayoutResolvedKeybinding(createKeybinding(keybinding, OS), OS);
|
||||
assert.equal(usResolvedKeybinding.getAriaLabel(), expected);
|
||||
}
|
||||
|
||||
assertAriaLabel(OperatingSystem.Windows, KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.KEY_A, 'Control+Shift+Alt+Windows+A');
|
||||
assertAriaLabel(OperatingSystem.Linux, KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.KEY_A, 'Control+Shift+Alt+Windows+A');
|
||||
assertAriaLabel(OperatingSystem.Macintosh, KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.KEY_A, 'Control+Shift+Alt+Command+A');
|
||||
});
|
||||
|
||||
test('Electron Accelerator label', () => {
|
||||
function assertElectronAcceleratorLabel(OS: OperatingSystem, keybinding: number, expected: string): void {
|
||||
const usResolvedKeybinding = new USLayoutResolvedKeybinding(createKeybinding(keybinding, OS), OS);
|
||||
assert.equal(usResolvedKeybinding.getElectronAccelerator(), expected);
|
||||
}
|
||||
|
||||
assertElectronAcceleratorLabel(OperatingSystem.Windows, KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.KEY_A, 'Ctrl+Shift+Alt+Super+A');
|
||||
assertElectronAcceleratorLabel(OperatingSystem.Linux, KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.KEY_A, 'Ctrl+Shift+Alt+Super+A');
|
||||
assertElectronAcceleratorLabel(OperatingSystem.Macintosh, KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.KEY_A, 'Ctrl+Shift+Alt+Cmd+A');
|
||||
|
||||
// electron cannot handle chords
|
||||
assertElectronAcceleratorLabel(OperatingSystem.Windows, KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_A, KeyMod.CtrlCmd | KeyCode.KEY_B), null);
|
||||
assertElectronAcceleratorLabel(OperatingSystem.Linux, KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_A, KeyMod.CtrlCmd | KeyCode.KEY_B), null);
|
||||
assertElectronAcceleratorLabel(OperatingSystem.Macintosh, KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_A, KeyMod.CtrlCmd | KeyCode.KEY_B), null);
|
||||
|
||||
// electron cannot handle numpad keys
|
||||
assertElectronAcceleratorLabel(OperatingSystem.Windows, KeyCode.NUMPAD_1, null);
|
||||
assertElectronAcceleratorLabel(OperatingSystem.Linux, KeyCode.NUMPAD_1, null);
|
||||
assertElectronAcceleratorLabel(OperatingSystem.Macintosh, KeyCode.NUMPAD_1, null);
|
||||
|
||||
// special
|
||||
assertElectronAcceleratorLabel(OperatingSystem.Macintosh, KeyCode.LeftArrow, 'Left');
|
||||
assertElectronAcceleratorLabel(OperatingSystem.Macintosh, KeyCode.UpArrow, 'Up');
|
||||
assertElectronAcceleratorLabel(OperatingSystem.Macintosh, KeyCode.RightArrow, 'Right');
|
||||
assertElectronAcceleratorLabel(OperatingSystem.Macintosh, KeyCode.DownArrow, 'Down');
|
||||
});
|
||||
|
||||
test('User Settings label', () => {
|
||||
function assertElectronAcceleratorLabel(OS: OperatingSystem, keybinding: number, expected: string): void {
|
||||
const usResolvedKeybinding = new USLayoutResolvedKeybinding(createKeybinding(keybinding, OS), OS);
|
||||
assert.equal(usResolvedKeybinding.getUserSettingsLabel(), expected);
|
||||
}
|
||||
|
||||
assertElectronAcceleratorLabel(OperatingSystem.Windows, KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.KEY_A, 'ctrl+shift+alt+win+a');
|
||||
assertElectronAcceleratorLabel(OperatingSystem.Linux, KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.KEY_A, 'ctrl+shift+alt+meta+a');
|
||||
assertElectronAcceleratorLabel(OperatingSystem.Macintosh, KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyMod.WinCtrl | KeyCode.KEY_A, 'ctrl+shift+alt+cmd+a');
|
||||
|
||||
// electron cannot handle chords
|
||||
assertElectronAcceleratorLabel(OperatingSystem.Windows, KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_A, KeyMod.CtrlCmd | KeyCode.KEY_B), 'ctrl+a ctrl+b');
|
||||
assertElectronAcceleratorLabel(OperatingSystem.Linux, KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_A, KeyMod.CtrlCmd | KeyCode.KEY_B), 'ctrl+a ctrl+b');
|
||||
assertElectronAcceleratorLabel(OperatingSystem.Macintosh, KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_A, KeyMod.CtrlCmd | KeyCode.KEY_B), 'cmd+a cmd+b');
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,398 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { KeyCode, KeyMod, KeyChord, createKeybinding, KeybindingType, SimpleKeybinding } from 'vs/base/common/keyCodes';
|
||||
import { KeybindingResolver } from 'vs/platform/keybinding/common/keybindingResolver';
|
||||
import { ContextKeyAndExpr, ContextKeyExpr, IContext } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem';
|
||||
import { USLayoutResolvedKeybinding } from 'vs/platform/keybinding/common/usLayoutResolvedKeybinding';
|
||||
import { OS } from 'vs/base/common/platform';
|
||||
|
||||
function createContext(ctx: any) {
|
||||
return {
|
||||
getValue: (key: string) => {
|
||||
return ctx[key];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
suite('KeybindingResolver', () => {
|
||||
|
||||
function kbItem(keybinding: number, command: string, commandArgs: any, when: ContextKeyExpr, isDefault: boolean): ResolvedKeybindingItem {
|
||||
const resolvedKeybinding = (keybinding !== 0 ? new USLayoutResolvedKeybinding(createKeybinding(keybinding, OS), OS) : null);
|
||||
return new ResolvedKeybindingItem(
|
||||
resolvedKeybinding,
|
||||
command,
|
||||
commandArgs,
|
||||
when,
|
||||
isDefault
|
||||
);
|
||||
}
|
||||
|
||||
function getDispatchStr(runtimeKb: SimpleKeybinding): string {
|
||||
return USLayoutResolvedKeybinding.getDispatchStr(runtimeKb);
|
||||
}
|
||||
|
||||
test('resolve key', function () {
|
||||
let keybinding = KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_Z;
|
||||
let runtimeKeybinding = createKeybinding(keybinding, OS);
|
||||
let contextRules = ContextKeyExpr.equals('bar', 'baz');
|
||||
let keybindingItem = kbItem(keybinding, 'yes', null, contextRules, true);
|
||||
|
||||
assert.equal(KeybindingResolver.contextMatchesRules(createContext({ bar: 'baz' }), contextRules), true);
|
||||
assert.equal(KeybindingResolver.contextMatchesRules(createContext({ bar: 'bz' }), contextRules), false);
|
||||
|
||||
let resolver = new KeybindingResolver([keybindingItem], []);
|
||||
assert.equal(resolver.resolve(createContext({ bar: 'baz' }), null, getDispatchStr(<SimpleKeybinding>runtimeKeybinding)).commandId, 'yes');
|
||||
assert.equal(resolver.resolve(createContext({ bar: 'bz' }), null, getDispatchStr(<SimpleKeybinding>runtimeKeybinding)), null);
|
||||
});
|
||||
|
||||
test('resolve key with arguments', function () {
|
||||
let commandArgs = { text: 'no' };
|
||||
let keybinding = KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_Z;
|
||||
let runtimeKeybinding = createKeybinding(keybinding, OS);
|
||||
let contextRules = ContextKeyExpr.equals('bar', 'baz');
|
||||
let keybindingItem = kbItem(keybinding, 'yes', commandArgs, contextRules, true);
|
||||
|
||||
let resolver = new KeybindingResolver([keybindingItem], []);
|
||||
assert.equal(resolver.resolve(createContext({ bar: 'baz' }), null, getDispatchStr(<SimpleKeybinding>runtimeKeybinding)).commandArgs, commandArgs);
|
||||
});
|
||||
|
||||
test('KeybindingResolver.combine simple 1', function () {
|
||||
let defaults = [
|
||||
kbItem(KeyCode.KEY_A, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true)
|
||||
];
|
||||
let overrides = [
|
||||
kbItem(KeyCode.KEY_B, 'yes2', null, ContextKeyExpr.equals('2', 'b'), false)
|
||||
];
|
||||
let actual = KeybindingResolver.combine(defaults, overrides);
|
||||
assert.deepEqual(actual, [
|
||||
kbItem(KeyCode.KEY_A, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KEY_B, 'yes2', null, ContextKeyExpr.equals('2', 'b'), false),
|
||||
]);
|
||||
});
|
||||
|
||||
test('KeybindingResolver.combine simple 2', function () {
|
||||
let defaults = [
|
||||
kbItem(KeyCode.KEY_A, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KEY_B, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
];
|
||||
let overrides = [
|
||||
kbItem(KeyCode.KEY_C, 'yes3', null, ContextKeyExpr.equals('3', 'c'), false)
|
||||
];
|
||||
let actual = KeybindingResolver.combine(defaults, overrides);
|
||||
assert.deepEqual(actual, [
|
||||
kbItem(KeyCode.KEY_A, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KEY_B, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true),
|
||||
kbItem(KeyCode.KEY_C, 'yes3', null, ContextKeyExpr.equals('3', 'c'), false),
|
||||
]);
|
||||
});
|
||||
|
||||
test('KeybindingResolver.combine removal with not matching when', function () {
|
||||
let defaults = [
|
||||
kbItem(KeyCode.KEY_A, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KEY_B, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
];
|
||||
let overrides = [
|
||||
kbItem(KeyCode.KEY_A, '-yes1', null, ContextKeyExpr.equals('1', 'b'), false)
|
||||
];
|
||||
let actual = KeybindingResolver.combine(defaults, overrides);
|
||||
assert.deepEqual(actual, [
|
||||
kbItem(KeyCode.KEY_A, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KEY_B, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
]);
|
||||
});
|
||||
|
||||
test('KeybindingResolver.combine removal with not matching keybinding', function () {
|
||||
let defaults = [
|
||||
kbItem(KeyCode.KEY_A, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KEY_B, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
];
|
||||
let overrides = [
|
||||
kbItem(KeyCode.KEY_B, '-yes1', null, ContextKeyExpr.equals('1', 'a'), false)
|
||||
];
|
||||
let actual = KeybindingResolver.combine(defaults, overrides);
|
||||
assert.deepEqual(actual, [
|
||||
kbItem(KeyCode.KEY_A, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KEY_B, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
]);
|
||||
});
|
||||
|
||||
test('KeybindingResolver.combine removal with matching keybinding and when', function () {
|
||||
let defaults = [
|
||||
kbItem(KeyCode.KEY_A, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KEY_B, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
];
|
||||
let overrides = [
|
||||
kbItem(KeyCode.KEY_A, '-yes1', null, ContextKeyExpr.equals('1', 'a'), false)
|
||||
];
|
||||
let actual = KeybindingResolver.combine(defaults, overrides);
|
||||
assert.deepEqual(actual, [
|
||||
kbItem(KeyCode.KEY_B, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
]);
|
||||
});
|
||||
|
||||
test('KeybindingResolver.combine removal with unspecified keybinding', function () {
|
||||
let defaults = [
|
||||
kbItem(KeyCode.KEY_A, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KEY_B, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
];
|
||||
let overrides = [
|
||||
kbItem(0, '-yes1', null, ContextKeyExpr.equals('1', 'a'), false)
|
||||
];
|
||||
let actual = KeybindingResolver.combine(defaults, overrides);
|
||||
assert.deepEqual(actual, [
|
||||
kbItem(KeyCode.KEY_B, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
]);
|
||||
});
|
||||
|
||||
test('KeybindingResolver.combine removal with unspecified when', function () {
|
||||
let defaults = [
|
||||
kbItem(KeyCode.KEY_A, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KEY_B, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
];
|
||||
let overrides = [
|
||||
kbItem(KeyCode.KEY_A, '-yes1', null, null, false)
|
||||
];
|
||||
let actual = KeybindingResolver.combine(defaults, overrides);
|
||||
assert.deepEqual(actual, [
|
||||
kbItem(KeyCode.KEY_B, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
]);
|
||||
});
|
||||
|
||||
test('KeybindingResolver.combine removal with unspecified when and unspecified keybinding', function () {
|
||||
let defaults = [
|
||||
kbItem(KeyCode.KEY_A, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KEY_B, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
];
|
||||
let overrides = [
|
||||
kbItem(0, '-yes1', null, null, false)
|
||||
];
|
||||
let actual = KeybindingResolver.combine(defaults, overrides);
|
||||
assert.deepEqual(actual, [
|
||||
kbItem(KeyCode.KEY_B, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
]);
|
||||
});
|
||||
|
||||
test('issue #612#issuecomment-222109084 cannot remove keybindings for commands with ^', function () {
|
||||
let defaults = [
|
||||
kbItem(KeyCode.KEY_A, '^yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KEY_B, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
];
|
||||
let overrides = [
|
||||
kbItem(KeyCode.KEY_A, '-yes1', null, null, false)
|
||||
];
|
||||
let actual = KeybindingResolver.combine(defaults, overrides);
|
||||
assert.deepEqual(actual, [
|
||||
kbItem(KeyCode.KEY_B, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
]);
|
||||
});
|
||||
|
||||
test('contextIsEntirelyIncluded', function () {
|
||||
let assertIsIncluded = (a: ContextKeyExpr[], b: ContextKeyExpr[]) => {
|
||||
assert.equal(KeybindingResolver.whenIsEntirelyIncluded(false, new ContextKeyAndExpr(a), new ContextKeyAndExpr(b)), true);
|
||||
};
|
||||
let assertIsNotIncluded = (a: ContextKeyExpr[], b: ContextKeyExpr[]) => {
|
||||
assert.equal(KeybindingResolver.whenIsEntirelyIncluded(false, new ContextKeyAndExpr(a), new ContextKeyAndExpr(b)), false);
|
||||
};
|
||||
let key1IsTrue = ContextKeyExpr.equals('key1', true);
|
||||
let key1IsNotFalse = ContextKeyExpr.notEquals('key1', false);
|
||||
let key1IsFalse = ContextKeyExpr.equals('key1', false);
|
||||
let key1IsNotTrue = ContextKeyExpr.notEquals('key1', true);
|
||||
let key2IsTrue = ContextKeyExpr.equals('key2', true);
|
||||
let key2IsNotFalse = ContextKeyExpr.notEquals('key2', false);
|
||||
let key3IsTrue = ContextKeyExpr.equals('key3', true);
|
||||
let key4IsTrue = ContextKeyExpr.equals('key4', true);
|
||||
|
||||
assertIsIncluded([key1IsTrue], null);
|
||||
assertIsIncluded([key1IsTrue], []);
|
||||
assertIsIncluded([key1IsTrue], [key1IsTrue]);
|
||||
assertIsIncluded([key1IsTrue], [key1IsNotFalse]);
|
||||
|
||||
assertIsIncluded([key1IsFalse], []);
|
||||
assertIsIncluded([key1IsFalse], [key1IsFalse]);
|
||||
assertIsIncluded([key1IsFalse], [key1IsNotTrue]);
|
||||
|
||||
assertIsIncluded([key2IsNotFalse], []);
|
||||
assertIsIncluded([key2IsNotFalse], [key2IsNotFalse]);
|
||||
assertIsIncluded([key2IsNotFalse], [key2IsTrue]);
|
||||
|
||||
assertIsIncluded([key1IsTrue, key2IsNotFalse], [key2IsTrue]);
|
||||
assertIsIncluded([key1IsTrue, key2IsNotFalse], [key2IsNotFalse]);
|
||||
assertIsIncluded([key1IsTrue, key2IsNotFalse], [key1IsTrue]);
|
||||
assertIsIncluded([key1IsTrue, key2IsNotFalse], [key1IsNotFalse]);
|
||||
assertIsIncluded([key1IsTrue, key2IsNotFalse], []);
|
||||
|
||||
assertIsNotIncluded([key1IsTrue], [key1IsFalse]);
|
||||
assertIsNotIncluded([key1IsTrue], [key1IsNotTrue]);
|
||||
assertIsNotIncluded([key1IsNotFalse], [key1IsFalse]);
|
||||
assertIsNotIncluded([key1IsNotFalse], [key1IsNotTrue]);
|
||||
|
||||
assertIsNotIncluded([key1IsFalse], [key1IsTrue]);
|
||||
assertIsNotIncluded([key1IsFalse], [key1IsNotFalse]);
|
||||
assertIsNotIncluded([key1IsNotTrue], [key1IsTrue]);
|
||||
assertIsNotIncluded([key1IsNotTrue], [key1IsNotFalse]);
|
||||
|
||||
assertIsNotIncluded([key1IsTrue, key2IsNotFalse], [key3IsTrue]);
|
||||
assertIsNotIncluded([key1IsTrue, key2IsNotFalse], [key4IsTrue]);
|
||||
assertIsNotIncluded([key1IsTrue], [key2IsTrue]);
|
||||
assertIsNotIncluded([], [key2IsTrue]);
|
||||
assertIsNotIncluded(null, [key2IsTrue]);
|
||||
});
|
||||
|
||||
test('resolve command', function () {
|
||||
|
||||
function _kbItem(keybinding: number, command: string, when: ContextKeyExpr): ResolvedKeybindingItem {
|
||||
return kbItem(keybinding, command, null, when, true);
|
||||
}
|
||||
|
||||
let items = [
|
||||
// This one will never match because its "when" is always overwritten by another one
|
||||
_kbItem(
|
||||
KeyCode.KEY_X,
|
||||
'first',
|
||||
ContextKeyExpr.and(
|
||||
ContextKeyExpr.equals('key1', true),
|
||||
ContextKeyExpr.notEquals('key2', false)
|
||||
)
|
||||
),
|
||||
// This one always overwrites first
|
||||
_kbItem(
|
||||
KeyCode.KEY_X,
|
||||
'second',
|
||||
ContextKeyExpr.equals('key2', true)
|
||||
),
|
||||
// This one is a secondary mapping for `second`
|
||||
_kbItem(
|
||||
KeyCode.KEY_Z,
|
||||
'second',
|
||||
null
|
||||
),
|
||||
// This one sometimes overwrites first
|
||||
_kbItem(
|
||||
KeyCode.KEY_X,
|
||||
'third',
|
||||
ContextKeyExpr.equals('key3', true)
|
||||
),
|
||||
// This one is always overwritten by another one
|
||||
_kbItem(
|
||||
KeyMod.CtrlCmd | KeyCode.KEY_Y,
|
||||
'fourth',
|
||||
ContextKeyExpr.equals('key4', true)
|
||||
),
|
||||
// This one overwrites with a chord the previous one
|
||||
_kbItem(
|
||||
KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_Y, KeyCode.KEY_Z),
|
||||
'fifth',
|
||||
null
|
||||
),
|
||||
// This one has no keybinding
|
||||
_kbItem(
|
||||
0,
|
||||
'sixth',
|
||||
null
|
||||
),
|
||||
_kbItem(
|
||||
KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_U),
|
||||
'seventh',
|
||||
null
|
||||
),
|
||||
_kbItem(
|
||||
KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_K),
|
||||
'seventh',
|
||||
null
|
||||
),
|
||||
_kbItem(
|
||||
KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_U),
|
||||
'uncomment lines',
|
||||
null
|
||||
),
|
||||
_kbItem(
|
||||
KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_C),
|
||||
'comment lines',
|
||||
null
|
||||
),
|
||||
_kbItem(
|
||||
KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_G, KeyMod.CtrlCmd | KeyCode.KEY_C),
|
||||
'unreachablechord',
|
||||
null
|
||||
),
|
||||
_kbItem(
|
||||
KeyMod.CtrlCmd | KeyCode.KEY_G,
|
||||
'eleven',
|
||||
null
|
||||
)
|
||||
];
|
||||
|
||||
let resolver = new KeybindingResolver(items, []);
|
||||
|
||||
let testKey = (commandId: string, expectedKeys: number[]) => {
|
||||
// Test lookup
|
||||
let lookupResult = resolver.lookupKeybindings(commandId);
|
||||
assert.equal(lookupResult.length, expectedKeys.length, 'Length mismatch @ commandId ' + commandId + '; GOT: ' + JSON.stringify(lookupResult, null, '\t'));
|
||||
for (let i = 0, len = lookupResult.length; i < len; i++) {
|
||||
const expected = new USLayoutResolvedKeybinding(createKeybinding(expectedKeys[i], OS), OS);
|
||||
|
||||
assert.equal(lookupResult[i].resolvedKeybinding.getUserSettingsLabel(), expected.getUserSettingsLabel(), 'value mismatch @ commandId ' + commandId);
|
||||
}
|
||||
};
|
||||
|
||||
let testResolve = (ctx: IContext, _expectedKey: number, commandId: string) => {
|
||||
const expectedKey = createKeybinding(_expectedKey, OS);
|
||||
|
||||
if (expectedKey.type === KeybindingType.Chord) {
|
||||
let firstPart = getDispatchStr(expectedKey.firstPart);
|
||||
let chordPart = getDispatchStr(expectedKey.chordPart);
|
||||
|
||||
let result = resolver.resolve(ctx, null, firstPart);
|
||||
assert.ok(result !== null, 'Enters chord for ' + commandId);
|
||||
assert.equal(result.commandId, null, 'Enters chord for ' + commandId);
|
||||
assert.equal(result.enterChord, true, 'Enters chord for ' + commandId);
|
||||
|
||||
result = resolver.resolve(ctx, firstPart, chordPart);
|
||||
assert.ok(result !== null, 'Enters chord for ' + commandId);
|
||||
assert.equal(result.commandId, commandId, 'Finds chorded command ' + commandId);
|
||||
assert.equal(result.enterChord, false, 'Finds chorded command ' + commandId);
|
||||
} else {
|
||||
let result = resolver.resolve(ctx, null, getDispatchStr(expectedKey));
|
||||
assert.ok(result !== null, 'Finds command ' + commandId);
|
||||
assert.equal(result.commandId, commandId, 'Finds command ' + commandId);
|
||||
assert.equal(result.enterChord, false, 'Finds command ' + commandId);
|
||||
}
|
||||
};
|
||||
|
||||
testKey('first', []);
|
||||
|
||||
testKey('second', [KeyCode.KEY_Z, KeyCode.KEY_X]);
|
||||
testResolve(createContext({ key2: true }), KeyCode.KEY_X, 'second');
|
||||
testResolve(createContext({}), KeyCode.KEY_Z, 'second');
|
||||
|
||||
testKey('third', [KeyCode.KEY_X]);
|
||||
testResolve(createContext({ key3: true }), KeyCode.KEY_X, 'third');
|
||||
|
||||
testKey('fourth', []);
|
||||
|
||||
testKey('fifth', [KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_Y, KeyCode.KEY_Z)]);
|
||||
testResolve(createContext({}), KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_Y, KeyCode.KEY_Z), 'fifth');
|
||||
|
||||
testKey('seventh', [KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_K)]);
|
||||
testResolve(createContext({}), KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_K), 'seventh');
|
||||
|
||||
testKey('uncomment lines', [KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_U)]);
|
||||
testResolve(createContext({}), KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_U), 'uncomment lines');
|
||||
|
||||
testKey('comment lines', [KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_C)]);
|
||||
testResolve(createContext({}), KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_C), 'comment lines');
|
||||
|
||||
testKey('unreachablechord', []);
|
||||
|
||||
testKey('eleven', [KeyMod.CtrlCmd | KeyCode.KEY_G]);
|
||||
testResolve(createContext({}), KeyMod.CtrlCmd | KeyCode.KEY_G, 'eleven');
|
||||
|
||||
testKey('sixth', []);
|
||||
});
|
||||
});
|
||||
125
src/vs/platform/keybinding/test/common/mockKeybindingService.ts
Normal file
125
src/vs/platform/keybinding/test/common/mockKeybindingService.ts
Normal file
@@ -0,0 +1,125 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import { ResolvedKeybinding, Keybinding, SimpleKeybinding } from 'vs/base/common/keyCodes';
|
||||
import Event from 'vs/base/common/event';
|
||||
import { IKeybindingService, IKeybindingEvent, IKeyboardEvent } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IContextKey, IContextKeyService, IContextKeyServiceTarget, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IResolveResult } from 'vs/platform/keybinding/common/keybindingResolver';
|
||||
import { USLayoutResolvedKeybinding } from 'vs/platform/keybinding/common/usLayoutResolvedKeybinding';
|
||||
import { OS } from 'vs/base/common/platform';
|
||||
import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem';
|
||||
|
||||
class MockKeybindingContextKey<T> implements IContextKey<T> {
|
||||
private _key: string;
|
||||
private _defaultValue: T;
|
||||
private _value: T;
|
||||
|
||||
constructor(key: string, defaultValue: T) {
|
||||
this._key = key;
|
||||
this._defaultValue = defaultValue;
|
||||
this._value = this._defaultValue;
|
||||
}
|
||||
|
||||
public set(value: T): void {
|
||||
this._value = value;
|
||||
}
|
||||
|
||||
public reset(): void {
|
||||
this._value = this._defaultValue;
|
||||
}
|
||||
|
||||
public get(): T {
|
||||
return this._value;
|
||||
}
|
||||
}
|
||||
|
||||
export class MockContextKeyService implements IContextKeyService {
|
||||
|
||||
public _serviceBrand: any;
|
||||
private _keys = new Map<string, IContextKey<any>>();
|
||||
|
||||
public dispose(): void {
|
||||
//
|
||||
}
|
||||
public createKey<T>(key: string, defaultValue: T): IContextKey<T> {
|
||||
let ret = new MockKeybindingContextKey(key, defaultValue);
|
||||
this._keys.set(key, ret);
|
||||
return ret;
|
||||
}
|
||||
public contextMatchesRules(rules: ContextKeyExpr): boolean {
|
||||
return false;
|
||||
}
|
||||
public get onDidChangeContext(): Event<string[]> {
|
||||
return Event.None;
|
||||
}
|
||||
public getContextKeyValue(key: string) {
|
||||
if (this._keys.has(key)) {
|
||||
return this._keys.get(key).get();
|
||||
}
|
||||
}
|
||||
public getContext(domNode: HTMLElement): any {
|
||||
return null;
|
||||
}
|
||||
public createScoped(domNode: HTMLElement): IContextKeyService {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
export class MockKeybindingService implements IKeybindingService {
|
||||
public _serviceBrand: any;
|
||||
|
||||
public get onDidUpdateKeybindings(): Event<IKeybindingEvent> {
|
||||
return Event.None;
|
||||
}
|
||||
|
||||
public getDefaultKeybindingsContent(): string {
|
||||
return null;
|
||||
}
|
||||
|
||||
public getDefaultKeybindings(): ResolvedKeybindingItem[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
public getKeybindings(): ResolvedKeybindingItem[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
public resolveKeybinding(keybinding: Keybinding): ResolvedKeybinding[] {
|
||||
return [new USLayoutResolvedKeybinding(keybinding, OS)];
|
||||
}
|
||||
|
||||
public resolveKeyboardEvent(keyboardEvent: IKeyboardEvent): ResolvedKeybinding {
|
||||
let keybinding = new SimpleKeybinding(
|
||||
keyboardEvent.ctrlKey,
|
||||
keyboardEvent.shiftKey,
|
||||
keyboardEvent.altKey,
|
||||
keyboardEvent.metaKey,
|
||||
keyboardEvent.keyCode
|
||||
);
|
||||
return this.resolveKeybinding(keybinding)[0];
|
||||
}
|
||||
|
||||
public resolveUserBinding(userBinding: string): ResolvedKeybinding[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
public lookupKeybindings(commandId: string): ResolvedKeybinding[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
public lookupKeybinding(commandId: string): ResolvedKeybinding {
|
||||
return null;
|
||||
}
|
||||
|
||||
public customKeybindingsCount(): number {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public softDispatch(keybinding: IKeyboardEvent, target: IContextKeyServiceTarget): IResolveResult {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user