From 69bb0ad98a0c7c7ffe44490c02b132fc0997d409 Mon Sep 17 00:00:00 2001 From: Ulugbek Abdullaev Date: Thu, 16 Mar 2023 15:48:48 +0100 Subject: [PATCH] add a new command `runCommands` that allows to run several commands sequentially (#177104) add a new command `runCommands` that allows to run several commands sequentially --- build/lib/i18n.resources.json | 4 + .../commands/common/commands.contribution.ts | 110 ++++++++++++++++++ src/vs/workbench/workbench.common.main.ts | 3 + 3 files changed, 117 insertions(+) create mode 100644 src/vs/workbench/contrib/commands/common/commands.contribution.ts diff --git a/build/lib/i18n.resources.json b/build/lib/i18n.resources.json index 35538d67cf5..d257a8bc4f9 100644 --- a/build/lib/i18n.resources.json +++ b/build/lib/i18n.resources.json @@ -54,6 +54,10 @@ "name": "vs/workbench/contrib/codeActions", "project": "vscode-workbench" }, + { + "name": "vs/workbench/contrib/commands", + "project": "vscode-workbench" + }, { "name": "vs/workbench/contrib/comments", "project": "vscode-workbench" diff --git a/src/vs/workbench/contrib/commands/common/commands.contribution.ts b/src/vs/workbench/contrib/commands/common/commands.contribution.ts new file mode 100644 index 00000000000..309e9b78d65 --- /dev/null +++ b/src/vs/workbench/contrib/commands/common/commands.contribution.ts @@ -0,0 +1,110 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as nls from 'vs/nls'; +import { Action2, registerAction2 } from 'vs/platform/actions/common/actions'; +import { ICommandService } from 'vs/platform/commands/common/commands'; +import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; +import { INotificationService } from 'vs/platform/notification/common/notification'; + +type RunnableCommand = string | { id: string; args: any[] }; + +/** Runs several commands passed to it as an argument */ +class RunCommands extends Action2 { + + constructor() { + super({ + id: 'runCommands', + title: { value: nls.localize('runCommands', "Run Commands"), original: 'Run Commands' }, + f1: false, + description: { + description: nls.localize('runCommands.description', "Run several commands"), + args: [ + { + name: 'args', + schema: { + type: 'object', + required: ['commands'], + properties: { + commands: { + type: 'array', + description: nls.localize('runCommands.commands', "Commands to run"), + items: { + type: ['string', 'object'], + required: ['command'], + properties: { + command: { + type: 'string' + }, + args: { // type: any + } + } + } + } + } + + } + } + ] + } + }); + } + + // dev decisions: + // - this command takes a single argument-object because + // - keybinding definitions don't allow running commands with several arguments + // - and we want to be able to take on different other arguments in future, e.g., `runMode : 'serial' | 'concurrent'` + async run(accessor: ServicesAccessor, args: any) { + if (!this._validateInput(args)) { + throw new Error('runCommands: invalid arguments'); + } + const commandService = accessor.get(ICommandService); + try { + for (const cmd of args.commands) { + await this._runCommand(commandService, cmd); + } + } catch (err) { + accessor.get(INotificationService).warn(err); + } + } + + private _validateInput(args: any): args is { commands: RunnableCommand[] } { + if (!args || typeof args !== 'object') { + return false; + } + if (!Array.isArray(args.commands)) { + return false; + } + for (const cmd of args.commands) { + if (typeof cmd === 'string') { + continue; + } + if (typeof cmd === 'object' && typeof cmd.id === 'string') { + continue; + } + return false; + } + return true; + } + + private _runCommand(commandService: ICommandService, cmd: RunnableCommand) { + let commandID: string, commandArgs; + + if (typeof cmd === 'string') { + commandID = cmd; + } else { + commandID = cmd.id; + commandArgs = cmd.args; + } + + if (commandArgs === undefined) { + return commandService.executeCommand(commandID); + } else { + return commandService.executeCommand(commandID, ...commandArgs); + } + } +} + +registerAction2(RunCommands); diff --git a/src/vs/workbench/workbench.common.main.ts b/src/vs/workbench/workbench.common.main.ts index d1945cb9b23..3597f6a3dbf 100644 --- a/src/vs/workbench/workbench.common.main.ts +++ b/src/vs/workbench/workbench.common.main.ts @@ -219,6 +219,9 @@ import 'vs/workbench/contrib/markers/browser/markers.contribution'; // Merge Editor import 'vs/workbench/contrib/mergeEditor/browser/mergeEditor.contribution'; +// Commands +import 'vs/workbench/contrib/commands/common/commands.contribution'; + // Comments import 'vs/workbench/contrib/comments/browser/comments.contribution';