Skip to content

Commit 72208d7

Browse files
authored
Merge pull request microsoft#147463 from amanasifkhalid/terminal-tab-defaults
Close microsoft#134566: Added settings for terminal tab default color/icon
2 parents ce8b7a9 + 4c358e0 commit 72208d7

13 files changed

+86
-36
lines changed

src/vs/platform/terminal/common/terminal.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ export const enum TerminalSettingId {
4040
DefaultProfileMacOs = 'terminal.integrated.defaultProfile.osx',
4141
DefaultProfileWindows = 'terminal.integrated.defaultProfile.windows',
4242
UseWslProfiles = 'terminal.integrated.useWslProfiles',
43+
TabsDefaultIconColor = 'terminal.integrated.tabs.defaultIconColor',
44+
TabsDefaultIconId = 'terminal.integrated.tabs.defaultIconId',
4345
TabsEnabled = 'terminal.integrated.tabs.enabled',
4446
TabsEnableAnimation = 'terminal.integrated.tabs.enableAnimation',
4547
TabsHideCondition = 'terminal.integrated.tabs.hideCondition',

src/vs/platform/terminal/common/terminalPlatformConfiguration.ts

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,27 @@ import { Registry } from 'vs/platform/registry/common/platform';
1212
import { IExtensionTerminalProfile, ITerminalProfile, TerminalSettingId } from 'vs/platform/terminal/common/terminal';
1313
import { createProfileSchemaEnums } from 'vs/platform/terminal/common/terminalProfiles';
1414

15+
export const terminalColorSchema: IJSONSchema = {
16+
type: ['string', 'null'],
17+
enum: [
18+
'terminal.ansiBlack',
19+
'terminal.ansiRed',
20+
'terminal.ansiGreen',
21+
'terminal.ansiYellow',
22+
'terminal.ansiBlue',
23+
'terminal.ansiMagenta',
24+
'terminal.ansiCyan',
25+
'terminal.ansiWhite'
26+
],
27+
default: null
28+
};
29+
30+
export const terminalIconSchema: IJSONSchema = {
31+
type: 'string',
32+
enum: Array.from(Codicon.getAll(), icon => icon.id),
33+
markdownEnumDescriptions: Array.from(Codicon.getAll(), icon => `$(${icon.id})`),
34+
};
35+
1536
const terminalProfileBaseProperties: IJSONSchemaMap = {
1637
args: {
1738
description: localize('terminalProfile.args', 'An optional set of arguments to run the shell executable with.'),
@@ -26,24 +47,11 @@ const terminalProfileBaseProperties: IJSONSchemaMap = {
2647
},
2748
icon: {
2849
description: localize('terminalProfile.icon', 'A codicon ID to associate with this terminal.'),
29-
type: 'string',
30-
enum: Array.from(Codicon.getAll(), icon => icon.id),
31-
markdownEnumDescriptions: Array.from(Codicon.getAll(), icon => `$(${icon.id})`),
50+
...terminalIconSchema
3251
},
3352
color: {
3453
description: localize('terminalProfile.color', 'A theme color ID to associate with this terminal.'),
35-
type: ['string', 'null'],
36-
enum: [
37-
'terminal.ansiBlack',
38-
'terminal.ansiRed',
39-
'terminal.ansiGreen',
40-
'terminal.ansiYellow',
41-
'terminal.ansiBlue',
42-
'terminal.ansiMagenta',
43-
'terminal.ansiCyan',
44-
'terminal.ansiWhite'
45-
],
46-
default: null
54+
...terminalColorSchema
4755
},
4856
env: {
4957
markdownDescription: localize('terminalProfile.env', "An object with environment variables that will be added to the terminal profile process. Set to `null` to delete environment variables from the base environment."),

src/vs/workbench/contrib/terminal/browser/terminalActions.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1723,6 +1723,7 @@ export function registerTerminalActions() {
17231723
const themeService = accessor.get(IThemeService);
17241724
const groupService = accessor.get(ITerminalGroupService);
17251725
const notificationService = accessor.get(INotificationService);
1726+
17261727
const picks: ITerminalQuickPickItem[] = [];
17271728
if (groupService.instances.length <= 1) {
17281729
notificationService.warn(localize('workbench.action.terminal.join.insufficientTerminals', 'Insufficient terminals for the join action'));
@@ -1732,7 +1733,7 @@ export function registerTerminalActions() {
17321733
for (const terminal of otherInstances) {
17331734
const group = groupService.getGroupForInstance(terminal);
17341735
if (group?.terminalInstances.length === 1) {
1735-
const iconId = getIconId(terminal);
1736+
const iconId = getIconId(accessor, terminal);
17361737
const label = `$(${iconId}): ${terminal.title}`;
17371738
const iconClasses: string[] = [];
17381739
const colorClass = getColorClass(terminal);

src/vs/workbench/contrib/terminal/browser/terminalIcon.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { Codicon } from 'vs/base/common/codicons';
76
import { hash } from 'vs/base/common/hash';
87
import { URI } from 'vs/base/common/uri';
8+
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
99
import { IExtensionTerminalProfile, ITerminalProfile } from 'vs/platform/terminal/common/terminal';
1010
import { getIconRegistry } from 'vs/platform/theme/common/iconRegistry';
1111
import { ColorScheme } from 'vs/platform/theme/common/theme';
1212
import { IColorTheme, ThemeIcon } from 'vs/platform/theme/common/themeService';
1313
import { ITerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminal';
14+
import { ITerminalProfileResolverService } from 'vs/workbench/contrib/terminal/common/terminal';
1415
import { ansiColorMap } from 'vs/workbench/contrib/terminal/common/terminalColorRegistry';
1516

1617

@@ -116,9 +117,9 @@ export function getUriClasses(terminal: ITerminalInstance | IExtensionTerminalPr
116117
return iconClasses;
117118
}
118119

119-
export function getIconId(terminal: ITerminalInstance | IExtensionTerminalProfile | ITerminalProfile): string {
120+
export function getIconId(accessor: ServicesAccessor, terminal: ITerminalInstance | IExtensionTerminalProfile | ITerminalProfile): string {
120121
if (!terminal.icon || (terminal.icon instanceof Object && !('id' in terminal.icon))) {
121-
return Codicon.terminal.id;
122+
return accessor.get(ITerminalProfileResolverService).getDefaultIcon().id;
122123
}
123124
return typeof terminal.icon === 'string' ? terminal.icon : terminal.icon.id;
124125
}

src/vs/workbench/contrib/terminal/browser/terminalInstance.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ import type { IMarker, ITerminalAddon, Terminal as XTermTerminal } from 'xterm';
8686
import { IOpenerService } from 'vs/platform/opener/common/opener';
8787
import { IGenericMarkProperties } from 'vs/platform/terminal/common/terminalProcess';
8888
import { ICommandService } from 'vs/platform/commands/common/commands';
89+
import { getIconRegistry } from 'vs/platform/theme/common/iconRegistry';
8990

9091
const enum Constants {
9192
/**
@@ -548,7 +549,9 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
548549

549550
private _getIcon(): TerminalIcon | undefined {
550551
if (!this._icon) {
551-
this._icon = this._processManager.processState >= ProcessState.Launching ? Codicon.terminal : undefined;
552+
this._icon = this._processManager.processState >= ProcessState.Launching
553+
? getIconRegistry().getIcon(this._configurationService.getValue(TerminalSettingId.TabsDefaultIconId))
554+
: undefined;
552555
}
553556
return this._icon;
554557
}

src/vs/workbench/contrib/terminal/browser/terminalProfileQuickpick.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { getUriClasses, getColorClass, getColorStyleElement } from 'vs/workbench
1111
import { configureTerminalProfileIcon } from 'vs/workbench/contrib/terminal/browser/terminalIcons';
1212
import * as nls from 'vs/nls';
1313
import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService';
14-
import { ITerminalProfileService } from 'vs/workbench/contrib/terminal/common/terminal';
14+
import { ITerminalProfileResolverService, ITerminalProfileService } from 'vs/workbench/contrib/terminal/common/terminal';
1515
import { IQuickPickTerminalObject, ITerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminal';
1616
import { IPickerQuickAccessItem } from 'vs/platform/quickinput/browser/pickerQuickAccess';
1717
import { getIconRegistry } from 'vs/platform/theme/common/iconRegistry';
@@ -22,6 +22,7 @@ type DefaultProfileName = string;
2222
export class TerminalProfileQuickpick {
2323
constructor(
2424
@ITerminalProfileService private readonly _terminalProfileService: ITerminalProfileService,
25+
@ITerminalProfileResolverService private readonly _terminalProfileResolverService: ITerminalProfileResolverService,
2526
@IConfigurationService private readonly _configurationService: IConfigurationService,
2627
@IQuickInputService private readonly _quickInputService: IQuickInputService,
2728
@IThemeService private readonly _themeService: IThemeService
@@ -155,7 +156,7 @@ export class TerminalProfileQuickpick {
155156
}
156157
}
157158
if (!icon || !getIconRegistry().getIcon(icon.id)) {
158-
icon = Codicon.terminal;
159+
icon = this._terminalProfileResolverService.getDefaultIcon();
159160
}
160161
const uriClasses = getUriClasses(contributed, this._themeService.getColorTheme().type, true);
161162
const colorClass = getColorClass(contributed);

src/vs/workbench/contrib/terminal/browser/terminalProfileResolverService.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { IShellLaunchConfig, ITerminalProfile, ITerminalProfileObject, TerminalI
1616
import { IShellLaunchConfigResolveOptions, ITerminalProfileResolverService, ITerminalProfileService } from 'vs/workbench/contrib/terminal/common/terminal';
1717
import * as path from 'vs/base/common/path';
1818
import { Codicon } from 'vs/base/common/codicons';
19+
import { getIconRegistry, IIconRegistry } from 'vs/platform/theme/common/iconRegistry';
1920
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
2021
import { debounce } from 'vs/base/common/decorators';
2122
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
@@ -51,6 +52,8 @@ export abstract class BaseTerminalProfileResolverService implements ITerminalPro
5152

5253
private _primaryBackendOs: OperatingSystem | undefined;
5354

55+
private readonly _iconRegistry: IIconRegistry = getIconRegistry();
56+
5457
private _defaultProfileName: string | undefined;
5558
get defaultProfileName(): string | undefined { return this._defaultProfileName; }
5659

@@ -94,11 +97,11 @@ export abstract class BaseTerminalProfileResolverService implements ITerminalPro
9497

9598
resolveIcon(shellLaunchConfig: IShellLaunchConfig, os: OperatingSystem): void {
9699
if (shellLaunchConfig.icon) {
97-
shellLaunchConfig.icon = this._getCustomIcon(shellLaunchConfig.icon) || Codicon.terminal;
100+
shellLaunchConfig.icon = this._getCustomIcon(shellLaunchConfig.icon) || this.getDefaultIcon();
98101
return;
99102
}
100103
if (shellLaunchConfig.customPtyImplementation) {
101-
shellLaunchConfig.icon = Codicon.terminal;
104+
shellLaunchConfig.icon = this.getDefaultIcon();
102105
return;
103106
}
104107
if (shellLaunchConfig.executable) {
@@ -108,6 +111,13 @@ export abstract class BaseTerminalProfileResolverService implements ITerminalPro
108111
if (defaultProfile) {
109112
shellLaunchConfig.icon = defaultProfile.icon;
110113
}
114+
if (!shellLaunchConfig.icon) {
115+
shellLaunchConfig.icon = this.getDefaultIcon();
116+
}
117+
}
118+
119+
getDefaultIcon(): TerminalIcon & ThemeIcon {
120+
return this._iconRegistry.getIcon(this._configurationService.getValue(TerminalSettingId.TabsDefaultIconId)) || Codicon.terminal;
111121
}
112122

113123
async resolveShellLaunchConfig(shellLaunchConfig: IShellLaunchConfig, options: IShellLaunchConfigResolveOptions): Promise<void> {
@@ -135,15 +145,19 @@ export abstract class BaseTerminalProfileResolverService implements ITerminalPro
135145

136146
// Verify the icon is valid, and fallback correctly to the generic terminal id if there is
137147
// an issue
138-
shellLaunchConfig.icon = this._getCustomIcon(shellLaunchConfig.icon) || this._getCustomIcon(resolvedProfile.icon) || Codicon.terminal;
148+
shellLaunchConfig.icon = this._getCustomIcon(shellLaunchConfig.icon)
149+
|| this._getCustomIcon(resolvedProfile.icon)
150+
|| this.getDefaultIcon();
139151

140152
// Override the name if specified
141153
if (resolvedProfile.overrideName) {
142154
shellLaunchConfig.name = resolvedProfile.profileName;
143155
}
144156

145157
// Apply the color
146-
shellLaunchConfig.color = shellLaunchConfig.color || resolvedProfile.color;
158+
shellLaunchConfig.color = shellLaunchConfig.color
159+
|| resolvedProfile.color
160+
|| this._configurationService.getValue(TerminalSettingId.TabsDefaultIconColor);
147161

148162
// Resolve useShellEnvironment based on the setting if it's not set
149163
if (shellLaunchConfig.useShellEnvironment === undefined) {
@@ -232,6 +246,7 @@ export abstract class BaseTerminalProfileResolverService implements ITerminalPro
232246
if (defaultProfileName && typeof defaultProfileName === 'string') {
233247
return this._terminalProfileService.availableProfiles.find(e => e.profileName === defaultProfileName);
234248
}
249+
235250
return undefined;
236251
}
237252

src/vs/workbench/contrib/terminal/browser/terminalQuickAccess.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { getColorClass, getIconId, getUriClasses } from 'vs/workbench/contrib/te
1616
import { terminalStrings } from 'vs/workbench/contrib/terminal/common/terminalStrings';
1717
import { TerminalLocation } from 'vs/platform/terminal/common/terminal';
1818
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
19+
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
1920
let terminalPicks: Array<IPickerQuickAccessItem | IQuickPickSeparator> = [];
2021

2122
export class TerminalQuickAccessProvider extends PickerQuickAccessProvider<IPickerQuickAccessItem> {
@@ -27,7 +28,8 @@ export class TerminalQuickAccessProvider extends PickerQuickAccessProvider<IPick
2728
@ITerminalEditorService private readonly _terminalEditorService: ITerminalEditorService,
2829
@ITerminalGroupService private readonly _terminalGroupService: ITerminalGroupService,
2930
@ICommandService private readonly _commandService: ICommandService,
30-
@IThemeService private readonly _themeService: IThemeService
31+
@IThemeService private readonly _themeService: IThemeService,
32+
@IInstantiationService private readonly _instantiationService: IInstantiationService
3133
) {
3234
super(TerminalQuickAccessProvider.PREFIX, { canAcceptInBackground: true });
3335
}
@@ -80,7 +82,7 @@ export class TerminalQuickAccessProvider extends PickerQuickAccessProvider<IPick
8082
}
8183

8284
private _createPick(terminal: ITerminalInstance, terminalIndex: number, filter: string, groupInfo?: { groupIndex: number; groupSize: number }): IPickerQuickAccessItem | undefined {
83-
const iconId = getIconId(terminal);
85+
const iconId = this._instantiationService.invokeFunction(getIconId, terminal);
8486
const index = groupInfo
8587
? (groupInfo.groupSize > 1
8688
? `${groupInfo.groupIndex + 1}.${terminalIndex + 1}`

src/vs/workbench/contrib/terminal/browser/terminalTabsList.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ class TerminalTabsRenderer implements IListRenderer<ITerminalInstance, ITerminal
309309
}
310310

311311
const shellIntegrationString = getShellIntegrationTooltip(instance, true, this._configurationService);
312-
const iconId = getIconId(instance);
312+
const iconId = this._instantiationService.invokeFunction(getIconId, instance);
313313
const hasActionbar = !this.shouldHideActionBar();
314314
let label: string = '';
315315
if (!hasText) {

src/vs/workbench/contrib/terminal/browser/terminalView.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import { withNullAsUndefined } from 'vs/base/common/types';
4545
import { getTerminalActionBarArgs } from 'vs/workbench/contrib/terminal/browser/terminalMenus';
4646
import { TerminalContextKeys } from 'vs/workbench/contrib/terminal/common/terminalContextKey';
4747
import { getShellIntegrationTooltip } from 'vs/workbench/contrib/terminal/browser/terminalTooltip';
48+
import { ServicesAccessor } from 'vs/editor/browser/editorExtensions';
4849

4950
export class TerminalViewPane extends ViewPane {
5051
private _actions: IAction[] | undefined;
@@ -374,12 +375,13 @@ class SingleTerminalTabActionViewItem extends MenuEntryActionViewItem {
374375
@ITerminalGroupService private readonly _terminalGroupService: ITerminalGroupService,
375376
@IContextMenuService private readonly _contextMenuService: IContextMenuService,
376377
@ICommandService private readonly _commandService: ICommandService,
377-
@IConfigurationService configurationService: IConfigurationService
378+
@IConfigurationService configurationService: IConfigurationService,
379+
@IInstantiationService private readonly _instantiationService: IInstantiationService,
378380
) {
379381
super(new MenuItemAction(
380382
{
381383
id: action.id,
382-
title: getSingleTabLabel(_terminalGroupService.activeInstance, _terminalService.configHelper.config.tabs.separator),
384+
title: _instantiationService.invokeFunction(getSingleTabLabel, _terminalGroupService.activeInstance, _terminalService.configHelper.config.tabs.separator),
383385
tooltip: getSingleTabTooltip(_terminalGroupService.activeInstance, _terminalService.configHelper.config.tabs.separator, configurationService)
384386
},
385387
{
@@ -473,7 +475,7 @@ class SingleTerminalTabActionViewItem extends MenuEntryActionViewItem {
473475
}
474476
}
475477
label.style.color = colorStyle;
476-
dom.reset(label, ...renderLabelWithIcons(getSingleTabLabel(instance, this._terminalService.configHelper.config.tabs.separator, ThemeIcon.isThemeIcon(this._commandAction.item.icon) ? this._commandAction.item.icon : undefined)));
478+
dom.reset(label, ...renderLabelWithIcons(this._instantiationService.invokeFunction(getSingleTabLabel, instance, this._terminalService.configHelper.config.tabs.separator, ThemeIcon.isThemeIcon(this._commandAction.item.icon) ? this._commandAction.item.icon : undefined)));
477479

478480
if (this._altCommand) {
479481
label.classList.remove(this._altCommand);
@@ -515,13 +517,13 @@ class SingleTerminalTabActionViewItem extends MenuEntryActionViewItem {
515517
}
516518
}
517519

518-
function getSingleTabLabel(instance: ITerminalInstance | undefined, separator: string, icon?: ThemeIcon) {
520+
function getSingleTabLabel(accessor: ServicesAccessor, instance: ITerminalInstance | undefined, separator: string, icon?: ThemeIcon) {
519521
// Don't even show the icon if there is no title as the icon would shift around when the title
520522
// is added
521523
if (!instance || !instance.title) {
522524
return '';
523525
}
524-
const iconClass = ThemeIcon.isThemeIcon(instance.icon) ? instance.icon?.id : Codicon.terminal.id;
526+
const iconClass = ThemeIcon.isThemeIcon(instance.icon) ? instance.icon.id : accessor.get(ITerminalProfileResolverService).getDefaultIcon();
525527
const label = `$(${icon?.id || iconClass}) ${getSingleTabTitle(instance, separator)}`;
526528

527529
const primaryStatus = instance.statusList.primary;

0 commit comments

Comments
 (0)