Skip to content

Commit

Permalink
Get zsh shell integration working again (#143963)
Browse files Browse the repository at this point in the history
ZDOTDIR/.zshrc is now created manually on the pty host

Fixes #143629
  • Loading branch information
Tyriar committed Feb 25, 2022
1 parent 1aaf7cd commit 2687b53
Show file tree
Hide file tree
Showing 7 changed files with 24 additions and 13 deletions.
1 change: 1 addition & 0 deletions build/filters.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ module.exports.copyrightFilter = [
'!**/*.icns',
'!**/*.xml',
'!**/*.sh',
'!**/*.zsh',
'!**/*.txt',
'!**/*.xpm',
'!**/*.opts',
Expand Down
4 changes: 2 additions & 2 deletions build/gulpfile.reh.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,9 @@ const serverResources = [
'out-build/vs/base/node/ps.sh',

// Terminal shell integration
'out-build/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh',
'out-build/vs/workbench/contrib/terminal/browser/media/.zshrc',
'out-build/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1',
'out-build/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh',
'out-build/vs/workbench/contrib/terminal/browser/media/shellIntegration.zsh',

'!**/test/**'
];
Expand Down
2 changes: 1 addition & 1 deletion build/gulpfile.vscode.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ const vscodeResources = [
'out-build/vs/workbench/contrib/debug/**/*.json',
'out-build/vs/workbench/contrib/externalTerminal/**/*.scpt',
'out-build/vs/workbench/contrib/terminal/browser/media/*.ps1',
'out-build/vs/workbench/contrib/terminal/browser/media/.zshrc',
'out-build/vs/workbench/contrib/terminal/browser/media/*.sh',
'out-build/vs/workbench/contrib/terminal/browser/media/*.zsh',
'out-build/vs/workbench/contrib/webview/browser/pre/*.js',
'out-build/vs/**/markdown.css',
'out-build/vs/workbench/contrib/tasks/**/*.json',
Expand Down
14 changes: 14 additions & 0 deletions src/vs/platform/terminal/node/terminalProcess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@
*--------------------------------------------------------------------------------------------*/

import { exec } from 'child_process';
import { promises as fs } from 'fs';
import type * as pty from 'node-pty';
import { tmpdir } from 'os';
import { timeout } from 'vs/base/common/async';
import { Emitter, Event } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import { FileAccess } from 'vs/base/common/network';
import * as path from 'vs/base/common/path';
import { IProcessEnvironment, isLinux, isMacintosh, isWindows } from 'vs/base/common/platform';
import { URI } from 'vs/base/common/uri';
Expand Down Expand Up @@ -184,6 +187,17 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess
return firstError;
}

// Handle zsh shell integration - Set $ZDOTDIR to a temp dir and create $ZDOTDIR/.zshrc
if (this.shellLaunchConfig.env?.['_ZDOTDIR'] === '1') {
const zdotdir = path.join(tmpdir(), 'vscode-zsh');
await fs.mkdir(zdotdir, { recursive: true });
const source = path.join(path.dirname(FileAccess.asFileUri('', require).fsPath), 'out/vs/workbench/contrib/terminal/browser/media/shellIntegration.zsh');
await fs.copyFile(source, path.join(zdotdir, '.zshrc'));
this._ptyOptions.env = this._ptyOptions.env || {};
this._ptyOptions.env['ZDOTDIR'] = zdotdir;
delete this._ptyOptions.env['_ZDOTDIR'];
}

try {
await this.setupPtyProcess(this.shellLaunchConfig, this._ptyOptions);
return undefined;
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -273,9 +273,9 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce
shellLaunchConfig.env = shellLaunchConfig.env || {} as IProcessEnvironment;
shellLaunchConfig.env['VSCODE_SHELL_LOGIN'] = '1';
}
if (env?.['ZDOTDIR']) {
if (env?.['_ZDOTDIR']) {
shellLaunchConfig.env = shellLaunchConfig.env || {} as IProcessEnvironment;
shellLaunchConfig.env['ZDOTDIR'] = env['ZDOTDIR'].replace('${execInstallFolder}', remoteEnv.appRoot.fsPath);
shellLaunchConfig.env['_ZDOTDIR'] = '1';
}

newProcess = await backend.createProcess(
Expand Down Expand Up @@ -455,12 +455,9 @@ 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']) {
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;
shellLaunchConfig.env['_ZDOTDIR'] = '1';
}
// Always resolve the injected arguments on local processes
await this._terminalProfileResolverService.resolveShellLaunchConfig(shellLaunchConfig, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -494,9 +494,8 @@ export function injectShellIntegrationArgs(
} 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';
// Set _ZDOTDIR which will defer setting ZDOTDIR to the pty host
env['_ZDOTDIR'] = '1';
const showWelcome = configurationService.getValue(TerminalSettingId.ShellIntegrationShowWelcome);
if (!showWelcome) {
env['VSCODE_SHELL_HIDE_WELCOME'] = '1';
Expand Down

0 comments on commit 2687b53

Please sign in to comment.