未验证 提交 5fb0f1ea 编写于 作者: A Alexandru Dima 提交者: GitHub

Merge pull request #66458 from usernamehw/json_if_validation

Autocomplete/validation `args` for keybindings.json
...@@ -86,7 +86,28 @@ export namespace EditorScroll_ { ...@@ -86,7 +86,28 @@ export namespace EditorScroll_ {
* 'value': Number of units to move. Default is '1'. * 'value': Number of units to move. Default is '1'.
* 'revealCursor': If 'true' reveals the cursor if it is outside view port. * 'revealCursor': If 'true' reveals the cursor if it is outside view port.
`, `,
constraint: isEditorScrollArgs constraint: isEditorScrollArgs,
schema: {
'type': 'object',
'required': ['to'],
'properties': {
'to': {
'type': 'string',
'enum': ['up', 'down']
},
'by': {
'type': 'string',
'enum': ['line', 'wrappedLine', 'page', 'halfPage']
},
'value': {
'type': 'number',
'default': 1
},
'revealCursor': {
'type': 'boolean',
}
}
}
} }
] ]
}; };
...@@ -217,7 +238,20 @@ export namespace RevealLine_ { ...@@ -217,7 +238,20 @@ export namespace RevealLine_ {
'top', 'center', 'bottom' 'top', 'center', 'bottom'
\`\`\` \`\`\`
`, `,
constraint: isRevealLineArgs constraint: isRevealLineArgs,
schema: {
'type': 'object',
'required': ['lineNumber'],
'properties': {
'lineNumber': {
'type': 'number',
},
'at': {
'type': 'string',
'enum': ['top', 'center', 'bottom']
}
}
}
} }
] ]
}; };
...@@ -1691,10 +1725,11 @@ class EditorHandlerCommand extends Command { ...@@ -1691,10 +1725,11 @@ class EditorHandlerCommand extends Command {
private readonly _handlerId: string; private readonly _handlerId: string;
constructor(id: string, handlerId: string) { constructor(id: string, handlerId: string, description?: ICommandHandlerDescription) {
super({ super({
id: id, id: id,
precondition: null precondition: null,
description: description
}); });
this._handlerId = handlerId; this._handlerId = handlerId;
} }
...@@ -1767,12 +1802,26 @@ registerCommand(new EditorOrNativeTextInputCommand({ ...@@ -1767,12 +1802,26 @@ registerCommand(new EditorOrNativeTextInputCommand({
})); }));
registerCommand(new EditorHandlerCommand('default:' + Handler.Redo, Handler.Redo)); registerCommand(new EditorHandlerCommand('default:' + Handler.Redo, Handler.Redo));
function registerOverwritableCommand(handlerId: string): void { function registerOverwritableCommand(handlerId: string, description?: ICommandHandlerDescription): void {
registerCommand(new EditorHandlerCommand('default:' + handlerId, handlerId)); registerCommand(new EditorHandlerCommand('default:' + handlerId, handlerId));
registerCommand(new EditorHandlerCommand(handlerId, handlerId)); registerCommand(new EditorHandlerCommand(handlerId, handlerId, description));
} }
registerOverwritableCommand(Handler.Type); registerOverwritableCommand(Handler.Type, {
description: `Type`,
args: [{
name: 'args',
schema: {
'type': 'object',
'required': ['text'],
'properties': {
'text': {
'type': 'string'
}
},
}
}]
});
registerOverwritableCommand(Handler.ReplacePreviousChar); registerOverwritableCommand(Handler.ReplacePreviousChar);
registerOverwritableCommand(Handler.CompositionStart); registerOverwritableCommand(Handler.CompositionStart);
registerOverwritableCommand(Handler.CompositionEnd); registerOverwritableCommand(Handler.CompositionEnd);
......
...@@ -616,7 +616,29 @@ export namespace CursorMove { ...@@ -616,7 +616,29 @@ export namespace CursorMove {
* 'value': Number of units to move. Default is '1'. * 'value': Number of units to move. Default is '1'.
* 'select': If 'true' makes the selection. Default is 'false'. * 'select': If 'true' makes the selection. Default is 'false'.
`, `,
constraint: isCursorMoveArgs constraint: isCursorMoveArgs,
schema: {
'type': 'object',
'required': ['to'],
'properties': {
'to': {
'type': 'string',
'enum': ['left', 'right', 'up', 'down', 'wrappedLineStart', 'wrappedLineEnd', 'wrappedLineColumnCenter', 'wrappedLineFirstNonWhitespaceCharacter', 'wrappedLineLastNonWhitespaceCharacter', 'viewPortTop', 'viewPortCenter', 'viewPortBottom', 'viewPortIfOutside']
},
'by': {
'type': 'string',
'enum': ['line', 'wrappedLine', 'character', 'halfLine']
},
'value': {
'type': 'number',
'default': 1
},
'select': {
'type': 'boolean',
'default': false
}
}
}
} }
] ]
}; };
......
...@@ -253,7 +253,27 @@ export class CodeActionCommand extends EditorCommand { ...@@ -253,7 +253,27 @@ export class CodeActionCommand extends EditorCommand {
constructor() { constructor() {
super({ super({
id: CodeActionCommand.Id, id: CodeActionCommand.Id,
precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasCodeActionsProvider) precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasCodeActionsProvider),
description: {
description: `Trigger a code action`,
args: [{
name: 'args',
schema: {
'type': 'object',
'required': ['kind'],
'properties': {
'kind': {
'type': 'string'
},
'apply': {
'type': 'string',
'default': 'ifSingle',
'enum': ['first', 'ifSingle', 'never']
}
}
}
}]
}
}); });
} }
...@@ -297,6 +317,25 @@ export class RefactorAction extends EditorAction { ...@@ -297,6 +317,25 @@ export class RefactorAction extends EditorAction {
when: ContextKeyExpr.and( when: ContextKeyExpr.and(
EditorContextKeys.writable, EditorContextKeys.writable,
contextKeyForSupportedActions(CodeActionKind.Refactor)), contextKeyForSupportedActions(CodeActionKind.Refactor)),
},
description: {
description: 'Refactor...',
args: [{
name: 'args',
schema: {
'type': 'object',
'properties': {
'kind': {
'type': 'string'
},
'apply': {
'type': 'string',
'default': 'never',
'enum': ['first', 'ifSingle', 'never']
}
}
}
}]
} }
}); });
} }
...@@ -333,6 +372,25 @@ export class SourceAction extends EditorAction { ...@@ -333,6 +372,25 @@ export class SourceAction extends EditorAction {
when: ContextKeyExpr.and( when: ContextKeyExpr.and(
EditorContextKeys.writable, EditorContextKeys.writable,
contextKeyForSupportedActions(CodeActionKind.Source)), contextKeyForSupportedActions(CodeActionKind.Source)),
},
description: {
description: 'Source Action...',
args: [{
name: 'args',
schema: {
'type': 'object',
'properties': {
'kind': {
'type': 'string'
},
'apply': {
'type': 'string',
'default': 'never',
'enum': ['first', 'ifSingle', 'never']
}
}
}
}]
} }
}); });
} }
......
...@@ -519,7 +519,27 @@ class UnfoldAction extends FoldingAction<FoldingArguments> { ...@@ -519,7 +519,27 @@ class UnfoldAction extends FoldingAction<FoldingArguments> {
* 'direction': If 'up', unfold given number of levels up otherwise unfolds down. * 'direction': If 'up', unfold given number of levels up otherwise unfolds down.
* 'selectionLines': The start lines (0-based) of the editor selections to apply the unfold action to. If not set, the active selection(s) will be used. * 'selectionLines': The start lines (0-based) of the editor selections to apply the unfold action to. If not set, the active selection(s) will be used.
`, `,
constraint: foldingArgumentsConstraint constraint: foldingArgumentsConstraint,
schema: {
'type': 'object',
'properties': {
'levels': {
'type': 'number',
'default': 1
},
'direction': {
'type': 'string',
'enum': ['up', 'down'],
'default': 'down'
},
'selectionLines': {
'type': 'array',
'items': {
'type': 'number'
}
}
}
}
} }
] ]
} }
...@@ -584,7 +604,27 @@ class FoldAction extends FoldingAction<FoldingArguments> { ...@@ -584,7 +604,27 @@ class FoldAction extends FoldingAction<FoldingArguments> {
* 'direction': If 'up', folds given number of levels up otherwise folds down. * 'direction': If 'up', folds given number of levels up otherwise folds down.
* 'selectionLines': The start lines (0-based) of the editor selections to apply the fold action to. If not set, the active selection(s) will be used. * 'selectionLines': The start lines (0-based) of the editor selections to apply the fold action to. If not set, the active selection(s) will be used.
`, `,
constraint: foldingArgumentsConstraint constraint: foldingArgumentsConstraint,
schema: {
'type': 'object',
'properties': {
'levels': {
'type': 'number',
'default': 1
},
'direction': {
'type': 'string',
'enum': ['up', 'down'],
'default': 'down'
},
'selectionLines': {
'type': 'array',
'items': {
'type': 'number'
}
}
}
}
} }
] ]
} }
......
...@@ -8,6 +8,7 @@ import { TypeConstraint, validateConstraints } from 'vs/base/common/types'; ...@@ -8,6 +8,7 @@ import { TypeConstraint, validateConstraints } from 'vs/base/common/types';
import { ServicesAccessor, createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { ServicesAccessor, createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { Event, Emitter } from 'vs/base/common/event'; import { Event, Emitter } from 'vs/base/common/event';
import { LinkedList } from 'vs/base/common/linkedList'; import { LinkedList } from 'vs/base/common/linkedList';
import { IJSONSchema } from 'vs/base/common/jsonSchema';
export const ICommandService = createDecorator<ICommandService>('commandService'); export const ICommandService = createDecorator<ICommandService>('commandService');
...@@ -37,7 +38,7 @@ export interface ICommand { ...@@ -37,7 +38,7 @@ export interface ICommand {
export interface ICommandHandlerDescription { export interface ICommandHandlerDescription {
description: string; description: string;
args: { name: string; description?: string; constraint?: TypeConstraint; }[]; args: { name: string; description?: string; constraint?: TypeConstraint; schema?: IJSONSchema; }[];
returns?: string; returns?: string;
} }
......
...@@ -65,7 +65,24 @@ export class OpenFolderAPICommand { ...@@ -65,7 +65,24 @@ export class OpenFolderAPICommand {
return executor.executeCommand('_files.windowOpen', { urisToOpen: [{ uri }], forceNewWindow }); return executor.executeCommand('_files.windowOpen', { urisToOpen: [{ uri }], forceNewWindow });
} }
} }
CommandsRegistry.registerCommand(OpenFolderAPICommand.ID, adjustHandler(OpenFolderAPICommand.execute)); CommandsRegistry.registerCommand({
id: OpenFolderAPICommand.ID,
handler: adjustHandler(OpenFolderAPICommand.execute),
description: {
description: `Open a folder`,
args: [{
name: 'uri',
schema: {
'type': 'string'
}
}, {
name: 'forceNewWindow',
schema: {
'type': 'boolean'
}
}]
}
});
export class DiffAPICommand { export class DiffAPICommand {
public static ID = 'vscode.diff'; public static ID = 'vscode.diff';
...@@ -126,7 +143,31 @@ export class SetEditorLayoutAPICommand { ...@@ -126,7 +143,31 @@ export class SetEditorLayoutAPICommand {
return executor.executeCommand('layoutEditorGroups', layout); return executor.executeCommand('layoutEditorGroups', layout);
} }
} }
CommandsRegistry.registerCommand(SetEditorLayoutAPICommand.ID, adjustHandler(SetEditorLayoutAPICommand.execute)); CommandsRegistry.registerCommand({
id: SetEditorLayoutAPICommand.ID,
handler: adjustHandler(SetEditorLayoutAPICommand.execute),
description: {
description: 'Set Editor Layout',
args: [{
name: 'args',
schema: {
'type': 'object',
'required': ['groups'],
'properties': {
'orientation': {
'type': 'number',
'default': 0,
'enum': [0, 1]
},
'groups': {
'$ref': '#/definitions/editorGroupsSchema', // defined in keybindingService.ts ...
'default': [{}, {}],
}
}
}
}]
}
});
CommandsRegistry.registerCommand('_workbench.downloadResource', function (accessor: ServicesAccessor, resource: URI) { CommandsRegistry.registerCommand('_workbench.downloadResource', function (accessor: ServicesAccessor, resource: URI) {
const downloadService = accessor.get(IDownloadService); const downloadService = accessor.get(IDownloadService);
......
...@@ -90,7 +90,24 @@ function registerActiveEditorMoveCommand(): void { ...@@ -90,7 +90,24 @@ function registerActiveEditorMoveCommand(): void {
{ {
name: nls.localize('editorCommand.activeEditorMove.arg.name', "Active editor move argument"), name: nls.localize('editorCommand.activeEditorMove.arg.name', "Active editor move argument"),
description: nls.localize('editorCommand.activeEditorMove.arg.description', "Argument Properties:\n\t* 'to': String value providing where to move.\n\t* 'by': String value providing the unit for move (by tab or by group).\n\t* 'value': Number value providing how many positions or an absolute position to move."), description: nls.localize('editorCommand.activeEditorMove.arg.description', "Argument Properties:\n\t* 'to': String value providing where to move.\n\t* 'by': String value providing the unit for move (by tab or by group).\n\t* 'value': Number value providing how many positions or an absolute position to move."),
constraint: isActiveEditorMoveArg constraint: isActiveEditorMoveArg,
schema: {
'type': 'object',
'required': ['to'],
'properties': {
'to': {
'type': 'string',
'enum': ['left', 'right']
},
'by': {
'type': 'string',
'enum': ['tab', 'group']
},
'value': {
'type': 'number'
}
},
}
} }
] ]
} }
......
...@@ -19,12 +19,24 @@ export const defaultQuickOpenContext = ContextKeyExpr.and(inQuickOpenContext, Co ...@@ -19,12 +19,24 @@ export const defaultQuickOpenContext = ContextKeyExpr.and(inQuickOpenContext, Co
export const QUICKOPEN_ACTION_ID = 'workbench.action.quickOpen'; export const QUICKOPEN_ACTION_ID = 'workbench.action.quickOpen';
export const QUICKOPEN_ACION_LABEL = nls.localize('quickOpen', "Go to File..."); export const QUICKOPEN_ACION_LABEL = nls.localize('quickOpen', "Go to File...");
CommandsRegistry.registerCommand(QUICKOPEN_ACTION_ID, function (accessor: ServicesAccessor, prefix: string | null = null) { CommandsRegistry.registerCommand({
id: QUICKOPEN_ACTION_ID,
handler: function (accessor: ServicesAccessor, prefix: string | null = null) {
const quickOpenService = accessor.get(IQuickOpenService); const quickOpenService = accessor.get(IQuickOpenService);
return quickOpenService.show(typeof prefix === 'string' ? prefix : undefined).then(() => { return quickOpenService.show(typeof prefix === 'string' ? prefix : undefined).then(() => {
return undefined; return undefined;
}); });
},
description: {
description: `Quick open`,
args: [{
name: 'prefix',
schema: {
'type': 'string'
}
}]
}
}); });
export const QUICKOPEN_FOCUS_SECONDARY_ACTION_ID = 'workbench.action.quickOpenPreviousEditor'; export const QUICKOPEN_FOCUS_SECONDARY_ACTION_ID = 'workbench.action.quickOpenPreviousEditor';
......
...@@ -54,7 +54,28 @@ class InsertSnippetAction extends EditorAction { ...@@ -54,7 +54,28 @@ class InsertSnippetAction extends EditorAction {
id: 'editor.action.insertSnippet', id: 'editor.action.insertSnippet',
label: nls.localize('snippet.suggestions.label', "Insert Snippet"), label: nls.localize('snippet.suggestions.label', "Insert Snippet"),
alias: 'Insert Snippet', alias: 'Insert Snippet',
precondition: EditorContextKeys.writable precondition: EditorContextKeys.writable,
description: {
description: `Insert Snippet`,
args: [{
name: 'args',
schema: {
'type': 'object',
'properties': {
'snippet': {
'type': 'string'
},
'langId': {
'type': 'string',
},
'name': {
'type': 'string'
}
},
}
}]
}
}); });
} }
......
...@@ -549,8 +549,20 @@ class TaskService extends Disposable implements ITaskService { ...@@ -549,8 +549,20 @@ class TaskService extends Disposable implements ITaskService {
} }
private registerCommands(): void { private registerCommands(): void {
CommandsRegistry.registerCommand('workbench.action.tasks.runTask', (accessor, arg) => { CommandsRegistry.registerCommand({
id: 'workbench.action.tasks.runTask',
handler: (accessor, arg) => {
this.runTaskCommand(arg); this.runTaskCommand(arg);
},
description: {
description: 'Run Task',
args: [{
name: 'args',
schema: {
'type': 'string',
}
}]
}
}); });
CommandsRegistry.registerCommand('workbench.action.tasks.reRunTask', (accessor, arg) => { CommandsRegistry.registerCommand('workbench.action.tasks.reRunTask', (accessor, arg) => {
......
...@@ -514,7 +514,22 @@ actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FindPrevious, Fi ...@@ -514,7 +514,22 @@ actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FindPrevious, Fi
const sendSequenceTerminalCommand = new SendSequenceTerminalCommand({ const sendSequenceTerminalCommand = new SendSequenceTerminalCommand({
id: SendSequenceTerminalCommand.ID, id: SendSequenceTerminalCommand.ID,
precondition: null precondition: null,
description: {
description: `Send Custom Sequence To Terminal`,
args: [{
name: 'args',
schema: {
'type': 'object',
'required': ['text'],
'properties': {
'text': {
'type': 'string'
}
},
}
}]
}
}); });
sendSequenceTerminalCommand.register(); sendSequenceTerminalCommand.register();
......
...@@ -15,7 +15,7 @@ import { Keybinding, ResolvedKeybinding } from 'vs/base/common/keyCodes'; ...@@ -15,7 +15,7 @@ import { Keybinding, ResolvedKeybinding } from 'vs/base/common/keyCodes';
import { KeybindingParser } from 'vs/base/common/keybindingParser'; import { KeybindingParser } from 'vs/base/common/keybindingParser';
import { OS, OperatingSystem } from 'vs/base/common/platform'; import { OS, OperatingSystem } from 'vs/base/common/platform';
import { ConfigWatcher } from 'vs/base/node/config'; import { ConfigWatcher } from 'vs/base/node/config';
import { ICommandService } from 'vs/platform/commands/common/commands'; import { ICommandService, CommandsRegistry } from 'vs/platform/commands/common/commands';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { Extensions as ConfigExtensions, IConfigurationNode, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; import { Extensions as ConfigExtensions, IConfigurationNode, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry';
import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
...@@ -280,6 +280,8 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService { ...@@ -280,6 +280,8 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService {
) { ) {
super(contextKeyService, commandService, telemetryService, notificationService, statusBarService); super(contextKeyService, commandService, telemetryService, notificationService, statusBarService);
updateSchema();
let dispatchConfig = getDispatchConfig(configurationService); let dispatchConfig = getDispatchConfig(configurationService);
configurationService.onDidChangeConfiguration((e) => { configurationService.onDidChangeConfiguration((e) => {
let newDispatchConfig = getDispatchConfig(configurationService); let newDispatchConfig = getDispatchConfig(configurationService);
...@@ -573,6 +575,24 @@ let schema: IJSONSchema = { ...@@ -573,6 +575,24 @@ let schema: IJSONSchema = {
'id': schemaId, 'id': schemaId,
'type': 'array', 'type': 'array',
'title': nls.localize('keybindings.json.title', "Keybindings configuration"), 'title': nls.localize('keybindings.json.title', "Keybindings configuration"),
'definitions': {
'editorGroupsSchema': {
'type': 'array',
'items': {
'type': 'object',
'properties': {
'groups': {
'$ref': '#/definitions/editorGroupsSchema',
'default': [{}, {}]
},
'size': {
'type': 'number',
'default': 0.5
}
}
}
}
},
'items': { 'items': {
'required': ['key'], 'required': ['key'],
'type': 'object', 'type': 'object',
...@@ -593,13 +613,40 @@ let schema: IJSONSchema = { ...@@ -593,13 +613,40 @@ let schema: IJSONSchema = {
'args': { 'args': {
'description': nls.localize('keybindings.json.args', "Arguments to pass to the command to execute.") 'description': nls.localize('keybindings.json.args', "Arguments to pass to the command to execute.")
} }
} },
'allOf': []
} }
}; };
let schemaRegistry = Registry.as<IJSONContributionRegistry>(Extensions.JSONContribution); let schemaRegistry = Registry.as<IJSONContributionRegistry>(Extensions.JSONContribution);
schemaRegistry.registerSchema(schemaId, schema); schemaRegistry.registerSchema(schemaId, schema);
function updateSchema() {
const allCommands = CommandsRegistry.getCommands();
for (let commandId in allCommands) {
const commandDescription = allCommands[commandId].description;
if (!commandDescription || !commandDescription.args || commandDescription.args.length !== 1 || !commandDescription.args[0].schema) {
continue;
}
const argsSchema = commandDescription.args[0].schema;
const addition = {
'if': {
'properties': {
'command': { 'const': commandId }
}
},
'then': {
'properties': {
'args': argsSchema
}
}
};
schema['items']['allOf'].push(addition);
}
}
const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigExtensions.Configuration); const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigExtensions.Configuration);
const keyboardConfiguration: IConfigurationNode = { const keyboardConfiguration: IConfigurationNode = {
'id': 'keyboard', 'id': 'keyboard',
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册