提交 80e93de8 编写于 作者: A Alex Dima

Bring editor command classes together

上级 d2bac293
/*---------------------------------------------------------------------------------------------
* 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 { TPromise } from 'vs/base/common/winjs.base';
import { IEditorService } from 'vs/platform/editor/common/editor';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { ICommandAndKeybindingRule, IKeybindings } from 'vs/platform/keybinding/common/keybindingsRegistry';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { ICodeEditorService, getCodeEditor } from 'vs/editor/common/services/codeEditorService';
import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
export interface ICommandKeybindingsOptions extends IKeybindings {
kbExpr?: ContextKeyExpr;
weight?: number;
}
export interface ICommandOptions {
id: string;
precondition: ContextKeyExpr;
kbOpts?: ICommandKeybindingsOptions;
description?: ICommandHandlerDescription;
}
export abstract class Command {
public readonly id: string;
public readonly precondition: ContextKeyExpr;
private readonly _kbOpts: ICommandKeybindingsOptions;
private readonly _description: ICommandHandlerDescription;
constructor(opts: ICommandOptions) {
this.id = opts.id;
this.precondition = opts.precondition;
this._kbOpts = opts.kbOpts;
this._description = opts.description;
}
public toCommandAndKeybindingRule(defaultWeight: number): ICommandAndKeybindingRule {
const kbOpts = this._kbOpts || { primary: 0 };
let kbWhen = kbOpts.kbExpr;
if (this.precondition) {
if (kbWhen) {
kbWhen = ContextKeyExpr.and(kbWhen, this.precondition);
} else {
kbWhen = this.precondition;
}
}
const weight = (typeof kbOpts.weight === 'number' ? kbOpts.weight : defaultWeight);
return {
id: this.id,
handler: (accessor, args) => this.runCommand(accessor, args),
weight: weight,
when: kbWhen,
primary: kbOpts.primary,
secondary: kbOpts.secondary,
win: kbOpts.win,
linux: kbOpts.linux,
mac: kbOpts.mac,
description: this._description
};
}
public abstract runCommand(accessor: ServicesAccessor, args: any): void | TPromise<void>;
}
export interface IContributionCommandOptions<T> extends ICommandOptions {
handler: (controller: T) => void;
}
export interface EditorControllerCommand<T extends editorCommon.IEditorContribution> {
new (opts: IContributionCommandOptions<T>): EditorCommand;
}
function findFocusedEditor(accessor: ServicesAccessor): editorCommon.ICommonCodeEditor {
return accessor.get(ICodeEditorService).getFocusedCodeEditor();
}
function getWorkbenchActiveEditor(accessor: ServicesAccessor): editorCommon.ICommonCodeEditor {
const editorService = accessor.get(IEditorService);
let activeEditor = (<any>editorService).getActiveEditor && (<any>editorService).getActiveEditor();
return getCodeEditor(activeEditor);
}
export abstract class EditorCommand extends Command {
/**
* Create a command class that is bound to a certain editor contribution.
*/
public static bindToContribution<T extends editorCommon.IEditorContribution>(controllerGetter: (editor: editorCommon.ICommonCodeEditor) => T): EditorControllerCommand<T> {
return class EditorControllerCommandImpl extends EditorCommand {
private _callback: (controller: T) => void;
constructor(opts: IContributionCommandOptions<T>) {
super(opts);
this._callback = opts.handler;
}
public runEditorCommand(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor, args: any): void {
let controller = controllerGetter(editor);
if (controller) {
this._callback(controllerGetter(editor));
}
}
};
}
public runCommand(accessor: ServicesAccessor, args: any): void | TPromise<void> {
// Find the editor with text focus
let editor = findFocusedEditor(accessor);
if (!editor) {
// Fallback to use what the workbench considers the active editor
editor = getWorkbenchActiveEditor(accessor);
}
if (!editor) {
// well, at least we tried...
return;
}
return editor.invokeWithinContext((editorAccessor) => {
const kbService = editorAccessor.get(IContextKeyService);
if (!kbService.contextMatchesRules(this.precondition)) {
// precondition does not hold
return;
}
return this.runEditorCommand(editorAccessor, editor, args);
});
}
public abstract runEditorCommand(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor, args: any): void | TPromise<void>;
}
...@@ -11,9 +11,8 @@ import * as editorCommon from 'vs/editor/common/editorCommon'; ...@@ -11,9 +11,8 @@ import * as editorCommon from 'vs/editor/common/editorCommon';
import { CursorState, ICursors, RevealTarget, IColumnSelectData, CursorContext } from 'vs/editor/common/controller/cursorCommon'; import { CursorState, ICursors, RevealTarget, IColumnSelectData, CursorContext } from 'vs/editor/common/controller/cursorCommon';
import { CursorChangeReason, VerticalRevealType } from 'vs/editor/common/controller/cursorEvents'; import { CursorChangeReason, VerticalRevealType } from 'vs/editor/common/controller/cursorEvents';
import { CursorMoveCommands, CursorMove as CursorMove_ } from 'vs/editor/common/controller/cursorMoveCommands'; import { CursorMoveCommands, CursorMove as CursorMove_ } from 'vs/editor/common/controller/cursorMoveCommands';
import { EditorCommand, ICommandOptions, Command } from 'vs/editor/common/config/config';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { registerEditorCommand } from 'vs/editor/common/editorCommonExtensions'; import { registerEditorCommand, ICommandOptions, EditorCommand, Command } from 'vs/editor/common/editorCommonExtensions';
import { IColumnSelectResult, ColumnSelection } from 'vs/editor/common/controller/cursorColumnSelection'; import { IColumnSelectResult, ColumnSelection } from 'vs/editor/common/controller/cursorColumnSelection';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
......
...@@ -8,22 +8,148 @@ import { illegalArgument } from 'vs/base/common/errors'; ...@@ -8,22 +8,148 @@ import { illegalArgument } from 'vs/base/common/errors';
import URI from 'vs/base/common/uri'; import URI from 'vs/base/common/uri';
import { TPromise } from 'vs/base/common/winjs.base'; import { TPromise } from 'vs/base/common/winjs.base';
import { ServicesAccessor, IConstructorSignature1 } from 'vs/platform/instantiation/common/instantiation'; import { ServicesAccessor, IConstructorSignature1 } from 'vs/platform/instantiation/common/instantiation';
import { CommandsRegistry } from 'vs/platform/commands/common/commands'; import { CommandsRegistry, ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { KeybindingsRegistry, ICommandAndKeybindingRule, IKeybindings } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { Registry } from 'vs/platform/platform'; import { Registry } from 'vs/platform/platform';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { ICommandOptions, Command as ConfigBasicCommand, EditorCommand as ConfigEditorCommand } from 'vs/editor/common/config/config';
import { Position } from 'vs/editor/common/core/position'; import { Position } from 'vs/editor/common/core/position';
import * as editorCommon from 'vs/editor/common/editorCommon'; import * as editorCommon from 'vs/editor/common/editorCommon';
import { IModelService } from 'vs/editor/common/services/modelService'; import { IModelService } from 'vs/editor/common/services/modelService';
import { MenuId, MenuRegistry, IMenuItem } from 'vs/platform/actions/common/actions'; import { MenuId, MenuRegistry, IMenuItem } from 'vs/platform/actions/common/actions';
import { IEditorService } from 'vs/platform/editor/common/editor';
import { IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { ICodeEditorService, getCodeEditor } from 'vs/editor/common/services/codeEditorService';
export type ServicesAccessor = ServicesAccessor; export type ServicesAccessor = ServicesAccessor;
export const Command = ConfigBasicCommand;
export const EditorCommand = ConfigEditorCommand;
export type ICommandOptions = ICommandOptions;
export type ICommonEditorContributionCtor = IConstructorSignature1<editorCommon.ICommonCodeEditor, editorCommon.IEditorContribution>; export type ICommonEditorContributionCtor = IConstructorSignature1<editorCommon.ICommonCodeEditor, editorCommon.IEditorContribution>;
// ----- Generic Command
export interface ICommandKeybindingsOptions extends IKeybindings {
kbExpr?: ContextKeyExpr;
weight?: number;
}
export interface ICommandOptions {
id: string;
precondition: ContextKeyExpr;
kbOpts?: ICommandKeybindingsOptions;
description?: ICommandHandlerDescription;
}
export abstract class Command {
public readonly id: string;
public readonly precondition: ContextKeyExpr;
private readonly _kbOpts: ICommandKeybindingsOptions;
private readonly _description: ICommandHandlerDescription;
constructor(opts: ICommandOptions) {
this.id = opts.id;
this.precondition = opts.precondition;
this._kbOpts = opts.kbOpts;
this._description = opts.description;
}
public toCommandAndKeybindingRule(defaultWeight: number): ICommandAndKeybindingRule {
const kbOpts = this._kbOpts || { primary: 0 };
let kbWhen = kbOpts.kbExpr;
if (this.precondition) {
if (kbWhen) {
kbWhen = ContextKeyExpr.and(kbWhen, this.precondition);
} else {
kbWhen = this.precondition;
}
}
const weight = (typeof kbOpts.weight === 'number' ? kbOpts.weight : defaultWeight);
return {
id: this.id,
handler: (accessor, args) => this.runCommand(accessor, args),
weight: weight,
when: kbWhen,
primary: kbOpts.primary,
secondary: kbOpts.secondary,
win: kbOpts.win,
linux: kbOpts.linux,
mac: kbOpts.mac,
description: this._description
};
}
public abstract runCommand(accessor: ServicesAccessor, args: any): void | TPromise<void>;
}
// ----- Editor Command & Editor Contribution Command
function findFocusedEditor(accessor: ServicesAccessor): editorCommon.ICommonCodeEditor {
return accessor.get(ICodeEditorService).getFocusedCodeEditor();
}
function getWorkbenchActiveEditor(accessor: ServicesAccessor): editorCommon.ICommonCodeEditor {
const editorService = accessor.get(IEditorService);
let activeEditor = (<any>editorService).getActiveEditor && (<any>editorService).getActiveEditor();
return getCodeEditor(activeEditor);
}
export interface IContributionCommandOptions<T> extends ICommandOptions {
handler: (controller: T) => void;
}
export interface EditorControllerCommand<T extends editorCommon.IEditorContribution> {
new (opts: IContributionCommandOptions<T>): EditorCommand;
}
export abstract class EditorCommand extends Command {
/**
* Create a command class that is bound to a certain editor contribution.
*/
public static bindToContribution<T extends editorCommon.IEditorContribution>(controllerGetter: (editor: editorCommon.ICommonCodeEditor) => T): EditorControllerCommand<T> {
return class EditorControllerCommandImpl extends EditorCommand {
private _callback: (controller: T) => void;
constructor(opts: IContributionCommandOptions<T>) {
super(opts);
this._callback = opts.handler;
}
public runEditorCommand(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor, args: any): void {
let controller = controllerGetter(editor);
if (controller) {
this._callback(controllerGetter(editor));
}
}
};
}
public runCommand(accessor: ServicesAccessor, args: any): void | TPromise<void> {
// Find the editor with text focus
let editor = findFocusedEditor(accessor);
if (!editor) {
// Fallback to use what the workbench considers the active editor
editor = getWorkbenchActiveEditor(accessor);
}
if (!editor) {
// well, at least we tried...
return;
}
return editor.invokeWithinContext((editorAccessor) => {
const kbService = editorAccessor.get(IContextKeyService);
if (!kbService.contextMatchesRules(this.precondition)) {
// precondition does not hold
return;
}
return this.runEditorCommand(editorAccessor, editor, args);
});
}
public abstract runEditorCommand(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor, args: any): void | TPromise<void>;
}
// ----- Editor Action
export interface IEditorCommandMenuOptions { export interface IEditorCommandMenuOptions {
group?: string; group?: string;
order?: number; order?: number;
...@@ -33,7 +159,7 @@ export interface IActionOptions extends ICommandOptions { ...@@ -33,7 +159,7 @@ export interface IActionOptions extends ICommandOptions {
alias: string; alias: string;
menuOpts?: IEditorCommandMenuOptions; menuOpts?: IEditorCommandMenuOptions;
} }
export abstract class EditorAction extends ConfigEditorCommand { export abstract class EditorAction extends EditorCommand {
public label: string; public label: string;
public alias: string; public alias: string;
...@@ -74,17 +200,17 @@ export abstract class EditorAction extends ConfigEditorCommand { ...@@ -74,17 +200,17 @@ export abstract class EditorAction extends ConfigEditorCommand {
public abstract run(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor, args: any): void | TPromise<void>; public abstract run(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor, args: any): void | TPromise<void>;
} }
// --- Editor Actions // --- Registration of commands and actions
export function editorAction(ctor: { new (): EditorAction; }): void { export function editorAction(ctor: { new (): EditorAction; }): void {
CommonEditorRegistry.registerEditorAction(new ctor()); CommonEditorRegistry.registerEditorAction(new ctor());
} }
export function editorCommand(ctor: { new (): ConfigEditorCommand }): void { export function editorCommand(ctor: { new (): EditorCommand }): void {
registerEditorCommand(new ctor()); registerEditorCommand(new ctor());
} }
export function registerEditorCommand<T extends ConfigEditorCommand>(editorCommand: T): T { export function registerEditorCommand<T extends EditorCommand>(editorCommand: T): T {
CommonEditorRegistry.registerEditorCommand(editorCommand); CommonEditorRegistry.registerEditorCommand(editorCommand);
return editorCommand; return editorCommand;
} }
...@@ -103,7 +229,7 @@ export module CommonEditorRegistry { ...@@ -103,7 +229,7 @@ export module CommonEditorRegistry {
export function getEditorActions(): EditorAction[] { export function getEditorActions(): EditorAction[] {
return EditorContributionRegistry.INSTANCE.getEditorActions(); return EditorContributionRegistry.INSTANCE.getEditorActions();
} }
export function getEditorCommand(commandId: string): ConfigEditorCommand { export function getEditorCommand(commandId: string): EditorCommand {
return EditorContributionRegistry.INSTANCE.getEditorCommand(commandId); return EditorContributionRegistry.INSTANCE.getEditorCommand(commandId);
} }
...@@ -119,7 +245,7 @@ export module CommonEditorRegistry { ...@@ -119,7 +245,7 @@ export module CommonEditorRegistry {
return KeybindingsRegistry.WEIGHT.editorContrib(importance); return KeybindingsRegistry.WEIGHT.editorContrib(importance);
} }
export function registerEditorCommand(editorCommand: ConfigEditorCommand): void { export function registerEditorCommand(editorCommand: EditorCommand): void {
EditorContributionRegistry.INSTANCE.registerEditorCommand(editorCommand); EditorContributionRegistry.INSTANCE.registerEditorCommand(editorCommand);
} }
...@@ -161,7 +287,7 @@ class EditorContributionRegistry { ...@@ -161,7 +287,7 @@ class EditorContributionRegistry {
private editorContributions: ICommonEditorContributionCtor[]; private editorContributions: ICommonEditorContributionCtor[];
private editorActions: EditorAction[]; private editorActions: EditorAction[];
private editorCommands: { [commandId: string]: ConfigEditorCommand; }; private editorCommands: { [commandId: string]: EditorCommand; };
constructor() { constructor() {
this.editorContributions = []; this.editorContributions = [];
...@@ -193,12 +319,12 @@ class EditorContributionRegistry { ...@@ -193,12 +319,12 @@ class EditorContributionRegistry {
return this.editorActions.slice(0); return this.editorActions.slice(0);
} }
public registerEditorCommand(editorCommand: ConfigEditorCommand) { public registerEditorCommand(editorCommand: EditorCommand) {
KeybindingsRegistry.registerCommandAndKeybindingRule(editorCommand.toCommandAndKeybindingRule(KeybindingsRegistry.WEIGHT.editorContrib())); KeybindingsRegistry.registerCommandAndKeybindingRule(editorCommand.toCommandAndKeybindingRule(KeybindingsRegistry.WEIGHT.editorContrib()));
this.editorCommands[editorCommand.id] = editorCommand; this.editorCommands[editorCommand.id] = editorCommand;
} }
public getEditorCommand(commandId: string): ConfigEditorCommand { public getEditorCommand(commandId: string): EditorCommand {
return (this.editorCommands[commandId] || null); return (this.editorCommands[commandId] || null);
} }
......
...@@ -7,10 +7,9 @@ ...@@ -7,10 +7,9 @@
import { RawContextKey, IContextKey, IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { RawContextKey, IContextKey, IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { ICommonCodeEditor } from 'vs/editor/common/editorCommon'; import { ICommonCodeEditor } from 'vs/editor/common/editorCommon';
import { commonEditorContribution, CommonEditorRegistry } from 'vs/editor/common/editorCommonExtensions'; import { commonEditorContribution, CommonEditorRegistry, EditorCommand } from 'vs/editor/common/editorCommonExtensions';
import { dispose, IDisposable } from 'vs/base/common/lifecycle'; import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import { SnippetSession } from './snippetSession'; import { SnippetSession } from './snippetSession';
import { EditorCommand } from 'vs/editor/common/config/config';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
......
...@@ -17,7 +17,7 @@ import { ...@@ -17,7 +17,7 @@ import {
DeleteWordLeft, DeleteWordStartLeft, DeleteWordEndLeft, DeleteWordLeft, DeleteWordStartLeft, DeleteWordEndLeft,
DeleteWordRight, DeleteWordStartRight, DeleteWordEndRight DeleteWordRight, DeleteWordStartRight, DeleteWordEndRight
} from 'vs/editor/contrib/wordOperations/common/wordOperations'; } from 'vs/editor/contrib/wordOperations/common/wordOperations';
import { EditorCommand } from 'vs/editor/common/config/config'; import { EditorCommand } from "vs/editor/common/editorCommonExtensions";
suite('WordOperations', () => { suite('WordOperations', () => {
......
...@@ -7,8 +7,7 @@ ...@@ -7,8 +7,7 @@
import { TPromise } from 'vs/base/common/winjs.base'; import { TPromise } from 'vs/base/common/winjs.base';
import { ICommonCodeEditor } from 'vs/editor/common/editorCommon'; import { ICommonCodeEditor } from 'vs/editor/common/editorCommon';
import { EditorAction, ServicesAccessor, IActionOptions } from 'vs/editor/common/editorCommonExtensions'; import { EditorAction, ServicesAccessor, IActionOptions, ICommandKeybindingsOptions } from 'vs/editor/common/editorCommonExtensions';
import { ICommandKeybindingsOptions } from 'vs/editor/common/config/config';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { grammarsExtPoint, ITMSyntaxExtensionPoint } from 'vs/editor/node/textMate/TMGrammars'; import { grammarsExtPoint, ITMSyntaxExtensionPoint } from 'vs/editor/node/textMate/TMGrammars';
import { IModeService } from 'vs/editor/common/services/modeService'; import { IModeService } from 'vs/editor/common/services/modeService';
......
...@@ -15,7 +15,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti ...@@ -15,7 +15,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { Range } from 'vs/editor/common/core/range'; import { Range } from 'vs/editor/common/core/range';
import * as editorCommon from 'vs/editor/common/editorCommon'; import * as editorCommon from 'vs/editor/common/editorCommon';
import { ServicesAccessor, registerEditorCommand } from 'vs/editor/common/editorCommonExtensions'; import { ServicesAccessor, registerEditorCommand, EditorCommand } from 'vs/editor/common/editorCommonExtensions';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { editorContribution } from 'vs/editor/browser/editorBrowserExtensions'; import { editorContribution } from 'vs/editor/browser/editorBrowserExtensions';
import { SnippetController2 } from 'vs/editor/contrib/snippet/browser/snippetController2'; import { SnippetController2 } from 'vs/editor/contrib/snippet/browser/snippetController2';
...@@ -26,7 +26,6 @@ import { parseTree, Node } from 'vs/base/common/json'; ...@@ -26,7 +26,6 @@ import { parseTree, Node } from 'vs/base/common/json';
import { KeybindingIO } from 'vs/workbench/services/keybinding/common/keybindingIO'; import { KeybindingIO } from 'vs/workbench/services/keybinding/common/keybindingIO';
import { ScanCodeBinding } from 'vs/workbench/services/keybinding/common/scanCode'; import { ScanCodeBinding } from 'vs/workbench/services/keybinding/common/scanCode';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { EditorCommand } from 'vs/editor/common/config/config';
const NLS_LAUNCH_MESSAGE = nls.localize('defineKeybinding.start', "Define Keybinding"); const NLS_LAUNCH_MESSAGE = nls.localize('defineKeybinding.start', "Define Keybinding");
const NLS_KB_LAYOUT_INFO_MESSAGE = nls.localize('defineKeybinding.kbLayoutInfoMessage', "For your current keyboard layout press "); const NLS_KB_LAYOUT_INFO_MESSAGE = nls.localize('defineKeybinding.kbLayoutInfoMessage', "For your current keyboard layout press ");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册