diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts index aeaad82b61273..f884c2899526e 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts @@ -985,6 +985,7 @@ export class TerminalService implements ITerminalService { return { executable: profile.path, args: profile.args, + env: profile.env, icon: profile.icon, name: profile.overrideName ? profile.profileName : undefined }; diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index 848c8815a580d..7a7644e24a0d1 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -9,7 +9,7 @@ import { IDisposable } from 'vs/base/common/lifecycle'; import { RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { OperatingSystem } from 'vs/base/common/platform'; import { IExtensionPointDescriptor } from 'vs/workbench/services/extensions/common/extensionsRegistry'; -import { IProcessDataEvent, IShellLaunchConfig, ITerminalDimensions, ITerminalDimensionsOverride, ITerminalLaunchError, TerminalShellType } from 'vs/platform/terminal/common/terminal'; +import { IProcessDataEvent, IShellLaunchConfig, ITerminalDimensions, ITerminalDimensionsOverride, ITerminalEnvironment, ITerminalLaunchError, TerminalShellType } from 'vs/platform/terminal/common/terminal'; import { IEnvironmentVariableInfo } from 'vs/workbench/contrib/terminal/common/environmentVariable'; export const TERMINAL_VIEW_ID = 'terminal'; @@ -237,6 +237,7 @@ export interface ITerminalProfile { isAutoDetected?: boolean; isWorkspaceProfile?: boolean; args?: string | string[] | undefined; + env?: ITerminalEnvironment; overrideName?: boolean; icon?: string; } @@ -252,6 +253,7 @@ export interface ITerminalExecutable { isAutoDetected?: boolean; overrideName?: boolean; icon?: string; + env?: ITerminalEnvironment; } export interface ITerminalProfileSource { @@ -260,6 +262,7 @@ export interface ITerminalProfileSource { overrideName?: boolean; args?: string | string[] | undefined; icon?: string; + env?: ITerminalEnvironment; } export type ITerminalProfileObject = ITerminalExecutable | ITerminalProfileSource | null; diff --git a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts index 94d866cba3cf1..bd4d9534de54b 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts @@ -35,6 +35,14 @@ const terminalProfileSchema: IJSONSchema = { icon: { description: localize('terminalProfile.icon', 'A codicon ID to associate with this terminal.'), type: 'string' + }, + env: { + 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."), + type: 'object', + additionalProperties: { + type: ['string', 'null'] + }, + default: {} } } }; @@ -153,6 +161,14 @@ export const terminalConfiguration: IConfigurationNode = { icon: { description: localize('terminalProfile.icon', 'A codicon ID to associate with this terminal.'), type: 'string' + }, + env: { + 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."), + type: 'object', + additionalProperties: { + type: ['string', 'null'] + }, + default: {} } } }, diff --git a/src/vs/workbench/contrib/terminal/node/terminalProfiles.ts b/src/vs/workbench/contrib/terminal/node/terminalProfiles.ts index 463adfc642ab2..1ed0da9a643ee 100644 --- a/src/vs/workbench/contrib/terminal/node/terminalProfiles.ts +++ b/src/vs/workbench/contrib/terminal/node/terminalProfiles.ts @@ -14,6 +14,7 @@ import { ExtHostVariableResolverService } from 'vs/workbench/api/common/extHostD 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'; let profileSources: Map | undefined; @@ -113,7 +114,7 @@ async function transformToTerminalProfiles(entries: IterableIterator<[string, IT for (let i = 0; i < paths.length; i++) { paths[i] = await variableResolver?.resolveAsync(workspaceFolder, paths[i]) || paths[i]; } - const validatedProfile = await validateProfilePaths(profileName, paths, fsProvider, args, profile.overrideName, profile.isAutoDetected, logService); + const validatedProfile = await validateProfilePaths(profileName, paths, fsProvider, args, profile.env, profile.overrideName, profile.isAutoDetected, logService); if (validatedProfile) { validatedProfile.isAutoDetected = profile.isAutoDetected; validatedProfile.icon = icon; @@ -258,16 +259,16 @@ function applyConfigProfilesToMap(configProfiles: { [key: string]: ITerminalProf } } -async function validateProfilePaths(profileName: string, potentialPaths: string[], fsProvider: IFsProvider, args?: string[] | string, overrideName?: boolean, isAutoDetected?: boolean, logService?: ILogService): Promise { +async function validateProfilePaths(profileName: string, potentialPaths: string[], fsProvider: IFsProvider, args?: string[] | string, env?: ITerminalEnvironment, overrideName?: boolean, isAutoDetected?: boolean, logService?: ILogService): Promise { if (potentialPaths.length === 0) { return Promise.resolve(undefined); } const path = potentialPaths.shift()!; if (path === '') { - return validateProfilePaths(profileName, potentialPaths, fsProvider, args, overrideName, isAutoDetected); + return validateProfilePaths(profileName, potentialPaths, fsProvider, args, env, overrideName, isAutoDetected); } - const profile = { profileName, path, args, overrideName, isAutoDetected }; + const profile: ITerminalProfile = { profileName, path, args, env, overrideName, isAutoDetected }; // For non-absolute paths, check if it's available on $PATH if (basename(path) === path) { @@ -285,7 +286,7 @@ async function validateProfilePaths(profileName: string, potentialPaths: string[ return profile; } - return validateProfilePaths(profileName, potentialPaths, fsProvider, args, overrideName, isAutoDetected); + return validateProfilePaths(profileName, potentialPaths, fsProvider, args, env, overrideName, isAutoDetected); } export interface IFsProvider {