Skip to content
Merged
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
7 changes: 7 additions & 0 deletions src/vs/workbench/contrib/terminal/browser/terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,13 @@ export interface ITerminalService extends ITerminalInstanceHost {
*/
createTerminal(options?: ICreateTerminalOptions): Promise<ITerminalInstance>;

/**
* Creates and focuses a terminal.
* @param options The options to create the terminal with, when not specified the default
* profile will be used at the default target.
*/
createAndFocusTerminal(options?: ICreateTerminalOptions): Promise<ITerminalInstance>;

/**
* Creates a detached xterm instance which is not attached to the DOM or
* tracked as a terminal instance.
Expand Down
44 changes: 19 additions & 25 deletions src/vs/workbench/contrib/terminal/browser/terminalMenus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { ICreateTerminalOptions, ITerminalLocationOptions, ITerminalService } fr
import { TerminalCommandId, TERMINAL_VIEW_ID } from '../common/terminal.js';
import { TerminalContextKeys, TerminalContextKeyStrings } from '../common/terminalContextKey.js';
import { terminalStrings } from '../common/terminalStrings.js';
import { ACTIVE_GROUP, SIDE_GROUP } from '../../../services/editor/common/editorService.js';
import { ACTIVE_GROUP, AUX_WINDOW_GROUP, SIDE_GROUP } from '../../../services/editor/common/editorService.js';
import { DisposableStore } from '../../../../base/common/lifecycle.js';

const enum ContextMenuGroup {
Expand Down Expand Up @@ -706,39 +706,45 @@ export function getTerminalActionBarArgs(location: ITerminalLocationOptions, pro
className: string;
dropdownIcon?: string;
} {
let dropdownActions: IAction[] = [];
let submenuActions: IAction[] = [];
profiles = profiles.filter(e => !e.isAutoDetected);
const dropdownActions: IAction[] = [];
const submenuActions: IAction[] = [];
const splitLocation = (location === TerminalLocation.Editor || (typeof location === 'object' && 'viewColumn' in location && location.viewColumn === ACTIVE_GROUP)) ? { viewColumn: SIDE_GROUP } : { splitActiveTerminal: true };

dropdownActions.push(disposableStore.add(new Action(TerminalCommandId.New, terminalStrings.new, undefined, true, () => terminalService.createAndFocusTerminal())));
dropdownActions.push(disposableStore.add(new Action(TerminalCommandId.NewInNewWindow, terminalStrings.newInNewWindow.short, undefined, true, () => terminalService.createAndFocusTerminal({
location: { viewColumn: AUX_WINDOW_GROUP }
}))));
dropdownActions.push(disposableStore.add(new Action(TerminalCommandId.Split, terminalStrings.split.value, undefined, true, () => terminalService.createAndFocusTerminal({
location: splitLocation
}))));
dropdownActions.push(new Separator());

profiles = profiles.filter(e => !e.isAutoDetected);
for (const p of profiles) {
const isDefault = p.profileName === defaultProfileName;
const options: ICreateTerminalOptions = { config: p, location };
const splitOptions: ICreateTerminalOptions = { config: p, location: splitLocation };
const sanitizedProfileName = p.profileName.replace(/[\n\r\t]/g, '');
dropdownActions.push(disposableStore.add(new Action(TerminalCommandId.NewWithProfile, isDefault ? localize('defaultTerminalProfile', "{0} (Default)", sanitizedProfileName) : sanitizedProfileName, undefined, true, async () => {
const instance = await terminalService.createTerminal(options);
terminalService.setActiveInstance(instance);
await terminalService.focusActiveInstance();
await terminalService.createAndFocusTerminal(options);
})));
submenuActions.push(disposableStore.add(new Action(TerminalCommandId.Split, isDefault ? localize('defaultTerminalProfile', "{0} (Default)", sanitizedProfileName) : sanitizedProfileName, undefined, true, async () => {
const instance = await terminalService.createTerminal(splitOptions);
terminalService.setActiveInstance(instance);
await terminalService.focusActiveInstance();
await terminalService.createAndFocusTerminal(splitOptions);
})));
}

for (const contributed of contributedProfiles) {
const isDefault = contributed.title === defaultProfileName;
const title = isDefault ? localize('defaultTerminalProfile', "{0} (Default)", contributed.title.replace(/[\n\r\t]/g, '')) : contributed.title.replace(/[\n\r\t]/g, '');
dropdownActions.push(disposableStore.add(new Action('contributed', title, undefined, true, () => terminalService.createTerminal({
dropdownActions.push(disposableStore.add(new Action('contributed', title, undefined, true, () => terminalService.createAndFocusTerminal({
config: {
extensionIdentifier: contributed.extensionIdentifier,
id: contributed.id,
title
},
location
}))));
submenuActions.push(disposableStore.add(new Action('contributed-split', title, undefined, true, () => terminalService.createTerminal({
submenuActions.push(disposableStore.add(new Action('contributed-split', title, undefined, true, () => terminalService.createAndFocusTerminal({
config: {
extensionIdentifier: contributed.extensionIdentifier,
id: contributed.id,
Expand All @@ -748,25 +754,13 @@ export function getTerminalActionBarArgs(location: ITerminalLocationOptions, pro
}))));
}

const defaultProfileAction = dropdownActions.find(d => d.label.endsWith('(Default)'));
if (defaultProfileAction) {
dropdownActions = dropdownActions.filter(d => d !== defaultProfileAction).sort((a, b) => a.label.localeCompare(b.label));
dropdownActions.unshift(defaultProfileAction);
}

if (dropdownActions.length > 0) {
dropdownActions.push(new SubmenuAction('split.profile', localize('splitTerminal', 'Split Terminal'), submenuActions));
dropdownActions.push(new SubmenuAction('split.profile', localize('split.profile', 'Split Terminal with Profile'), submenuActions));
dropdownActions.push(new Separator());
}
const actions = dropdownMenu.getActions();
dropdownActions.push(...Separator.join(...actions.map(a => a[1])));

const defaultSubmenuProfileAction = submenuActions.find(d => d.label.endsWith('(Default)'));
if (defaultSubmenuProfileAction) {
submenuActions = submenuActions.filter(d => d !== defaultSubmenuProfileAction).sort((a, b) => a.label.localeCompare(b.label));
submenuActions.unshift(defaultSubmenuProfileAction);
}

const dropdownAction = disposableStore.add(new Action('refresh profiles', localize('launchProfile', 'Launch Profile...'), 'codicon-chevron-down', true));
return { dropdownAction, dropdownMenuActions: dropdownActions, className: `terminal-tab-actions-${terminalService.resolveLocation(location)}` };
}
7 changes: 7 additions & 0 deletions src/vs/workbench/contrib/terminal/browser/terminalService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1036,6 +1036,13 @@ export class TerminalService extends Disposable implements ITerminalService {
return instance;
}

async createAndFocusTerminal(options?: ICreateTerminalOptions): Promise<ITerminalInstance> {
const instance = await this.createTerminal(options);
this.setActiveInstance(instance);
await instance.focusWhenReady();
return instance;
}

private async _getContributedProfile(shellLaunchConfig: IShellLaunchConfig, options?: ICreateTerminalOptions): Promise<IExtensionTerminalProfile | undefined> {
if (options?.config && 'extensionIdentifier' in options.config) {
return options.config;
Expand Down
11 changes: 6 additions & 5 deletions src/vs/workbench/contrib/terminal/browser/terminalView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export class TerminalViewPane extends ViewPane {
@IContextKeyService private readonly _contextKeyService: IContextKeyService,
@IViewDescriptorService viewDescriptorService: IViewDescriptorService,
@IConfigurationService private readonly _configurationService: IConfigurationService,
@IContextMenuService private readonly _contextMenuService: IContextMenuService,
@IContextMenuService contextMenuService: IContextMenuService,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@ITerminalService private readonly _terminalService: ITerminalService,
@ITerminalConfigurationService private readonly _terminalConfigurationService: ITerminalConfigurationService,
Expand All @@ -89,10 +89,8 @@ export class TerminalViewPane extends ViewPane {
@IMenuService private readonly _menuService: IMenuService,
@ITerminalProfileService private readonly _terminalProfileService: ITerminalProfileService,
@ITerminalProfileResolverService private readonly _terminalProfileResolverService: ITerminalProfileResolverService,
@IThemeService private readonly _themeService: IThemeService,
@IAccessibilityService private readonly _accessibilityService: IAccessibilityService
) {
super(options, keybindingService, _contextMenuService, _configurationService, _contextKeyService, viewDescriptorService, _instantiationService, openerService, themeService, hoverService);
super(options, keybindingService, contextMenuService, _configurationService, _contextKeyService, viewDescriptorService, _instantiationService, openerService, themeService, hoverService);
this._register(this._terminalService.onDidRegisterProcessSupport(() => {
this._onDidChangeViewWelcomeState.fire();
}));
Expand Down Expand Up @@ -293,7 +291,10 @@ export class TerminalViewPane extends ViewPane {
case TerminalCommandId.New: {
if (action instanceof MenuItemAction) {
const actions = getTerminalActionBarArgs(TerminalLocation.Panel, this._terminalProfileService.availableProfiles, this._getDefaultProfileName(), this._terminalProfileService.contributedProfiles, this._terminalService, this._dropdownMenu, this._disposableStore);
this._newDropdown.value = new DropdownWithPrimaryActionViewItem(action, actions.dropdownAction, actions.dropdownMenuActions, actions.className, { hoverDelegate: options.hoverDelegate }, this._contextMenuService, this._keybindingService, this._notificationService, this._contextKeyService, this._themeService, this._accessibilityService);
this._newDropdown.value = this._instantiationService.createInstance(DropdownWithPrimaryActionViewItem, action, actions.dropdownAction, actions.dropdownMenuActions, actions.className, {
hoverDelegate: options.hoverDelegate,
getKeyBinding: (action: IAction) => this._keybindingService.lookupKeybinding(action.id, this._contextKeyService)
});
this._newDropdown.value?.update(actions.dropdownAction, actions.dropdownMenuActions);
return this._newDropdown.value;
}
Expand Down
5 changes: 4 additions & 1 deletion src/vs/workbench/contrib/terminal/common/terminalStrings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ export const terminalStrings = {
},
moveToEditor: localize2('moveToEditor', "Move Terminal into Editor Area"),
moveIntoNewWindow: localize2('moveIntoNewWindow', "Move Terminal into New Window"),
newInNewWindow: localize2('newInNewWindow', "New Terminal in New Window"),
newInNewWindow: {
...localize2('newInNewWindow', "New Terminal in New Window"),
short: localize('newInNewWindow.short', "New in New Window")
},
moveToTerminalPanel: localize2('workbench.action.terminal.moveToTerminalPanel', "Move Terminal into Panel"),
changeIcon: localize2('workbench.action.terminal.changeIcon', "Change Icon..."),
changeColor: localize2('workbench.action.terminal.changeColor', "Change Color..."),
Expand Down
Loading