Merge branch 'master' into ben/electron
This commit is contained in:
commit
d2e85a97f4
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"account": "monacobuild",
|
||||
"container": "debuggers",
|
||||
"zip": "2985e20/node-debug.zip",
|
||||
"zip": "b5b96dd/node-debug.zip",
|
||||
"output": ""
|
||||
}
|
||||
|
|
|
@ -417,6 +417,52 @@ export function commonSuffixLength(a: string, b: string): number {
|
|||
// return 0xDC00 <= chrCode && chrCode <= 0xDFFF;
|
||||
//}
|
||||
|
||||
export function isFullWidthCharacter(charCode:number): boolean {
|
||||
// Do a cheap trick to better support wrapping of wide characters, treat them as 2 columns
|
||||
// http://jrgraphix.net/research/unicode_blocks.php
|
||||
// 2E80 — 2EFF CJK Radicals Supplement
|
||||
// 2F00 — 2FDF Kangxi Radicals
|
||||
// 2FF0 — 2FFF Ideographic Description Characters
|
||||
// 3000 — 303F CJK Symbols and Punctuation
|
||||
// 3040 — 309F Hiragana
|
||||
// 30A0 — 30FF Katakana
|
||||
// 3100 — 312F Bopomofo
|
||||
// 3130 — 318F Hangul Compatibility Jamo
|
||||
// 3190 — 319F Kanbun
|
||||
// 31A0 — 31BF Bopomofo Extended
|
||||
// 31F0 — 31FF Katakana Phonetic Extensions
|
||||
// 3200 — 32FF Enclosed CJK Letters and Months
|
||||
// 3300 — 33FF CJK Compatibility
|
||||
// 3400 — 4DBF CJK Unified Ideographs Extension A
|
||||
// 4DC0 — 4DFF Yijing Hexagram Symbols
|
||||
// 4E00 — 9FFF CJK Unified Ideographs
|
||||
// A000 — A48F Yi Syllables
|
||||
// A490 — A4CF Yi Radicals
|
||||
// AC00 — D7AF Hangul Syllables
|
||||
// [IGNORE] D800 — DB7F High Surrogates
|
||||
// [IGNORE] DB80 — DBFF High Private Use Surrogates
|
||||
// [IGNORE] DC00 — DFFF Low Surrogates
|
||||
// [IGNORE] E000 — F8FF Private Use Area
|
||||
// F900 — FAFF CJK Compatibility Ideographs
|
||||
// [IGNORE] FB00 — FB4F Alphabetic Presentation Forms
|
||||
// [IGNORE] FB50 — FDFF Arabic Presentation Forms-A
|
||||
// [IGNORE] FE00 — FE0F Variation Selectors
|
||||
// [IGNORE] FE20 — FE2F Combining Half Marks
|
||||
// [IGNORE] FE30 — FE4F CJK Compatibility Forms
|
||||
// [IGNORE] FE50 — FE6F Small Form Variants
|
||||
// [IGNORE] FE70 — FEFF Arabic Presentation Forms-B
|
||||
// FF00 — FFEF Halfwidth and Fullwidth Forms
|
||||
// [https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms]
|
||||
// of which FF01 - FF5E fullwidth ASCII of 21 to 7E
|
||||
// [IGNORE] and FF65 - FFDC halfwidth of Katakana and Hangul
|
||||
// [IGNORE] FFF0 — FFFF Specials
|
||||
return (
|
||||
(charCode >= 0x2E80 && charCode <= 0xD7AF)
|
||||
|| (charCode >= 0xF900 && charCode <= 0xFAFF)
|
||||
|| (charCode >= 0xFF01 && charCode <= 0xFF5E)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the difference score for two strings. More similar strings have a higher score.
|
||||
* We use largest common subsequence dynamic programming approach but penalize in the end for length differences.
|
||||
|
|
|
@ -126,51 +126,8 @@ export class CharacterHardWrappingLineMapperFactory implements ILineMapperFactor
|
|||
niceBreakVisibleColumn = 0;
|
||||
}
|
||||
|
||||
// Do a cheap trick to better support wrapping of wide characters, treat them as 2 columns
|
||||
// http://jrgraphix.net/research/unicode_blocks.php
|
||||
// 2E80 — 2EFF CJK Radicals Supplement
|
||||
// 2F00 — 2FDF Kangxi Radicals
|
||||
// 2FF0 — 2FFF Ideographic Description Characters
|
||||
// 3000 — 303F CJK Symbols and Punctuation
|
||||
// 3040 — 309F Hiragana
|
||||
// 30A0 — 30FF Katakana
|
||||
// 3100 — 312F Bopomofo
|
||||
// 3130 — 318F Hangul Compatibility Jamo
|
||||
// 3190 — 319F Kanbun
|
||||
// 31A0 — 31BF Bopomofo Extended
|
||||
// 31F0 — 31FF Katakana Phonetic Extensions
|
||||
// 3200 — 32FF Enclosed CJK Letters and Months
|
||||
// 3300 — 33FF CJK Compatibility
|
||||
// 3400 — 4DBF CJK Unified Ideographs Extension A
|
||||
// 4DC0 — 4DFF Yijing Hexagram Symbols
|
||||
// 4E00 — 9FFF CJK Unified Ideographs
|
||||
// A000 — A48F Yi Syllables
|
||||
// A490 — A4CF Yi Radicals
|
||||
// AC00 — D7AF Hangul Syllables
|
||||
// [IGNORE] D800 — DB7F High Surrogates
|
||||
// [IGNORE] DB80 — DBFF High Private Use Surrogates
|
||||
// [IGNORE] DC00 — DFFF Low Surrogates
|
||||
// [IGNORE] E000 — F8FF Private Use Area
|
||||
// F900 — FAFF CJK Compatibility Ideographs
|
||||
// [IGNORE] FB00 — FB4F Alphabetic Presentation Forms
|
||||
// [IGNORE] FB50 — FDFF Arabic Presentation Forms-A
|
||||
// [IGNORE] FE00 — FE0F Variation Selectors
|
||||
// [IGNORE] FE20 — FE2F Combining Half Marks
|
||||
// [IGNORE] FE30 — FE4F CJK Compatibility Forms
|
||||
// [IGNORE] FE50 — FE6F Small Form Variants
|
||||
// [IGNORE] FE70 — FEFF Arabic Presentation Forms-B
|
||||
// FF00 — FFEF Halfwidth and Fullwidth Forms
|
||||
// [https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms]
|
||||
// of which FF01 - FF5E fullwidth ASCII of 21 to 7E
|
||||
// [IGNORE] and FF65 - FFDC halfwidth of Katakana and Hangul
|
||||
// [IGNORE] FFF0 — FFFF Specials
|
||||
|
||||
var charColumnSize = 1;
|
||||
if (
|
||||
(charCode >= 0x2E80 && charCode <= 0xD7AF)
|
||||
|| (charCode >= 0xF900 && charCode <= 0xFAFF)
|
||||
|| (charCode >= 0xFF01 && charCode <= 0xFF5E)
|
||||
) {
|
||||
if (Strings.isFullWidthCharacter(charCode)) {
|
||||
charColumnSize = columnsForFullWidthChar;
|
||||
}
|
||||
|
||||
|
|
|
@ -130,13 +130,25 @@ export class ElectronIntegration {
|
|||
ipc.on('vscode:showAutoSaveInfo', () => {
|
||||
this.messageService.show(
|
||||
Severity.Info, {
|
||||
message: nls.localize('autoSaveInfo', "The **File | Auto Save** option moved into settings. Please configure **files.autoSaveDelay: 1** to restore the old behavior."),
|
||||
message: nls.localize('autoSaveInfo', "The **File | Auto Save** option moved into settings and **files.autoSaveDelay: 1** will be added to preserve it."),
|
||||
actions: [
|
||||
CloseAction,
|
||||
this.instantiationService.createInstance(OpenGlobalSettingsAction, OpenGlobalSettingsAction.ID, OpenGlobalSettingsAction.LABEL)
|
||||
]
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
ipc.on('vscode:showAutoSaveError', () => {
|
||||
this.messageService.show(
|
||||
Severity.Warning, {
|
||||
message: nls.localize('autoSaveError', "Unable to write to settings. Please add **files.autoSaveDelay: 1** to settings.json."),
|
||||
actions: [
|
||||
CloseAction,
|
||||
this.instantiationService.createInstance(OpenGlobalSettingsAction, OpenGlobalSettingsAction.ID, OpenGlobalSettingsAction.LABEL)
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private resolveKeybindings(actionIds: string[]): TPromise<{ id: string; binding: number; }[]> {
|
||||
|
|
|
@ -40,7 +40,7 @@ import {ConfigurationService} from 'vs/workbench/services/configuration/node/con
|
|||
import {FileService} from 'vs/workbench/services/files/electron-browser/fileService';
|
||||
import {SearchService} from 'vs/workbench/services/search/node/searchService';
|
||||
import {LifecycleService} from 'vs/workbench/services/lifecycle/electron-browser/lifecycleService';
|
||||
import PluginWorkbenchKeybindingService from 'vs/workbench/services/keybinding/electron-browser/pluginKeybindingService';
|
||||
import {WorkbenchKeybindingService} from 'vs/workbench/services/keybinding/electron-browser/keybindingService';
|
||||
import {MainThreadService} from 'vs/workbench/services/thread/electron-browser/threadService';
|
||||
import {MarkerService} from 'vs/platform/markers/common/markerService';
|
||||
import {IActionsService} from 'vs/platform/actions/common/actions';
|
||||
|
@ -164,7 +164,7 @@ export class WorkbenchShell {
|
|||
private themeService: IThemeService;
|
||||
private contextService: WorkspaceContextService;
|
||||
private telemetryService: ElectronTelemetryService;
|
||||
private keybindingService: PluginWorkbenchKeybindingService;
|
||||
private keybindingService: WorkbenchKeybindingService;
|
||||
|
||||
private container: HTMLElement;
|
||||
private toUnbind: { (): void; }[];
|
||||
|
@ -275,7 +275,7 @@ export class WorkbenchShell {
|
|||
let enableTelemetry = this.configuration.env.isBuilt && !this.configuration.env.pluginDevelopmentPath ? !!this.configuration.env.enableTelemetry : false;
|
||||
this.telemetryService = new ElectronTelemetryService(this.storageService, { enableTelemetry: enableTelemetry, version: this.configuration.env.version, commitHash: this.configuration.env.commitHash });
|
||||
|
||||
this.keybindingService = new PluginWorkbenchKeybindingService(this.contextService, eventService, this.telemetryService, <any>window);
|
||||
this.keybindingService = new WorkbenchKeybindingService(this.contextService, eventService, this.telemetryService, <any>window);
|
||||
|
||||
this.messageService = new MessageService(this.contextService, this.windowService, this.telemetryService, this.keybindingService);
|
||||
this.keybindingService.setMessageService(this.messageService);
|
||||
|
@ -517,7 +517,7 @@ export class WorkbenchShell {
|
|||
console.error(errorMsg);
|
||||
|
||||
// Show to user if friendly message provided
|
||||
if (error.friendlyMessage && this.messageService) {
|
||||
if (error && error.friendlyMessage && this.messageService) {
|
||||
this.messageService.show(Severity.Error, error.friendlyMessage);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import window = require('vs/workbench/electron-main/window');
|
|||
import lifecycle = require('vs/workbench/electron-main/lifecycle');
|
||||
import nls = require('vs/nls');
|
||||
import paths = require('vs/base/common/paths');
|
||||
import json = require('vs/base/common/json');
|
||||
import arrays = require('vs/base/common/arrays');
|
||||
import objects = require('vs/base/common/objects');
|
||||
import storage = require('vs/workbench/electron-main/storage');
|
||||
|
@ -174,10 +175,7 @@ export class WindowsManager {
|
|||
eventEmitter.emit(EventTypes.READY, win);
|
||||
|
||||
// TODO@Ben remove me in a couple of versions
|
||||
if (storage.getItem<number>('autoSaveDelay') === 1000) {
|
||||
storage.removeItem('autoSaveDelay');
|
||||
win.send('vscode:showAutoSaveInfo');
|
||||
}
|
||||
this.migrateAutoSave(win);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -341,6 +339,46 @@ export class WindowsManager {
|
|||
});
|
||||
}
|
||||
|
||||
private migrateAutoSave(win: window.VSCodeWindow): void {
|
||||
if (storage.getItem<number>('autoSaveDelay') === 1000) {
|
||||
storage.removeItem('autoSaveDelay');
|
||||
win.send('vscode:showAutoSaveInfo');
|
||||
|
||||
try {
|
||||
|
||||
// Initial settings file
|
||||
if (!fs.existsSync(env.appSettingsPath)) {
|
||||
fs.writeFileSync(env.appSettingsPath, JSON.stringify({ 'files.autoSaveDelay': 1 }, null, ' '));
|
||||
}
|
||||
|
||||
// Update existing settings file
|
||||
else {
|
||||
const settingsRaw = fs.readFileSync(env.appSettingsPath).toString();
|
||||
const lastClosing = settingsRaw.lastIndexOf('}');
|
||||
const errors = [];
|
||||
const res = json.parse(settingsRaw, errors);
|
||||
|
||||
// We found a closing '}' and the JSON does not contain errors
|
||||
if (lastClosing > 0 && !errors.length) {
|
||||
const hasOtherKeys = Object.getOwnPropertyNames(res).length > 0;
|
||||
|
||||
const migratedSettings = settingsRaw.substring(0, lastClosing) + '\n // Migrated from previous File | Auto Save setting:\n' + (hasOtherKeys ? ' , "files.autoSaveDelay": 1\n' : ' "files.autoSaveDelay": 1\n') + '}';
|
||||
|
||||
fs.writeFileSync(env.appSettingsPath, migratedSettings);
|
||||
}
|
||||
|
||||
// Otherwise inform user that we cannot migrate the settings
|
||||
else {
|
||||
win.send('vscode:showAutoSaveError');
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
env.log(error);
|
||||
win.send('vscode:showAutoSaveError');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public reload(win: window.VSCodeWindow, cli?: env.ICommandLineArguments): void {
|
||||
|
||||
// Only reload when the window has not vetoed this
|
||||
|
@ -599,7 +637,7 @@ export class WindowsManager {
|
|||
recentPaths.unshift(workspacePath);
|
||||
}
|
||||
|
||||
// Clear those dupes
|
||||
// Clear those dupes
|
||||
recentPaths = arrays.distinct(recentPaths);
|
||||
|
||||
// Make sure it is bounded
|
||||
|
|
|
@ -376,7 +376,7 @@ export class Model extends ee.EventEmitter implements debug.IModel {
|
|||
}
|
||||
|
||||
public addBreakpoints(rawData: debug.IRawBreakpoint[]): void {
|
||||
this.breakpoints = this.breakpoints.concat(rawData.map(rawBp => new Breakpoint(Source.fromUri(rawBp.uri), rawBp.lineNumber, rawBp.enabled, rawBp.condition)));
|
||||
this.breakpoints = this.breakpoints.concat(rawData.map(rawBp => new Breakpoint(new Source(Source.toRawSource(rawBp.uri, this)), rawBp.lineNumber, rawBp.enabled, rawBp.condition)));
|
||||
this.breakpointsActivated = true;
|
||||
this.emit(debug.ModelEvents.BREAKPOINTS_UPDATED);
|
||||
}
|
||||
|
@ -610,10 +610,10 @@ export class Model extends ee.EventEmitter implements debug.IModel {
|
|||
this.threads[data.threadId].callStack = data.callStack.map(
|
||||
(rsf, level) => {
|
||||
if (!rsf) {
|
||||
return new StackFrame(data.threadId, 0, Source.fromUri(uri.parse('unknown')), nls.localize('unknownStack', "Unknown stack location"), undefined, undefined);
|
||||
return new StackFrame(data.threadId, 0, new Source({ name: 'unknown' }), nls.localize('unknownStack', "Unknown stack location"), undefined, undefined);
|
||||
}
|
||||
|
||||
return new StackFrame(data.threadId, rsf.id, rsf.source ? new Source(rsf.source) : Source.fromUri(uri.parse('unknown')), rsf.name, rsf.line, rsf.column);
|
||||
|
||||
return new StackFrame(data.threadId, rsf.id, rsf.source ? new Source(rsf.source) : new Source({ name: 'unknown' }), rsf.name, rsf.line, rsf.column);
|
||||
});
|
||||
|
||||
this.threads[data.threadId].stoppedReason = data.stoppedReason;
|
||||
|
|
|
@ -52,13 +52,6 @@ export class Source {
|
|||
{ path: paths.normalize(uri.fsPath, true) };
|
||||
}
|
||||
|
||||
public static fromUri(uri: uri): Source {
|
||||
return new Source({
|
||||
name: Source.getName(uri),
|
||||
path: uri.fsPath,
|
||||
});
|
||||
}
|
||||
|
||||
private static getName(uri: uri): string {
|
||||
const uriStr = uri.toString();
|
||||
return uriStr.substr(uriStr.lastIndexOf('/') + 1);
|
||||
|
|
|
@ -110,7 +110,6 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService
|
|||
private registerListeners(eventService: IEventService, lifecycleService: ILifecycleService): void {
|
||||
this.toDispose.push(eventService.addListener2(EventType.FILE_CHANGES, (e: FileChangesEvent) => this.onFileChanges(e)));
|
||||
|
||||
|
||||
if (this.taskService) {
|
||||
this.toDispose.push(this.taskService.addListener2(TaskServiceEvents.Active, (e: TaskEvent) => {
|
||||
this.lastTaskEvent = e;
|
||||
|
@ -312,7 +311,7 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService
|
|||
private loadBreakpoints(): debug.IBreakpoint[] {
|
||||
try {
|
||||
return JSON.parse(this.storageService.get(DEBUG_BREAKPOINTS_KEY, StorageScope.WORKSPACE, '[]')).map((breakpoint: any) => {
|
||||
return new model.Breakpoint(breakpoint.source.raw ? new Source(breakpoint.source.raw) : Source.fromUri(uri.parse(breakpoint.source.uri)),
|
||||
return new model.Breakpoint(new Source(breakpoint.source.raw ? breakpoint.source.raw : { path: uri.parse(breakpoint.source.uri).fsPath, name: breakpoint.source.name }),
|
||||
breakpoint.desiredLineNumber || breakpoint.lineNumber, breakpoint.enabled, breakpoint.condition);
|
||||
});
|
||||
} catch (e) {
|
||||
|
|
|
@ -9,16 +9,6 @@ import { Source } from 'vs/workbench/parts/debug/common/debugSource';
|
|||
|
||||
suite('Debug - Source', () => {
|
||||
|
||||
test('from uri', () => {
|
||||
const u = uri.file('/a/b/c/d');
|
||||
const source = Source.fromUri(u);
|
||||
|
||||
assert.equal(source.available, true);
|
||||
assert.equal(source.inMemory, false);
|
||||
assert.equal(source.uri.toString(), u.toString());
|
||||
assert.equal(source.name, 'd');
|
||||
});
|
||||
|
||||
test('from raw source', () => {
|
||||
const rawSource = {
|
||||
name: 'zz',
|
||||
|
|
|
@ -1,100 +0,0 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import nls = require('vs/nls');
|
||||
import {Registry} from 'vs/platform/platform';
|
||||
import {KeybindingService} from 'vs/platform/keybinding/browser/keybindingServiceImpl';
|
||||
import {OptionsChangeEvent, EventType} from 'vs/workbench/common/events';
|
||||
import {IEventService} from 'vs/platform/event/common/event';
|
||||
import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry';
|
||||
import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace';
|
||||
import {IKeybindingItem, IUserFriendlyKeybinding} from 'vs/platform/keybinding/common/keybindingService';
|
||||
import {IOSupport} from 'vs/platform/keybinding/common/commonKeybindingResolver';
|
||||
import * as JSONContributionRegistry from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
|
||||
import {IJSONSchema} from 'vs/base/common/jsonSchema';
|
||||
|
||||
export abstract class WorkbenchKeybindingService extends KeybindingService {
|
||||
private contextService: IWorkspaceContextService;
|
||||
private eventService: IEventService;
|
||||
private telemetryService: ITelemetryService;
|
||||
private toDispose: Function;
|
||||
|
||||
constructor(contextService: IWorkspaceContextService, eventService: IEventService, telemetryService: ITelemetryService, domNode: HTMLElement) {
|
||||
this.contextService = contextService;
|
||||
super(domNode);
|
||||
this.eventService = eventService;
|
||||
this.telemetryService = telemetryService;
|
||||
this.toDispose = this.eventService.addListener(EventType.WORKBENCH_OPTIONS_CHANGED, (e) => this.onOptionsChanged(e));
|
||||
}
|
||||
|
||||
public customKeybindingsCount(): number {
|
||||
let opts = this.contextService.getOptions();
|
||||
if (opts.globalSettings && opts.globalSettings.keybindings && Array.isArray(opts.globalSettings.keybindings)) {
|
||||
return opts.globalSettings.keybindings.length;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected _getExtraKeybindings(isFirstTime: boolean): IKeybindingItem[] {
|
||||
let extras: IUserFriendlyKeybinding[] = [];
|
||||
let opts = this.contextService.getOptions();
|
||||
if (opts.globalSettings && opts.globalSettings.keybindings) {
|
||||
if (!isFirstTime) {
|
||||
let cnt = 0;
|
||||
if (Array.isArray(opts.globalSettings.keybindings)) {
|
||||
cnt = opts.globalSettings.keybindings.length;
|
||||
}
|
||||
this.telemetryService.publicLog('customKeybindingsChanged', {
|
||||
keyCount: cnt
|
||||
});
|
||||
}
|
||||
if (Array.isArray(opts.globalSettings.keybindings)) {
|
||||
extras = opts.globalSettings.keybindings;
|
||||
}
|
||||
}
|
||||
return extras.map((k, i) => IOSupport.readKeybindingItem(k, i));
|
||||
}
|
||||
|
||||
private onOptionsChanged(e: OptionsChangeEvent): void {
|
||||
if (e.key === 'globalSettings') {
|
||||
this.updateResolver();
|
||||
}
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this.toDispose();
|
||||
}
|
||||
}
|
||||
|
||||
let schemaId = 'local://schemas/keybindings';
|
||||
let schema : IJSONSchema = {
|
||||
'id': schemaId,
|
||||
'type': 'array',
|
||||
'title': nls.localize('keybindings.json.title', "Keybindings configuration"),
|
||||
'items': {
|
||||
'required': ['key'],
|
||||
'type': 'object',
|
||||
'default': { 'key': '{{_}}', 'command': '{{_}}', 'when': '{{_}}' },
|
||||
'properties': {
|
||||
'key': {
|
||||
'type': 'string',
|
||||
'description': nls.localize('keybindings.json.key', 'Key or key sequence (separated by space)'),
|
||||
},
|
||||
'command': {
|
||||
'description': nls.localize('keybindings.json.command', 'Name of the command to execute'),
|
||||
},
|
||||
'when': {
|
||||
'type': 'string',
|
||||
'description': nls.localize('keybindings.json.when', 'Condition when the key is active.')
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let schemaRegistry = <JSONContributionRegistry.IJSONContributionRegistry>Registry.as(JSONContributionRegistry.Extensions.JSONContribution);
|
||||
schemaRegistry.registerSchema(schemaId, schema);
|
||||
schemaRegistry.addSchemaFileAssociation('inmemory://defaults/keybindings.json', schemaId);
|
||||
schemaRegistry.addSchemaFileAssociation('%APP_SETTINGS_HOME%/keybindings.json', schemaId);
|
|
@ -0,0 +1,313 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import nls = require('vs/nls');
|
||||
import {TPromise} from 'vs/base/common/winjs.base';
|
||||
import {IJSONSchema} from 'vs/base/common/jsonSchema';
|
||||
import {IHTMLContentElement} from 'vs/base/common/htmlContent';
|
||||
import {Registry} from 'vs/platform/platform';
|
||||
import {IEventService} from 'vs/platform/event/common/event';
|
||||
import * as JSONContributionRegistry from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
|
||||
import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry';
|
||||
import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace';
|
||||
import {PluginsRegistry, IMessageCollector} from 'vs/platform/plugins/common/pluginsRegistry';
|
||||
import {IPluginService} from 'vs/platform/plugins/common/plugins';
|
||||
import {IOSupport} from 'vs/platform/keybinding/common/commonKeybindingResolver';
|
||||
import {KeybindingService} from 'vs/platform/keybinding/browser/keybindingServiceImpl';
|
||||
import {IKeybindingItem, IUserFriendlyKeybinding} from 'vs/platform/keybinding/common/keybindingService';
|
||||
import {ICommandRule, KeybindingsRegistry} from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import {Keybinding} from 'vs/base/common/keyCodes';
|
||||
import * as Platform from 'vs/base/common/platform';
|
||||
import {getNativeLabelProvider} from 'vs/workbench/services/keybinding/electron-browser/nativeKeymap';
|
||||
import {OptionsChangeEvent, EventType} from 'vs/workbench/common/events';
|
||||
|
||||
interface ContributedKeyBinding {
|
||||
command: string;
|
||||
key: string;
|
||||
when?: string;
|
||||
mac?: string;
|
||||
linux?: string;
|
||||
win?: string;
|
||||
}
|
||||
|
||||
function isContributedKeyBindingsArray(thing: ContributedKeyBinding|ContributedKeyBinding[]): thing is ContributedKeyBinding[] {
|
||||
return Array.isArray(thing);
|
||||
}
|
||||
|
||||
function isValidContributedKeyBinding(keyBinding: ContributedKeyBinding, rejects: string[]): boolean {
|
||||
if (!keyBinding) {
|
||||
rejects.push(nls.localize('nonempty', "expected non-empty value."));
|
||||
return false;
|
||||
}
|
||||
if (typeof keyBinding.command !== 'string') {
|
||||
rejects.push(nls.localize('requirestring', "property `{0}` is mandatory and must be of type `string`", 'command'));
|
||||
return false;
|
||||
}
|
||||
if (typeof keyBinding.key !== 'string') {
|
||||
rejects.push(nls.localize('requirestring', "property `{0}` is mandatory and must be of type `string`", 'key'));
|
||||
return false;
|
||||
}
|
||||
if (keyBinding.when && typeof keyBinding.when !== 'string') {
|
||||
rejects.push(nls.localize('optstring', "property `{0}` can be omitted or must be of type `string`", 'when'));
|
||||
return false;
|
||||
}
|
||||
if (keyBinding.mac && typeof keyBinding.mac !== 'string') {
|
||||
rejects.push(nls.localize('optstring', "property `{0}` can be omitted or must be of type `string`", 'mac'));
|
||||
return false;
|
||||
}
|
||||
if (keyBinding.linux && typeof keyBinding.linux !== 'string') {
|
||||
rejects.push(nls.localize('optstring', "property `{0}` can be omitted or must be of type `string`", 'linux'));
|
||||
return false;
|
||||
}
|
||||
if (keyBinding.win && typeof keyBinding.win !== 'string') {
|
||||
rejects.push(nls.localize('optstring', "property `{0}` can be omitted or must be of type `string`", 'win'));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
let keybindingType:IJSONSchema = {
|
||||
type: 'object',
|
||||
default: { command: '', key: '' },
|
||||
properties: {
|
||||
command: {
|
||||
description: nls.localize('vscode.extension.contributes.keybindings.command', 'Identifier of the command to run when keybinding is triggered.'),
|
||||
type: 'string'
|
||||
},
|
||||
key: {
|
||||
description: nls.localize('vscode.extension.contributes.keybindings.key', 'Key or key sequence (separate keys with plus-sign and sequences with space, e.g Ctrl+O and Ctrl+L L for a chord'),
|
||||
type: 'string'
|
||||
},
|
||||
mac: {
|
||||
description: nls.localize('vscode.extension.contributes.keybindings.mac', 'Mac specific key or key sequence.'),
|
||||
type: 'string'
|
||||
},
|
||||
linux: {
|
||||
description: nls.localize('vscode.extension.contributes.keybindings.linux', 'Linux specific key or key sequence.'),
|
||||
type: 'string'
|
||||
},
|
||||
win: {
|
||||
description: nls.localize('vscode.extension.contributes.keybindings.win', 'Windows specific key or key sequence.'),
|
||||
type: 'string'
|
||||
},
|
||||
when: {
|
||||
description: nls.localize('vscode.extension.contributes.keybindings.when', 'Condition when the key is active.'),
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let keybindingsExtPoint = PluginsRegistry.registerExtensionPoint<ContributedKeyBinding | ContributedKeyBinding[]>('keybindings', {
|
||||
description: nls.localize('vscode.extension.contributes.keybindings', "Contributes keybindings."),
|
||||
oneOf: [
|
||||
keybindingType,
|
||||
{
|
||||
type: 'array',
|
||||
items: keybindingType
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
export class WorkbenchKeybindingService extends KeybindingService {
|
||||
|
||||
private contextService: IWorkspaceContextService;
|
||||
private eventService: IEventService;
|
||||
private telemetryService: ITelemetryService;
|
||||
private toDispose: Function;
|
||||
private _pluginService: IPluginService;
|
||||
private _eventService: IEventService;
|
||||
|
||||
constructor(contextService: IWorkspaceContextService, eventService: IEventService, telemetryService: ITelemetryService, domNode: HTMLElement) {
|
||||
this.contextService = contextService;
|
||||
super(domNode);
|
||||
this.eventService = eventService;
|
||||
this.telemetryService = telemetryService;
|
||||
this.toDispose = this.eventService.addListener(EventType.WORKBENCH_OPTIONS_CHANGED, (e) => this.onOptionsChanged(e));
|
||||
this._eventService = eventService;
|
||||
keybindingsExtPoint.setHandler((extensions) => {
|
||||
let commandAdded = false;
|
||||
|
||||
for (let extension of extensions) {
|
||||
commandAdded = this._handleKeybindingsExtensionPointUser(extension.description.isBuiltin, extension.value, extension.collector) || commandAdded;
|
||||
}
|
||||
|
||||
if (commandAdded) {
|
||||
this.updateResolver();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setPluginService(pluginService: IPluginService): void {
|
||||
this._pluginService = pluginService;
|
||||
}
|
||||
|
||||
public customKeybindingsCount(): number {
|
||||
let opts = this.contextService.getOptions();
|
||||
if (opts.globalSettings && opts.globalSettings.keybindings && Array.isArray(opts.globalSettings.keybindings)) {
|
||||
return opts.globalSettings.keybindings.length;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected _getExtraKeybindings(isFirstTime: boolean): IKeybindingItem[] {
|
||||
let extras: IUserFriendlyKeybinding[] = [];
|
||||
let opts = this.contextService.getOptions();
|
||||
if (opts.globalSettings && opts.globalSettings.keybindings) {
|
||||
if (!isFirstTime) {
|
||||
let cnt = 0;
|
||||
if (Array.isArray(opts.globalSettings.keybindings)) {
|
||||
cnt = opts.globalSettings.keybindings.length;
|
||||
}
|
||||
this.telemetryService.publicLog('customKeybindingsChanged', {
|
||||
keyCount: cnt
|
||||
});
|
||||
}
|
||||
if (Array.isArray(opts.globalSettings.keybindings)) {
|
||||
extras = opts.globalSettings.keybindings;
|
||||
}
|
||||
}
|
||||
return extras.map((k, i) => IOSupport.readKeybindingItem(k, i));
|
||||
}
|
||||
|
||||
private onOptionsChanged(e: OptionsChangeEvent): void {
|
||||
if (e.key === 'globalSettings') {
|
||||
this.updateResolver();
|
||||
}
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this.toDispose();
|
||||
}
|
||||
|
||||
public getLabelFor(keybinding:Keybinding): string {
|
||||
return keybinding.toCustomLabel(getNativeLabelProvider());
|
||||
}
|
||||
|
||||
public getHTMLLabelFor(keybinding:Keybinding): IHTMLContentElement[] {
|
||||
return keybinding.toCustomHTMLLabel(getNativeLabelProvider());
|
||||
}
|
||||
|
||||
public getElectronAcceleratorFor(keybinding:Keybinding): string {
|
||||
if (Platform.isWindows) {
|
||||
// electron menus always do the correct rendering on Windows
|
||||
return super.getElectronAcceleratorFor(keybinding);
|
||||
}
|
||||
|
||||
let usLabel = keybinding._toUSLabel();
|
||||
let label = this.getLabelFor(keybinding);
|
||||
if (usLabel !== label) {
|
||||
// electron menus are incorrect in rendering (linux) and in rendering and interpreting (mac)
|
||||
// for non US standard keyboard layouts
|
||||
return null;
|
||||
}
|
||||
|
||||
return super.getElectronAcceleratorFor(keybinding);
|
||||
}
|
||||
|
||||
private _handleKeybindingsExtensionPointUser(isBuiltin: boolean, keybindings:ContributedKeyBinding | ContributedKeyBinding[], collector:IMessageCollector): boolean {
|
||||
if (isContributedKeyBindingsArray(keybindings)) {
|
||||
let commandAdded = false;
|
||||
for (let i = 0, len = keybindings.length; i < len; i++) {
|
||||
commandAdded = this._handleKeybinding(isBuiltin, i + 1, keybindings[i], collector) || commandAdded;
|
||||
}
|
||||
return commandAdded;
|
||||
} else {
|
||||
return this._handleKeybinding(isBuiltin, 1, keybindings, collector);
|
||||
}
|
||||
}
|
||||
|
||||
private _handleKeybinding(isBuiltin: boolean, idx:number, keybindings:ContributedKeyBinding, collector:IMessageCollector): boolean {
|
||||
|
||||
let rejects: string[] = [];
|
||||
let commandAdded = false;
|
||||
|
||||
if (isValidContributedKeyBinding(keybindings, rejects)) {
|
||||
let rule = this._asCommandRule(isBuiltin, idx++, keybindings);
|
||||
if (rule) {
|
||||
KeybindingsRegistry.registerCommandRule(rule);
|
||||
commandAdded = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (rejects.length > 0) {
|
||||
collector.error(nls.localize(
|
||||
'invalid.keybindings',
|
||||
"Invalid `contributes.{0}`: {1}",
|
||||
keybindingsExtPoint.name,
|
||||
rejects.join('\n')
|
||||
));
|
||||
}
|
||||
|
||||
return commandAdded;
|
||||
}
|
||||
|
||||
protected _invokeHandler(commandId: string, args: any): TPromise<any> {
|
||||
if (this._pluginService) {
|
||||
return this._pluginService.activateByEvent('onCommand:' + commandId).then(_ => {
|
||||
return super._invokeHandler(commandId, args);
|
||||
});
|
||||
}
|
||||
return TPromise.as(null);
|
||||
}
|
||||
|
||||
private _asCommandRule(isBuiltin: boolean, idx:number, binding: ContributedKeyBinding): ICommandRule {
|
||||
|
||||
let {command, when, key, mac, linux, win} = binding;
|
||||
|
||||
let weight: number;
|
||||
if (isBuiltin) {
|
||||
weight = KeybindingsRegistry.WEIGHT.builtinExtension(idx);
|
||||
} else {
|
||||
weight = KeybindingsRegistry.WEIGHT.externalExtension(idx);
|
||||
}
|
||||
|
||||
let desc = {
|
||||
id: command,
|
||||
context: IOSupport.readKeybindingContexts(when),
|
||||
weight: weight,
|
||||
primary: IOSupport.readKeybinding(key),
|
||||
mac: mac && { primary: IOSupport.readKeybinding(mac) },
|
||||
linux: linux && { primary: IOSupport.readKeybinding(linux) },
|
||||
win: win && { primary: IOSupport.readKeybinding(win) }
|
||||
};
|
||||
|
||||
if (!desc.primary && !desc.mac && !desc.linux && !desc.win) {
|
||||
return;
|
||||
}
|
||||
|
||||
return desc;
|
||||
}
|
||||
}
|
||||
|
||||
let schemaId = 'local://schemas/keybindings';
|
||||
let schema : IJSONSchema = {
|
||||
'id': schemaId,
|
||||
'type': 'array',
|
||||
'title': nls.localize('keybindings.json.title', "Keybindings configuration"),
|
||||
'items': {
|
||||
'required': ['key'],
|
||||
'type': 'object',
|
||||
'default': { 'key': '{{_}}', 'command': '{{_}}', 'when': '{{_}}' },
|
||||
'properties': {
|
||||
'key': {
|
||||
'type': 'string',
|
||||
'description': nls.localize('keybindings.json.key', 'Key or key sequence (separated by space)'),
|
||||
},
|
||||
'command': {
|
||||
'description': nls.localize('keybindings.json.command', 'Name of the command to execute'),
|
||||
},
|
||||
'when': {
|
||||
'type': 'string',
|
||||
'description': nls.localize('keybindings.json.when', 'Condition when the key is active.')
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let schemaRegistry = <JSONContributionRegistry.IJSONContributionRegistry>Registry.as(JSONContributionRegistry.Extensions.JSONContribution);
|
||||
schemaRegistry.registerSchema(schemaId, schema);
|
||||
schemaRegistry.addSchemaFileAssociation('inmemory://defaults/keybindings.json', schemaId);
|
||||
schemaRegistry.addSchemaFileAssociation('%APP_SETTINGS_HOME%/keybindings.json', schemaId);
|
|
@ -4,109 +4,10 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import nls = require('vs/nls');
|
||||
import {TPromise} from 'vs/base/common/winjs.base';
|
||||
import {IEventService} from 'vs/platform/event/common/event';
|
||||
import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry';
|
||||
import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace';
|
||||
import {PluginsRegistry, IMessageCollector} from 'vs/platform/plugins/common/pluginsRegistry';
|
||||
import {IPluginService} from 'vs/platform/plugins/common/plugins';
|
||||
import {IOSupport} from 'vs/platform/keybinding/common/commonKeybindingResolver';
|
||||
import {WorkbenchKeybindingService} from 'vs/workbench/services/keybinding/browser/keybindingService';
|
||||
import {ICommandRule, KeybindingsRegistry} from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import {IJSONSchema} from 'vs/base/common/jsonSchema';
|
||||
import {KeyCode, Keybinding, IKeyBindingLabelProvider, MacUIKeyLabelProvider, ClassicUIKeyLabelProvider} from 'vs/base/common/keyCodes';
|
||||
import * as nativeKeymap from 'native-keymap';
|
||||
import Platform = require('vs/base/common/platform');
|
||||
import {IHTMLContentElement} from 'vs/base/common/htmlContent';
|
||||
import {KeyCode, Keybinding, IKeyBindingLabelProvider, MacUIKeyLabelProvider, ClassicUIKeyLabelProvider} from 'vs/base/common/keyCodes';
|
||||
import {lookupKeyCode, setExtractKeyCode} from 'vs/base/browser/keyboardEvent';
|
||||
|
||||
interface ContributedKeyBinding {
|
||||
command: string;
|
||||
key: string;
|
||||
when?: string;
|
||||
mac?: string;
|
||||
linux?: string;
|
||||
win?: string;
|
||||
}
|
||||
|
||||
function isContributedKeyBindingsArray(thing: ContributedKeyBinding|ContributedKeyBinding[]): thing is ContributedKeyBinding[] {
|
||||
return Array.isArray(thing);
|
||||
}
|
||||
|
||||
function isValidContributedKeyBinding(keyBinding: ContributedKeyBinding, rejects: string[]): boolean {
|
||||
if (!keyBinding) {
|
||||
rejects.push(nls.localize('nonempty', "expected non-empty value."));
|
||||
return false;
|
||||
}
|
||||
if (typeof keyBinding.command !== 'string') {
|
||||
rejects.push(nls.localize('requirestring', "property `{0}` is mandatory and must be of type `string`", 'command'));
|
||||
return false;
|
||||
}
|
||||
if (typeof keyBinding.key !== 'string') {
|
||||
rejects.push(nls.localize('requirestring', "property `{0}` is mandatory and must be of type `string`", 'key'));
|
||||
return false;
|
||||
}
|
||||
if (keyBinding.when && typeof keyBinding.when !== 'string') {
|
||||
rejects.push(nls.localize('optstring', "property `{0}` can be omitted or must be of type `string`", 'when'));
|
||||
return false;
|
||||
}
|
||||
if (keyBinding.mac && typeof keyBinding.mac !== 'string') {
|
||||
rejects.push(nls.localize('optstring', "property `{0}` can be omitted or must be of type `string`", 'mac'));
|
||||
return false;
|
||||
}
|
||||
if (keyBinding.linux && typeof keyBinding.linux !== 'string') {
|
||||
rejects.push(nls.localize('optstring', "property `{0}` can be omitted or must be of type `string`", 'linux'));
|
||||
return false;
|
||||
}
|
||||
if (keyBinding.win && typeof keyBinding.win !== 'string') {
|
||||
rejects.push(nls.localize('optstring', "property `{0}` can be omitted or must be of type `string`", 'win'));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
let keybindingType:IJSONSchema = {
|
||||
type: 'object',
|
||||
default: { command: '', key: '' },
|
||||
properties: {
|
||||
command: {
|
||||
description: nls.localize('vscode.extension.contributes.keybindings.command', 'Identifier of the command to run when keybinding is triggered.'),
|
||||
type: 'string'
|
||||
},
|
||||
key: {
|
||||
description: nls.localize('vscode.extension.contributes.keybindings.key', 'Key or key sequence (separate keys with plus-sign and sequences with space, e.g Ctrl+O and Ctrl+L L for a chord'),
|
||||
type: 'string'
|
||||
},
|
||||
mac: {
|
||||
description: nls.localize('vscode.extension.contributes.keybindings.mac', 'Mac specific key or key sequence.'),
|
||||
type: 'string'
|
||||
},
|
||||
linux: {
|
||||
description: nls.localize('vscode.extension.contributes.keybindings.linux', 'Linux specific key or key sequence.'),
|
||||
type: 'string'
|
||||
},
|
||||
win: {
|
||||
description: nls.localize('vscode.extension.contributes.keybindings.win', 'Windows specific key or key sequence.'),
|
||||
type: 'string'
|
||||
},
|
||||
when: {
|
||||
description: nls.localize('vscode.extension.contributes.keybindings.when', 'Condition when the key is active.'),
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let keybindingsExtPoint = PluginsRegistry.registerExtensionPoint<ContributedKeyBinding | ContributedKeyBinding[]>('keybindings', {
|
||||
description: nls.localize('vscode.extension.contributes.keybindings', "Contributes keybindings."),
|
||||
oneOf: [
|
||||
keybindingType,
|
||||
{
|
||||
type: 'array',
|
||||
items: keybindingType
|
||||
}
|
||||
]
|
||||
});
|
||||
import Platform = require('vs/base/common/platform');
|
||||
|
||||
let getNativeKeymap = (function() {
|
||||
let called = false;
|
||||
|
@ -122,7 +23,7 @@ let getNativeKeymap = (function() {
|
|||
})();
|
||||
|
||||
// See https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
|
||||
// See https://github.com/alexandrudima/vscode-keyboard/blob/master/deps/chromium/keyboard_codes_win.h
|
||||
// See https://github.com/Microsoft/node-native-keymap/blob/master/deps/chromium/keyboard_codes_win.h
|
||||
const NATIVE_KEY_CODE_TO_KEY_CODE: {[nativeKeyCode:string]:KeyCode;} = {
|
||||
VKEY_BACK: KeyCode.Backspace,
|
||||
VKEY_TAB: KeyCode.Tab,
|
||||
|
@ -430,139 +331,11 @@ setExtractKeyCode((e:KeyboardEvent) => {
|
|||
return lookupKeyCode(e);
|
||||
});
|
||||
|
||||
export default class PluginWorkbenchKeybindingService extends WorkbenchKeybindingService {
|
||||
|
||||
private _pluginService: IPluginService;
|
||||
private _eventService: IEventService;
|
||||
|
||||
constructor(contextService: IWorkspaceContextService, eventService: IEventService, telemetryService: ITelemetryService, domNode: HTMLElement) {
|
||||
super(contextService, eventService, telemetryService, domNode);
|
||||
this._eventService = eventService;
|
||||
keybindingsExtPoint.setHandler((extensions) => {
|
||||
let commandAdded = false;
|
||||
|
||||
for (let extension of extensions) {
|
||||
commandAdded = this._handleKeybindingsExtensionPointUser(extension.description.isBuiltin, extension.value, extension.collector) || commandAdded;
|
||||
}
|
||||
|
||||
if (commandAdded) {
|
||||
this.updateResolver();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setPluginService(pluginService: IPluginService): void {
|
||||
this._pluginService = pluginService;
|
||||
}
|
||||
|
||||
public getLabelFor(keybinding:Keybinding): string {
|
||||
this._ensureNativeKeymap();
|
||||
return keybinding.toCustomLabel(this._nativeLabelProvider);
|
||||
}
|
||||
|
||||
public getHTMLLabelFor(keybinding:Keybinding): IHTMLContentElement[] {
|
||||
this._ensureNativeKeymap();
|
||||
return keybinding.toCustomHTMLLabel(this._nativeLabelProvider);
|
||||
}
|
||||
|
||||
public getElectronAcceleratorFor(keybinding:Keybinding): string {
|
||||
if (Platform.isWindows) {
|
||||
// electron menus always do the correct rendering on Windows
|
||||
return super.getElectronAcceleratorFor(keybinding);
|
||||
}
|
||||
|
||||
let usLabel = keybinding._toUSLabel();
|
||||
let label = this.getLabelFor(keybinding);
|
||||
if (usLabel !== label) {
|
||||
// electron menus are incorrect in rendering (linux) and in rendering and interpreting (mac)
|
||||
// for non US standard keyboard layouts
|
||||
return null;
|
||||
}
|
||||
|
||||
return super.getElectronAcceleratorFor(keybinding);
|
||||
}
|
||||
|
||||
private _handleKeybindingsExtensionPointUser(isBuiltin: boolean, keybindings:ContributedKeyBinding | ContributedKeyBinding[], collector:IMessageCollector): boolean {
|
||||
if (isContributedKeyBindingsArray(keybindings)) {
|
||||
let commandAdded = false;
|
||||
for (let i = 0, len = keybindings.length; i < len; i++) {
|
||||
commandAdded = this._handleKeybinding(isBuiltin, i + 1, keybindings[i], collector) || commandAdded;
|
||||
}
|
||||
return commandAdded;
|
||||
} else {
|
||||
return this._handleKeybinding(isBuiltin, 1, keybindings, collector);
|
||||
}
|
||||
}
|
||||
|
||||
private _handleKeybinding(isBuiltin: boolean, idx:number, keybindings:ContributedKeyBinding, collector:IMessageCollector): boolean {
|
||||
|
||||
let rejects: string[] = [];
|
||||
let commandAdded = false;
|
||||
|
||||
if (isValidContributedKeyBinding(keybindings, rejects)) {
|
||||
let rule = this._asCommandRule(isBuiltin, idx++, keybindings);
|
||||
if (rule) {
|
||||
KeybindingsRegistry.registerCommandRule(rule);
|
||||
commandAdded = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (rejects.length > 0) {
|
||||
collector.error(nls.localize(
|
||||
'invalid.keybindings',
|
||||
"Invalid `contributes.{0}`: {1}",
|
||||
keybindingsExtPoint.name,
|
||||
rejects.join('\n')
|
||||
));
|
||||
}
|
||||
|
||||
return commandAdded;
|
||||
}
|
||||
|
||||
protected _invokeHandler(commandId: string, args: any): TPromise<any> {
|
||||
return this._pluginService.activateByEvent('onCommand:' + commandId).then(_ => {
|
||||
return super._invokeHandler(commandId, args);
|
||||
});
|
||||
}
|
||||
|
||||
private _asCommandRule(isBuiltin: boolean, idx:number, binding: ContributedKeyBinding): ICommandRule {
|
||||
|
||||
let {command, when, key, mac, linux, win} = binding;
|
||||
|
||||
let weight: number;
|
||||
if (isBuiltin) {
|
||||
weight = KeybindingsRegistry.WEIGHT.builtinExtension(idx);
|
||||
} else {
|
||||
weight = KeybindingsRegistry.WEIGHT.externalExtension(idx);
|
||||
}
|
||||
|
||||
let desc = {
|
||||
id: command,
|
||||
context: IOSupport.readKeybindingContexts(when),
|
||||
weight: weight,
|
||||
primary: IOSupport.readKeybinding(key),
|
||||
mac: mac && { primary: IOSupport.readKeybinding(mac) },
|
||||
linux: linux && { primary: IOSupport.readKeybinding(linux) },
|
||||
win: win && { primary: IOSupport.readKeybinding(win) }
|
||||
};
|
||||
|
||||
if (!desc.primary && !desc.mac && !desc.linux && !desc.win) {
|
||||
return;
|
||||
}
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
private _gotNativeKeymap = false;
|
||||
private _nativeLabelProvider:IKeyBindingLabelProvider = null;
|
||||
private _ensureNativeKeymap(): void {
|
||||
if (this._gotNativeKeymap) {
|
||||
return;
|
||||
}
|
||||
this._gotNativeKeymap = true;
|
||||
|
||||
let nativeLabelProvider:IKeyBindingLabelProvider = null;
|
||||
export function getNativeLabelProvider(): IKeyBindingLabelProvider {
|
||||
if (!nativeLabelProvider) {
|
||||
// See https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
|
||||
// See https://github.com/alexandrudima/vscode-keyboard/blob/master/deps/chromium/keyboard_codes_win.h
|
||||
// See https://github.com/Microsoft/node-native-keymap/blob/master/deps/chromium/keyboard_codes_win.h
|
||||
let interestingKeyCodes:{[vkeyCode:string]:boolean;} = {
|
||||
VKEY_OEM_1: true,
|
||||
VKEY_OEM_PLUS: true,
|
||||
|
@ -608,11 +381,12 @@ export default class PluginWorkbenchKeybindingService extends WorkbenchKeybindin
|
|||
}
|
||||
|
||||
if (Platform.isMacintosh) {
|
||||
this._nativeLabelProvider = new NativeMacUIKeyLabelProvider(remaps);
|
||||
nativeLabelProvider = new NativeMacUIKeyLabelProvider(remaps);
|
||||
} else {
|
||||
this._nativeLabelProvider = new NativeClassicUIKeyLabelProvider(remaps);
|
||||
nativeLabelProvider = new NativeClassicUIKeyLabelProvider(remaps);
|
||||
}
|
||||
}
|
||||
return nativeLabelProvider;
|
||||
}
|
||||
|
||||
class NativeMacUIKeyLabelProvider extends MacUIKeyLabelProvider {
|
Loading…
Reference in a new issue