提交 e0ba314c 编写于 作者: A Alex Dima

Tweaks for #68863

上级 0566e654
......@@ -107,24 +107,17 @@ export class KeybindingParser {
return [new SimpleKeybinding(mods.ctrl, mods.shift, mods.alt, mods.meta, keyCode), mods.remains];
}
static parseUserBinding(input: string): Array<SimpleKeybinding | ScanCodeBinding> {
// TODO@chords: allow users to define N chords
static parseUserBinding(input: string): (SimpleKeybinding | ScanCodeBinding)[] {
if (!input) {
return [];
}
let parts = [];
let remains = input;
while (remains.length > 0) {
let [part, nextRemains] = this.parseSimpleUserBinding(remains);
let parts: (SimpleKeybinding | ScanCodeBinding)[] = [];
let part: SimpleKeybinding | ScanCodeBinding;
while (input.length > 0) {
[part, input] = this.parseSimpleUserBinding(input);
parts.push(part);
// check equality to break out of a possible infinite loop.
// if nothing was consumed it implies that an empty keybinding
// was returned.
if (remains === nextRemains) {
break;
}
remains = nextRemains;
}
return parts;
}
......
......@@ -45,6 +45,7 @@ export class KeybindingResolver {
continue;
}
// TODO@chords
this._addKeyPress(k.keypressParts[0], k);
}
}
......@@ -53,9 +54,11 @@ export class KeybindingResolver {
if (defaultKb.command !== command) {
return false;
}
// TODO@chords
if (keypressFirstPart && defaultKb.keypressParts[0] !== keypressFirstPart) {
return false;
}
// TODO@chords
if (keypressChordPart && defaultKb.keypressParts[1] !== keypressChordPart) {
return false;
}
......@@ -84,6 +87,7 @@ export class KeybindingResolver {
}
const command = override.command.substr(1);
// TODO@chords
const keypressFirstPart = override.keypressParts[0];
const keypressChordPart = override.keypressParts[1];
const when = override.when;
......@@ -117,6 +121,7 @@ export class KeybindingResolver {
const conflictIsChord = (conflict.keypressParts.length > 1);
const itemIsChord = (item.keypressParts.length > 1);
// TODO@chords
if (conflictIsChord && itemIsChord && conflict.keypressParts[1] !== item.keypressParts[1]) {
// The conflict only shares the chord start with this command
continue;
......@@ -247,6 +252,7 @@ export class KeybindingResolver {
lookupMap = [];
for (let i = 0, len = candidates.length; i < len; i++) {
let candidate = candidates[i];
// TODO@chords
if (candidate.keypressParts[1] === keypress) {
lookupMap.push(candidate);
}
......@@ -266,6 +272,7 @@ export class KeybindingResolver {
return null;
}
// TODO@chords
if (currentChord === null && result.keypressParts.length > 1 && result.keypressParts[1] !== null) {
return {
enterChord: true,
......
......@@ -10,8 +10,8 @@ import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
export class ResolvedKeybindingItem {
_resolvedKeybindingItemBrand: void;
public readonly keypressParts: string[];
public readonly resolvedKeybinding: ResolvedKeybinding | null;
public readonly keypressParts: string[];
public readonly bubble: boolean;
public readonly command: string | null;
public readonly commandArgs: any;
......@@ -20,11 +20,7 @@ export class ResolvedKeybindingItem {
constructor(resolvedKeybinding: ResolvedKeybinding | null, command: string | null, commandArgs: any, when: ContextKeyExpr | null, isDefault: boolean) {
this.resolvedKeybinding = resolvedKeybinding;
if (resolvedKeybinding) {
this.keypressParts = resolvedKeybinding.getDispatchParts();
} else {
this.keypressParts = [];
}
this.keypressParts = resolvedKeybinding ? removeElementsAfterNulls(resolvedKeybinding.getDispatchParts()) : [];
this.bubble = (command ? command.charCodeAt(0) === CharCode.Caret : false);
this.command = this.bubble ? command!.substr(1) : command;
this.commandArgs = commandArgs;
......@@ -32,3 +28,16 @@ export class ResolvedKeybindingItem {
this.isDefault = isDefault;
}
}
export function removeElementsAfterNulls<T>(arr: (T | null)[]): T[] {
let result: T[] = [];
for (let i = 0, len = arr.length; i < len; i++) {
const element = arr[i];
if (!element) {
// stop processing at first encountered null
return result;
}
result.push(element);
}
return result;
}
......@@ -272,11 +272,12 @@ export class KeybindingEditorDecorationsRenderer extends Disposable {
return false;
}
for (let i = 0, length = aParts.length; i < length; i++) {
for (let i = 0, len = aParts.length; i < len; i++) {
if (!this._userBindingEquals(aParts[i], bParts[i])) {
return false;
}
}
return true;
}
......
......@@ -11,8 +11,6 @@ suite('KeybindingsEditorContribution', () => {
function assertUserSettingsFuzzyEquals(a: string, b: string, expected: boolean): void {
const actual = KeybindingEditorDecorationsRenderer._userSettingsFuzzyEquals(a, b);
const message = expected ? `${a} == ${b}` : `${a} != ${b}`;
console.log(a);
console.log(b);
assert.equal(actual, expected, 'fuzzy: ' + message);
}
......
......@@ -5,15 +5,13 @@
import { SimpleKeybinding } from 'vs/base/common/keyCodes';
import { KeybindingParser } from 'vs/base/common/keybindingParser';
import { OperatingSystem } from 'vs/base/common/platform';
import { ScanCodeBinding } from 'vs/base/common/scanCode';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { IUserFriendlyKeybinding } from 'vs/platform/keybinding/common/keybinding';
import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem';
export interface IUserKeybindingItem {
firstPart: SimpleKeybinding | ScanCodeBinding | null;
chordPart: SimpleKeybinding | ScanCodeBinding | null;
parts: (SimpleKeybinding | ScanCodeBinding)[];
command: string | null;
commandArgs?: any;
when: ContextKeyExpr | null;
......@@ -21,7 +19,7 @@ export interface IUserKeybindingItem {
export class KeybindingIO {
public static writeKeybindingItem(out: OutputBuilder, item: ResolvedKeybindingItem, OS: OperatingSystem): void {
public static writeKeybindingItem(out: OutputBuilder, item: ResolvedKeybindingItem): void {
if (!item.resolvedKeybinding) {
return;
}
......@@ -41,15 +39,13 @@ export class KeybindingIO {
out.write('}');
}
public static readUserKeybindingItem(input: IUserFriendlyKeybinding, OS: OperatingSystem): IUserKeybindingItem {
// TODO yusuke: replace with keychords.
const [firstPart, chordPart] = (typeof input.key === 'string' ? KeybindingParser.parseUserBinding(input.key) : [null, null]);
public static readUserKeybindingItem(input: IUserFriendlyKeybinding): IUserKeybindingItem {
const parts = (typeof input.key === 'string' ? KeybindingParser.parseUserBinding(input.key) : []);
const when = (typeof input.when === 'string' ? ContextKeyExpr.deserialize(input.when) : null);
const command = (typeof input.command === 'string' ? input.command : null);
const commandArgs = (typeof input.args !== 'undefined' ? input.args : undefined);
return {
firstPart: firstPart,
chordPart: chordPart,
parts: parts,
command: command,
commandArgs: commandArgs,
when: when
......
......@@ -11,7 +11,7 @@ export interface IKeyboardMapper {
dumpDebugInfo(): string;
resolveKeybinding(keybinding: Keybinding): ResolvedKeybinding[];
resolveKeyboardEvent(keyboardEvent: IKeyboardEvent): ResolvedKeybinding;
resolveUserBinding(firstPart: Array<SimpleKeybinding | ScanCodeBinding>): ResolvedKeybinding[];
resolveUserBinding(firstPart: (SimpleKeybinding | ScanCodeBinding)[]): ResolvedKeybinding[];
}
export class CachedKeyboardMapper implements IKeyboardMapper {
......@@ -43,7 +43,7 @@ export class CachedKeyboardMapper implements IKeyboardMapper {
return this._actual.resolveKeyboardEvent(keyboardEvent);
}
public resolveUserBinding(parts: Array<SimpleKeybinding | ScanCodeBinding>): ResolvedKeybinding[] {
public resolveUserBinding(parts: (SimpleKeybinding | ScanCodeBinding)[]): ResolvedKeybinding[] {
return this._actual.resolveUserBinding(parts);
}
}
......@@ -9,6 +9,7 @@ import { IMMUTABLE_CODE_TO_KEY_CODE, ScanCode, ScanCodeBinding } from 'vs/base/c
import { IKeyboardEvent } from 'vs/platform/keybinding/common/keybinding';
import { USLayoutResolvedKeybinding } from 'vs/platform/keybinding/common/usLayoutResolvedKeybinding';
import { IKeyboardMapper } from 'vs/workbench/services/keybinding/common/keyboardMapper';
import { removeElementsAfterNulls } from 'vs/platform/keybinding/common/resolvedKeybindingItem';
/**
* A keyboard mapper to be used when reading the keymap from the OS fails.
......@@ -117,8 +118,8 @@ export class MacLinuxFallbackKeyboardMapper implements IKeyboardMapper {
return new SimpleKeybinding(binding.ctrlKey, binding.shiftKey, binding.altKey, binding.metaKey, keyCode);
}
public resolveUserBinding(input: Array<SimpleKeybinding | ScanCodeBinding>): ResolvedKeybinding[] {
let parts: SimpleKeybinding[] = input.map(this._resolveSimpleUserBinding.bind(this));
public resolveUserBinding(input: (SimpleKeybinding | ScanCodeBinding)[]): ResolvedKeybinding[] {
const parts: SimpleKeybinding[] = removeElementsAfterNulls(input.map(keybinding => this._resolveSimpleUserBinding(keybinding)));
if (parts.length > 0) {
return [new USLayoutResolvedKeybinding(new ChordKeybinding(parts), this._OS)];
}
......
......@@ -1053,8 +1053,8 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper {
return this.simpleKeybindingToScanCodeBinding(binding);
}
public resolveUserBinding(input: Array<SimpleKeybinding | ScanCodeBinding>): ResolvedKeybinding[] {
let parts: ScanCodeBinding[][] = input.map(this._resolveSimpleUserBinding.bind(this));
public resolveUserBinding(input: (SimpleKeybinding | ScanCodeBinding)[]): ResolvedKeybinding[] {
const parts: ScanCodeBinding[][] = input.map(keybinding => this._resolveSimpleUserBinding(keybinding));
let result: NativeResolvedKeybinding[] = [];
this._generateResolvedKeybindings(parts, 0, [], result);
return result;
......
......@@ -11,6 +11,7 @@ import { IMMUTABLE_CODE_TO_KEY_CODE, ScanCode, ScanCodeBinding, ScanCodeUtils }
import { IKeyboardEvent } from 'vs/platform/keybinding/common/keybinding';
import { IKeyboardMapper } from 'vs/workbench/services/keybinding/common/keyboardMapper';
import { BaseResolvedKeybinding } from 'vs/platform/keybinding/common/baseResolvedKeybinding';
import { removeElementsAfterNulls } from 'vs/platform/keybinding/common/resolvedKeybindingItem';
export interface IWindowsKeyMapping {
vkey: string;
......@@ -464,8 +465,8 @@ export class WindowsKeyboardMapper implements IKeyboardMapper {
return new SimpleKeybinding(binding.ctrlKey, binding.shiftKey, binding.altKey, binding.metaKey, keyCode);
}
public resolveUserBinding(input: Array<SimpleKeybinding | ScanCodeBinding>): ResolvedKeybinding[] {
let parts: SimpleKeybinding[] = input.map(this._resolveSimpleUserBinding.bind(this));
public resolveUserBinding(input: (SimpleKeybinding | ScanCodeBinding)[]): ResolvedKeybinding[] {
const parts: SimpleKeybinding[] = removeElementsAfterNulls(input.map(keybinding => this._resolveSimpleUserBinding(keybinding)));
if (parts.length > 0) {
return [new WindowsNativeResolvedKeybinding(this, parts)];
}
......
......@@ -412,16 +412,11 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService {
let result: ResolvedKeybindingItem[] = [], resultLen = 0;
for (const item of items) {
const when = (item.when ? item.when.normalize() : null);
const firstPart = item.firstPart;
const chordPart = item.chordPart;
if (!firstPart) {
const parts = item.parts;
if (parts.length === 0) {
// This might be a removal keybinding item in user settings => accept it
result[resultLen++] = new ResolvedKeybindingItem(null, item.command, item.commandArgs, when, isDefault);
} else {
let parts = [firstPart];
if (chordPart !== null) {
parts.push(chordPart);
}
const resolvedKeybindings = this._keyboardMapper.resolveUserBinding(parts);
for (const resolvedKeybinding of resolvedKeybindings) {
result[resultLen++] = new ResolvedKeybindingItem(resolvedKeybinding, item.command, item.commandArgs, when, isDefault);
......@@ -447,7 +442,7 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService {
});
}
return extraUserKeybindings.map((k) => KeybindingIO.readUserKeybindingItem(k, OS));
return extraUserKeybindings.map((k) => KeybindingIO.readUserKeybindingItem(k));
}
public resolveKeybinding(kb: Keybinding): ResolvedKeybinding[] {
......@@ -540,7 +535,7 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService {
let lastIndex = defaultKeybindings.length - 1;
defaultKeybindings.forEach((k, index) => {
KeybindingIO.writeKeybindingItem(out, k, OS);
KeybindingIO.writeKeybindingItem(out, k);
if (index !== lastIndex) {
out.writeLine(',');
} else {
......
......@@ -5,7 +5,7 @@
import * as assert from 'assert';
import { KeyChord, KeyCode, KeyMod, SimpleKeybinding, createKeybinding } from 'vs/base/common/keyCodes';
import { KeybindingParser } from 'vs/base/common/keybindingParser';
import { OS, OperatingSystem } from 'vs/base/common/platform';
import { OperatingSystem } from 'vs/base/common/platform';
import { ScanCode, ScanCodeBinding } from 'vs/base/common/scanCode';
import { IUserFriendlyKeybinding } from 'vs/platform/keybinding/common/keybinding';
import { USLayoutResolvedKeybinding } from 'vs/platform/keybinding/common/usLayoutResolvedKeybinding';
......@@ -126,37 +126,35 @@ suite('keybindingIO', () => {
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);
let keybindingItem = KeybindingIO.readUserKeybindingItem(userKeybinding);
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);
let keybindingItem = KeybindingIO.readUserKeybindingItem(userKeybinding);
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);
let keybindingItem = KeybindingIO.readUserKeybindingItem(userKeybinding);
assert.deepEqual(keybindingItem.parts, []);
});
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);
let keybindingItem = KeybindingIO.readUserKeybindingItem(userKeybinding);
assert.deepEqual(keybindingItem.parts, []);
});
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);
let keybindingItem = KeybindingIO.readUserKeybindingItem(userKeybinding);
assert.equal(keybindingItem.commandArgs.text, 'theText');
});
});
......@@ -44,7 +44,7 @@ export function assertResolveKeyboardEvent(mapper: IKeyboardMapper, keyboardEven
assert.deepEqual(actual, expected);
}
export function assertResolveUserBinding(mapper: IKeyboardMapper, parts: Array<SimpleKeybinding | ScanCodeBinding>, expected: IResolvedKeybinding[]): void {
export function assertResolveUserBinding(mapper: IKeyboardMapper, parts: (SimpleKeybinding | ScanCodeBinding)[], expected: IResolvedKeybinding[]): void {
let actual: IResolvedKeybinding[] = mapper.resolveUserBinding(parts).map(toIResolvedKeybinding);
assert.deepEqual(actual, expected);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册