Skip to content

Commit bca94b8

Browse files
committed
Let KeybindingResolver work with NormalizedKeybindingItem
1 parent e3e7bee commit bca94b8

8 files changed

Lines changed: 253 additions & 402 deletions

File tree

src/vs/editor/browser/standalone/simpleServices.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { IConfigurationService, IConfigurationServiceEvent, IConfigurationValue,
1212
import { IEditor, IEditorInput, IEditorOptions, IEditorService, IResourceInput, Position } from 'vs/platform/editor/common/editor';
1313
import { ICommandService, ICommand, ICommandEvent, ICommandHandler, CommandsRegistry } from 'vs/platform/commands/common/commands';
1414
import { SimpleResolvedKeybinding, AbstractKeybindingService } from 'vs/platform/keybinding/common/abstractKeybindingService';
15-
import { KeybindingResolver } from 'vs/platform/keybinding/common/keybindingResolver';
15+
import { KeybindingResolver, NormalizedKeybindingItem } from 'vs/platform/keybinding/common/keybindingResolver';
1616
import { IKeybindingEvent, IKeybindingItem, KeybindingSource } from 'vs/platform/keybinding/common/keybinding';
1717
import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
1818
import { IConfirmation, IMessageService } from 'vs/platform/message/common/message';
@@ -371,15 +371,13 @@ export class StandaloneKeybindingService extends AbstractKeybindingService {
371371

372372
protected _getResolver(): KeybindingResolver {
373373
if (!this._cachedResolver) {
374-
this._cachedResolver = new KeybindingResolver(KeybindingsRegistry.getDefaultKeybindings(), this._getExtraKeybindings());
374+
const defaults = KeybindingsRegistry.getDefaultKeybindings().map(k => NormalizedKeybindingItem.fromKeybindingItem(k, true));
375+
const overrides = this._dynamicKeybindings.map(k => NormalizedKeybindingItem.fromKeybindingItem(k, false));
376+
this._cachedResolver = new KeybindingResolver(defaults, overrides);
375377
}
376378
return this._cachedResolver;
377379
}
378380

379-
private _getExtraKeybindings(): IKeybindingItem[] {
380-
return this._dynamicKeybindings;
381-
}
382-
383381
protected _createResolvedKeybinding(kb: Keybinding): ResolvedKeybinding {
384382
return new SimpleResolvedKeybinding(kb);
385383
}

src/vs/editor/browser/standalone/standaloneCodeEditor.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import { CodeEditor } from 'vs/editor/browser/codeEditor';
2121
import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget';
2222
import { ICodeEditor, IDiffEditor } from 'vs/editor/browser/editorBrowser';
2323
import { IStandaloneColorService } from 'vs/editor/common/services/standaloneColorService';
24-
import { IOSupport } from 'vs/platform/keybinding/common/keybindingResolver';
2524
import { InternalEditorAction } from 'vs/editor/common/editorAction';
2625
import { MenuId, MenuRegistry, IMenuItem } from 'vs/platform/actions/common/actions';
2726

@@ -93,7 +92,7 @@ export class StandaloneCodeEditor extends CodeEditor implements IStandaloneCodeE
9392
return null;
9493
}
9594
let commandId = 'DYNAMIC_' + (++LAST_GENERATED_COMMAND_ID);
96-
let whenExpression = IOSupport.readKeybindingWhen(context);
95+
let whenExpression = ContextKeyExpr.deserialize(context);
9796
this._standaloneKeybindingService.addDynamicKeybinding(commandId, keybinding, handler, whenExpression);
9897
return commandId;
9998
}
@@ -116,24 +115,22 @@ export class StandaloneCodeEditor extends CodeEditor implements IStandaloneCodeE
116115
const label = _descriptor.label;
117116
const precondition = ContextKeyExpr.and(
118117
ContextKeyExpr.equals('editorId', this.getId()),
119-
IOSupport.readKeybindingWhen(_descriptor.precondition)
118+
ContextKeyExpr.deserialize(_descriptor.precondition)
120119
);
121120
const keybindings = _descriptor.keybindings;
122121
const keybindingsWhen = ContextKeyExpr.and(
123122
precondition,
124-
IOSupport.readKeybindingWhen(_descriptor.keybindingContext)
123+
ContextKeyExpr.deserialize(_descriptor.keybindingContext)
125124
);
126125
const contextMenuGroupId = _descriptor.contextMenuGroupId || null;
127126
const contextMenuOrder = _descriptor.contextMenuOrder || 0;
128127
const run = (): TPromise<void> => {
129128
return TPromise.as(_descriptor.run(this));
130129
};
131-
// return TPromise.as(this._run(this._editor));
132130

133131

134132
let toDispose: IDisposable[] = [];
135133

136-
137134
// Generate a unique id to allow the same descriptor.id across multiple editor instances
138135
const uniqueId = this.getId() + ':' + id;
139136

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
'use strict';
6+
7+
import * as assert from 'assert';
8+
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
9+
10+
suite('ContextKeyExpr', () => {
11+
test('ContextKeyExpr.equals', function () {
12+
let a = ContextKeyExpr.and(
13+
ContextKeyExpr.has('a1'),
14+
ContextKeyExpr.and(ContextKeyExpr.has('and.a')),
15+
ContextKeyExpr.has('a2'),
16+
ContextKeyExpr.equals('b1', 'bb1'),
17+
ContextKeyExpr.equals('b2', 'bb2'),
18+
ContextKeyExpr.notEquals('c1', 'cc1'),
19+
ContextKeyExpr.notEquals('c2', 'cc2'),
20+
ContextKeyExpr.not('d1'),
21+
ContextKeyExpr.not('d2')
22+
);
23+
let b = ContextKeyExpr.and(
24+
ContextKeyExpr.equals('b2', 'bb2'),
25+
ContextKeyExpr.notEquals('c1', 'cc1'),
26+
ContextKeyExpr.not('d1'),
27+
ContextKeyExpr.notEquals('c2', 'cc2'),
28+
ContextKeyExpr.has('a2'),
29+
ContextKeyExpr.equals('b1', 'bb1'),
30+
ContextKeyExpr.has('a1'),
31+
ContextKeyExpr.and(ContextKeyExpr.equals('and.a', true)),
32+
ContextKeyExpr.not('d2')
33+
);
34+
assert(a.equals(b), 'expressions should be equal');
35+
});
36+
37+
test('normalize', function () {
38+
let key1IsTrue = ContextKeyExpr.equals('key1', true);
39+
let key1IsNotFalse = ContextKeyExpr.notEquals('key1', false);
40+
let key1IsFalse = ContextKeyExpr.equals('key1', false);
41+
let key1IsNotTrue = ContextKeyExpr.notEquals('key1', true);
42+
43+
assert.ok(key1IsTrue.normalize().equals(ContextKeyExpr.has('key1')));
44+
assert.ok(key1IsNotFalse.normalize().equals(ContextKeyExpr.has('key1')));
45+
assert.ok(key1IsFalse.normalize().equals(ContextKeyExpr.not('key1')));
46+
assert.ok(key1IsNotTrue.normalize().equals(ContextKeyExpr.not('key1')));
47+
});
48+
49+
test('evaluate', function () {
50+
/* tslint:disable:triple-equals */
51+
let context = {
52+
'a': true,
53+
'b': false,
54+
'c': '5'
55+
};
56+
function testExpression(expr: string, expected: boolean): void {
57+
let rules = ContextKeyExpr.deserialize(expr);
58+
assert.equal(rules.evaluate(context), expected, expr);
59+
}
60+
function testBatch(expr: string, value: any): void {
61+
testExpression(expr, !!value);
62+
testExpression(expr + ' == true', !!value);
63+
testExpression(expr + ' != true', !value);
64+
testExpression(expr + ' == false', !value);
65+
testExpression(expr + ' != false', !!value);
66+
testExpression(expr + ' == 5', value == <any>'5');
67+
testExpression(expr + ' != 5', value != <any>'5');
68+
testExpression('!' + expr, !value);
69+
}
70+
71+
testBatch('a', true);
72+
testBatch('b', false);
73+
testBatch('c', '5');
74+
testBatch('z', undefined);
75+
76+
testExpression('a && !b', true && !false);
77+
testExpression('a && b', true && false);
78+
testExpression('a && !b && c == 5', true && !false && '5' == '5');
79+
/* tslint:enable:triple-equals */
80+
});
81+
});

src/vs/platform/keybinding/common/keybindingResolver.ts

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ export class NormalizedKeybindingItem {
6868
}
6969

7070
export class KeybindingResolver {
71-
private _defaultKeybindings: IKeybindingItem[];
71+
private _defaultKeybindings: NormalizedKeybindingItem[];
7272
private _defaultBoundCommands: IBoundCommands;
7373
private _map: ICommandMap;
7474
private _chords: IChordsMap;
@@ -79,7 +79,7 @@ export class KeybindingResolver {
7979
private _lookupMapUnreachable: Map<string, ArrayBuffer>;
8080
private _shouldWarnOnConflict: boolean;
8181

82-
constructor(defaultKeybindings: IKeybindingItem[], overrides: IKeybindingItem[], shouldWarnOnConflict: boolean = true) {
82+
constructor(defaultKeybindings: NormalizedKeybindingItem[], overrides: NormalizedKeybindingItem[], shouldWarnOnConflict: boolean = true) {
8383
this._defaultKeybindings = defaultKeybindings;
8484
this._shouldWarnOnConflict = shouldWarnOnConflict;
8585

@@ -146,11 +146,11 @@ export class KeybindingResolver {
146146

147147
}
148148

149-
public static combine(rawDefaults: IKeybindingItem[], rawOverrides: IKeybindingItem[]): NormalizedKeybindingItem[] {
150-
let defaults = rawDefaults.map(kb => NormalizedKeybindingItem.fromKeybindingItem(kb, true));
149+
public static combine(defaults: NormalizedKeybindingItem[], rawOverrides: NormalizedKeybindingItem[]): NormalizedKeybindingItem[] {
150+
defaults = defaults.slice(0);
151151
let overrides: NormalizedKeybindingItem[] = [];
152152
for (let i = 0, len = rawOverrides.length; i < len; i++) {
153-
let override = NormalizedKeybindingItem.fromKeybindingItem(rawOverrides[i], false);
153+
let override = rawOverrides[i];
154154
if (!override.command || override.command.length === 0 || override.command.charAt(0) !== '-') {
155155
overrides.push(override);
156156
continue;
@@ -412,7 +412,7 @@ export class OutputBuilder {
412412

413413
export class IOSupport {
414414

415-
public static writeKeybindingItem(out: OutputBuilder, item: IKeybindingItem): void {
415+
public static writeKeybindingItem(out: OutputBuilder, item: NormalizedKeybindingItem): void {
416416
let quotedSerializedKeybinding = JSON.stringify(IOSupport.writeKeybinding(item.keybinding));
417417
out.write(`{ "key": ${rightPaddedString(quotedSerializedKeybinding + ',', 25)} "command": `);
418418

@@ -437,7 +437,7 @@ export class IOSupport {
437437

438438
let when: ContextKeyExpr = null;
439439
if (typeof input.when === 'string') {
440-
when = IOSupport.readKeybindingWhen(input.when);
440+
when = ContextKeyExpr.deserialize(input.when);
441441
}
442442

443443
let command: string = null;
@@ -460,15 +460,11 @@ export class IOSupport {
460460
};
461461
}
462462

463-
public static writeKeybinding(input: number, Platform: ISimplifiedPlatform = platform): string {
464-
return KeybindingLabels.toUserSettingsLabel(createKeybinding(input), Platform);
463+
public static writeKeybinding(keybinding: Keybinding, Platform: ISimplifiedPlatform = platform): string {
464+
return KeybindingLabels.toUserSettingsLabel(keybinding, Platform);
465465
}
466466

467467
public static readKeybinding(input: string, Platform: ISimplifiedPlatform = platform): number {
468468
return KeybindingLabels.fromUserSettingsLabel(input, Platform);
469469
}
470-
471-
public static readKeybindingWhen(input: string): ContextKeyExpr {
472-
return ContextKeyExpr.deserialize(input);
473-
}
474470
}

src/vs/platform/keybinding/test/common/abstractKeybindingService.test.ts

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,11 @@ import { KeybindingLabels } from 'vs/platform/keybinding/common/keybindingLabels
1111
import { IDisposable } from 'vs/base/common/lifecycle';
1212
import Severity from 'vs/base/common/severity';
1313
import { ICommandService } from 'vs/platform/commands/common/commands';
14-
import { KeybindingResolver } from 'vs/platform/keybinding/common/keybindingResolver';
14+
import { KeybindingResolver, NormalizedKeybindingItem } from 'vs/platform/keybinding/common/keybindingResolver';
1515
import { ContextKeyExpr, IContextKeyService, IContextKeyServiceTarget } from 'vs/platform/contextkey/common/contextkey';
1616
import { IStatusbarService } from 'vs/platform/statusbar/common/statusbar';
1717
import { IMessageService } from 'vs/platform/message/common/message';
1818
import { TPromise } from 'vs/base/common/winjs.base';
19-
import { IKeybindingItem } from 'vs/platform/keybinding/common/keybinding';
2019

2120
suite('AbstractKeybindingService', () => {
2221

@@ -47,7 +46,7 @@ suite('AbstractKeybindingService', () => {
4746
}
4847
}
4948

50-
let createTestKeybindingService: (items: IKeybindingItem[], contextValue?: any) => TestKeybindingService = null;
49+
let createTestKeybindingService: (items: NormalizedKeybindingItem[], contextValue?: any) => TestKeybindingService = null;
5150
let currentContextValue: any = null;
5251
let executeCommandCalls: { commandId: string; args: any[]; }[] = null;
5352
let showMessageCalls: { sev: Severity, message: any; }[] = null;
@@ -60,7 +59,7 @@ suite('AbstractKeybindingService', () => {
6059
statusMessageCalls = [];
6160
statusMessageCallsDisposed = [];
6261

63-
createTestKeybindingService = (items: IKeybindingItem[]): TestKeybindingService => {
62+
createTestKeybindingService = (items: NormalizedKeybindingItem[]): TestKeybindingService => {
6463

6564
let contextKeyService: IContextKeyService = {
6665
_serviceBrand: undefined,
@@ -128,15 +127,9 @@ suite('AbstractKeybindingService', () => {
128127
statusMessageCallsDisposed = null;
129128
});
130129

131-
let lastWeight = 0;
132-
function kbItem(keybinding: number, command: string, when: ContextKeyExpr = null): IKeybindingItem {
133-
return {
134-
keybinding: keybinding,
135-
when: when,
136-
command: command,
137-
weight1: ++lastWeight,
138-
weight2: 0
139-
};
130+
function kbItem(keybinding: number, command: string, when: ContextKeyExpr = null): NormalizedKeybindingItem {
131+
let kb = (keybinding !== 0 ? createKeybinding(keybinding) : null);
132+
return new NormalizedKeybindingItem(kb, command, null, when, true);
140133
}
141134

142135
test('issue #16498: chord mode is quit for invalid chords', () => {

src/vs/platform/keybinding/test/common/keybindingIO.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
'use strict';
66

77
import * as assert from 'assert';
8-
import { KeyCode, KeyMod, KeyChord } from 'vs/base/common/keyCodes';
8+
import { createKeybinding, KeyCode, KeyMod, KeyChord } from 'vs/base/common/keyCodes';
99
import { NormalizedKeybindingItem, IOSupport } from 'vs/platform/keybinding/common/keybindingResolver';
1010
import { IUserFriendlyKeybinding } from 'vs/platform/keybinding/common/keybinding';
1111
import { ISimplifiedPlatform } from 'vs/platform/keybinding/common/keybindingLabels';
@@ -18,7 +18,7 @@ suite('Keybinding IO', () => {
1818
const LINUX = { isMacintosh: false, isWindows: false };
1919

2020
function testOneSerialization(keybinding: number, expected: string, msg: string, Platform: ISimplifiedPlatform): void {
21-
let actualSerialized = IOSupport.writeKeybinding(keybinding, Platform);
21+
let actualSerialized = IOSupport.writeKeybinding(createKeybinding(keybinding), Platform);
2222
assert.equal(actualSerialized, expected, expected + ' - ' + msg);
2323
}
2424
function testSerialization(keybinding: number, expectedWin: string, expectedMac: string, expectedLinux: string): void {

0 commit comments

Comments
 (0)