From 10d5275207879334d0052a2e8a4d85c82fe30245 Mon Sep 17 00:00:00 2001 From: "Ju, Gyeongmin" <46707197+amos42@users.noreply.github.com> Date: Thu, 9 Sep 2021 20:58:28 +0900 Subject: [PATCH] register vscode.openWith api (#9881) Signed-off-by: Ju, Gyeong-min --- .../plugin-vscode-commands-contribution.ts | 89 +++++++++++++++---- .../custom-editors/custom-editor-opener.tsx | 6 +- 2 files changed, 78 insertions(+), 17 deletions(-) diff --git a/packages/plugin-ext-vscode/src/browser/plugin-vscode-commands-contribution.ts b/packages/plugin-ext-vscode/src/browser/plugin-vscode-commands-contribution.ts index f9a098cae7adc..18bc8fd5c9b6c 100755 --- a/packages/plugin-ext-vscode/src/browser/plugin-vscode-commands-contribution.ts +++ b/packages/plugin-ext-vscode/src/browser/plugin-vscode-commands-contribution.ts @@ -20,7 +20,7 @@ import { CommonCommands, NavigatableWidget, open, - OpenerService, + OpenerService, OpenHandler, QuickInputService, Saveable, TabBar, @@ -76,12 +76,17 @@ import { fromDefinition, toDefinition } from '@theia/plugin-ext/lib/main/browser/callhierarchy/callhierarchy-type-converters'; +import { CustomEditorOpener } from '@theia/plugin-ext/lib/main/browser/custom-editors/custom-editor-opener'; export namespace VscodeCommands { export const OPEN: Command = { id: 'vscode.open' }; + export const OPEN_WITH: Command = { + id: 'vscode.openWith' + }; + export const OPEN_FOLDER: Command = { id: 'vscode.openFolder' }; @@ -132,29 +137,81 @@ export class PluginVscodeCommandsContribution implements CommandContribution { @inject(MonacoTextModelService) protected readonly textModelService: MonacoTextModelService; + private async openWith(commandId: string, resource: URI, columnOrOptions?: ViewColumn | TextDocumentShowOptions, openerId?: string): Promise { + if (!resource) { + throw new Error(`${commandId} command requires at least URI argument.`); + } + if (!URI.isUri(resource)) { + throw new Error(`Invalid argument for ${commandId} command with URI argument. Found ${resource}`); + } + + let options: TextDocumentShowOptions | undefined; + if (typeof columnOrOptions === 'number') { + options = { + viewColumn: columnOrOptions + }; + } else if (columnOrOptions) { + options = { + ...columnOrOptions + }; + } + + const uri = new TheiaURI(resource); + const editorOptions = DocumentsMainImpl.toEditorOpenerOptions(this.shell, options); + + let opener: OpenHandler | undefined; + if (typeof openerId === 'string') { + const lowerViewType = openerId.toLowerCase(); + const openers = await this.openerService.getOpeners(); + for (const opnr of openers) { + const idLowerCase = opnr.id.toLowerCase(); + if (lowerViewType === idLowerCase) { + opener = opnr; + break; + } + } + } else { + opener = await this.openerService.getOpener(uri, editorOptions); + } + + if (opener) { + await opener.open(uri, editorOptions); + return true; + } + + return false; + } + registerCommands(commands: CommandRegistry): void { commands.registerCommand(VscodeCommands.OPEN, { isVisible: () => false, execute: async (resource: URI, columnOrOptions?: ViewColumn | TextDocumentShowOptions) => { - if (!resource) { - throw new Error(`${VscodeCommands.OPEN.id} command requires at least URI argument.`); + const result = await this.openWith(VscodeCommands.OPEN.id, resource, columnOrOptions); + if (!result) { + throw new Error(`Could not find an editor for ${resource}`); } - if (!URI.isUri(resource)) { - throw new Error(`Invalid argument for ${VscodeCommands.OPEN.id} command with URI argument. Found ${resource}`); + } + }); + + commands.registerCommand(VscodeCommands.OPEN_WITH, { + isVisible: () => false, + execute: async (resource: URI, viewType: string, columnOrOptions?: ViewColumn | TextDocumentShowOptions) => { + if (!viewType) { + throw new Error(`Running the contributed command: ${VscodeCommands.OPEN_WITH} failed.`); } - let options: TextDocumentShowOptions | undefined; - if (typeof columnOrOptions === 'number') { - options = { - viewColumn: columnOrOptions - }; - } else if (columnOrOptions) { - options = { - ...columnOrOptions - }; + if (viewType.toLowerCase() === 'default') { + return commands.executeCommand(VscodeCommands.OPEN.id, resource, columnOrOptions); + } + + let result = await this.openWith(VscodeCommands.OPEN_WITH.id, resource, columnOrOptions, viewType); + if (!result) { + result = await this.openWith(VscodeCommands.OPEN_WITH.id, resource, columnOrOptions, CustomEditorOpener.toCustomEditorId(viewType)); + } + + if (!result) { + throw new Error(`Could not find an editor for '${viewType}'`); } - const editorOptions = DocumentsMainImpl.toEditorOpenerOptions(this.shell, options); - await open(this.openerService, new TheiaURI(resource), editorOptions); } }); diff --git a/packages/plugin-ext/src/main/browser/custom-editors/custom-editor-opener.tsx b/packages/plugin-ext/src/main/browser/custom-editors/custom-editor-opener.tsx index 0b45d0db75ece..51d7f0d9b94e0 100644 --- a/packages/plugin-ext/src/main/browser/custom-editors/custom-editor-opener.tsx +++ b/packages/plugin-ext/src/main/browser/custom-editors/custom-editor-opener.tsx @@ -37,10 +37,14 @@ export class CustomEditorOpener implements OpenHandler { @inject(ApplicationShell) protected readonly shell: ApplicationShell, @inject(WidgetManager) protected readonly widgetManager: WidgetManager ) { - this.id = `custom-editor-${this.editor.viewType}`; + this.id = CustomEditorOpener.toCustomEditorId(this.editor.viewType); this.label = this.editor.displayName; } + static toCustomEditorId(editorViewType: string): string { + return `custom-editor-${editorViewType}`; + } + canHandle(uri: URI): number { if (this.matches(this.editor.selector, uri)) { return this.getPriority();