Skip to content

Commit

Permalink
terminal: allow terminal types to be contributed
Browse files Browse the repository at this point in the history
* terminal: allow terminal types to be contributed

* fixup! only allow terminal extensions on proposed APIs

* fixup! rm unused import
  • Loading branch information
connor4312 authored Jun 25, 2020
1 parent 6878988 commit 4941478
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 8 deletions.
38 changes: 30 additions & 8 deletions src/vs/workbench/contrib/terminal/browser/terminalActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegis
import { localize } from 'vs/nls';
import { CONTEXT_ACCESSIBILITY_MODE_ENABLED } from 'vs/platform/accessibility/common/accessibility';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { ITerminalContributionService } from 'vs/workbench/contrib/terminal/common/terminalExtensionPoints';

async function getCwdForSplit(configHelper: ITerminalConfigHelper, instance: ITerminalInstance, folders?: IWorkspaceFolder[], commandService?: ICommandService): Promise<string | URI | undefined> {
switch (configHelper.config.splitCwd) {
Expand Down Expand Up @@ -304,14 +305,18 @@ export class SelectDefaultShellWindowsTerminalAction extends Action {
}
}

const terminalIndexRe = /^([0-9]+): /;

export class SwitchTerminalAction extends Action {

public static readonly ID = TERMINAL_COMMAND_ID.SWITCH_TERMINAL;
public static readonly LABEL = localize('workbench.action.terminal.switchTerminal', "Switch Terminal");

constructor(
id: string, label: string,
@ITerminalService private readonly _terminalService: ITerminalService
@ITerminalService private readonly _terminalService: ITerminalService,
@ITerminalContributionService private readonly _contributions: ITerminalContributionService,
@ICommandService private readonly _commands: ICommandService,
) {
super(id, label, 'terminal-action switch-terminal');
}
Expand All @@ -328,9 +333,20 @@ export class SwitchTerminalAction extends Action {
this._terminalService.refreshActiveTab();
return this._terminalService.selectDefaultShell();
}
const selectedTabIndex = parseInt(item.split(':')[0], 10) - 1;
this._terminalService.setActiveTabByIndex(selectedTabIndex);
return this._terminalService.showPanel(true);

const indexMatches = terminalIndexRe.exec(item);
if (indexMatches) {
this._terminalService.setActiveTabByIndex(Number(indexMatches[1]) - 1);
return this._terminalService.showPanel(true);
}

const customType = this._contributions.terminalTypes.find(t => t.title === item);
if (customType) {
return this._commands.executeCommand(customType.command);
}

console.warn(`Unmatched terminal item: "${item}"`);
return Promise.resolve();
}
}

Expand All @@ -342,9 +358,10 @@ export class SwitchTerminalActionViewItem extends SelectActionViewItem {
action: IAction,
@ITerminalService private readonly _terminalService: ITerminalService,
@IThemeService private readonly _themeService: IThemeService,
@IContextViewService contextViewService: IContextViewService
@ITerminalContributionService private readonly _contributions: ITerminalContributionService,
@IContextViewService contextViewService: IContextViewService,
) {
super(null, action, getTerminalSelectOpenItems(_terminalService), _terminalService.activeTabIndex, contextViewService, { ariaLabel: localize('terminals', 'Open Terminals.'), optionsAsChildren: true });
super(null, action, getTerminalSelectOpenItems(_terminalService, _contributions), _terminalService.activeTabIndex, contextViewService, { ariaLabel: localize('terminals', 'Open Terminals.'), optionsAsChildren: true });

this._register(_terminalService.onInstancesChanged(this._updateItems, this));
this._register(_terminalService.onActiveTabChanged(this._updateItems, this));
Expand All @@ -362,13 +379,18 @@ export class SwitchTerminalActionViewItem extends SelectActionViewItem {
}

private _updateItems(): void {
this.setOptions(getTerminalSelectOpenItems(this._terminalService), this._terminalService.activeTabIndex);
this.setOptions(getTerminalSelectOpenItems(this._terminalService, this._contributions), this._terminalService.activeTabIndex);
}
}

function getTerminalSelectOpenItems(terminalService: ITerminalService): ISelectOptionItem[] {
function getTerminalSelectOpenItems(terminalService: ITerminalService, contributions: ITerminalContributionService): ISelectOptionItem[] {
const items = terminalService.getTabLabels().map(label => <ISelectOptionItem>{ text: label });
items.push({ text: SwitchTerminalActionViewItem.SEPARATOR, isDisabled: true });

for (const contributed of contributions.terminalTypes) {
items.push({ text: contributed.title });
}

items.push({ text: SelectDefaultShellWindowsTerminalAction.LABEL });
return items;
}
Expand Down
39 changes: 39 additions & 0 deletions src/vs/workbench/contrib/terminal/common/terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { URI } from 'vs/base/common/uri';
import { OperatingSystem } from 'vs/base/common/platform';
import { IOpenFileRequest } from 'vs/platform/windows/common/windows';
import { IEnvironmentVariableInfo } from 'vs/workbench/contrib/terminal/common/environmentVariable';
import { IExtensionPointDescriptor } from 'vs/workbench/services/extensions/common/extensionsRegistry';

export const TERMINAL_VIEW_ID = 'workbench.panel.terminal';

Expand Down Expand Up @@ -625,3 +626,41 @@ export const DEFAULT_COMMANDS_TO_SKIP_SHELL: string[] = [
'workbench.action.quickOpenView',
'workbench.action.toggleMaximizedPanel'
];

export interface ITerminalContributions {
types?: ITerminalTypeContribution[];
}

export interface ITerminalTypeContribution {
title: string;
command: string;
}

export const terminalContributionsDescriptor: IExtensionPointDescriptor = {
extensionPoint: 'terminal',
defaultExtensionKind: 'workspace',
jsonSchema: {
description: nls.localize('vscode.extension.contributes.terminal', 'Contributes terminal functionality.'),
type: 'object',
properties: {
types: {
type: 'array',
description: nls.localize('vscode.extension.contributes.terminal.types', "Defines additional terminal types that the user can create."),
items: {
type: 'object',
required: ['command', 'title'],
properties: {
command: {
description: nls.localize('vscode.extension.contributes.terminal.types.command', "Command to execute when the user creates this type of terminal."),
type: 'string',
},
title: {
description: nls.localize('vscode.extension.contributes.terminal.types.title', "Title for this type of terminal."),
type: 'string',
},
},
},
},
},
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { ITerminalContributionService, TerminalContributionService } from './terminalExtensionPoints';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';

registerSingleton(ITerminalContributionService, TerminalContributionService, true);
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import * as extensionsRegistry from 'vs/workbench/services/extensions/common/extensionsRegistry';
import { ITerminalTypeContribution, ITerminalContributions, terminalContributionsDescriptor } from 'vs/workbench/contrib/terminal/common/terminal';
import { flatten } from 'vs/base/common/arrays';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';

// terminal extension point
export const terminalsExtPoint = extensionsRegistry.ExtensionsRegistry.registerExtensionPoint<ITerminalContributions>(terminalContributionsDescriptor);

export interface ITerminalContributionService {
readonly _serviceBrand: undefined;

readonly terminalTypes: ReadonlyArray<ITerminalTypeContribution>;
}

export const ITerminalContributionService = createDecorator<ITerminalContributionService>('terminalContributionsService');

export class TerminalContributionService implements ITerminalContributionService {
public readonly _serviceBrand = undefined;

private _terminalTypes: ReadonlyArray<ITerminalTypeContribution> = [];

public get terminalTypes() {
return this._terminalTypes;
}

constructor() {
terminalsExtPoint.setHandler(contributions => {
this._terminalTypes = flatten(contributions.filter(c => c.description.enableProposedApi).map(c => c.value?.types ?? []));
});
}
}
1 change: 1 addition & 0 deletions src/vs/workbench/workbench.common.main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ import 'vs/workbench/contrib/output/browser/outputView';

// Terminal
import 'vs/workbench/contrib/terminal/common/environmentVariable.contribution';
import 'vs/workbench/contrib/terminal/common/terminalExtensionPoints.contribution';
import 'vs/workbench/contrib/terminal/browser/terminal.contribution';
import 'vs/workbench/contrib/terminal/browser/terminalView';

Expand Down

0 comments on commit 4941478

Please sign in to comment.