Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Terminal profiles #118790

Merged
merged 45 commits into from
Mar 17, 2021
Merged
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
92bffd8
get basics working in current dropdown
meganrogge Mar 8, 2021
bd90eb1
Merge branch 'main' into merogge/shell-selector
meganrogge Mar 9, 2021
5b3e34e
filter profiles based on what we want in the dropdown and other info
meganrogge Mar 10, 2021
b1fe07c
add copywright
meganrogge Mar 10, 2021
4faa4a0
terminal.ts -> terminalProfile.ts
meganrogge Mar 10, 2021
cd416ae
seperate linux distro code
meganrogge Mar 10, 2021
07da6ca
improve terminalConfig setting description
meganrogge Mar 10, 2021
8f304a0
add passing tests and fix #79572
meganrogge Mar 11, 2021
5a2257c
add test for login args
meganrogge Mar 11, 2021
6f670f4
add wsl stuff
meganrogge Mar 12, 2021
ce33538
more wsl
meganrogge Mar 12, 2021
4b254a6
fix #77652
meganrogge Mar 12, 2021
d5c42ed
lengthen throttle time to 10s
meganrogge Mar 12, 2021
19733c3
shell -> process and fire update profiles so dropdown is updated
meganrogge Mar 12, 2021
2d99cf1
consolidate code in terminalProfile
meganrogge Mar 12, 2021
e3c1c5f
change profile selection logic
meganrogge Mar 12, 2021
1b81682
change profile config structure
meganrogge Mar 12, 2021
14db624
use <ProfileName, IterminalProfileObject> and get wsl distro names to…
meganrogge Mar 15, 2021
3a18e45
provide terminalConfig to terminalProfiles
meganrogge Mar 15, 2021
fb0d4b6
move detection/validation to terminalProfiles
meganrogge Mar 15, 2021
3e7788d
forEach -> for( of )
meganrogge Mar 15, 2021
a1c6568
use matching format for path
meganrogge Mar 15, 2021
9f66c80
improve wsl setting
meganrogge Mar 15, 2021
980164b
Merge branch 'main' into merogge/shell-selector
meganrogge Mar 16, 2021
08bbe6e
isWorkspaceShellAllowed
meganrogge Mar 16, 2021
92b85e1
clean up
meganrogge Mar 15, 2021
cdc9586
rename var
meganrogge Mar 16, 2021
37bec40
yet again fix tests attempt 3
meganrogge Mar 16, 2021
ca0f41b
more work on tests
meganrogge Mar 16, 2021
b4bf365
re-add type for test
meganrogge Mar 16, 2021
ed70117
add quickPickOnly so Select Default Profiles returns all and otherwis…
meganrogge Mar 16, 2021
bc8febf
Add logs for errors within terminalProfiles
meganrogge Mar 16, 2021
6d37892
Merge branch 'main' into merogge/shell-selector
meganrogge Mar 16, 2021
c4c3316
change return type
meganrogge Mar 16, 2021
9cbb1eb
use sync
meganrogge Mar 16, 2021
7c39f32
fix bug, get custom generated to work
meganrogge Mar 16, 2021
f06284f
remove console.trace
meganrogge Mar 16, 2021
bd05a40
workspace shell permissions
meganrogge Mar 16, 2021
c99090e
fix bug w windows shell permissions
meganrogge Mar 16, 2021
5d53994
add some comments and clean up
meganrogge Mar 16, 2021
aef25fa
when ext host ready update profiles
meganrogge Mar 16, 2021
1bbb1e2
improve terminalProfileObjectEqual check
meganrogge Mar 16, 2021
c6afb24
remove await
meganrogge Mar 16, 2021
58d1b9b
don't use windows powershell unless no other powershell
meganrogge Mar 16, 2021
3255f32
comment out test
meganrogge Mar 16, 2021
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
8 changes: 4 additions & 4 deletions src/vs/workbench/api/browser/mainThreadTerminalService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
import { ITerminalExternalLinkProvider, ITerminalInstance, ITerminalInstanceService, ITerminalLink, ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal';
import { IEnvironmentVariableService, ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable';
import { deserializeEnvironmentVariableCollection, serializeEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariableShared';
import { IAvailableShellsRequest, IDefaultShellAndArgsRequest, IStartExtensionTerminalRequest, ITerminalProcessExtHostProxy } from 'vs/workbench/contrib/terminal/common/terminal';
import { IAvailableProfilesRequest as IAvailableProfilesRequest, IDefaultShellAndArgsRequest, IStartExtensionTerminalRequest, ITerminalProcessExtHostProxy } from 'vs/workbench/contrib/terminal/common/terminal';
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';

@extHostNamedCustomer(MainContext.MainThreadTerminalService)
Expand Down Expand Up @@ -66,7 +66,7 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
this._toDispose.add(_terminalService.onActiveInstanceChanged(instance => this._onActiveTerminalChanged(instance ? instance.instanceId : null)));
this._toDispose.add(_terminalService.onInstanceTitleChanged(instance => instance && this._onTitleChanged(instance.instanceId, instance.title)));
this._toDispose.add(_terminalService.configHelper.onWorkspacePermissionsChanged(isAllowed => this._onWorkspacePermissionsChanged(isAllowed)));
this._toDispose.add(_terminalService.onRequestAvailableShells(e => this._onRequestAvailableShells(e)));
this._toDispose.add(_terminalService.onRequestAvailableProfiles(e => this._onRequestAvailableProfiles(e)));

// ITerminalInstanceService listeners
if (terminalInstanceService.onRequestDefaultShellAndArgs) {
Expand Down Expand Up @@ -349,9 +349,9 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
return true;
}

private async _onRequestAvailableShells(req: IAvailableShellsRequest): Promise<void> {
private async _onRequestAvailableProfiles(req: IAvailableProfilesRequest): Promise<void> {
if (this._isPrimaryExtHost()) {
req.callback(await this._proxy.$getAvailableShells());
req.callback(await this._proxy.$getAvailableProfiles(req.quickLaunchOnly));
}
}

Expand Down
8 changes: 2 additions & 6 deletions src/vs/workbench/api/common/extHost.protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ import { CandidatePort } from 'vs/workbench/services/remote/common/remoteExplore
import { WorkspaceTrustRequest, WorkspaceTrustStateChangeEvent } from 'vs/platform/workspace/common/workspaceTrust';
import { ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable';
import { IShellLaunchConfig, ITerminalDimensions, ITerminalLaunchError } from 'vs/platform/terminal/common/terminal';
import { ITerminalProfile } from 'vs/workbench/contrib/terminal/common/terminal';

export interface IEnvironment {
isExtensionDevelopmentDebug: boolean;
Expand Down Expand Up @@ -1609,11 +1610,6 @@ export interface IShellLaunchConfigDto {
hideFromUser?: boolean;
}

export interface IShellDefinitionDto {
label: string;
path: string;
}

export interface IShellAndArgsDto {
shell: string;
args: string[] | string | undefined;
Expand Down Expand Up @@ -1653,7 +1649,7 @@ export interface ExtHostTerminalServiceShape {
$acceptProcessRequestCwd(id: number): void;
$acceptProcessRequestLatency(id: number): number;
$acceptWorkspacePermissionsChanged(isAllowed: boolean): void;
$getAvailableShells(): Promise<IShellDefinitionDto[]>;
$getAvailableProfiles(quickLaunchOnly: boolean): Promise<ITerminalProfile[]>;
$getDefaultShellAndArgs(useAutomationShell: boolean): Promise<IShellAndArgsDto>;
$provideLinks(id: number, line: string): Promise<ITerminalLinkDto[]>;
$activateLink(id: number, linkId: number): void;
Expand Down
7 changes: 4 additions & 3 deletions src/vs/workbench/api/common/extHostTerminalService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import type * as vscode from 'vscode';
import { Event, Emitter } from 'vs/base/common/event';
import { ExtHostTerminalServiceShape, MainContext, MainThreadTerminalServiceShape, IShellLaunchConfigDto, IShellDefinitionDto, IShellAndArgsDto, ITerminalDimensionsDto, ITerminalLinkDto, TerminalIdentifier } from 'vs/workbench/api/common/extHost.protocol';
import { ExtHostTerminalServiceShape, MainContext, MainThreadTerminalServiceShape, IShellLaunchConfigDto, IShellAndArgsDto, ITerminalDimensionsDto, ITerminalLinkDto, TerminalIdentifier } from 'vs/workbench/api/common/extHost.protocol';
import { ExtHostConfigProvider } from 'vs/workbench/api/common/extHostConfiguration';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { URI } from 'vs/base/common/uri';
Expand All @@ -21,6 +21,7 @@ import { generateUuid } from 'vs/base/common/uuid';
import { ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable';
import { ITerminalChildProcess, ITerminalDimensionsOverride, ITerminalLaunchError, TerminalShellType } from 'vs/platform/terminal/common/terminal';
import { TerminalDataBufferer } from 'vs/platform/terminal/common/terminalDataBuffering';
import { ITerminalProfile } from 'vs/workbench/contrib/terminal/common/terminal';

export interface IExtHostTerminalService extends ExtHostTerminalServiceShape, IDisposable {

Expand Down Expand Up @@ -327,7 +328,7 @@ export abstract class BaseExtHostTerminalService extends Disposable implements I
public abstract createTerminalFromOptions(options: vscode.TerminalOptions): vscode.Terminal;
public abstract getDefaultShell(useAutomationShell: boolean, configProvider: ExtHostConfigProvider): string;
public abstract getDefaultShellArgs(useAutomationShell: boolean, configProvider: ExtHostConfigProvider): string[] | string;
public abstract $getAvailableShells(): Promise<IShellDefinitionDto[]>;
public abstract $getAvailableProfiles(quickLaunchOnly: boolean): Promise<ITerminalProfile[]>;
public abstract $getDefaultShellAndArgs(useAutomationShell: boolean): Promise<IShellAndArgsDto>;
public abstract $acceptWorkspacePermissionsChanged(isAllowed: boolean): void;

Expand Down Expand Up @@ -778,7 +779,7 @@ export class WorkerExtHostTerminalService extends BaseExtHostTerminalService {
throw new NotSupportedError();
}

public $getAvailableShells(): Promise<IShellDefinitionDto[]> {
public $getAvailableProfiles(quickLaunchOnly: boolean): Promise<ITerminalProfile[]> {
throw new NotSupportedError();
}

Expand Down
10 changes: 6 additions & 4 deletions src/vs/workbench/api/node/extHostTerminalService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,16 @@ import { generateUuid } from 'vs/base/common/uuid';
import { getSystemShell, getSystemShellSync } from 'vs/base/node/shell';
import { ILogService } from 'vs/platform/log/common/log';
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { IShellAndArgsDto, IShellDefinitionDto } from 'vs/workbench/api/common/extHost.protocol';
import { IShellAndArgsDto } from 'vs/workbench/api/common/extHost.protocol';
import { ExtHostConfigProvider, ExtHostConfiguration, IExtHostConfiguration } from 'vs/workbench/api/common/extHostConfiguration';
import { ExtHostVariableResolverService } from 'vs/workbench/api/common/extHostDebugService';
import { ExtHostDocumentsAndEditors, IExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
import { BaseExtHostTerminalService, ExtHostTerminal } from 'vs/workbench/api/common/extHostTerminalService';
import { ExtHostWorkspace, IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
import { ITerminalConfiguration, ITerminalProfile } from 'vs/workbench/contrib/terminal/common/terminal';
import * as terminalEnvironment from 'vs/workbench/contrib/terminal/common/terminalEnvironment';
import { detectAvailableShells } from 'vs/workbench/contrib/terminal/node/terminal';
import { detectAvailableProfiles } from 'vs/workbench/contrib/terminal/node/terminalProfiles';
import type * as vscode from 'vscode';

export class ExtHostTerminalService extends BaseExtHostTerminalService {
Expand Down Expand Up @@ -131,8 +132,9 @@ export class ExtHostTerminalService extends BaseExtHostTerminalService {
this._variableResolver = new ExtHostVariableResolverService(workspaceFolders || [], this._extHostDocumentsAndEditors, configProvider);
}

public $getAvailableShells(): Promise<IShellDefinitionDto[]> {
return detectAvailableShells();
public async $getAvailableProfiles(quickLaunchOnly: boolean): Promise<ITerminalProfile[]> {
const config = await (await this._extHostConfiguration.getConfigProvider()).getConfiguration().get('terminal.integrated');
return detectAvailableProfiles(quickLaunchOnly, this._logService, config as ITerminalConfiguration, this._variableResolver, this._lastActiveWorkspace);
}

public async $getDefaultShellAndArgs(useAutomationShell: boolean): Promise<IShellAndArgsDto> {
Expand Down
12 changes: 9 additions & 3 deletions src/vs/workbench/contrib/terminal/browser/terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { URI } from 'vs/base/common/uri';
import { FindReplaceState } from 'vs/editor/contrib/find/findState';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IOffProcessTerminalService, IShellLaunchConfig, ITerminalChildProcess, ITerminalDimensions, ITerminalLaunchError, ITerminalTabLayoutInfoById, TerminalShellType } from 'vs/platform/terminal/common/terminal';
import { IAvailableShellsRequest, ICommandTracker, IDefaultShellAndArgsRequest, INavigationMode, IRemoteTerminalAttachTarget, IStartExtensionTerminalRequest, ITerminalConfigHelper, ITerminalNativeWindowsDelegate, ITerminalProcessExtHostProxy, LinuxDistro, TitleEventSource } from 'vs/workbench/contrib/terminal/common/terminal';
import { IAvailableProfilesRequest, ICommandTracker, IDefaultShellAndArgsRequest, INavigationMode, IRemoteTerminalAttachTarget, ITerminalProfile, IStartExtensionTerminalRequest, ITerminalConfigHelper, ITerminalNativeWindowsDelegate, ITerminalProcessExtHostProxy, LinuxDistro, TitleEventSource } from 'vs/workbench/contrib/terminal/common/terminal';
import type { Terminal as XTermTerminal } from 'xterm';
import type { SearchAddon as XTermSearchAddon } from 'xterm-addon-search';
import type { Unicode11Addon as XTermUnicode11Addon } from 'xterm-addon-unicode11';
Expand Down Expand Up @@ -96,9 +96,10 @@ export interface ITerminalService {
onInstancesChanged: Event<void>;
onInstanceTitleChanged: Event<ITerminalInstance | undefined>;
onActiveInstanceChanged: Event<ITerminalInstance | undefined>;
onRequestAvailableShells: Event<IAvailableShellsRequest>;
onRequestAvailableProfiles: Event<IAvailableProfilesRequest>;
onDidRegisterProcessSupport: Event<void>;
onDidChangeConnectionState: Event<void>;
onProfilesConfigChanged: Event<void>;

/**
* Creates a terminal.
Expand Down Expand Up @@ -154,7 +155,12 @@ export interface ITerminalService {
*/
registerLinkProvider(linkProvider: ITerminalExternalLinkProvider): IDisposable;

selectDefaultShell(): Promise<void>;
selectDefaultProfile(): Promise<void>;

/**
* Gets the detected terminal profiles for the platform
*/
getAvailableProfiles(): ITerminalProfile[];

setContainers(panelContainer: HTMLElement, terminalContainer: HTMLElement): void;
manageWorkspaceShellPermissions(): void;
Expand Down
33 changes: 22 additions & 11 deletions src/vs/workbench/contrib/terminal/browser/terminalActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import { IPreferencesService } from 'vs/workbench/services/preferences/common/pr
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';

export const switchTerminalActionViewItemSeparator = '─────────';
export const selectDefaultShellTitle = localize('workbench.action.terminal.selectDefaultShell', "Select Default Shell");
export const selectDefaultProfileTitle = localize('workbench.action.terminal.selectDefaultProfile', "Select Default Profile");
export const configureTerminalSettingsTitle = localize('workbench.action.terminal.openSettings', "Configure Terminal Settings");

const enum ContextMenuGroup {
Expand Down Expand Up @@ -1332,15 +1332,15 @@ export function registerTerminalActions() {
registerAction2(class extends Action2 {
constructor() {
super({
id: TERMINAL_COMMAND_ID.SELECT_DEFAULT_SHELL,
title: { value: localize('workbench.action.terminal.selectDefaultShell', "Select Default Shell"), original: 'Select Default Shell' },
id: TERMINAL_COMMAND_ID.SELECT_DEFAULT_PROFILE,
title: { value: localize('workbench.action.terminal.selectDefaultProfile', "Select Default Profile"), original: 'Select Default Profile' },
f1: true,
category,
precondition: KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED
});
}
async run(accessor: ServicesAccessor) {
await accessor.get(ITerminalService).selectDefaultShell();
await accessor.get(ITerminalService).selectDefaultProfile();
}
});
registerAction2(class extends Action2 {
Expand Down Expand Up @@ -1446,9 +1446,9 @@ export function registerTerminalActions() {
terminalService.refreshActiveTab();
return Promise.resolve(null);
}
if (item === selectDefaultShellTitle) {
if (item === selectDefaultProfileTitle) {
terminalService.refreshActiveTab();
return terminalService.selectDefaultShell();
return terminalService.selectDefaultProfile();
}
if (item === configureTerminalSettingsTitle) {
await commandService.executeCommand(TERMINAL_COMMAND_ID.CONFIGURE_TERMINAL_SETTINGS);
Expand All @@ -1459,13 +1459,24 @@ export function registerTerminalActions() {
terminalService.setActiveTabByIndex(Number(indexMatches[1]) - 1);
return terminalService.showPanel(true);
}
const detectedProfiles = await terminalService.getAvailableProfiles();
meganrogge marked this conversation as resolved.
Show resolved Hide resolved

const customType = terminalContributionService.terminalTypes.find(t => t.title === item);
if (customType) {
return commandService.executeCommand(customType.command);
}
// Remove 'New ' from the selected item to get the profile name
const profileSelection = item.substring(4);

console.warn(`Unmatched terminal item: "${item}"`);
if (detectedProfiles) {
let launchConfig = detectedProfiles?.find((profile: { profileName: string; }) => profile.profileName === profileSelection);
if (launchConfig) {
const instance = terminalService.createTerminal({ executable: launchConfig.path, name: launchConfig.profileName, args: launchConfig.args });
terminalService.setActiveInstance(instance);
}
} else {
const customType = terminalContributionService.terminalTypes.find(t => t.title === item);
if (customType) {
return commandService.executeCommand(customType.command);
}
console.warn(`Unmatched terminal item: "${item}"`);
}
return Promise.resolve();
}
});
Expand Down
13 changes: 11 additions & 2 deletions src/vs/workbench/contrib/terminal/browser/terminalConfigHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,16 +220,18 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper {
const shellConfigValue = this._configurationService.inspect<string>(`terminal.integrated.shell.${platformKey}`);
const shellArgsConfigValue = this._configurationService.inspect<string[]>(`terminal.integrated.shellArgs.${platformKey}`);
const envConfigValue = this._configurationService.inspect<{ [key: string]: string }>(`terminal.integrated.env.${platformKey}`);
const profiles = this._configurationService.inspect<{ [key: string]: string }>(`terminal.integrated.profiles.${platformKey}`);

// Check if workspace setting exists and whether it's allowed
let isWorkspaceShellAllowed: boolean | undefined = false;
if (shellConfigValue.workspaceValue !== undefined || shellArgsConfigValue.workspaceValue !== undefined || envConfigValue.workspaceValue !== undefined) {
if (shellConfigValue.workspaceValue !== undefined || shellArgsConfigValue.workspaceValue !== undefined || envConfigValue.workspaceValue !== undefined || profiles.workspaceValue !== undefined) {
isWorkspaceShellAllowed = this.isWorkspaceShellAllowed(undefined);
}

// Always allow [] args as it would lead to an odd error message and should not be dangerous
if (shellConfigValue.workspaceValue === undefined && envConfigValue.workspaceValue === undefined &&
shellArgsConfigValue.workspaceValue && shellArgsConfigValue.workspaceValue.length === 0) {
shellArgsConfigValue.workspaceValue && shellArgsConfigValue.workspaceValue.length === 0
&& profiles.workspaceValue === undefined) {
isWorkspaceShellAllowed = true;
}

Expand All @@ -248,6 +250,10 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper {
if (envConfigValue.workspaceValue) {
envString = `env: {${Object.keys(envConfigValue.workspaceValue).map(k => `${k}:${envConfigValue.workspaceValue![k]}`).join(', ')}}`;
}
let profilesString: string | undefined;
if (profiles.workspaceValue) {
profilesString = `profiles: {${Object.keys(profiles.workspaceValue).map(k => `${k}:${profiles.workspaceValue![k]}`).join(', ')}}`;
}
// Should not be localized as it's json-like syntax referencing settings keys
const workspaceConfigStrings: string[] = [];
if (shellString) {
Expand All @@ -259,6 +265,9 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper {
if (envString) {
workspaceConfigStrings.push(envString);
}
if (profilesString) {
workspaceConfigStrings.push(profilesString);
}
const workspaceConfigString = workspaceConfigStrings.join(', ');
this._notificationService.prompt(Severity.Info, nls.localize('terminal.integrated.allowWorkspaceShell', "Do you allow this workspace to modify your terminal shell? {0}", workspaceConfigString),
[{
Expand Down
Loading