From 98216b59be7fdcd0d077cc68938ab249b26e3ac9 Mon Sep 17 00:00:00 2001 From: Liang Huang Date: Mon, 30 Mar 2020 15:08:20 -0400 Subject: [PATCH] set focus to terminal that the attached task is running from - Same task can be attached over and over again, producing multiple terminal widgets. With this change, Theia sets focus to the teminal widget that the to-be-attached task is running from. If such terminal widget is not found, Theia creates a new terminal widget for the attached task. - fixes #7407 Signed-off-by: Liang Huang --- packages/task/src/browser/task-service.ts | 51 ++++++++++++------- .../src/browser/base/terminal-service.ts | 6 +++ .../browser/terminal-frontend-contribution.ts | 4 ++ 3 files changed, 42 insertions(+), 19 deletions(-) diff --git a/packages/task/src/browser/task-service.ts b/packages/task/src/browser/task-service.ts index 5cca84ec7f6ec..897f227f28fe1 100644 --- a/packages/task/src/browser/task-service.ts +++ b/packages/task/src/browser/task-service.ts @@ -26,7 +26,7 @@ import { EditorManager } from '@theia/editor/lib/browser'; import { ProblemManager } from '@theia/markers/lib/browser/problem/problem-manager'; import { TerminalService } from '@theia/terminal/lib/browser/base/terminal-service'; import { TerminalWidget } from '@theia/terminal/lib/browser/base/terminal-widget'; -import { TerminalWidgetFactoryOptions, TERMINAL_WIDGET_FACTORY_ID } from '@theia/terminal/lib/browser/terminal-widget-impl'; +import { TerminalWidgetFactoryOptions } from '@theia/terminal/lib/browser/terminal-widget-impl'; import { VariableResolverService } from '@theia/variable-resolver/lib/browser'; import { WorkspaceService } from '@theia/workspace/lib/browser/workspace-service'; import { inject, injectable, named, postConstruct } from 'inversify'; @@ -228,7 +228,7 @@ export class TaskService implements TaskConfigurationClient { if (isTaskActiveAndOutputSilent && problem.marker.severity === DiagnosticSeverity.Error) { const terminalId = matchedRunningTaskInfo!.terminalId; if (terminalId) { - const terminal = this.terminalService.getById(this.getTerminalWidgetId(terminalId)); + const terminal = this.terminalService.getByTerminalId(terminalId); if (terminal) { const focus = !!matchedRunningTaskInfo!.config.presentation!.focus; if (focus) { // assign focus to the terminal if presentation.focus is true @@ -304,7 +304,7 @@ export class TaskService implements TaskConfigurationClient { } else { const eventTaskConfig = event.config; if (eventTaskConfig && eventTaskConfig.presentation && eventTaskConfig.presentation.reveal === RevealKind.Silent && event.terminalId) { - const terminal = this.terminalService.getById(this.getTerminalWidgetId(event.terminalId)); + const terminal = this.terminalService.getByTerminalId(event.terminalId); const focus = !!eventTaskConfig.presentation.focus; if (terminal) { if (focus) { // assign focus to the terminal if presentation.focus is true @@ -700,12 +700,15 @@ export class TaskService implements TaskConfigurationClient { const taskName = this.taskNameResolver.resolve(task); const terminalId = matchedRunningTaskInfo.terminalId; if (terminalId) { - const terminal = this.terminalService.getById(this.getTerminalWidgetId(terminalId)); - if (terminal && task.presentation) { - if (task.presentation.focus) { // assign focus to the terminal if presentation.focus is true - this.terminalService.open(terminal, { mode: 'activate' }); - } else if (task.presentation.reveal === RevealKind.Always) { // show the terminal but not assign focus - this.terminalService.open(terminal, { mode: 'reveal' }); + const widgetId = this.getTerminalWidgetId(terminalId); + if (widgetId) { + const terminal = this.terminalService.getById(widgetId); + if (terminal && task.presentation) { + if (task.presentation.focus) { // assign focus to the terminal if presentation.focus is true + this.terminalService.open(terminal, { mode: 'activate' }); + } else if (task.presentation.reveal === RevealKind.Always) { // show the terminal but not assign focus + this.terminalService.open(terminal, { mode: 'reveal' }); + } } } } @@ -979,17 +982,24 @@ export class TaskService implements TaskConfigurationClient { terminal.sendText(selectedText); } - async attach(processId: number, taskId: number): Promise { + async attach(terminalId: number, taskId: number): Promise { // Get the list of all available running tasks. const runningTasks: TaskInfo[] = await this.getRunningTasks(); // Get the corresponding task information based on task id if available. const taskInfo: TaskInfo | undefined = runningTasks.find((t: TaskInfo) => t.taskId === taskId); let widgetOpenMode: WidgetOpenMode = 'open'; - if (taskInfo && taskInfo.config.presentation && taskInfo.config.presentation.reveal === RevealKind.Always) { - if (taskInfo.config.presentation.focus) { // assign focus to the terminal if presentation.focus is true - widgetOpenMode = 'activate'; - } else { // show the terminal but not assign focus - widgetOpenMode = 'reveal'; + if (taskInfo) { + const terminalWidget = this.terminalService.getByTerminalId(terminalId); + if (terminalWidget) { + this.messageService.error('Task is already running in terminal'); + return this.terminalService.open(terminalWidget, { mode: 'activate' }); + } + if (taskInfo.config.presentation && taskInfo.config.presentation.reveal === RevealKind.Always) { + if (taskInfo.config.presentation.focus) { // assign focus to the terminal if presentation.focus is true + widgetOpenMode = 'activate'; + } else { // show the terminal but not assign focus + widgetOpenMode = 'reveal'; + } } } @@ -998,7 +1008,7 @@ export class TaskService implements TaskConfigurationClient { { created: new Date().toString(), taskId, - id: this.getTerminalWidgetId(processId), + id: this.getTerminalWidgetId(terminalId), title: taskInfo ? `Task: ${taskInfo.config.label}` : `Task: #${taskId}`, @@ -1008,11 +1018,14 @@ export class TaskService implements TaskConfigurationClient { taskConfig: taskInfo ? taskInfo.config : undefined } ); - widget.start(processId); + widget.start(terminalId); } - private getTerminalWidgetId(terminalId: number): string { - return `${TERMINAL_WIDGET_FACTORY_ID}-${terminalId}`; + protected getTerminalWidgetId(terminalId: number): string | undefined { + const terminalWidget = this.terminalService.getByTerminalId(terminalId); + if (terminalWidget) { + return terminalWidget.id; + } } async configure(task: TaskConfiguration): Promise { diff --git a/packages/terminal/src/browser/base/terminal-service.ts b/packages/terminal/src/browser/base/terminal-service.ts index a3ce7453b9a1f..0570cf80b74c5 100644 --- a/packages/terminal/src/browser/base/terminal-service.ts +++ b/packages/terminal/src/browser/base/terminal-service.ts @@ -46,6 +46,12 @@ export interface TerminalService { */ getById(id: string): TerminalWidget | undefined; + /** + * @param id - the terminal id (NOT the terminal widget id!) + * @return the widget + */ + getByTerminalId(terminalId: number): TerminalWidget | undefined; + /** * Returns detected default shell. */ diff --git a/packages/terminal/src/browser/terminal-frontend-contribution.ts b/packages/terminal/src/browser/terminal-frontend-contribution.ts index b7150a3fb3b7b..739e037fadb3f 100644 --- a/packages/terminal/src/browser/terminal-frontend-contribution.ts +++ b/packages/terminal/src/browser/terminal-frontend-contribution.ts @@ -257,6 +257,10 @@ export class TerminalFrontendContribution implements TerminalService, CommandCon return this.all.find(terminal => terminal.id === id); } + getByTerminalId(terminalId: number): TerminalWidget | undefined { + return this.all.find(terminal => terminal.terminalId === terminalId); + } + getDefaultShell(): Promise { return this.shellTerminalServer.getDefaultShell(); }