diff --git a/build/gulpfile.reh.js b/build/gulpfile.reh.js index d6126ce90d9..b695a105ee4 100644 --- a/build/gulpfile.reh.js +++ b/build/gulpfile.reh.js @@ -76,7 +76,7 @@ const serverResources = [ // Terminal shell integration 'out-build/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh', - 'out-build/vs/workbench/contrib/terminal/browser/media/shellIntegration-zsh.sh', + 'out-build/vs/workbench/contrib/terminal/browser/media/.zshrc', 'out-build/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1', '!**/test/**' diff --git a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-zsh.sh b/src/vs/workbench/contrib/terminal/browser/media/.zshrc similarity index 90% rename from src/vs/workbench/contrib/terminal/browser/media/shellIntegration-zsh.sh rename to src/vs/workbench/contrib/terminal/browser/media/.zshrc index af52a164a20..e7d38a2ff7d 100755 --- a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-zsh.sh +++ b/src/vs/workbench/contrib/terminal/browser/media/.zshrc @@ -1,3 +1,5 @@ +autoload -Uz add-zsh-hook + IN_COMMAND_EXECUTION="1" prompt_start() { printf "\033]633;A\007" @@ -47,8 +49,8 @@ preexec() { IN_COMMAND_EXECUTION="1" command_output_start } -precmd_functions+=($precmd_functions precmd) -preexec_functions+=($preexec_functions preexec) +add-zsh-hook precmd precmd +add-zsh-hook preexec preexec # Show the welcome message if [ -z "${VSCODE_SHELL_HIDE_WELCOME-}" ]; then diff --git a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts index 603ed03ea2a..f35509b463d 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts @@ -273,6 +273,10 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce shellLaunchConfig.env = shellLaunchConfig.env || {} as IProcessEnvironment; shellLaunchConfig.env['VSCODE_SHELL_LOGIN'] = '1'; } + if (env?.['ZDOTDIR']) { + shellLaunchConfig.env = shellLaunchConfig.env || {} as IProcessEnvironment; + shellLaunchConfig.env['ZDOTDIR'] = env['ZDOTDIR'].replace('${execInstallFolder}', remoteEnv.appRoot.fsPath); + } newProcess = await backend.createProcess( shellLaunchConfig, @@ -451,6 +455,13 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce const shellIntegration = terminalEnvironment.injectShellIntegrationArgs(this._logService, this._configurationService, env, this._configHelper.config.shellIntegration?.enabled || false, shellLaunchConfig, OS); if (shellIntegration.enableShellIntegration) { shellLaunchConfig.args = shellIntegration.args; + if (env?.['ZDOTDIR']) { + shellLaunchConfig.env = shellLaunchConfig.env || {} as IProcessEnvironment; + const activeWorkspaceRootUri = this._historyService.getLastActiveWorkspaceRoot(Schemas.file); + const lastActiveWorkspaceRoot = activeWorkspaceRootUri ? withNullAsUndefined(this._workspaceContextService.getWorkspaceFolder(activeWorkspaceRootUri)) : undefined; + const resolved = await this._configurationResolverService.resolveAsync(lastActiveWorkspaceRoot, env['ZDOTDIR']); + env['ZDOTDIR'] = resolved; + } // Always resolve the injected arguments on local processes await this._terminalProfileResolverService.resolveShellLaunchConfig(shellLaunchConfig, { remoteAuthority: undefined, diff --git a/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts b/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts index a6bb1100595..96210ec7965 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts @@ -416,8 +416,8 @@ shellIntegrationArgs.set(ShellIntegrationExecutable.WindowsPwsh, ['-noexit', ' - shellIntegrationArgs.set(ShellIntegrationExecutable.WindowsPwshLogin, ['-l', '-noexit', ' -command', '. \"${execInstallFolder}\\out\\vs\\workbench\\contrib\\terminal\\browser\\media\\shellIntegration.ps1\"{0}']); shellIntegrationArgs.set(ShellIntegrationExecutable.Pwsh, ['-noexit', '-command', '. "${execInstallFolder}/out/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1"{0}']); shellIntegrationArgs.set(ShellIntegrationExecutable.PwshLogin, ['-l', '-noexit', '-command', '. "${execInstallFolder}/out/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1"']); -shellIntegrationArgs.set(ShellIntegrationExecutable.Zsh, ['-c', '"${execInstallFolder}/out/vs/workbench/contrib/terminal/browser/media/shellIntegration-zsh.sh"; zsh -i']); -shellIntegrationArgs.set(ShellIntegrationExecutable.ZshLogin, ['-c', '"${execInstallFolder}/out/vs/workbench/contrib/terminal/browser/media/shellIntegration-zsh.sh"; zsh -il']); +shellIntegrationArgs.set(ShellIntegrationExecutable.Zsh, ['-i']); +shellIntegrationArgs.set(ShellIntegrationExecutable.ZshLogin, ['-il']); shellIntegrationArgs.set(ShellIntegrationExecutable.Bash, ['--init-file', '${execInstallFolder}/out/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh']); const loginArgs = ['-login', '-l']; const pwshImpliedArgs = ['-nol', '-nologo']; @@ -491,7 +491,12 @@ export function injectShellIntegrationArgs( newArgs = shellIntegrationArgs.get(ShellIntegrationExecutable.Zsh); } else if (areZshBashLoginArgs(originalArgs)) { newArgs = shellIntegrationArgs.get(ShellIntegrationExecutable.ZshLogin); + } else if (originalArgs === shellIntegrationArgs.get(ShellIntegrationExecutable.Zsh) || originalArgs === shellIntegrationArgs.get(ShellIntegrationExecutable.ZshLogin)) { + newArgs = originalArgs; } + // Set the ZDOTDIR to be the dir of the shell integration script so that it runs + // as a .zshrc file and the autoload hook will work and set precmd and preexec correctly + env['ZDOTDIR'] = '${execInstallFolder}/out/vs/workbench/contrib/terminal/browser/media'; const showWelcome = configurationService.getValue(TerminalSettingId.ShellIntegrationShowWelcome); if (!showWelcome) { env['VSCODE_SHELL_HIDE_WELCOME'] = '1'; diff --git a/src/vs/workbench/contrib/terminal/test/browser/terminalProcessManager.test.ts b/src/vs/workbench/contrib/terminal/test/browser/terminalProcessManager.test.ts index ad8ba91ed53..5e27446e046 100644 --- a/src/vs/workbench/contrib/terminal/test/browser/terminalProcessManager.test.ts +++ b/src/vs/workbench/contrib/terminal/test/browser/terminalProcessManager.test.ts @@ -90,7 +90,10 @@ suite('Workbench - TerminalProcessManager', () => { await configurationService.setUserConfiguration('terminal', { integrated: { fontFamily: 'bar', - enablePersistentSessions: true + enablePersistentSessions: true, + shellIntegration: { + enabled: false + } } }); instantiationService.stub(IConfigurationService, configurationService);