diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/terminal.shellIntegration.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/terminal.shellIntegration.test.ts index 8f094091f962d..291d3d354b5d3 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/terminal.shellIntegration.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/terminal.shellIntegration.test.ts @@ -30,7 +30,7 @@ import { assertNoRpc } from '../utils'; disposables.length = 0; }); - function createTerminalAndWaitForShellIntegration(): Promise<{ terminal: Terminal; shellIntegration: TerminalShellIntegration }> { + function createTerminalAndWaitForShellIntegration(shellPath?: string): Promise<{ terminal: Terminal; shellIntegration: TerminalShellIntegration }> { return new Promise<{ terminal: Terminal; shellIntegration: TerminalShellIntegration }>(resolve => { disposables.push(window.onDidChangeTerminalShellIntegration(e => { if (e.terminal === terminal) { @@ -41,8 +41,8 @@ import { assertNoRpc } from '../utils'; } })); const terminal = platform() === 'win32' - ? window.createTerminal() - : window.createTerminal({ shellPath: '/bin/bash' }); + ? window.createTerminal({ shellPath }) + : window.createTerminal({ shellPath: shellPath ?? '/bin/bash' }); terminal.show(); }); } @@ -102,6 +102,20 @@ import { assertNoRpc } from '../utils'; ok(shellIntegration.env.PATH); ok(shellIntegration.env.PATH.length > 0, 'env.PATH should have a length greater than 0'); }); + + test.skip('Test if zsh env is set', async () => { + const { shellIntegration } = await createTerminalAndWaitForShellIntegration('/bin/zsh'); + await new Promise(r => { + disposables.push(window.onDidChangeTerminalShellIntegration(e => { + if (e.shellIntegration.env) { + r(); + } + })); + }); + ok(shellIntegration.env); + ok(shellIntegration.env.PATH); + ok(shellIntegration.env.PATH.length > 0, 'env.PATH should have a length greater than 0'); + }); } test('execution events should fire in order when a command runs', async () => { diff --git a/src/vs/platform/terminal/node/terminalEnvironment.ts b/src/vs/platform/terminal/node/terminalEnvironment.ts index 3688900dc2bc8..71398d253731b 100644 --- a/src/vs/platform/terminal/node/terminalEnvironment.ts +++ b/src/vs/platform/terminal/node/terminalEnvironment.ts @@ -224,6 +224,7 @@ export function getShellIntegrationInjection( source: path.join(appRoot, 'out/vs/workbench/contrib/terminal/common/scripts/shellIntegration-login.zsh'), dest: path.join(zdotdir, '.zlogin') }); + envMixin['VSCODE_STABLE'] = productService.quality === 'stable' ? '1' : '0'; return { newArgs, envMixin, filesToCopy }; } } diff --git a/src/vs/platform/terminal/test/node/terminalEnvironment.test.ts b/src/vs/platform/terminal/test/node/terminalEnvironment.test.ts index 6248f83003d4f..0829f838db638 100644 --- a/src/vs/platform/terminal/test/node/terminalEnvironment.test.ts +++ b/src/vs/platform/terminal/test/node/terminalEnvironment.test.ts @@ -132,7 +132,6 @@ suite('platform - terminalEnvironment', () => { /.+\/out\/vs\/workbench\/contrib\/terminal\/common\/scripts\/shellIntegration-login.zsh/ ]; function assertIsEnabled(result: IShellIntegrationConfigInjection, globalZdotdir = homedir()) { - strictEqual(Object.keys(result.envMixin!).length, 3); ok(result.envMixin!['ZDOTDIR']?.match(expectedDir)); strictEqual(result.envMixin!['USER_ZDOTDIR'], globalZdotdir); ok(result.envMixin!['VSCODE_INJECTION']?.match('1')); diff --git a/src/vs/workbench/contrib/terminal/common/scripts/shellIntegration-rc.zsh b/src/vs/workbench/contrib/terminal/common/scripts/shellIntegration-rc.zsh index 54a13d575f164..75ab0ceb44d58 100644 --- a/src/vs/workbench/contrib/terminal/common/scripts/shellIntegration-rc.zsh +++ b/src/vs/workbench/contrib/terminal/common/scripts/shellIntegration-rc.zsh @@ -75,13 +75,15 @@ __vsc_escape_value() { for (( i = 0; i < ${#str}; ++i )); do byte="${str:$i:1}" - # Escape backslashes, semi-colons and newlines + # Escape backslashes, semi-colons, newlines, and hyphens. if [ "$byte" = "\\" ]; then token="\\\\" elif [ "$byte" = ";" ]; then token="\\x3b" elif [ "$byte" = $'\n' ]; then token="\x0a" + elif [ "$byte" = "-" ]; then + token="\\x2d" else token="$byte" fi @@ -99,6 +101,10 @@ __vsc_current_command="" __vsc_nonce="$VSCODE_NONCE" unset VSCODE_NONCE +# Some features should only work in Insiders +__vsc_stable="$VSCODE_STABLE" +unset VSCODE_STABLE + __vsc_prompt_start() { builtin printf '\e]633;A\a' } @@ -111,6 +117,17 @@ __vsc_update_cwd() { builtin printf '\e]633;P;Cwd=%s\a' "$(__vsc_escape_value "${PWD}")" } +__vsc_update_env() { + builtin printf '\e]633;EnvSingleStart;%s;\a' $__vsc_nonce + for var in ${(k)parameters}; do + if printenv "$var" >/dev/null 2>&1; then + value=$(builtin printf '%s' "${(P)var}") + builtin printf '\e]633;EnvSingleEntry;%s;%s;%s\a' "$var" "$(__vsc_escape_value "$value")" $__vsc_nonce + fi + done + builtin printf '\e]633;EnvSingleEnd;%s;\a' $__vsc_nonce +} + __vsc_command_output_start() { builtin printf '\e]633;E;%s;%s\a' "$(__vsc_escape_value "${__vsc_current_command}")" $__vsc_nonce builtin printf '\e]633;C\a' @@ -139,6 +156,10 @@ __vsc_command_complete() { builtin printf '\e]633;D;%s\a' "$__vsc_status" fi __vsc_update_cwd + + if [[ "$__vsc_stable" == "0" ]]; then + __vsc_update_env + fi } if [[ -o NOUNSET ]]; then @@ -173,6 +194,10 @@ __vsc_precmd() { # non null __vsc_update_prompt fi + + if [[ "$__vsc_stable" == "0" ]]; then + __vsc_update_env + fi } __vsc_preexec() {