Merge pull request #122540 from microsoft/tyriar/122104
Bring back workspace shells via setting
This commit is contained in:
commit
06694a8e57
11 changed files with 130 additions and 84 deletions
|
@ -439,3 +439,5 @@ export interface ITerminalDimensionsOverride extends Readonly<ITerminalDimension
|
|||
*/
|
||||
forceExactSize?: boolean;
|
||||
}
|
||||
|
||||
export type SafeConfigProvider = <T>(key: string) => T | undefined;
|
||||
|
|
|
@ -8,6 +8,7 @@ import { withNullAsUndefined } from 'vs/base/common/types';
|
|||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { getSystemShell, getSystemShellSync } from 'vs/base/node/shell';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { SafeConfigProvider } from 'vs/platform/terminal/common/terminal';
|
||||
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { IShellAndArgsDto } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostConfigProvider, ExtHostConfiguration, IExtHostConfiguration } from 'vs/workbench/api/common/extHostConfiguration';
|
||||
|
@ -16,7 +17,7 @@ import { ExtHostDocumentsAndEditors, IExtHostDocumentsAndEditors } from 'vs/work
|
|||
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 { ITerminalProfile } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import * as terminalEnvironment from 'vs/workbench/contrib/terminal/common/terminalEnvironment';
|
||||
import { detectAvailableProfiles } from 'vs/workbench/contrib/terminal/node/terminalProfiles';
|
||||
import type * as vscode from 'vscode';
|
||||
|
@ -75,14 +76,8 @@ export class ExtHostTerminalService extends BaseExtHostTerminalService {
|
|||
}
|
||||
|
||||
public getDefaultShell(useAutomationShell: boolean, configProvider: ExtHostConfigProvider): string {
|
||||
const fetchSetting = (key: string): string | undefined => {
|
||||
return configProvider
|
||||
.getConfiguration(key.substr(0, key.lastIndexOf('.')))
|
||||
.get<string>(key.substr(key.lastIndexOf('.') + 1));
|
||||
};
|
||||
|
||||
return terminalEnvironment.getDefaultShell(
|
||||
fetchSetting,
|
||||
this._buildSafeConfigProvider(configProvider),
|
||||
this._defaultShell ?? getSystemShellSync(platform.OS, process.env as platform.IProcessEnvironment),
|
||||
process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432'),
|
||||
process.env.windir,
|
||||
|
@ -93,13 +88,12 @@ export class ExtHostTerminalService extends BaseExtHostTerminalService {
|
|||
}
|
||||
|
||||
public getDefaultShellArgs(useAutomationShell: boolean, configProvider: ExtHostConfigProvider): string[] | string {
|
||||
const fetchSetting = (key: string): string | string[] | undefined => {
|
||||
return configProvider
|
||||
.getConfiguration(key.substr(0, key.lastIndexOf('.')))
|
||||
.get<string | string[]>(key.substr(key.lastIndexOf('.') + 1));
|
||||
};
|
||||
|
||||
return terminalEnvironment.getDefaultShellArgs(fetchSetting, useAutomationShell, terminalEnvironment.createVariableResolver(this._lastActiveWorkspace, process.env, this._variableResolver), this._logService);
|
||||
return terminalEnvironment.getDefaultShellArgs(
|
||||
this._buildSafeConfigProvider(configProvider),
|
||||
useAutomationShell,
|
||||
terminalEnvironment.createVariableResolver(this._lastActiveWorkspace, process.env, this._variableResolver),
|
||||
this._logService
|
||||
);
|
||||
}
|
||||
|
||||
private _registerListeners(): void {
|
||||
|
@ -124,8 +118,8 @@ export class ExtHostTerminalService extends BaseExtHostTerminalService {
|
|||
}
|
||||
|
||||
public async $getAvailableProfiles(configuredProfilesOnly: boolean): Promise<ITerminalProfile[]> {
|
||||
const config = await (await this._extHostConfiguration.getConfigProvider()).getConfiguration().get('terminal.integrated');
|
||||
return detectAvailableProfiles(configuredProfilesOnly, undefined, this._logService, config as ITerminalConfiguration, await this._variableResolverPromise, this._lastActiveWorkspace);
|
||||
const safeConfigProvider = this._buildSafeConfigProvider(await this._extHostConfiguration.getConfigProvider());
|
||||
return detectAvailableProfiles(configuredProfilesOnly, safeConfigProvider, undefined, this._logService, await this._variableResolverPromise, this._lastActiveWorkspace);
|
||||
}
|
||||
|
||||
public async $getDefaultShellAndArgs(useAutomationShell: boolean): Promise<IShellAndArgsDto> {
|
||||
|
@ -135,4 +129,17 @@ export class ExtHostTerminalService extends BaseExtHostTerminalService {
|
|||
args: this.getDefaultShellArgs(useAutomationShell, configProvider)
|
||||
};
|
||||
}
|
||||
|
||||
// TODO: Remove when workspace trust is enabled
|
||||
private _buildSafeConfigProvider(configProvider: ExtHostConfigProvider): SafeConfigProvider {
|
||||
const config = configProvider.getConfiguration();
|
||||
return (key: string) => {
|
||||
const isWorkspaceConfigAllowed = config.get('terminal.integrated.allowWorkspaceConfiguration');
|
||||
if (isWorkspaceConfigAllowed) {
|
||||
return config.get(key) as any;
|
||||
}
|
||||
const inspected = config.inspect(key);
|
||||
return inspected?.globalValue || inspected?.defaultValue;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ import { getRemoteAuthority } from 'vs/platform/remote/common/remoteHosts';
|
|||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { IRemoteTerminalService, ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
|
||||
import { Disposable, dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { withNullAsUndefined } from 'vs/base/common/types';
|
||||
|
@ -27,7 +26,7 @@ import { IProcessDataEvent, IShellLaunchConfig, ITerminalChildProcess, ITerminal
|
|||
import { TerminalRecorder } from 'vs/platform/terminal/common/terminalRecorder';
|
||||
import { localize } from 'vs/nls';
|
||||
import { formatMessageForTerminal } from 'vs/workbench/contrib/terminal/common/terminalStrings';
|
||||
import { IProcessEnvironment, isMacintosh, isWindows, OperatingSystem, OS } from 'vs/base/common/platform';
|
||||
import { IProcessEnvironment, OperatingSystem, OS } from 'vs/base/common/platform';
|
||||
|
||||
/** The amount of time to consider terminal errors to be related to the launch */
|
||||
const LAUNCHING_DURATION = 500;
|
||||
|
@ -117,7 +116,6 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce
|
|||
@ILogService private readonly _logService: ILogService,
|
||||
@IWorkspaceContextService private readonly _workspaceContextService: IWorkspaceContextService,
|
||||
@IConfigurationResolverService private readonly _configurationResolverService: IConfigurationResolverService,
|
||||
@IConfigurationService private readonly _configurationService: IConfigurationService,
|
||||
@IWorkbenchEnvironmentService private readonly _workbenchEnvironmentService: IWorkbenchEnvironmentService,
|
||||
@IProductService private readonly _productService: IProductService,
|
||||
@ITerminalInstanceService private readonly _terminalInstanceService: ITerminalInstanceService,
|
||||
|
@ -335,8 +333,9 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce
|
|||
|
||||
// Fetch any extension environment additions and apply them
|
||||
private async _setupEnvVariableInfo(variableResolver: terminalEnvironment.VariableResolver | undefined, shellLaunchConfig: IShellLaunchConfig): Promise<IProcessEnvironment> {
|
||||
const platformKey = isWindows ? 'windows' : (isMacintosh ? 'osx' : 'linux');
|
||||
const envFromConfigValue = this._configurationService.getValue<ITerminalEnvironment | undefined>(`terminal.integrated.env.${platformKey}`);
|
||||
// const platformKey = isWindows ? 'windows' : (isMacintosh ? 'osx' : 'linux');
|
||||
// this._configurationService.getValue<ITerminalEnvironment | undefined>(`terminal.integrated.env.${platformKey}`);
|
||||
const envFromConfigValue = this._terminalProfileResolverService.getSafeConfigValue('env', OS) as ITerminalEnvironment | undefined;
|
||||
this._configHelper.showRecommendations(shellLaunchConfig);
|
||||
const baseEnv = await (this._configHelper.config.inheritEnv
|
||||
? this._terminalProfileResolverService.getShellEnvironment(this.remoteAuthority)
|
||||
|
|
|
@ -116,7 +116,7 @@ export abstract class BaseTerminalProfileResolverService implements ITerminalPro
|
|||
private _getRealDefaultProfile(sync: true, os: OperatingSystem): ITerminalProfile | undefined;
|
||||
private _getRealDefaultProfile(sync: false, os: OperatingSystem): Promise<ITerminalProfile | undefined>;
|
||||
private _getRealDefaultProfile(sync: boolean, os: OperatingSystem): ITerminalProfile | undefined | Promise<ITerminalProfile | undefined> {
|
||||
const defaultProfileName = this._configurationService.getValue(`terminal.integrated.defaultProfile.${this._getOsKey(os)}`);
|
||||
const defaultProfileName = this.getSafeConfigValue('defaultProfile', os);
|
||||
if (defaultProfileName && typeof defaultProfileName === 'string') {
|
||||
if (sync) {
|
||||
const profiles = this._terminalService.availableProfiles;
|
||||
|
@ -131,10 +131,10 @@ export abstract class BaseTerminalProfileResolverService implements ITerminalPro
|
|||
private async _getFallbackDefaultProfile(options: IShellLaunchConfigResolveOptions): Promise<ITerminalProfile> {
|
||||
let executable: string;
|
||||
let args: string | string[] | undefined;
|
||||
const shellSetting = this._configurationService.getValue(`terminal.integrated.shell.${this._getOsKey(options.os)}`);
|
||||
const shellSetting = this.getSafeConfigValue('shell', options.os);
|
||||
if (this._isValidShell(shellSetting)) {
|
||||
executable = shellSetting;
|
||||
const shellArgsSetting = this._configurationService.getValue(`terminal.integrated.shellArgs.${this._getOsKey(options.os)}`);
|
||||
const shellArgsSetting = this.getSafeConfigValue('shellArgs', options.os);
|
||||
if (this._isValidShellArgs(shellArgsSetting, options.os)) {
|
||||
args = shellArgsSetting;
|
||||
}
|
||||
|
@ -163,7 +163,7 @@ export abstract class BaseTerminalProfileResolverService implements ITerminalPro
|
|||
}
|
||||
|
||||
private _getAutomationShellProfile(options: IShellLaunchConfigResolveOptions): ITerminalProfile | undefined {
|
||||
const automationShell = this._configurationService.getValue(`terminal.integrated.automationShell.${this._getOsKey(options.os)}`);
|
||||
const automationShell = this.getSafeConfigValue('automationShell', options.os);
|
||||
if (!automationShell || typeof automationShell !== 'string') {
|
||||
return undefined;
|
||||
}
|
||||
|
@ -267,6 +267,28 @@ export abstract class BaseTerminalProfileResolverService implements ITerminalPro
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Remove when workspace trust is enabled
|
||||
getSafeConfigValue(key: string, os: OperatingSystem): unknown | undefined {
|
||||
return this.getSafeConfigValueFullKey(`terminal.integrated.${key}.${this._getOsKey(os)}`);
|
||||
}
|
||||
getSafeConfigValueFullKey(key: string): unknown | undefined {
|
||||
const isWorkspaceConfigAllowed = this._configurationService.getValue('terminal.integrated.allowWorkspaceConfiguration');
|
||||
if (isWorkspaceConfigAllowed) {
|
||||
return this._configurationService.getValue(key);
|
||||
} else {
|
||||
const config = this._configurationService.inspect(key);
|
||||
const value = config.user?.value || config.default?.value;
|
||||
// Clone if needed to allow extensibility
|
||||
if (Array.isArray(value)) {
|
||||
return value.slice();
|
||||
}
|
||||
if (typeof value === 'object') {
|
||||
return { ...value };
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class BrowserTerminalProfileResolverService extends BaseTerminalProfileResolverService {
|
||||
|
|
|
@ -19,7 +19,7 @@ import { Schemas } from 'vs/base/common/network';
|
|||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
import { IEnvironmentVariableService, ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable';
|
||||
import { IProcessDataEvent, IShellLaunchConfig, IShellLaunchConfigDto, ITerminalDimensionsOverride, ITerminalEnvironment, ITerminalLaunchError, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, TerminalShellType } from 'vs/platform/terminal/common/terminal';
|
||||
import { ITerminalConfiguration, TERMINAL_CONFIG_SECTION } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { ITerminalConfiguration, ITerminalProfileResolverService, TERMINAL_CONFIG_SECTION } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { IGetTerminalLayoutInfoArgs, IProcessDetails, IPtyHostProcessReplayEvent, ISetTerminalLayoutInfoArgs } from 'vs/platform/terminal/common/terminalProcess';
|
||||
import { IProcessEnvironment, OperatingSystem } from 'vs/base/common/platform';
|
||||
|
||||
|
@ -125,6 +125,7 @@ export class RemoteTerminalChannelClient {
|
|||
@IConfigurationResolverService private readonly _resolverService: IConfigurationResolverService,
|
||||
@IEnvironmentVariableService private readonly _environmentVariableService: IEnvironmentVariableService,
|
||||
@IRemoteAuthorityResolverService private readonly _remoteAuthorityResolverService: IRemoteAuthorityResolverService,
|
||||
@ITerminalProfileResolverService private readonly _terminalProfileResolverService: ITerminalProfileResolverService,
|
||||
@ILogService private readonly _logService: ILogService,
|
||||
@IEditorService private readonly _editorService: IEditorService,
|
||||
@ILabelService private readonly _labelService: ILabelService,
|
||||
|
@ -140,20 +141,20 @@ export class RemoteTerminalChannelClient {
|
|||
|
||||
const terminalConfig = this._configurationService.getValue<ITerminalConfiguration>(TERMINAL_CONFIG_SECTION);
|
||||
const configuration: ICompleteTerminalConfiguration = {
|
||||
'terminal.integrated.automationShell.windows': this._configurationService.getValue('terminal.integrated.automationShell.windows'),
|
||||
'terminal.integrated.automationShell.osx': this._configurationService.getValue('terminal.integrated.automationShell.osx'),
|
||||
'terminal.integrated.automationShell.linux': this._configurationService.getValue('terminal.integrated.automationShell.linux'),
|
||||
'terminal.integrated.shell.windows': this._configurationService.getValue('terminal.integrated.shell.windows'),
|
||||
'terminal.integrated.shell.osx': this._configurationService.getValue('terminal.integrated.shell.osx'),
|
||||
'terminal.integrated.shell.linux': this._configurationService.getValue('terminal.integrated.shell.linux'),
|
||||
'terminal.integrated.shellArgs.windows': this._configurationService.getValue('terminal.integrated.shellArgs.windows'),
|
||||
'terminal.integrated.shellArgs.osx': this._configurationService.getValue('terminal.integrated.shellArgs.osx'),
|
||||
'terminal.integrated.shellArgs.linux': this._configurationService.getValue('terminal.integrated.shellArgs.linux'),
|
||||
'terminal.integrated.env.windows': this._configurationService.getValue('terminal.integrated.env.windows'),
|
||||
'terminal.integrated.env.osx': this._configurationService.getValue('terminal.integrated.env.osx'),
|
||||
'terminal.integrated.env.linux': this._configurationService.getValue('terminal.integrated.env.linux'),
|
||||
'terminal.integrated.automationShell.windows': this._terminalProfileResolverService.getSafeConfigValueFullKey('terminal.integrated.automationShell.windows') as string,
|
||||
'terminal.integrated.automationShell.osx': this._terminalProfileResolverService.getSafeConfigValueFullKey('terminal.integrated.automationShell.osx') as string,
|
||||
'terminal.integrated.automationShell.linux': this._terminalProfileResolverService.getSafeConfigValueFullKey('terminal.integrated.automationShell.linux') as string,
|
||||
'terminal.integrated.shell.windows': this._terminalProfileResolverService.getSafeConfigValueFullKey('terminal.integrated.shell.windows') as string,
|
||||
'terminal.integrated.shell.osx': this._terminalProfileResolverService.getSafeConfigValueFullKey('terminal.integrated.shell.osx') as string,
|
||||
'terminal.integrated.shell.linux': this._terminalProfileResolverService.getSafeConfigValueFullKey('terminal.integrated.shell.linux') as string,
|
||||
'terminal.integrated.shellArgs.windows': this._terminalProfileResolverService.getSafeConfigValueFullKey('terminal.integrated.shellArgs.windows') as string | string[],
|
||||
'terminal.integrated.shellArgs.osx': this._terminalProfileResolverService.getSafeConfigValueFullKey('terminal.integrated.shellArgs.osx') as string | string[],
|
||||
'terminal.integrated.shellArgs.linux': this._terminalProfileResolverService.getSafeConfigValueFullKey('terminal.integrated.shellArgs.linux') as string | string[],
|
||||
'terminal.integrated.env.windows': this._terminalProfileResolverService.getSafeConfigValueFullKey('terminal.integrated.env.windows') as ITerminalEnvironment,
|
||||
'terminal.integrated.env.osx': this._terminalProfileResolverService.getSafeConfigValueFullKey('terminal.integrated.env.osx') as ITerminalEnvironment,
|
||||
'terminal.integrated.env.linux': this._terminalProfileResolverService.getSafeConfigValueFullKey('terminal.integrated.env.linux') as ITerminalEnvironment,
|
||||
'terminal.integrated.inheritEnv': terminalConfig.inheritEnv,
|
||||
'terminal.integrated.cwd': terminalConfig.cwd,
|
||||
'terminal.integrated.cwd': this._terminalProfileResolverService.getSafeConfigValueFullKey('terminal.integrated.cwd') as string,
|
||||
'terminal.integrated.detectLocale': terminalConfig.detectLocale
|
||||
};
|
||||
|
||||
|
|
|
@ -100,6 +100,10 @@ export interface ITerminalProfileResolverService {
|
|||
getDefaultShell(options: IShellLaunchConfigResolveOptions): Promise<string>;
|
||||
getDefaultShellArgs(options: IShellLaunchConfigResolveOptions): Promise<string | string[]>;
|
||||
getShellEnvironment(remoteAuthority: string | undefined): Promise<IProcessEnvironment>;
|
||||
|
||||
// TODO: Remove when workspace trust is enabled
|
||||
getSafeConfigValue(key: string, os: OperatingSystem): unknown | undefined;
|
||||
getSafeConfigValueFullKey(key: string): unknown | undefined;
|
||||
}
|
||||
|
||||
export interface IShellLaunchConfigResolveOptions {
|
||||
|
@ -195,6 +199,7 @@ export interface ITerminalConfiguration {
|
|||
focusMode: 'singleClick' | 'doubleClick';
|
||||
},
|
||||
bellDuration: number;
|
||||
allowWorkspaceConfiguration: boolean;
|
||||
}
|
||||
|
||||
export const DEFAULT_LOCAL_ECHO_EXCLUDE: ReadonlyArray<string> = ['vim', 'vi', 'nano', 'tmux'];
|
||||
|
|
|
@ -60,8 +60,6 @@ export const terminalConfiguration: IConfigurationNode = {
|
|||
},
|
||||
'terminal.integrated.automationShell.linux': {
|
||||
restricted: true,
|
||||
// TODO: Remove when workspace trust is enabled by default
|
||||
scope: ConfigurationScope.APPLICATION,
|
||||
markdownDescription: localize({
|
||||
key: 'terminal.integrated.automationShell.linux',
|
||||
comment: ['{0} and {1} are the `shell` and `shellArgs` settings keys']
|
||||
|
@ -71,8 +69,6 @@ export const terminalConfiguration: IConfigurationNode = {
|
|||
},
|
||||
'terminal.integrated.automationShell.osx': {
|
||||
restricted: true,
|
||||
// TODO: Remove when workspace trust is enabled by default
|
||||
scope: ConfigurationScope.APPLICATION,
|
||||
markdownDescription: localize({
|
||||
key: 'terminal.integrated.automationShell.osx',
|
||||
comment: ['{0} and {1} are the `shell` and `shellArgs` settings keys']
|
||||
|
@ -82,8 +78,6 @@ export const terminalConfiguration: IConfigurationNode = {
|
|||
},
|
||||
'terminal.integrated.automationShell.windows': {
|
||||
restricted: true,
|
||||
// TODO: Remove when workspace trust is enabled by default
|
||||
scope: ConfigurationScope.APPLICATION,
|
||||
markdownDescription: localize({
|
||||
key: 'terminal.integrated.automationShell.windows',
|
||||
comment: ['{0} and {1} are the `shell` and `shellArgs` settings keys']
|
||||
|
@ -93,8 +87,6 @@ export const terminalConfiguration: IConfigurationNode = {
|
|||
},
|
||||
'terminal.integrated.shellArgs.linux': {
|
||||
restricted: true,
|
||||
// TODO: Remove when workspace trust is enabled by default
|
||||
scope: ConfigurationScope.APPLICATION,
|
||||
markdownDescription: localize('terminal.integrated.shellArgs.linux', "The command line arguments to use when on the Linux terminal. [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration)."),
|
||||
type: 'array',
|
||||
items: {
|
||||
|
@ -105,8 +97,6 @@ export const terminalConfiguration: IConfigurationNode = {
|
|||
},
|
||||
'terminal.integrated.shellArgs.osx': {
|
||||
restricted: true,
|
||||
// TODO: Remove when workspace trust is enabled by default
|
||||
scope: ConfigurationScope.APPLICATION,
|
||||
markdownDescription: localize('terminal.integrated.shellArgs.osx', "The command line arguments to use when on the macOS terminal. [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration)."),
|
||||
type: 'array',
|
||||
items: {
|
||||
|
@ -120,8 +110,6 @@ export const terminalConfiguration: IConfigurationNode = {
|
|||
},
|
||||
'terminal.integrated.shellArgs.windows': {
|
||||
restricted: true,
|
||||
// TODO: Remove when workspace trust is enabled by default
|
||||
scope: ConfigurationScope.APPLICATION,
|
||||
markdownDescription: localize('terminal.integrated.shellArgs.windows', "The command line arguments to use when on the Windows terminal. [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration)."),
|
||||
'anyOf': [
|
||||
{
|
||||
|
@ -141,8 +129,6 @@ export const terminalConfiguration: IConfigurationNode = {
|
|||
},
|
||||
'terminal.integrated.profiles.windows': {
|
||||
restricted: true,
|
||||
// TODO: Remove when workspace trust is enabled by default
|
||||
scope: ConfigurationScope.APPLICATION,
|
||||
markdownDescription: localize(
|
||||
{
|
||||
key: 'terminal.integrated.profiles.windows',
|
||||
|
@ -203,8 +189,6 @@ export const terminalConfiguration: IConfigurationNode = {
|
|||
},
|
||||
'terminal.integrated.profiles.osx': {
|
||||
restricted: true,
|
||||
// TODO: Remove when workspace trust is enabled by default
|
||||
scope: ConfigurationScope.APPLICATION,
|
||||
markdownDescription: localize(
|
||||
{
|
||||
key: 'terminal.integrated.profile.osx',
|
||||
|
@ -242,8 +226,6 @@ export const terminalConfiguration: IConfigurationNode = {
|
|||
},
|
||||
'terminal.integrated.profiles.linux': {
|
||||
restricted: true,
|
||||
// TODO: Remove when workspace trust is enabled by default
|
||||
scope: ConfigurationScope.APPLICATION,
|
||||
markdownDescription: localize(
|
||||
{
|
||||
key: 'terminal.integrated.profile.linux',
|
||||
|
@ -493,6 +475,7 @@ export const terminalConfiguration: IConfigurationNode = {
|
|||
description: localize('terminal.integrated.rightClickBehavior', "Controls how terminal reacts to right click.")
|
||||
},
|
||||
'terminal.integrated.cwd': {
|
||||
restricted: true,
|
||||
description: localize('terminal.integrated.cwd', "An explicit start path where the terminal will be launched, this is used as the current working directory (cwd) for the shell process. This may be particularly useful in workspace settings if the root directory is not a convenient cwd."),
|
||||
type: 'string',
|
||||
default: undefined
|
||||
|
@ -532,8 +515,6 @@ export const terminalConfiguration: IConfigurationNode = {
|
|||
},
|
||||
'terminal.integrated.env.osx': {
|
||||
restricted: true,
|
||||
// TODO: Remove when workspace trust is enabled by default
|
||||
scope: ConfigurationScope.APPLICATION,
|
||||
markdownDescription: localize('terminal.integrated.env.osx', "Object with environment variables that will be added to the VS Code process to be used by the terminal on macOS. Set to `null` to delete the environment variable."),
|
||||
type: 'object',
|
||||
additionalProperties: {
|
||||
|
@ -543,8 +524,6 @@ export const terminalConfiguration: IConfigurationNode = {
|
|||
},
|
||||
'terminal.integrated.env.linux': {
|
||||
restricted: true,
|
||||
// TODO: Remove when workspace trust is enabled by default
|
||||
scope: ConfigurationScope.APPLICATION,
|
||||
markdownDescription: localize('terminal.integrated.env.linux', "Object with environment variables that will be added to the VS Code process to be used by the terminal on Linux. Set to `null` to delete the environment variable."),
|
||||
type: 'object',
|
||||
additionalProperties: {
|
||||
|
@ -554,8 +533,6 @@ export const terminalConfiguration: IConfigurationNode = {
|
|||
},
|
||||
'terminal.integrated.env.windows': {
|
||||
restricted: true,
|
||||
// TODO: Remove when workspace trust is enabled by default
|
||||
scope: ConfigurationScope.APPLICATION,
|
||||
markdownDescription: localize('terminal.integrated.env.windows', "Object with environment variables that will be added to the VS Code process to be used by the terminal on Windows. Set to `null` to delete the environment variable."),
|
||||
type: 'object',
|
||||
additionalProperties: {
|
||||
|
@ -665,6 +642,12 @@ export const terminalConfiguration: IConfigurationNode = {
|
|||
description: localize('terminal.integrated.enablePersistentSessions', "Persist terminal sessions for the workspace across window reloads."),
|
||||
type: 'boolean',
|
||||
default: true
|
||||
},
|
||||
'terminal.integrated.allowWorkspaceConfiguration': {
|
||||
scope: ConfigurationScope.APPLICATION,
|
||||
description: localize('terminal.integrated.allowWorkspaceConfiguration', "Allows shell and profile settings to be pick up from a workspace."),
|
||||
type: 'boolean',
|
||||
default: false
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -678,8 +661,6 @@ function getTerminalShellConfigurationStub(linux: string, osx: string, windows:
|
|||
properties: {
|
||||
'terminal.integrated.shell.linux': {
|
||||
restricted: true,
|
||||
// TODO: Remove when workspace trust is enabled by default
|
||||
scope: ConfigurationScope.APPLICATION,
|
||||
markdownDescription: linux,
|
||||
type: ['string', 'null'],
|
||||
default: null,
|
||||
|
@ -687,8 +668,6 @@ function getTerminalShellConfigurationStub(linux: string, osx: string, windows:
|
|||
},
|
||||
'terminal.integrated.shell.osx': {
|
||||
restricted: true,
|
||||
// TODO: Remove when workspace trust is enabled by default
|
||||
scope: ConfigurationScope.APPLICATION,
|
||||
markdownDescription: osx,
|
||||
type: ['string', 'null'],
|
||||
default: null,
|
||||
|
@ -696,8 +675,6 @@ function getTerminalShellConfigurationStub(linux: string, osx: string, windows:
|
|||
},
|
||||
'terminal.integrated.shell.windows': {
|
||||
restricted: true,
|
||||
// TODO: Remove when workspace trust is enabled by default
|
||||
scope: ConfigurationScope.APPLICATION,
|
||||
markdownDescription: windows,
|
||||
type: ['string', 'null'],
|
||||
default: null,
|
||||
|
|
|
@ -7,27 +7,43 @@ import * as fs from 'fs';
|
|||
import { normalize, basename, delimiter } from 'vs/base/common/path';
|
||||
import { enumeratePowerShellInstallations } from 'vs/base/node/powershell';
|
||||
import { findExecutable, getWindowsBuildNumber } from 'vs/platform/terminal/node/terminalEnvironment';
|
||||
import { ITerminalConfiguration, ITerminalProfile, ITerminalProfileObject, ProfileSource } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { ITerminalProfile, ITerminalProfileObject, ProfileSource } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import * as cp from 'child_process';
|
||||
import { ExtHostVariableResolverService } from 'vs/workbench/api/common/extHostDebugService';
|
||||
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import * as pfs from 'vs/base/node/pfs';
|
||||
import { ITerminalEnvironment } from 'vs/platform/terminal/common/terminal';
|
||||
import { ITerminalEnvironment, SafeConfigProvider } from 'vs/platform/terminal/common/terminal';
|
||||
import { Codicon } from 'vs/base/common/codicons';
|
||||
import { isMacintosh, isWindows } from 'vs/base/common/platform';
|
||||
|
||||
let profileSources: Map<string, IPotentialTerminalProfile> | undefined;
|
||||
|
||||
export function detectAvailableProfiles(configuredProfilesOnly: boolean, fsProvider?: IFsProvider, logService?: ILogService, config?: ITerminalConfiguration, variableResolver?: ExtHostVariableResolverService, workspaceFolder?: IWorkspaceFolder, testPaths?: string[]): Promise<ITerminalProfile[]> {
|
||||
export function detectAvailableProfiles(configuredProfilesOnly: boolean, safeConfigProvider: SafeConfigProvider, fsProvider?: IFsProvider, logService?: ILogService, variableResolver?: ExtHostVariableResolverService, workspaceFolder?: IWorkspaceFolder, testPaths?: string[]): Promise<ITerminalProfile[]> {
|
||||
fsProvider = fsProvider || {
|
||||
existsFile: pfs.SymlinkSupport.existsFile,
|
||||
readFile: fs.promises.readFile
|
||||
};
|
||||
if (isWindows) {
|
||||
return detectAvailableWindowsProfiles(configuredProfilesOnly, fsProvider, logService, config?.useWslProfiles, config?.profiles.windows, variableResolver, workspaceFolder);
|
||||
return detectAvailableWindowsProfiles(
|
||||
configuredProfilesOnly,
|
||||
fsProvider,
|
||||
logService,
|
||||
safeConfigProvider('terminal.integrated.useWslProfiles') || true,
|
||||
safeConfigProvider('terminal.integrated.profiles.windows'),
|
||||
variableResolver,
|
||||
workspaceFolder
|
||||
);
|
||||
}
|
||||
return detectAvailableUnixProfiles(fsProvider, logService, configuredProfilesOnly, isMacintosh ? config?.profiles.osx : config?.profiles.linux, testPaths, variableResolver, workspaceFolder);
|
||||
return detectAvailableUnixProfiles(
|
||||
fsProvider,
|
||||
logService,
|
||||
configuredProfilesOnly,
|
||||
safeConfigProvider(`terminal.integrated.profiles.${isMacintosh ? 'osx' : 'linux'}`),
|
||||
testPaths,
|
||||
variableResolver,
|
||||
workspaceFolder
|
||||
);
|
||||
}
|
||||
|
||||
async function detectAvailableWindowsProfiles(configuredProfilesOnly: boolean, fsProvider: IFsProvider, logService?: ILogService, useWslProfiles?: boolean, configProfiles?: { [key: string]: ITerminalProfileObject }, variableResolver?: ExtHostVariableResolverService, workspaceFolder?: IWorkspaceFolder): Promise<ITerminalProfile[]> {
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
import { deepStrictEqual, fail, ok, strictEqual } from 'assert';
|
||||
import { isWindows } from 'vs/base/common/platform';
|
||||
import { SafeConfigProvider } from 'vs/platform/terminal/common/terminal';
|
||||
import { ITerminalConfiguration, ITerminalProfile, ITerminalProfiles, ProfileSource } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { detectAvailableProfiles, IFsProvider } from 'vs/workbench/contrib/terminal/node/terminalProfiles';
|
||||
|
||||
|
@ -25,6 +26,18 @@ function profilesEqual(actualProfiles: ITerminalProfile[], expectedProfiles: ITe
|
|||
}
|
||||
}
|
||||
|
||||
function buildTestSafeConfigProvider(config: ITestTerminalConfig): SafeConfigProvider {
|
||||
return (key: string) => {
|
||||
switch (key) {
|
||||
case 'terminal.integrated.profiles.linux': return config.profiles.linux as any;
|
||||
case 'terminal.integrated.profiles.osx': return config.profiles.osx as any;
|
||||
case 'terminal.integrated.profiles.windows': return config.profiles.windows as any;
|
||||
case 'terminal.integrated.useWslProfiles': return config.useWslProfiles;
|
||||
default: throw new Error('Unexpected config key');
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
suite('Workbench - TerminalProfiles', () => {
|
||||
suite('detectAvailableProfiles', () => {
|
||||
if (isWindows) {
|
||||
|
@ -42,7 +55,7 @@ suite('Workbench - TerminalProfiles', () => {
|
|||
},
|
||||
useWslProfiles: false
|
||||
};
|
||||
const profiles = await detectAvailableProfiles(true, fsProvider, undefined, config as ITerminalConfiguration, undefined, undefined);
|
||||
const profiles = await detectAvailableProfiles(true, buildTestSafeConfigProvider(config), fsProvider, undefined, undefined, undefined);
|
||||
const expected = [
|
||||
{ profileName: 'Git Bash', path: 'C:\\Program Files\\Git\\bin\\bash.exe', args: ['--login'] }
|
||||
];
|
||||
|
@ -62,7 +75,7 @@ suite('Workbench - TerminalProfiles', () => {
|
|||
},
|
||||
useWslProfiles: false
|
||||
};
|
||||
const profiles = await detectAvailableProfiles(true, fsProvider, undefined, config as ITerminalConfiguration, undefined, undefined);
|
||||
const profiles = await detectAvailableProfiles(true, buildTestSafeConfigProvider(config), fsProvider, undefined, undefined, undefined);
|
||||
const expected = [
|
||||
{ profileName: 'PowerShell NoProfile', path: 'C:\\Program Files\\PowerShell\\7\\pwsh.exe', overrideName: true, args: ['-NoProfile'] }
|
||||
];
|
||||
|
@ -82,7 +95,7 @@ suite('Workbench - TerminalProfiles', () => {
|
|||
},
|
||||
useWslProfiles: false
|
||||
};
|
||||
const profiles = await detectAvailableProfiles(true, fsProvider, undefined, config as ITerminalConfiguration, undefined, undefined);
|
||||
const profiles = await detectAvailableProfiles(true, buildTestSafeConfigProvider(config), fsProvider, undefined, undefined, undefined);
|
||||
const expected = [{ profileName: 'Git Bash', path: 'C:\\Program Files\\Git\\bin\\bash.exe', args: [], isAutoDetected: undefined, overrideName: undefined }];
|
||||
profilesEqual(profiles, expected);
|
||||
});
|
||||
|
@ -104,7 +117,7 @@ suite('Workbench - TerminalProfiles', () => {
|
|||
'C:\\Sysnative\\WindowsPowerShell\\v1.0\\powershell.exe',
|
||||
'C:\\System32\\WindowsPowerShell\\v1.0\\powershell.exe'
|
||||
]);
|
||||
const profiles = await detectAvailableProfiles(true, fsProvider, undefined, pwshSourceConfig, undefined, undefined);
|
||||
const profiles = await detectAvailableProfiles(true, buildTestSafeConfigProvider(pwshSourceConfig), fsProvider, undefined, undefined, undefined);
|
||||
const expected = [
|
||||
{ profileName: 'PowerShell', path: 'C:\\Program Files\\PowerShell\\7\\pwsh.exe' }
|
||||
];
|
||||
|
@ -117,7 +130,7 @@ suite('Workbench - TerminalProfiles', () => {
|
|||
'C:\\Sysnative\\WindowsPowerShell\\v1.0\\powershell.exe',
|
||||
'C:\\System32\\WindowsPowerShell\\v1.0\\powershell.exe'
|
||||
]);
|
||||
const profiles = await detectAvailableProfiles(true, fsProvider, undefined, pwshSourceConfig, undefined, undefined);
|
||||
const profiles = await detectAvailableProfiles(true, buildTestSafeConfigProvider(pwshSourceConfig), fsProvider, undefined, undefined, undefined);
|
||||
const expected = [
|
||||
{ profileName: 'PowerShell', path: 'C:\\Program Files\\PowerShell\\7\\pwsh.exe' }
|
||||
];
|
||||
|
@ -128,7 +141,7 @@ suite('Workbench - TerminalProfiles', () => {
|
|||
'C:\\Windows\\Sysnative\\WindowsPowerShell\\v1.0\\powershell.exe',
|
||||
'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe'
|
||||
]);
|
||||
const profiles = await detectAvailableProfiles(true, fsProvider, undefined, pwshSourceConfig, undefined, undefined);
|
||||
const profiles = await detectAvailableProfiles(true, buildTestSafeConfigProvider(pwshSourceConfig), fsProvider, undefined, undefined, undefined);
|
||||
strictEqual(profiles.length, 1);
|
||||
strictEqual(profiles[0].profileName, 'PowerShell');
|
||||
});
|
||||
|
@ -172,7 +185,7 @@ suite('Workbench - TerminalProfiles', () => {
|
|||
'/bin/fakeshell1',
|
||||
'/bin/fakeshell3'
|
||||
]);
|
||||
const profiles = await detectAvailableProfiles(true, fsProvider, undefined, absoluteConfig, undefined, undefined);
|
||||
const profiles = await detectAvailableProfiles(true, buildTestSafeConfigProvider(absoluteConfig), fsProvider, undefined, undefined, undefined);
|
||||
const expected: ITerminalProfile[] = [
|
||||
{ profileName: 'fakeshell1', path: '/bin/fakeshell1' },
|
||||
{ profileName: 'fakeshell3', path: '/bin/fakeshell3' }
|
||||
|
@ -184,7 +197,7 @@ suite('Workbench - TerminalProfiles', () => {
|
|||
'/bin/fakeshell1',
|
||||
'/bin/fakeshell3'
|
||||
], '/bin/fakeshell1\n/bin/fakeshell3');
|
||||
const profiles = await detectAvailableProfiles(false, fsProvider, undefined, onPathConfig, undefined, undefined);
|
||||
const profiles = await detectAvailableProfiles(false, buildTestSafeConfigProvider(onPathConfig), fsProvider, undefined, undefined, undefined);
|
||||
const expected: ITerminalProfile[] = [
|
||||
{ profileName: 'fakeshell1', path: 'fakeshell1' },
|
||||
{ profileName: 'fakeshell3', path: 'fakeshell3' }
|
||||
|
@ -196,7 +209,7 @@ suite('Workbench - TerminalProfiles', () => {
|
|||
const fsProvider = createFsProvider([
|
||||
'/bin/fakeshell1'
|
||||
], '/bin/fakeshell1\n/bin/fakeshell3');
|
||||
const profiles = await detectAvailableProfiles(false, fsProvider, undefined, onPathConfig, undefined, undefined);
|
||||
const profiles = await detectAvailableProfiles(false, buildTestSafeConfigProvider(onPathConfig), fsProvider, undefined, undefined, undefined);
|
||||
const expected: ITerminalProfile[] = [
|
||||
{ profileName: 'fakeshell1', path: 'fakeshell1' }
|
||||
];
|
||||
|
|
|
@ -330,6 +330,8 @@ class SimpleTerminalProfileResolverService implements ITerminalProfileResolverSe
|
|||
getDefaultShell(options: IShellLaunchConfigResolveOptions): Promise<string> { throw new Error('Method not implemented.'); }
|
||||
getDefaultShellArgs(options: IShellLaunchConfigResolveOptions): Promise<string | string[]> { throw new Error('Method not implemented.'); }
|
||||
getShellEnvironment(remoteAuthority: string | undefined): Promise<IProcessEnvironment> { throw new Error('Method not implemented.'); }
|
||||
getSafeConfigValue(key: string, os: OperatingSystem): unknown | undefined { throw new Error('Method not implemented.'); }
|
||||
getSafeConfigValueFullKey(key: string): unknown | undefined { throw new Error('Method not implemented.'); }
|
||||
}
|
||||
|
||||
registerSingleton(ITerminalProfileResolverService, SimpleTerminalProfileResolverService);
|
||||
|
|
|
@ -1570,6 +1570,8 @@ export class TestTerminalProfileResolverService implements ITerminalProfileResol
|
|||
async getDefaultShell(options: IShellLaunchConfigResolveOptions): Promise<string> { return '/default'; }
|
||||
async getDefaultShellArgs(options: IShellLaunchConfigResolveOptions): Promise<string | string[]> { return []; }
|
||||
async getShellEnvironment(): Promise<IProcessEnvironment> { return process.env; }
|
||||
getSafeConfigValue(key: string, os: OperatingSystem): unknown | undefined { return undefined; }
|
||||
getSafeConfigValueFullKey(key: string): unknown | undefined { return undefined; }
|
||||
}
|
||||
|
||||
export class TestLocalTerminalService implements ILocalTerminalService {
|
||||
|
|
Loading…
Reference in a new issue