Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/vs/platform/accessibility/browser/accessibleView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export const enum AccessibleViewProviderId {
Terminal = 'terminal',
TerminalChat = 'terminal-chat',
TerminalHelp = 'terminal-help',
TerminalTabsHelp = 'terminal-tabs-help',
DiffEditor = 'diffEditor',
MergeEditor = 'mergeEditor',
PanelChat = 'panelChat',
Expand Down
131 changes: 131 additions & 0 deletions src/vs/workbench/contrib/terminal/browser/media/terminalTabsBar.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

.monaco-workbench .pane-body.integrated-terminal .tabs-container.horizontal-tabs {
border-left: none;
border-right: none;
border-bottom: var(--vscode-strokeThickness) solid var(--vscode-terminal-border);
box-sizing: border-box;
}

.monaco-workbench .pane-body.integrated-terminal .tabs-container.horizontal-tabs.tabs-bottom {
border-bottom: none;
border-top: var(--vscode-strokeThickness) solid var(--vscode-terminal-border);
}

.monaco-workbench .pane-body.integrated-terminal .horizontal-tabs .tabs-list-container {
flex-direction: row;
align-items: center;
min-width: 0;
}

.monaco-workbench .pane-body.integrated-terminal .horizontal-tabs .tabs-list {
min-width: 0;
}

.monaco-workbench .terminal-tabs-bar {
display: flex;
position: relative;
align-items: stretch;
overflow: hidden;
white-space: nowrap;
}

.monaco-workbench .terminal-tabs-bar .terminal-tabs-bar-tab {
position: relative;
flex: 0 0 auto;
min-width: 120px;
max-width: 240px;
box-sizing: border-box;
cursor: pointer;
outline-offset: -1px;
}

.monaco-workbench .terminal-tabs-bar .terminal-tabs-bar-tab.group-start {
margin-left: var(--vscode-spacing-size40);
border-left: var(--vscode-strokeThickness) solid var(--vscode-terminal-border);
}

.monaco-workbench .pane-body.integrated-terminal .horizontal-tabs .terminal-tabs-entry {
display: flex;
align-items: center;
height: 100%;
box-sizing: border-box;
}

.monaco-workbench .terminal-tabs-bar .monaco-icon-label {
display: flex;
align-items: center;
min-width: 0;
flex: 1;
}

.monaco-workbench .terminal-tabs-bar .monaco-icon-label-container {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
}

.monaco-workbench .pane-body.integrated-terminal .horizontal-tabs .terminal-tabs-bar-tab .actions {
display: block;
visibility: hidden;
flex-shrink: 0;
}

.monaco-workbench .pane-body.integrated-terminal .horizontal-tabs .terminal-tabs-bar-tab:hover .actions,
.monaco-workbench .pane-body.integrated-terminal .horizontal-tabs .terminal-tabs-bar-tab:focus-within .actions {
visibility: visible;
}

.monaco-workbench .terminal-tabs-bar .terminal-tabs-bar-tab:hover {
background-color: var(--vscode-list-hoverBackground);
color: var(--vscode-list-hoverForeground);
}

.monaco-workbench .terminal-tabs-bar .terminal-tabs-bar-tab.selected {
background-color: var(--vscode-list-inactiveSelectionBackground);
color: var(--vscode-list-inactiveSelectionForeground);
outline: var(--vscode-strokeThickness) solid var(--vscode-contrastBorder, transparent);
}

.monaco-workbench .terminal-tabs-bar:focus-within .terminal-tabs-bar-tab.selected {
background-color: var(--vscode-list-activeSelectionBackground);
color: var(--vscode-list-activeSelectionForeground);
}

.monaco-workbench .terminal-tabs-bar .terminal-tabs-bar-tab:focus-visible {
outline: var(--vscode-strokeThickness) solid var(--vscode-focusBorder);
}

.monaco-workbench .pane-body.integrated-terminal .horizontal-tabs .terminal-tabs-entry.is-active::before {
top: auto;
right: 0;
bottom: 0;
width: auto;
height: var(--vscode-strokeThickness);
}

.monaco-workbench .pane-body.integrated-terminal .horizontal-tabs.tabs-bottom .terminal-tabs-entry.is-active::before {
top: 0;
bottom: auto;
}

.monaco-workbench .terminal-tabs-bar.drop-target,
.monaco-workbench .terminal-tabs-bar .terminal-tabs-bar-tab.drop-target {
background-color: var(--vscode-list-dropBackground);
outline: var(--vscode-strokeThickness) solid var(--vscode-list-dropBetweenBackground);
outline-offset: -1px;
}

.monaco-workbench .pane-body.integrated-terminal .horizontal-tabs .terminal-tabs-chat-entry {
max-width: 40%;
min-width: 0;
height: 100%;
}

.monaco-workbench .pane-body.integrated-terminal .horizontal-tabs .terminal-tabs-chat-entry-icon,
.monaco-workbench .pane-body.integrated-terminal .horizontal-tabs .terminal-tabs-chat-entry-delete {
flex-shrink: 0;
}
1 change: 1 addition & 0 deletions src/vs/workbench/contrib/terminal/browser/terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -831,6 +831,7 @@ export interface ITerminalGroupService extends ITerminalInstanceHost {
showPanel(focus?: boolean): Promise<void>;
hidePanel(): void;
focusTabs(): void;
getSelectedTabInstances(): ITerminalInstance[] | undefined;
focusHover(): void;
updateVisibility(): void;
}
Expand Down
39 changes: 6 additions & 33 deletions src/vs/workbench/contrib/terminal/browser/terminalActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import { FileKind } from '../../../../platform/files/common/files.js';
import { ServicesAccessor } from '../../../../platform/instantiation/common/instantiation.js';
import { KeybindingWeight } from '../../../../platform/keybinding/common/keybindingsRegistry.js';
import { ILabelService } from '../../../../platform/label/common/label.js';
import { IListService } from '../../../../platform/list/browser/listService.js';
import { INotificationService, Severity } from '../../../../platform/notification/common/notification.js';
import { IOpenerService } from '../../../../platform/opener/common/opener.js';
import { IPickOptions, IQuickInputService, IQuickPickItem } from '../../../../platform/quickinput/common/quickInput.js';
Expand Down Expand Up @@ -61,7 +60,6 @@ import { InstanceContext } from './terminalContextMenu.js';
import { getColorClass, getIconId, getUriClasses } from './terminalIcon.js';
import { killTerminalIcon, newTerminalIcon } from './terminalIcons.js';
import { ITerminalQuickPickItem } from './terminalProfileQuickpick.js';
import { TerminalTabList } from './terminalTabsList.js';
import { ResourceContextKey } from '../../../common/contextkeys.js';
import { SeparatorSelectOption } from '../../../../base/browser/ui/selectBox/selectBox.js';

Expand Down Expand Up @@ -1331,7 +1329,7 @@ export function registerTerminalActions() {
},
run: async (c, accessor) => {
const disposePromises: Promise<void>[] = [];
for (const terminal of getSelectedViewInstances(accessor, true) ?? []) {
for (const terminal of getSelectedViewInstances(accessor) ?? []) {
disposePromises.push(c.service.safeDisposeTerminal(terminal));
}
await Promise.all(disposePromises);
Expand Down Expand Up @@ -1468,39 +1466,14 @@ function getSelectedViewInstances2(accessor: ServicesAccessor, args?: unknown):
return undefined;
}

function getSelectedViewInstances(accessor: ServicesAccessor, args?: unknown, args2?: unknown): ITerminalInstance[] | undefined {
const listService = accessor.get(IListService);
function getSelectedViewInstances(accessor: ServicesAccessor): ITerminalInstance[] | undefined {
const terminalGroupService = accessor.get(ITerminalGroupService);
const result: ITerminalInstance[] = [];

// Assign list only if it's an instance of TerminalTabList (#234791)
const list = listService.lastFocusedList instanceof TerminalTabList ? listService.lastFocusedList : undefined;
// Get selected tab list instance(s)
const selections = list?.getSelection();
// Get inline tab instance if there are not tab list selections #196578
if (terminalGroupService.lastAccessedMenu === 'inline-tab' && !selections?.length) {
const selection = terminalGroupService.getSelectedTabInstances();
if (terminalGroupService.lastAccessedMenu === 'inline-tab' && !selection?.length) {
const instance = terminalGroupService.activeInstance;
return instance ? [terminalGroupService.activeInstance] : undefined;
}

if (!list || !selections) {
return undefined;
}
const focused = list.getFocus();

const viewInstances = terminalGroupService.instances;
if (focused.length === 1 && !selections.includes(focused[0])) {
// focused length is always a max of 1
// if the focused one is not in the selected list, return that item
result.push(viewInstances[focused[0]]);
return result;
}

// multi-select
for (const selection of selections) {
result.push(viewInstances[selection]);
return instance ? [instance] : undefined;
}
return result.filter(r => !!r);
return selection;
}

export function validateTerminalName(name: string): { content: string; severity: Severity } | null {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,11 @@ export class TerminalGroupService extends Disposable implements ITerminalGroupSe
pane?.terminalTabbedView?.focusHover();
}

getSelectedTabInstances(): ITerminalInstance[] | undefined {
const pane = this._viewsService.getActiveViewWithId<TerminalViewPane>(TERMINAL_VIEW_ID);
return pane?.terminalTabbedView?.getSelectedTabInstances();
}

async focusInstance(instance: ITerminalInstance): Promise<void> {
if (this.instances.includes(instance)) {
this.setActiveInstance(instance);
Expand Down
Loading