mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-08 17:19:48 +01:00
Pull editable logic into separate service
This commit is contained in:
@@ -21,6 +21,7 @@ import { WorkbenchPhase, registerWorkbenchContribution2 } from '../../../common/
|
||||
import { EditorExtensions, IEditorFactoryRegistry } from '../../../common/editor.js';
|
||||
import { IViewContainersRegistry, IViewsRegistry, Extensions as ViewContainerExtensions, ViewContainerLocation } from '../../../common/views.js';
|
||||
import { ITerminalProfileService, TERMINAL_VIEW_ID, TerminalCommandId } from '../common/terminal.js';
|
||||
import { TerminalEditingService } from './terminalEditingService.js';
|
||||
import { registerColors } from '../common/terminalColorRegistry.js';
|
||||
import { registerTerminalConfiguration } from '../common/terminalConfiguration.js';
|
||||
import { terminalStrings } from '../common/terminalStrings.js';
|
||||
@@ -29,7 +30,7 @@ import './media/terminalVoice.css';
|
||||
import './media/widgets.css';
|
||||
import './media/xterm.css';
|
||||
import { RemoteTerminalBackendContribution } from './remoteTerminalBackend.js';
|
||||
import { ITerminalConfigurationService, ITerminalEditorService, ITerminalGroupService, ITerminalInstanceService, ITerminalService, TerminalDataTransfers, terminalEditorId } from './terminal.js';
|
||||
import { ITerminalConfigurationService, ITerminalEditingService, ITerminalEditorService, ITerminalGroupService, ITerminalInstanceService, ITerminalService, TerminalDataTransfers, terminalEditorId } from './terminal.js';
|
||||
import { registerTerminalActions } from './terminalActions.js';
|
||||
import { setupTerminalCommands } from './terminalCommands.js';
|
||||
import { TerminalConfigurationService } from './terminalConfigurationService.js';
|
||||
@@ -52,6 +53,7 @@ registerSingleton(ITerminalLogService, TerminalLogService, InstantiationType.Del
|
||||
registerSingleton(ITerminalConfigurationService, TerminalConfigurationService, InstantiationType.Delayed);
|
||||
registerSingleton(ITerminalService, TerminalService, InstantiationType.Delayed);
|
||||
registerSingleton(ITerminalEditorService, TerminalEditorService, InstantiationType.Delayed);
|
||||
registerSingleton(ITerminalEditingService, TerminalEditingService, InstantiationType.Delayed);
|
||||
registerSingleton(ITerminalGroupService, TerminalGroupService, InstantiationType.Delayed);
|
||||
registerSingleton(ITerminalInstanceService, TerminalInstanceService, InstantiationType.Delayed);
|
||||
registerSingleton(ITerminalProfileService, TerminalProfileService, InstantiationType.Delayed);
|
||||
|
||||
@@ -38,6 +38,7 @@ import type { TerminalEditorInput } from './terminalEditorInput.js';
|
||||
export const ITerminalService = createDecorator<ITerminalService>('terminalService');
|
||||
export const ITerminalConfigurationService = createDecorator<ITerminalConfigurationService>('terminalConfigurationService');
|
||||
export const ITerminalEditorService = createDecorator<ITerminalEditorService>('terminalEditorService');
|
||||
export const ITerminalEditingService = createDecorator<ITerminalEditingService>('terminalEditingService');
|
||||
export const ITerminalGroupService = createDecorator<ITerminalGroupService>('terminalGroupService');
|
||||
export const ITerminalInstanceService = createDecorator<ITerminalInstanceService>('terminalInstanceService');
|
||||
|
||||
@@ -99,6 +100,48 @@ export interface ITerminalInstanceService {
|
||||
didRegisterBackend(backend: ITerminalBackend): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* A service responsible for managing terminal editing state and functionality. This includes
|
||||
* tracking which terminal is currently being edited and managing editable data associated with
|
||||
* terminal instances.
|
||||
*/
|
||||
export interface ITerminalEditingService {
|
||||
readonly _serviceBrand: undefined;
|
||||
|
||||
/**
|
||||
* Get the editable data for a terminal instance.
|
||||
* @param instance The terminal instance.
|
||||
* @returns The editable data if the instance is editable, undefined otherwise.
|
||||
*/
|
||||
getEditableData(instance: ITerminalInstance): IEditableData | undefined;
|
||||
|
||||
/**
|
||||
* Set the editable data for a terminal instance.
|
||||
* @param instance The terminal instance.
|
||||
* @param data The editable data to set, or null to clear.
|
||||
*/
|
||||
setEditable(instance: ITerminalInstance, data: IEditableData | null): void;
|
||||
|
||||
/**
|
||||
* Check if a terminal instance is currently editable.
|
||||
* @param instance The terminal instance to check.
|
||||
* @returns True if the instance is editable, false otherwise.
|
||||
*/
|
||||
isEditable(instance: ITerminalInstance | undefined): boolean;
|
||||
|
||||
/**
|
||||
* Get the terminal instance that is currently being edited.
|
||||
* @returns The terminal instance being edited, or undefined if none.
|
||||
*/
|
||||
getEditingTerminal(): ITerminalInstance | undefined;
|
||||
|
||||
/**
|
||||
* Set the terminal instance that is currently being edited.
|
||||
* @param instance The terminal instance to set as editing, or undefined to clear.
|
||||
*/
|
||||
setEditingTerminal(instance: ITerminalInstance | undefined): void;
|
||||
}
|
||||
|
||||
export const enum Direction {
|
||||
Left = 0,
|
||||
Right = 1,
|
||||
@@ -337,9 +380,6 @@ export interface ITerminalService extends ITerminalInstanceHost {
|
||||
|
||||
requestStartExtensionTerminal(proxy: ITerminalProcessExtHostProxy, cols: number, rows: number): Promise<ITerminalLaunchError | undefined>;
|
||||
isAttachedToTerminal(remoteTerm: IRemoteTerminalAttachTarget): boolean;
|
||||
getEditableData(instance: ITerminalInstance): IEditableData | undefined;
|
||||
setEditable(instance: ITerminalInstance, data: IEditableData | null): void;
|
||||
isEditable(instance: ITerminalInstance | undefined): boolean;
|
||||
safeDisposeTerminal(instance: ITerminalInstance): Promise<void>;
|
||||
|
||||
getDefaultInstanceHost(): ITerminalInstanceHost;
|
||||
@@ -348,9 +388,6 @@ export interface ITerminalService extends ITerminalInstanceHost {
|
||||
resolveLocation(location?: ITerminalLocationOptions): Promise<TerminalLocation | undefined>;
|
||||
setNativeDelegate(nativeCalls: ITerminalServiceNativeDelegate): void;
|
||||
|
||||
getEditingTerminal(): ITerminalInstance | undefined;
|
||||
setEditingTerminal(instance: ITerminalInstance | undefined): void;
|
||||
|
||||
/**
|
||||
* Creates an instance event listener that listens to all instances, dynamically adding new
|
||||
* instances and removing old instances as needed.
|
||||
|
||||
@@ -55,7 +55,7 @@ import { accessibleViewCurrentProviderId, accessibleViewIsShown, accessibleViewO
|
||||
import { IRemoteTerminalAttachTarget, ITerminalProfileResolverService, ITerminalProfileService, TERMINAL_VIEW_ID, TerminalCommandId } from '../common/terminal.js';
|
||||
import { TerminalContextKeys } from '../common/terminalContextKey.js';
|
||||
import { terminalStrings } from '../common/terminalStrings.js';
|
||||
import { Direction, ICreateTerminalOptions, IDetachedTerminalInstance, ITerminalConfigurationService, ITerminalEditorService, ITerminalGroupService, ITerminalInstance, ITerminalInstanceService, ITerminalService, IXtermTerminal } from './terminal.js';
|
||||
import { Direction, ICreateTerminalOptions, IDetachedTerminalInstance, ITerminalConfigurationService, ITerminalEditorService, ITerminalEditingService, ITerminalGroupService, ITerminalInstance, ITerminalInstanceService, ITerminalService, IXtermTerminal } from './terminal.js';
|
||||
import { isAuxiliaryWindow } from '../../../../base/browser/window.js';
|
||||
import { InstanceContext } from './terminalContextMenu.js';
|
||||
import { getColorClass, getIconId, getUriClasses } from './terminalIcon.js';
|
||||
@@ -275,6 +275,7 @@ export interface ITerminalServicesCollection {
|
||||
groupService: ITerminalGroupService;
|
||||
instanceService: ITerminalInstanceService;
|
||||
editorService: ITerminalEditorService;
|
||||
editingService: ITerminalEditingService;
|
||||
profileService: ITerminalProfileService;
|
||||
profileResolverService: ITerminalProfileResolverService;
|
||||
}
|
||||
@@ -286,6 +287,7 @@ function getTerminalServices(accessor: ServicesAccessor): ITerminalServicesColle
|
||||
groupService: accessor.get(ITerminalGroupService),
|
||||
instanceService: accessor.get(ITerminalInstanceService),
|
||||
editorService: accessor.get(ITerminalEditorService),
|
||||
editingService: accessor.get(ITerminalEditingService),
|
||||
profileService: accessor.get(ITerminalProfileService),
|
||||
profileResolverService: accessor.get(ITerminalProfileResolverService)
|
||||
};
|
||||
@@ -787,13 +789,13 @@ export function registerTerminalActions() {
|
||||
return renameWithQuickPick(c, accessor, firstInstance);
|
||||
}
|
||||
|
||||
c.service.setEditingTerminal(firstInstance);
|
||||
c.service.setEditable(firstInstance, {
|
||||
c.editingService.setEditingTerminal(firstInstance);
|
||||
c.editingService.setEditable(firstInstance, {
|
||||
validationMessage: value => validateTerminalName(value),
|
||||
onFinish: async (value, success) => {
|
||||
// Cancel editing first as instance.rename will trigger a rerender automatically
|
||||
c.service.setEditable(firstInstance, null);
|
||||
c.service.setEditingTerminal(undefined);
|
||||
c.editingService.setEditable(firstInstance, null);
|
||||
c.editingService.setEditingTerminal(undefined);
|
||||
if (success) {
|
||||
const promises: Promise<void>[] = [];
|
||||
for (const instance of instances) {
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IEditableData } from '../../../common/views.js';
|
||||
import { IViewsService } from '../../../services/views/common/viewsService.js';
|
||||
import { ITerminalEditingService, ITerminalInstance } from './terminal.js';
|
||||
import { TERMINAL_VIEW_ID } from '../common/terminal.js';
|
||||
import { TerminalViewPane } from './terminalView.js';
|
||||
|
||||
export class TerminalEditingService implements ITerminalEditingService {
|
||||
readonly _serviceBrand: undefined;
|
||||
|
||||
private _editable: { instance: ITerminalInstance; data: IEditableData } | undefined;
|
||||
private _editingTerminal: ITerminalInstance | undefined;
|
||||
|
||||
constructor(
|
||||
@IViewsService private readonly _viewsService: IViewsService
|
||||
) {
|
||||
}
|
||||
|
||||
getEditableData(instance: ITerminalInstance): IEditableData | undefined {
|
||||
return this._editable && this._editable.instance === instance ? this._editable.data : undefined;
|
||||
}
|
||||
|
||||
setEditable(instance: ITerminalInstance, data: IEditableData | null): void {
|
||||
if (!data) {
|
||||
this._editable = undefined;
|
||||
} else {
|
||||
this._editable = { instance: instance, data };
|
||||
}
|
||||
const pane = this._viewsService.getActiveViewWithId<TerminalViewPane>(TERMINAL_VIEW_ID);
|
||||
const isEditing = this.isEditable(instance);
|
||||
pane?.terminalTabbedView?.setEditable(isEditing);
|
||||
}
|
||||
|
||||
isEditable(instance: ITerminalInstance | undefined): boolean {
|
||||
return !!this._editable && (this._editable.instance === instance || !instance);
|
||||
}
|
||||
|
||||
getEditingTerminal(): ITerminalInstance | undefined {
|
||||
return this._editingTerminal;
|
||||
}
|
||||
|
||||
setEditingTerminal(instance: ITerminalInstance | undefined): void {
|
||||
this._editingTerminal = instance;
|
||||
}
|
||||
}
|
||||
@@ -29,16 +29,14 @@ import { IThemeService, Themable } from '../../../../platform/theme/common/theme
|
||||
import { ThemeIcon } from '../../../../base/common/themables.js';
|
||||
import { IWorkspaceContextService } from '../../../../platform/workspace/common/workspace.js';
|
||||
import { VirtualWorkspaceContext } from '../../../common/contextkeys.js';
|
||||
import { IEditableData } from '../../../common/views.js';
|
||||
import { IViewsService } from '../../../services/views/common/viewsService.js';
|
||||
|
||||
import { ICreateTerminalOptions, IDetachedTerminalInstance, IDetachedXTermOptions, IRequestAddInstanceToGroupEvent, ITerminalConfigurationService, ITerminalEditorService, ITerminalGroup, ITerminalGroupService, ITerminalInstance, ITerminalInstanceHost, ITerminalInstanceService, ITerminalLocationOptions, ITerminalService, ITerminalServiceNativeDelegate, TerminalConnectionState, TerminalEditorLocation } from './terminal.js';
|
||||
import { getCwdForSplit } from './terminalActions.js';
|
||||
import { TerminalEditorInput } from './terminalEditorInput.js';
|
||||
import { getColorStyleContent, getUriClasses } from './terminalIcon.js';
|
||||
import { TerminalProfileQuickpick } from './terminalProfileQuickpick.js';
|
||||
import { getInstanceFromResource, getTerminalUri, parseTerminalUri } from './terminalUri.js';
|
||||
import { TerminalViewPane } from './terminalView.js';
|
||||
import { IRemoteTerminalAttachTarget, IStartExtensionTerminalRequest, ITerminalProcessExtHostProxy, ITerminalProfileService, TERMINAL_VIEW_ID } from '../common/terminal.js';
|
||||
import { IRemoteTerminalAttachTarget, IStartExtensionTerminalRequest, ITerminalProcessExtHostProxy, ITerminalProfileService } from '../common/terminal.js';
|
||||
import { TerminalContextKeys } from '../common/terminalContextKey.js';
|
||||
import { columnToEditorGroup } from '../../../services/editor/common/editorGroupColumn.js';
|
||||
import { IEditorGroupsService } from '../../../services/editor/common/editorGroupsService.js';
|
||||
@@ -80,8 +78,6 @@ export class TerminalService extends Disposable implements ITerminalService {
|
||||
private _nativeDelegate?: ITerminalServiceNativeDelegate;
|
||||
private _shutdownWindowCount?: number;
|
||||
|
||||
private _editable: { instance: ITerminalInstance; data: IEditableData } | undefined;
|
||||
|
||||
get isProcessSupportRegistered(): boolean { return !!this._processSupportContextKey.get(); }
|
||||
|
||||
private _connectionState: TerminalConnectionState = TerminalConnectionState.Connecting;
|
||||
@@ -127,8 +123,6 @@ export class TerminalService extends Disposable implements ITerminalService {
|
||||
return this._activeInstance;
|
||||
}
|
||||
|
||||
private _editingTerminal: ITerminalInstance | undefined;
|
||||
|
||||
private readonly _onDidCreateInstance = this._register(new Emitter<ITerminalInstance>());
|
||||
get onDidCreateInstance(): Event<ITerminalInstance> { return this._onDidCreateInstance.event; }
|
||||
private readonly _onDidChangeInstanceDimensions = this._register(new Emitter<ITerminalInstance>());
|
||||
@@ -175,7 +169,6 @@ export class TerminalService extends Disposable implements ITerminalService {
|
||||
@IDialogService private _dialogService: IDialogService,
|
||||
@IInstantiationService private _instantiationService: IInstantiationService,
|
||||
@IRemoteAgentService private _remoteAgentService: IRemoteAgentService,
|
||||
@IViewsService private _viewsService: IViewsService,
|
||||
@IConfigurationService private readonly _configurationService: IConfigurationService,
|
||||
@ITerminalConfigurationService private readonly _terminalConfigService: ITerminalConfigurationService,
|
||||
@IWorkbenchEnvironmentService private readonly _environmentService: IWorkbenchEnvironmentService,
|
||||
@@ -588,24 +581,7 @@ export class TerminalService extends Disposable implements ITerminalService {
|
||||
await this.revealTerminal(instance, preserveFocus);
|
||||
}
|
||||
|
||||
setEditable(instance: ITerminalInstance, data?: IEditableData | null): void {
|
||||
if (!data) {
|
||||
this._editable = undefined;
|
||||
} else {
|
||||
this._editable = { instance: instance, data };
|
||||
}
|
||||
const pane = this._viewsService.getActiveViewWithId<TerminalViewPane>(TERMINAL_VIEW_ID);
|
||||
const isEditing = this.isEditable(instance);
|
||||
pane?.terminalTabbedView?.setEditable(isEditing);
|
||||
}
|
||||
|
||||
isEditable(instance: ITerminalInstance | undefined): boolean {
|
||||
return !!this._editable && (this._editable.instance === instance || !instance);
|
||||
}
|
||||
|
||||
getEditableData(instance: ITerminalInstance): IEditableData | undefined {
|
||||
return this._editable && this._editable.instance === instance ? this._editable.data : undefined;
|
||||
}
|
||||
|
||||
requestStartExtensionTerminal(proxy: ITerminalProcessExtHostProxy, cols: number, rows: number): Promise<ITerminalLaunchError | undefined> {
|
||||
// The initial request came from the extension host, no need to wait for it
|
||||
@@ -1229,13 +1205,7 @@ export class TerminalService extends Disposable implements ITerminalService {
|
||||
this._terminalGroupService.setContainer(terminalContainer);
|
||||
}
|
||||
|
||||
getEditingTerminal(): ITerminalInstance | undefined {
|
||||
return this._editingTerminal;
|
||||
}
|
||||
|
||||
setEditingTerminal(instance: ITerminalInstance | undefined) {
|
||||
this._editingTerminal = instance;
|
||||
}
|
||||
|
||||
createOnInstanceEvent<T>(getEvent: (instance: ITerminalInstance) => Event<T>): DynamicListEventMultiplexer<ITerminalInstance, T> {
|
||||
return new DynamicListEventMultiplexer(this.instances, this.onDidCreateInstance, this.onDidDisposeInstance, getEvent);
|
||||
|
||||
@@ -10,7 +10,7 @@ import { IContextKey, IContextKeyService } from '../../../../platform/contextkey
|
||||
import { IKeybindingService } from '../../../../platform/keybinding/common/keybinding.js';
|
||||
import { IThemeService } from '../../../../platform/theme/common/themeService.js';
|
||||
import { ThemeIcon } from '../../../../base/common/themables.js';
|
||||
import { ITerminalConfigurationService, ITerminalGroupService, ITerminalInstance, ITerminalService, TerminalDataTransfers } from './terminal.js';
|
||||
import { ITerminalConfigurationService, ITerminalGroupService, ITerminalInstance, ITerminalService, ITerminalEditingService, TerminalDataTransfers } from './terminal.js';
|
||||
import { localize } from '../../../../nls.js';
|
||||
import * as DOM from '../../../../base/browser/dom.js';
|
||||
import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';
|
||||
@@ -81,6 +81,7 @@ export class TerminalTabList extends WorkbenchList<ITerminalInstance> {
|
||||
@IConfigurationService private readonly _configurationService: IConfigurationService,
|
||||
@ITerminalService private readonly _terminalService: ITerminalService,
|
||||
@ITerminalGroupService private readonly _terminalGroupService: ITerminalGroupService,
|
||||
@ITerminalEditingService private readonly _terminalEditingService: ITerminalEditingService,
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@IDecorationsService decorationsService: IDecorationsService,
|
||||
@IThemeService private readonly _themeService: IThemeService,
|
||||
@@ -154,7 +155,7 @@ export class TerminalTabList extends WorkbenchList<ITerminalInstance> {
|
||||
await instance.focusWhenReady();
|
||||
}
|
||||
|
||||
if (this._terminalService.getEditingTerminal()?.instanceId === e.element?.instanceId) {
|
||||
if (this._terminalEditingService.getEditingTerminal()?.instanceId === e.element?.instanceId) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -166,7 +167,7 @@ export class TerminalTabList extends WorkbenchList<ITerminalInstance> {
|
||||
// on left click, if focus mode = single click, focus the element
|
||||
// unless multi-selection is in progress
|
||||
this.disposables.add(this.onMouseClick(async e => {
|
||||
if (this._terminalService.getEditingTerminal()?.instanceId === e.element?.instanceId) {
|
||||
if (this._terminalEditingService.getEditingTerminal()?.instanceId === e.element?.instanceId) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -220,7 +221,7 @@ export class TerminalTabList extends WorkbenchList<ITerminalInstance> {
|
||||
}
|
||||
|
||||
refresh(cancelEditing: boolean = true): void {
|
||||
if (cancelEditing && this._terminalService.isEditable(undefined)) {
|
||||
if (cancelEditing && this._terminalEditingService.isEditable(undefined)) {
|
||||
this.domFocus();
|
||||
}
|
||||
|
||||
@@ -258,6 +259,7 @@ class TerminalTabsRenderer extends Disposable implements IListRenderer<ITerminal
|
||||
@ITerminalConfigurationService private readonly _terminalConfigurationService: ITerminalConfigurationService,
|
||||
@ITerminalService private readonly _terminalService: ITerminalService,
|
||||
@ITerminalGroupService private readonly _terminalGroupService: ITerminalGroupService,
|
||||
@ITerminalEditingService private readonly _terminalEditingService: ITerminalEditingService,
|
||||
@IHoverService private readonly _hoverService: IHoverService,
|
||||
@IKeybindingService private readonly _keybindingService: IKeybindingService,
|
||||
@IListService private readonly _listService: IListService,
|
||||
@@ -405,7 +407,7 @@ class TerminalTabsRenderer extends Disposable implements IListRenderer<ITerminal
|
||||
},
|
||||
extraClasses
|
||||
});
|
||||
const editableData = this._terminalService.getEditableData(instance);
|
||||
const editableData = this._terminalEditingService.getEditableData(instance);
|
||||
template.label.element.classList.toggle('editable-tab', !!editableData);
|
||||
if (editableData) {
|
||||
template.elementDisposables.add(this._renderInputBox(template.label.element.querySelector('.monaco-icon-label-container')!, instance, editableData));
|
||||
@@ -597,6 +599,7 @@ class TerminalTabsDragAndDrop extends Disposable implements IListDragAndDrop<ITe
|
||||
constructor(
|
||||
@ITerminalService private readonly _terminalService: ITerminalService,
|
||||
@ITerminalGroupService private readonly _terminalGroupService: ITerminalGroupService,
|
||||
@ITerminalEditingService private readonly _terminalEditingService: ITerminalEditingService,
|
||||
@IListService private readonly _listService: IListService,
|
||||
) {
|
||||
super();
|
||||
@@ -604,7 +607,7 @@ class TerminalTabsDragAndDrop extends Disposable implements IListDragAndDrop<ITe
|
||||
}
|
||||
|
||||
getDragURI(instance: ITerminalInstance): string | null {
|
||||
if (this._terminalService.getEditingTerminal()?.instanceId === instance.instanceId) {
|
||||
if (this._terminalEditingService.getEditingTerminal()?.instanceId === instance.instanceId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user