mirror of
https://github.com/Microsoft/vscode
synced 2024-09-18 01:58:27 +00:00
terminalTab -> terminalGroup (#122891)
This commit is contained in:
parent
840d3dce67
commit
088f35f702
|
@ -147,9 +147,9 @@ export class ViewQuickAccessProvider extends PickerQuickAccessProvider<IViewQuic
|
|||
}
|
||||
|
||||
// Terminals
|
||||
this.terminalService.terminalTabs.forEach((tab, tabIndex) => {
|
||||
tab.terminalInstances.forEach((terminal, terminalIndex) => {
|
||||
const label = localize('terminalTitle', "{0}: {1}", `${tabIndex + 1}.${terminalIndex + 1}`, terminal.title);
|
||||
this.terminalService.terminalGroups.forEach((group, groupIndex) => {
|
||||
group.terminalInstances.forEach((terminal, terminalIndex) => {
|
||||
const label = localize('terminalTitle', "{0}: {1}", `${groupIndex + 1}.${terminalIndex + 1}`, terminal.title);
|
||||
viewEntries.push({
|
||||
label,
|
||||
containerLabel: localize('terminals', "Terminal"),
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
overflow: hidden;
|
||||
}
|
||||
|
||||
.monaco-workbench .pane-body.integrated-terminal .terminal-tab {
|
||||
.monaco-workbench .pane-body.integrated-terminal .terminal-group {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
|
|
@ -47,11 +47,11 @@ export const enum Direction {
|
|||
Down = 3
|
||||
}
|
||||
|
||||
export interface ITerminalTab {
|
||||
export interface ITerminalGroup {
|
||||
activeInstance: ITerminalInstance | null;
|
||||
terminalInstances: ITerminalInstance[];
|
||||
title: string;
|
||||
onDisposed: Event<ITerminalTab>;
|
||||
onDisposed: Event<ITerminalGroup>;
|
||||
onInstancesChanged: Event<void>;
|
||||
focusPreviousPane(): void;
|
||||
focusNextPane(): void;
|
||||
|
@ -77,14 +77,14 @@ export interface ITerminalService {
|
|||
activeTabIndex: number;
|
||||
configHelper: ITerminalConfigHelper;
|
||||
terminalInstances: ITerminalInstance[];
|
||||
terminalTabs: ITerminalTab[];
|
||||
terminalGroups: ITerminalGroup[];
|
||||
isProcessSupportRegistered: boolean;
|
||||
readonly connectionState: TerminalConnectionState;
|
||||
readonly availableProfiles: ITerminalProfile[];
|
||||
|
||||
initializeTerminals(): Promise<void>;
|
||||
onActiveTabChanged: Event<void>;
|
||||
onTabDisposed: Event<ITerminalTab>;
|
||||
onTabDisposed: Event<ITerminalGroup>;
|
||||
onInstanceCreated: Event<ITerminalInstance>;
|
||||
onInstanceDisposed: Event<ITerminalInstance>;
|
||||
onInstanceProcessIdReady: Event<ITerminalInstance>;
|
||||
|
@ -134,7 +134,7 @@ export interface ITerminalService {
|
|||
*/
|
||||
doWithActiveInstance<T>(callback: (terminal: ITerminalInstance) => T): T | void;
|
||||
|
||||
getActiveTab(): ITerminalTab | null;
|
||||
getActiveGroup(): ITerminalGroup | null;
|
||||
setActiveTabToNext(): void;
|
||||
setActiveTabToPrevious(): void;
|
||||
setActiveTabByIndex(tabIndex: number): void;
|
||||
|
@ -166,7 +166,7 @@ export interface ITerminalService {
|
|||
|
||||
showProfileQuickPick(type: 'setDefault' | 'createInstance', cwd?: string | URI): Promise<ITerminalInstance | undefined>;
|
||||
|
||||
getTabForInstance(instance: ITerminalInstance): ITerminalTab | undefined;
|
||||
getGroupForInstance(instance: ITerminalInstance): ITerminalGroup | undefined;
|
||||
|
||||
setContainers(panelContainer: HTMLElement, terminalContainer: HTMLElement): void;
|
||||
|
||||
|
|
|
@ -230,7 +230,7 @@ export function registerTerminalActions() {
|
|||
}
|
||||
async run(accessor: ServicesAccessor) {
|
||||
const terminalService = accessor.get(ITerminalService);
|
||||
terminalService.getActiveTab()?.focusPreviousPane();
|
||||
terminalService.getActiveGroup()?.focusPreviousPane();
|
||||
await terminalService.showPanel(true);
|
||||
}
|
||||
});
|
||||
|
@ -256,7 +256,7 @@ export function registerTerminalActions() {
|
|||
}
|
||||
async run(accessor: ServicesAccessor) {
|
||||
const terminalService = accessor.get(ITerminalService);
|
||||
terminalService.getActiveTab()?.focusNextPane();
|
||||
terminalService.getActiveGroup()?.focusNextPane();
|
||||
await terminalService.showPanel(true);
|
||||
}
|
||||
});
|
||||
|
@ -277,7 +277,7 @@ export function registerTerminalActions() {
|
|||
});
|
||||
}
|
||||
async run(accessor: ServicesAccessor) {
|
||||
accessor.get(ITerminalService).getActiveTab()?.resizePane(Direction.Left);
|
||||
accessor.get(ITerminalService).getActiveGroup()?.resizePane(Direction.Left);
|
||||
}
|
||||
});
|
||||
registerAction2(class extends Action2 {
|
||||
|
@ -297,7 +297,7 @@ export function registerTerminalActions() {
|
|||
});
|
||||
}
|
||||
async run(accessor: ServicesAccessor) {
|
||||
accessor.get(ITerminalService).getActiveTab()?.resizePane(Direction.Right);
|
||||
accessor.get(ITerminalService).getActiveGroup()?.resizePane(Direction.Right);
|
||||
}
|
||||
});
|
||||
registerAction2(class extends Action2 {
|
||||
|
@ -316,7 +316,7 @@ export function registerTerminalActions() {
|
|||
});
|
||||
}
|
||||
async run(accessor: ServicesAccessor) {
|
||||
accessor.get(ITerminalService).getActiveTab()?.resizePane(Direction.Up);
|
||||
accessor.get(ITerminalService).getActiveGroup()?.resizePane(Direction.Up);
|
||||
}
|
||||
});
|
||||
registerAction2(class extends Action2 {
|
||||
|
@ -335,7 +335,7 @@ export function registerTerminalActions() {
|
|||
});
|
||||
}
|
||||
async run(accessor: ServicesAccessor) {
|
||||
accessor.get(ITerminalService).getActiveTab()?.resizePane(Direction.Down);
|
||||
accessor.get(ITerminalService).getActiveGroup()?.resizePane(Direction.Down);
|
||||
}
|
||||
});
|
||||
registerAction2(class extends Action2 {
|
||||
|
|
|
@ -9,7 +9,7 @@ import { IDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecyc
|
|||
import { SplitView, Orientation, IView, Sizing } from 'vs/base/browser/ui/splitview/splitview';
|
||||
import { IWorkbenchLayoutService, Parts, Position } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ITerminalInstance, Direction, ITerminalTab, ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { ITerminalInstance, Direction, ITerminalGroup, ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { ViewContainerLocation, IViewDescriptorService } from 'vs/workbench/common/views';
|
||||
import { IShellLaunchConfig, ITerminalTabLayoutInfoById } from 'vs/platform/terminal/common/terminal';
|
||||
|
||||
|
@ -226,10 +226,10 @@ class SplitPane implements IView {
|
|||
}
|
||||
}
|
||||
|
||||
export class TerminalTab extends Disposable implements ITerminalTab {
|
||||
export class TerminalGroup extends Disposable implements ITerminalGroup {
|
||||
private _terminalInstances: ITerminalInstance[] = [];
|
||||
private _splitPaneContainer: SplitPaneContainer | undefined;
|
||||
private _tabElement: HTMLElement | undefined;
|
||||
private _groupElement: HTMLElement | undefined;
|
||||
private _panelPosition: Position = Position.BOTTOM;
|
||||
private _terminalLocation: ViewContainerLocation = ViewContainerLocation.Panel;
|
||||
|
||||
|
@ -240,8 +240,8 @@ export class TerminalTab extends Disposable implements ITerminalTab {
|
|||
|
||||
private _initialRelativeSizes: number[] | undefined;
|
||||
|
||||
private readonly _onDisposed: Emitter<ITerminalTab> = this._register(new Emitter<ITerminalTab>());
|
||||
readonly onDisposed: Event<ITerminalTab> = this._onDisposed.event;
|
||||
private readonly _onDisposed: Emitter<ITerminalGroup> = this._register(new Emitter<ITerminalGroup>());
|
||||
public readonly onDisposed: Event<ITerminalGroup> = this._onDisposed.event;
|
||||
private readonly _onInstancesChanged: Emitter<void> = this._register(new Emitter<void>());
|
||||
readonly onInstancesChanged: Event<void> = this._onInstancesChanged.event;
|
||||
private readonly _onPanelMovedToSide = new Emitter<void>();
|
||||
|
@ -283,9 +283,9 @@ export class TerminalTab extends Disposable implements ITerminalTab {
|
|||
|
||||
override dispose(): void {
|
||||
super.dispose();
|
||||
if (this._container && this._tabElement) {
|
||||
this._container.removeChild(this._tabElement);
|
||||
this._tabElement = undefined;
|
||||
if (this._container && this._groupElement) {
|
||||
this._container.removeChild(this._groupElement);
|
||||
this._groupElement = undefined;
|
||||
}
|
||||
this._terminalInstances = [];
|
||||
this._onInstancesChanged.fire();
|
||||
|
@ -331,7 +331,7 @@ export class TerminalTab extends Disposable implements ITerminalTab {
|
|||
if (wasActiveInstance && this._terminalInstances.length > 0) {
|
||||
const newIndex = index < this._terminalInstances.length ? index : this._terminalInstances.length - 1;
|
||||
this.setActiveInstanceByIndex(newIndex);
|
||||
// TODO: Only focus the new instance if the tab had focus?
|
||||
// TODO: Only focus the new instance if the group had focus?
|
||||
if (this.activeInstance) {
|
||||
this.activeInstance.focus(true);
|
||||
}
|
||||
|
@ -345,7 +345,7 @@ export class TerminalTab extends Disposable implements ITerminalTab {
|
|||
this._splitPaneContainer.remove(instance);
|
||||
}
|
||||
|
||||
// Fire events and dispose tab if it was the last instance
|
||||
// Fire events and dispose group if it was the last instance
|
||||
if (this._terminalInstances.length === 0) {
|
||||
this._onDisposed.fire(this);
|
||||
this.dispose();
|
||||
|
@ -388,18 +388,18 @@ export class TerminalTab extends Disposable implements ITerminalTab {
|
|||
attachToElement(element: HTMLElement): void {
|
||||
this._container = element;
|
||||
|
||||
// If we already have a tab element, we can reparent it
|
||||
if (!this._tabElement) {
|
||||
this._tabElement = document.createElement('div');
|
||||
this._tabElement.classList.add('terminal-tab');
|
||||
// If we already have a group element, we can reparent it
|
||||
if (!this._groupElement) {
|
||||
this._groupElement = document.createElement('div');
|
||||
this._groupElement.classList.add('terminal-group');
|
||||
}
|
||||
|
||||
this._container.appendChild(this._tabElement);
|
||||
this._container.appendChild(this._groupElement);
|
||||
if (!this._splitPaneContainer) {
|
||||
this._panelPosition = this._layoutService.getPanelPosition();
|
||||
this._terminalLocation = this._viewDescriptorService.getViewLocationById(TERMINAL_VIEW_ID)!;
|
||||
const orientation = this._terminalLocation === ViewContainerLocation.Panel && this._panelPosition === Position.BOTTOM ? Orientation.HORIZONTAL : Orientation.VERTICAL;
|
||||
const newLocal = this._instantiationService.createInstance(SplitPaneContainer, this._tabElement, orientation);
|
||||
const newLocal = this._instantiationService.createInstance(SplitPaneContainer, this._groupElement, orientation);
|
||||
this._splitPaneContainer = newLocal;
|
||||
this.terminalInstances.forEach(instance => this._splitPaneContainer!.split(instance));
|
||||
}
|
||||
|
@ -408,8 +408,8 @@ export class TerminalTab extends Disposable implements ITerminalTab {
|
|||
|
||||
get title(): string {
|
||||
if (this._terminalInstances.length === 0) {
|
||||
// Normally consumers should not call into title at all after the tab is disposed but
|
||||
// this is required when the tab is used as part of a tree.
|
||||
// Normally consumers should not call into title at all after the group is disposed but
|
||||
// this is required when the group is used as part of a tree.
|
||||
return '';
|
||||
}
|
||||
let title = this.terminalInstances[0].title;
|
||||
|
@ -430,8 +430,8 @@ export class TerminalTab extends Disposable implements ITerminalTab {
|
|||
|
||||
setVisible(visible: boolean): void {
|
||||
this._isVisible = visible;
|
||||
if (this._tabElement) {
|
||||
this._tabElement.style.display = visible ? '' : 'none';
|
||||
if (this._groupElement) {
|
||||
this._groupElement.style.display = visible ? '' : 'none';
|
||||
}
|
||||
this.terminalInstances.forEach(i => i.setVisible(visible));
|
||||
}
|
|
@ -27,12 +27,12 @@ export class TerminalQuickAccessProvider extends PickerQuickAccessProvider<IPick
|
|||
protected _getPicks(filter: string): Array<IPickerQuickAccessItem | IQuickPickSeparator> {
|
||||
const terminalPicks: Array<IPickerQuickAccessItem | IQuickPickSeparator> = [];
|
||||
|
||||
const terminalTabs = this._terminalService.terminalTabs;
|
||||
for (let tabIndex = 0; tabIndex < terminalTabs.length; tabIndex++) {
|
||||
const terminalTab = terminalTabs[tabIndex];
|
||||
for (let terminalIndex = 0; terminalIndex < terminalTab.terminalInstances.length; terminalIndex++) {
|
||||
const terminal = terminalTab.terminalInstances[terminalIndex];
|
||||
const label = `$(${terminal.icon?.id}) ${tabIndex + 1}.${terminalIndex + 1}: ${terminal.title}`;
|
||||
const terminalGroups = this._terminalService.terminalGroups;
|
||||
for (let groupIndex = 0; groupIndex < terminalGroups.length; groupIndex++) {
|
||||
const terminalGroup = terminalGroups[groupIndex];
|
||||
for (let terminalIndex = 0; terminalIndex < terminalGroup.terminalInstances.length; terminalIndex++) {
|
||||
const terminal = terminalGroup.terminalInstances[terminalIndex];
|
||||
const label = `$(${terminal.icon?.id}) ${groupIndex + 1}.${terminalIndex + 1}: ${terminal.title}`;
|
||||
|
||||
const highlights = matchesFuzzy(filter, label, true);
|
||||
if (highlights) {
|
||||
|
|
|
@ -20,10 +20,10 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
|||
import { ILocalTerminalService, IShellLaunchConfig, ITerminalLaunchError, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, TerminalShellType, WindowsShellType } from 'vs/platform/terminal/common/terminal';
|
||||
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||
import { IViewDescriptorService, IViewsService, ViewContainerLocation } from 'vs/workbench/common/views';
|
||||
import { IRemoteTerminalService, ITerminalExternalLinkProvider, ITerminalInstance, ITerminalService, ITerminalTab, TerminalConnectionState } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { IRemoteTerminalService, ITerminalExternalLinkProvider, ITerminalInstance, ITerminalService, ITerminalGroup, TerminalConnectionState } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper';
|
||||
import { TerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminalInstance';
|
||||
import { TerminalTab } from 'vs/workbench/contrib/terminal/browser/terminalTab';
|
||||
import { TerminalGroup } from 'vs/workbench/contrib/terminal/browser/terminalGroup';
|
||||
import { TerminalViewPane } from 'vs/workbench/contrib/terminal/browser/terminalView';
|
||||
import { IAvailableProfilesRequest, IRemoteTerminalAttachTarget, ITerminalProfile, IStartExtensionTerminalRequest, ITerminalConfigHelper, ITerminalProcessExtHostProxy, KEYBINDING_CONTEXT_TERMINAL_ALT_BUFFER_ACTIVE, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_IS_OPEN, KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED, KEYBINDING_CONTEXT_TERMINAL_SHELL_TYPE, TERMINAL_VIEW_ID, ITerminalProfileObject, ITerminalTypeContribution, KEYBINDING_CONTEXT_TERMINAL_COUNT, TerminalSettingId } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
|
@ -56,22 +56,22 @@ export class TerminalService implements ITerminalService {
|
|||
private _terminalCountContextKey: IContextKey<number>;
|
||||
private _terminalShellTypeContextKey: IContextKey<string>;
|
||||
private _terminalAltBufferActiveContextKey: IContextKey<boolean>;
|
||||
private _terminalTabs: ITerminalTab[] = [];
|
||||
private _terminalGroups: ITerminalGroup[] = [];
|
||||
private _backgroundedTerminalInstances: ITerminalInstance[] = [];
|
||||
private get _terminalInstances(): ITerminalInstance[] {
|
||||
return this._terminalTabs.reduce((p, c) => p.concat(c.terminalInstances), <ITerminalInstance[]>[]);
|
||||
return this._terminalGroups.reduce((p, c) => p.concat(c.terminalInstances), <ITerminalInstance[]>[]);
|
||||
}
|
||||
private _findState: FindReplaceState;
|
||||
private _extHostsReady: { [authority: string]: IExtHostReadyEntry | undefined } = {};
|
||||
private _activeTabIndex: number;
|
||||
private _activeGroupIndex: number;
|
||||
private _linkProviders: Set<ITerminalExternalLinkProvider> = new Set();
|
||||
private _linkProviderDisposables: Map<ITerminalExternalLinkProvider, IDisposable[]> = new Map();
|
||||
private _processSupportContextKey: IContextKey<boolean>;
|
||||
|
||||
get activeTabIndex(): number { return this._activeTabIndex; }
|
||||
get terminalInstances(): ITerminalInstance[] { return this._terminalInstances; }
|
||||
get terminalTabs(): ITerminalTab[] { return this._terminalTabs; }
|
||||
get isProcessSupportRegistered(): boolean { return !!this._processSupportContextKey.get(); }
|
||||
public get activeTabIndex(): number { return this._activeGroupIndex; }
|
||||
public get terminalInstances(): ITerminalInstance[] { return this._terminalInstances; }
|
||||
public get terminalGroups(): ITerminalGroup[] { return this._terminalGroups; }
|
||||
public get isProcessSupportRegistered(): boolean { return !!this._processSupportContextKey.get(); }
|
||||
|
||||
private _configHelper: TerminalConfigHelper;
|
||||
private _terminalContainer: HTMLElement | undefined;
|
||||
|
@ -112,9 +112,9 @@ export class TerminalService implements ITerminalService {
|
|||
private readonly _onActiveInstanceChanged = new Emitter<ITerminalInstance | undefined>();
|
||||
get onActiveInstanceChanged(): Event<ITerminalInstance | undefined> { return this._onActiveInstanceChanged.event; }
|
||||
private readonly _onInstancePrimaryStatusChanged = new Emitter<ITerminalInstance>();
|
||||
get onInstancePrimaryStatusChanged(): Event<ITerminalInstance> { return this._onInstancePrimaryStatusChanged.event; }
|
||||
private readonly _onTabDisposed = new Emitter<ITerminalTab>();
|
||||
get onTabDisposed(): Event<ITerminalTab> { return this._onTabDisposed.event; }
|
||||
public get onInstancePrimaryStatusChanged(): Event<ITerminalInstance> { return this._onInstancePrimaryStatusChanged.event; }
|
||||
private readonly _onTabDisposed = new Emitter<ITerminalGroup>();
|
||||
public get onTabDisposed(): Event<ITerminalGroup> { return this._onTabDisposed.event; }
|
||||
private readonly _onRequestAvailableProfiles = new Emitter<IAvailableProfilesRequest>();
|
||||
get onRequestAvailableProfiles(): Event<IAvailableProfilesRequest> { return this._onRequestAvailableProfiles.event; }
|
||||
private readonly _onDidRegisterProcessSupport = new Emitter<void>();
|
||||
|
@ -148,7 +148,7 @@ export class TerminalService implements ITerminalService {
|
|||
) {
|
||||
this._localTerminalService = localTerminalService;
|
||||
|
||||
this._activeTabIndex = 0;
|
||||
this._activeGroupIndex = 0;
|
||||
this._isShuttingDown = false;
|
||||
this._findState = new FindReplaceState();
|
||||
lifecycleService.onBeforeShutdown(async e => e.veto(this._onBeforeShutdown(e.reason), 'veto.terminal'));
|
||||
|
@ -158,7 +158,7 @@ export class TerminalService implements ITerminalService {
|
|||
this._terminalShellTypeContextKey = KEYBINDING_CONTEXT_TERMINAL_SHELL_TYPE.bindTo(this._contextKeyService);
|
||||
this._terminalAltBufferActiveContextKey = KEYBINDING_CONTEXT_TERMINAL_ALT_BUFFER_ACTIVE.bindTo(this._contextKeyService);
|
||||
this._configHelper = this._instantiationService.createInstance(TerminalConfigHelper);
|
||||
this.onTabDisposed(tab => this._removeTab(tab));
|
||||
this.onTabDisposed(group => this._removeTab(group));
|
||||
this.onActiveTabChanged(() => {
|
||||
const instance = this.getActiveInstance();
|
||||
this._onActiveInstanceChanged.fire(instance ? instance : undefined);
|
||||
|
@ -255,38 +255,38 @@ export class TerminalService implements ITerminalService {
|
|||
|
||||
private _recreateTerminalTabs(layoutInfo?: ITerminalsLayoutInfo): number {
|
||||
let reconnectCounter = 0;
|
||||
let activeTab: ITerminalTab | undefined;
|
||||
let activeTab: ITerminalGroup | undefined;
|
||||
if (layoutInfo) {
|
||||
layoutInfo.tabs.forEach(tabLayout => {
|
||||
const terminalLayouts = tabLayout.terminals.filter(t => t.terminal && t.terminal.isOrphan);
|
||||
layoutInfo.tabs.forEach(groupLayout => {
|
||||
const terminalLayouts = groupLayout.terminals.filter(t => t.terminal && t.terminal.isOrphan);
|
||||
if (terminalLayouts.length) {
|
||||
reconnectCounter += terminalLayouts.length;
|
||||
let terminalInstance: ITerminalInstance | undefined;
|
||||
let tab: ITerminalTab | undefined;
|
||||
let group: ITerminalGroup | undefined;
|
||||
terminalLayouts.forEach((terminalLayout) => {
|
||||
if (!terminalInstance) {
|
||||
// create tab and terminal
|
||||
// create group and terminal
|
||||
terminalInstance = this.createTerminal({ attachPersistentProcess: terminalLayout.terminal! });
|
||||
tab = this.getTabForInstance(terminalInstance);
|
||||
if (tabLayout.isActive) {
|
||||
activeTab = tab;
|
||||
group = this.getGroupForInstance(terminalInstance);
|
||||
if (groupLayout.isActive) {
|
||||
activeTab = group;
|
||||
}
|
||||
} else {
|
||||
// add split terminals to this tab
|
||||
// add split terminals to this group
|
||||
this.splitInstance(terminalInstance, { attachPersistentProcess: terminalLayout.terminal! });
|
||||
}
|
||||
});
|
||||
const activeInstance = this.terminalInstances.find(t => {
|
||||
return t.shellLaunchConfig.attachPersistentProcess?.id === tabLayout.activePersistentProcessId;
|
||||
return t.shellLaunchConfig.attachPersistentProcess?.id === groupLayout.activePersistentProcessId;
|
||||
});
|
||||
if (activeInstance) {
|
||||
this.setActiveInstance(activeInstance);
|
||||
}
|
||||
tab?.resizePanes(tabLayout.terminals.map(terminal => terminal.relativeSize));
|
||||
group?.resizePanes(groupLayout.terminals.map(terminal => terminal.relativeSize));
|
||||
}
|
||||
});
|
||||
if (layoutInfo.tabs.length) {
|
||||
this.setActiveTabByIndex(activeTab ? this.terminalTabs.indexOf(activeTab) : 0);
|
||||
this.setActiveTabByIndex(activeTab ? this.terminalGroups.indexOf(activeTab) : 0);
|
||||
}
|
||||
}
|
||||
return reconnectCounter;
|
||||
|
@ -399,9 +399,9 @@ export class TerminalService implements ITerminalService {
|
|||
this._localTerminalService?.setTerminalLayoutInfo(undefined);
|
||||
}
|
||||
|
||||
getTabLabels(): string[] {
|
||||
return this._terminalTabs.filter(tab => tab.terminalInstances.length > 0).map((tab, index) => {
|
||||
return `${index + 1}: ${tab.title ? tab.title : ''}`;
|
||||
public getTabLabels(): string[] {
|
||||
return this._terminalGroups.filter(group => group.terminalInstances.length > 0).map((group, index) => {
|
||||
return `${index + 1}: ${group.title ? group.title : ''}`;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -413,7 +413,7 @@ export class TerminalService implements ITerminalService {
|
|||
private _updateRemoteState(): void {
|
||||
if (!!this._environmentService.remoteAuthority) {
|
||||
const state: ITerminalsLayoutInfoById = {
|
||||
tabs: this.terminalTabs.map(t => t.getLayoutInfo(t === this.getActiveTab()))
|
||||
tabs: this.terminalGroups.map(t => t.getLayoutInfo(t === this.getActiveGroup()))
|
||||
};
|
||||
this._remoteTerminalService.setTerminalLayoutInfo(state);
|
||||
}
|
||||
|
@ -422,38 +422,38 @@ export class TerminalService implements ITerminalService {
|
|||
@debounce(500)
|
||||
private _updateLocalState(): void {
|
||||
const state: ITerminalsLayoutInfoById = {
|
||||
tabs: this.terminalTabs.map(t => t.getLayoutInfo(t === this.getActiveTab()))
|
||||
tabs: this.terminalGroups.map(t => t.getLayoutInfo(t === this.getActiveGroup()))
|
||||
};
|
||||
this._localTerminalService!.setTerminalLayoutInfo(state);
|
||||
}
|
||||
|
||||
private _removeTab(tab: ITerminalTab): void {
|
||||
// Get the index of the tab and remove it from the list
|
||||
const index = this._terminalTabs.indexOf(tab);
|
||||
const activeTab = this.getActiveTab();
|
||||
const activeTabIndex = activeTab ? this._terminalTabs.indexOf(activeTab) : -1;
|
||||
const wasActiveTab = tab === activeTab;
|
||||
private _removeTab(group: ITerminalGroup): void {
|
||||
// Get the index of the group and remove it from the list
|
||||
const index = this._terminalGroups.indexOf(group);
|
||||
const activeTab = this.getActiveGroup();
|
||||
const activeTabIndex = activeTab ? this._terminalGroups.indexOf(activeTab) : -1;
|
||||
const wasActiveTab = group === activeTab;
|
||||
if (index !== -1) {
|
||||
this._terminalTabs.splice(index, 1);
|
||||
this._terminalGroups.splice(index, 1);
|
||||
}
|
||||
|
||||
// Adjust focus if the tab was active
|
||||
if (wasActiveTab && this._terminalTabs.length > 0) {
|
||||
const newIndex = index < this._terminalTabs.length ? index : this._terminalTabs.length - 1;
|
||||
// Adjust focus if the group was active
|
||||
if (wasActiveTab && this._terminalGroups.length > 0) {
|
||||
const newIndex = index < this._terminalGroups.length ? index : this._terminalGroups.length - 1;
|
||||
this.setActiveTabByIndex(newIndex);
|
||||
const activeInstance = this.getActiveInstance();
|
||||
if (activeInstance) {
|
||||
activeInstance.focus(true);
|
||||
}
|
||||
} else if (activeTabIndex >= this._terminalTabs.length) {
|
||||
const newIndex = this._terminalTabs.length - 1;
|
||||
} else if (activeTabIndex >= this._terminalGroups.length) {
|
||||
const newIndex = this._terminalGroups.length - 1;
|
||||
this.setActiveTabByIndex(newIndex);
|
||||
}
|
||||
|
||||
// Hide the panel if there are no more instances, provided that VS Code is not shutting
|
||||
// down. When shutting down the panel is locked in place so that it is restored upon next
|
||||
// launch.
|
||||
if (this._terminalTabs.length === 0 && !this._isShuttingDown) {
|
||||
if (this._terminalGroups.length === 0 && !this._isShuttingDown) {
|
||||
this.hidePanel();
|
||||
this._onActiveInstanceChanged.fire(undefined);
|
||||
}
|
||||
|
@ -470,19 +470,19 @@ export class TerminalService implements ITerminalService {
|
|||
this._onActiveTabChanged.fire();
|
||||
}
|
||||
|
||||
getActiveTab(): ITerminalTab | null {
|
||||
if (this._activeTabIndex < 0 || this._activeTabIndex >= this._terminalTabs.length) {
|
||||
public getActiveGroup(): ITerminalGroup | null {
|
||||
if (this._activeGroupIndex < 0 || this._activeGroupIndex >= this._terminalGroups.length) {
|
||||
return null;
|
||||
}
|
||||
return this._terminalTabs[this._activeTabIndex];
|
||||
return this._terminalGroups[this._activeGroupIndex];
|
||||
}
|
||||
|
||||
getActiveInstance(): ITerminalInstance | null {
|
||||
const tab = this.getActiveTab();
|
||||
if (!tab) {
|
||||
public getActiveInstance(): ITerminalInstance | null {
|
||||
const group = this.getActiveGroup();
|
||||
if (!group) {
|
||||
return null;
|
||||
}
|
||||
return tab.activeInstance;
|
||||
return group.activeInstance;
|
||||
}
|
||||
|
||||
doWithActiveInstance<T>(callback: (terminal: ITerminalInstance) => T): T | void {
|
||||
|
@ -515,22 +515,22 @@ export class TerminalService implements ITerminalService {
|
|||
|
||||
setActiveInstance(terminalInstance: ITerminalInstance): void {
|
||||
// If this was a hideFromUser terminal created by the API this was triggered by show,
|
||||
// in which case we need to create the terminal tab
|
||||
// in which case we need to create the terminal group
|
||||
if (terminalInstance.shellLaunchConfig.hideFromUser) {
|
||||
this._showBackgroundTerminal(terminalInstance);
|
||||
}
|
||||
this.setActiveInstanceByIndex(this._getIndexFromId(terminalInstance.instanceId));
|
||||
}
|
||||
|
||||
setActiveTabByIndex(tabIndex: number): void {
|
||||
if (tabIndex >= this._terminalTabs.length) {
|
||||
setActiveTabByIndex(groupIndex: number): void {
|
||||
if (groupIndex >= this._terminalGroups.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const didTabChange = this._activeTabIndex !== tabIndex;
|
||||
this._activeTabIndex = tabIndex;
|
||||
const didTabChange = this._activeGroupIndex !== groupIndex;
|
||||
this._activeGroupIndex = groupIndex;
|
||||
|
||||
this._terminalTabs.forEach((t, i) => t.setVisible(i === this._activeTabIndex));
|
||||
this._terminalGroups.forEach((g, i) => g.setVisible(i === this._activeGroupIndex));
|
||||
if (didTabChange) {
|
||||
this._onActiveTabChanged.fire();
|
||||
}
|
||||
|
@ -546,21 +546,21 @@ export class TerminalService implements ITerminalService {
|
|||
} else if (this._localTerminalsInitPromise) {
|
||||
await this._localTerminalsInitPromise;
|
||||
}
|
||||
if (this.terminalTabs.length === 0 && this.isProcessSupportRegistered) {
|
||||
if (this.terminalGroups.length === 0 && this.isProcessSupportRegistered) {
|
||||
this.createTerminal();
|
||||
}
|
||||
}
|
||||
|
||||
private _getInstanceFromGlobalInstanceIndex(index: number): { tab: ITerminalTab, tabIndex: number, instance: ITerminalInstance, localInstanceIndex: number } | null {
|
||||
private _getInstanceFromGlobalInstanceIndex(index: number): { group: ITerminalGroup, groupIndex: number, instance: ITerminalInstance, localInstanceIndex: number } | null {
|
||||
let currentTabIndex = 0;
|
||||
while (index >= 0 && currentTabIndex < this._terminalTabs.length) {
|
||||
const tab = this._terminalTabs[currentTabIndex];
|
||||
const count = tab.terminalInstances.length;
|
||||
while (index >= 0 && currentTabIndex < this._terminalGroups.length) {
|
||||
const group = this._terminalGroups[currentTabIndex];
|
||||
const count = group.terminalInstances.length;
|
||||
if (index < count) {
|
||||
return {
|
||||
tab,
|
||||
tabIndex: currentTabIndex,
|
||||
instance: tab.terminalInstances[index],
|
||||
group,
|
||||
groupIndex: currentTabIndex,
|
||||
instance: group.terminalInstances[index],
|
||||
localInstanceIndex: index
|
||||
};
|
||||
}
|
||||
|
@ -576,10 +576,10 @@ export class TerminalService implements ITerminalService {
|
|||
return;
|
||||
}
|
||||
|
||||
query.tab.setActiveInstanceByIndex(query.localInstanceIndex);
|
||||
const didTabChange = this._activeTabIndex !== query.tabIndex;
|
||||
this._activeTabIndex = query.tabIndex;
|
||||
this._terminalTabs.forEach((t, i) => t.setVisible(i === query.tabIndex));
|
||||
query.group.setActiveInstanceByIndex(query.localInstanceIndex);
|
||||
const didTabChange = this._activeGroupIndex !== query.groupIndex;
|
||||
this._activeGroupIndex = query.groupIndex;
|
||||
this._terminalGroups.forEach((g, i) => g.setVisible(i === query.groupIndex));
|
||||
|
||||
// Only fire the event if there was a change
|
||||
if (didTabChange) {
|
||||
|
@ -588,23 +588,23 @@ export class TerminalService implements ITerminalService {
|
|||
}
|
||||
|
||||
setActiveTabToNext(): void {
|
||||
if (this._terminalTabs.length <= 1) {
|
||||
if (this._terminalGroups.length <= 1) {
|
||||
return;
|
||||
}
|
||||
let newIndex = this._activeTabIndex + 1;
|
||||
if (newIndex >= this._terminalTabs.length) {
|
||||
let newIndex = this._activeGroupIndex + 1;
|
||||
if (newIndex >= this._terminalGroups.length) {
|
||||
newIndex = 0;
|
||||
}
|
||||
this.setActiveTabByIndex(newIndex);
|
||||
}
|
||||
|
||||
setActiveTabToPrevious(): void {
|
||||
if (this._terminalTabs.length <= 1) {
|
||||
if (this._terminalGroups.length <= 1) {
|
||||
return;
|
||||
}
|
||||
let newIndex = this._activeTabIndex - 1;
|
||||
let newIndex = this._activeGroupIndex - 1;
|
||||
if (newIndex < 0) {
|
||||
newIndex = this._terminalTabs.length - 1;
|
||||
newIndex = this._terminalGroups.length - 1;
|
||||
}
|
||||
this.setActiveTabByIndex(newIndex);
|
||||
}
|
||||
|
@ -612,17 +612,17 @@ export class TerminalService implements ITerminalService {
|
|||
splitInstance(instanceToSplit: ITerminalInstance, shellLaunchConfig?: IShellLaunchConfig): ITerminalInstance | null;
|
||||
splitInstance(instanceToSplit: ITerminalInstance, profile: ITerminalProfile, cwd?: string | URI): ITerminalInstance | null
|
||||
splitInstance(instanceToSplit: ITerminalInstance, shellLaunchConfigOrProfile: IShellLaunchConfig | ITerminalProfile = {}, cwd?: string | URI): ITerminalInstance | null {
|
||||
const tab = this.getTabForInstance(instanceToSplit);
|
||||
if (!tab) {
|
||||
const group = this.getGroupForInstance(instanceToSplit);
|
||||
if (!group) {
|
||||
return null;
|
||||
}
|
||||
const shellLaunchConfig = this._convertProfileToShellLaunchConfig(shellLaunchConfigOrProfile, cwd);
|
||||
const instance = tab.split(shellLaunchConfig);
|
||||
const instance = group.split(shellLaunchConfig);
|
||||
|
||||
this._initInstanceListeners(instance);
|
||||
this._onInstancesChanged.fire();
|
||||
|
||||
this._terminalTabs.forEach((t, i) => t.setVisible(i === this._activeTabIndex));
|
||||
this._terminalGroups.forEach((g, i) => g.setVisible(i === this._activeGroupIndex));
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
@ -678,8 +678,8 @@ export class TerminalService implements ITerminalService {
|
|||
}
|
||||
}
|
||||
|
||||
getTabForInstance(instance: ITerminalInstance): ITerminalTab | undefined {
|
||||
return this._terminalTabs.find(tab => tab.terminalInstances.indexOf(instance) !== -1);
|
||||
getGroupForInstance(instance: ITerminalInstance): ITerminalGroup | undefined {
|
||||
return this._terminalGroups.find(group => group.terminalInstances.indexOf(instance) !== -1);
|
||||
}
|
||||
|
||||
async showPanel(focus?: boolean): Promise<void> {
|
||||
|
@ -1004,14 +1004,14 @@ export class TerminalService implements ITerminalService {
|
|||
shellLaunchConfig.description = nls.localize('localTerminalDescription', "Local");
|
||||
}
|
||||
|
||||
const terminalTab = this._instantiationService.createInstance(TerminalTab, this._terminalContainer, shellLaunchConfig);
|
||||
this._terminalTabs.push(terminalTab);
|
||||
terminalTab.onPanelMovedToSide(() => this._onPanelMovedToSide.fire());
|
||||
const terminalGroup = this._instantiationService.createInstance(TerminalGroup, this._terminalContainer, shellLaunchConfig);
|
||||
this._terminalGroups.push(terminalGroup);
|
||||
terminalGroup.onPanelMovedToSide(() => this._onPanelMovedToSide.fire());
|
||||
|
||||
const instance = terminalTab.terminalInstances[0];
|
||||
const instance = terminalGroup.terminalInstances[0];
|
||||
|
||||
terminalTab.addDisposable(terminalTab.onDisposed(this._onTabDisposed.fire, this._onTabDisposed));
|
||||
terminalTab.addDisposable(terminalTab.onInstancesChanged(this._onInstancesChanged.fire, this._onInstancesChanged));
|
||||
terminalGroup.addDisposable(terminalGroup.onDisposed(this._onTabDisposed.fire, this._onTabDisposed));
|
||||
terminalGroup.addDisposable(terminalGroup.onInstancesChanged(this._onInstancesChanged.fire, this._onInstancesChanged));
|
||||
this._initInstanceListeners(instance);
|
||||
this._onInstancesChanged.fire();
|
||||
if (this.terminalInstances.length === 1) {
|
||||
|
@ -1025,10 +1025,10 @@ export class TerminalService implements ITerminalService {
|
|||
protected _showBackgroundTerminal(instance: ITerminalInstance): void {
|
||||
this._backgroundedTerminalInstances.splice(this._backgroundedTerminalInstances.indexOf(instance), 1);
|
||||
instance.shellLaunchConfig.hideFromUser = false;
|
||||
const terminalTab = this._instantiationService.createInstance(TerminalTab, this._terminalContainer, instance);
|
||||
this._terminalTabs.push(terminalTab);
|
||||
terminalTab.addDisposable(terminalTab.onDisposed(this._onTabDisposed.fire, this._onTabDisposed));
|
||||
terminalTab.addDisposable(terminalTab.onInstancesChanged(this._onInstancesChanged.fire, this._onInstancesChanged));
|
||||
const terminalGroup = this._instantiationService.createInstance(TerminalGroup, this._terminalContainer, instance);
|
||||
this._terminalGroups.push(terminalGroup);
|
||||
terminalGroup.addDisposable(terminalGroup.onDisposed(this._onTabDisposed.fire, this._onTabDisposed));
|
||||
terminalGroup.addDisposable(terminalGroup.onInstancesChanged(this._onInstancesChanged.fire, this._onInstancesChanged));
|
||||
if (this.terminalInstances.length === 1) {
|
||||
// It's the first instance so it should be made active automatically
|
||||
this.setActiveInstanceByIndex(0);
|
||||
|
@ -1066,7 +1066,7 @@ export class TerminalService implements ITerminalService {
|
|||
async setContainers(panelContainer: HTMLElement, terminalContainer: HTMLElement): Promise<void> {
|
||||
this._configHelper.panelContainer = panelContainer;
|
||||
this._terminalContainer = terminalContainer;
|
||||
this._terminalTabs.forEach(tab => tab.attachToElement(terminalContainer));
|
||||
this._terminalGroups.forEach(group => group.attachToElement(terminalContainer));
|
||||
}
|
||||
|
||||
hidePanel(): void {
|
||||
|
|
|
@ -204,7 +204,7 @@ export class TerminalTabbedView extends Disposable {
|
|||
// Size to include padding, icon, status icon (if any), split annotation (if any), + a little more
|
||||
const additionalWidth = 30;
|
||||
const statusIconWidth = instance.statusList.statuses.length > 0 ? STATUS_ICON_WIDTH : 0;
|
||||
const splitAnnotationWidth = (this._terminalService.getTabForInstance(instance)?.terminalInstances.length || 0) > 1 ? SPLIT_ANNOTATION_WIDTH : 0;
|
||||
const splitAnnotationWidth = (this._terminalService.getGroupForInstance(instance)?.terminalInstances.length || 0) > 1 ? SPLIT_ANNOTATION_WIDTH : 0;
|
||||
return additionalWidth + splitAnnotationWidth + statusIconWidth;
|
||||
}
|
||||
|
||||
|
@ -237,7 +237,7 @@ export class TerminalTabbedView extends Disposable {
|
|||
}
|
||||
this._splitView.addView({
|
||||
element: this._terminalContainer,
|
||||
layout: width => this._terminalService.terminalTabs.forEach(tab => tab.layout(width, this._height || 0)),
|
||||
layout: width => this._terminalService.terminalGroups.forEach(tab => tab.layout(width, this._height || 0)),
|
||||
minimumSize: 120,
|
||||
maximumSize: Number.POSITIVE_INFINITY,
|
||||
onDidChange: () => Disposable.None,
|
||||
|
|
|
@ -209,20 +209,20 @@ class TerminalTabsRenderer implements IListRenderer<ITerminalInstance, ITerminal
|
|||
}
|
||||
|
||||
renderElement(instance: ITerminalInstance, index: number, template: ITerminalTabEntryTemplate): void {
|
||||
const tab = this._terminalService.getTabForInstance(instance);
|
||||
if (!tab) {
|
||||
throw new Error(`Could not find tab for instance "${instance.instanceId}"`);
|
||||
const group = this._terminalService.getGroupForInstance(instance);
|
||||
if (!group) {
|
||||
throw new Error(`Could not find group for instance "${instance.instanceId}"`);
|
||||
}
|
||||
|
||||
const hasText = !this.shouldHideText();
|
||||
template.element.classList.toggle('has-text', hasText);
|
||||
|
||||
let prefix: string = '';
|
||||
if (tab.terminalInstances.length > 1) {
|
||||
const terminalIndex = tab.terminalInstances.indexOf(instance);
|
||||
if (group.terminalInstances.length > 1) {
|
||||
const terminalIndex = group.terminalInstances.indexOf(instance);
|
||||
if (terminalIndex === 0) {
|
||||
prefix = `┌ `;
|
||||
} else if (terminalIndex === tab!.terminalInstances.length - 1) {
|
||||
} else if (terminalIndex === group!.terminalInstances.length - 1) {
|
||||
prefix = `└ `;
|
||||
} else {
|
||||
prefix = `├ `;
|
||||
|
@ -346,7 +346,7 @@ class TerminalTabsAccessibilityProvider implements IListAccessibilityProvider<IT
|
|||
|
||||
getAriaLabel(instance: ITerminalInstance): string {
|
||||
let ariaLabel: string = '';
|
||||
const tab = this._terminalService.getTabForInstance(instance);
|
||||
const tab = this._terminalService.getGroupForInstance(instance);
|
||||
if (tab && tab.terminalInstances?.length > 1) {
|
||||
const terminalIndex = tab.terminalInstances.indexOf(instance);
|
||||
ariaLabel = localize({
|
||||
|
|
|
@ -123,7 +123,7 @@ export class TerminalViewPane extends ViewPane {
|
|||
|
||||
this._register(this.onDidChangeBodyVisibility(visible => {
|
||||
if (visible) {
|
||||
const hadTerminals = !!this._terminalService.terminalTabs.length;
|
||||
const hadTerminals = !!this._terminalService.terminalGroups.length;
|
||||
if (this._terminalService.isProcessSupportRegistered) {
|
||||
if (this._terminalsInitialized) {
|
||||
if (!hadTerminals) {
|
||||
|
@ -136,14 +136,14 @@ export class TerminalViewPane extends ViewPane {
|
|||
}
|
||||
|
||||
if (hadTerminals) {
|
||||
this._terminalService.getActiveTab()?.setVisible(visible);
|
||||
this._terminalService.getActiveGroup()?.setVisible(visible);
|
||||
} else {
|
||||
// TODO@Tyriar - this call seems unnecessary
|
||||
this.layoutBody(this._bodyDimensions.height, this._bodyDimensions.width);
|
||||
}
|
||||
this._terminalService.showPanel(true);
|
||||
} else {
|
||||
this._terminalService.getActiveTab()?.setVisible(false);
|
||||
this._terminalService.getActiveGroup()?.setVisible(false);
|
||||
}
|
||||
}));
|
||||
this.layoutBody(this._parentDomElement.offsetHeight, this._parentDomElement.offsetWidth);
|
||||
|
|
Loading…
Reference in a new issue