提交 0aab08ed 编写于 作者: D Daniel Imms

Add getDefaultShellAndArgs

Also differentiate default from system shell
上级 87e16500
......@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { ITerminalService, ITerminalInstance, IShellLaunchConfig, ITerminalProcessExtHostProxy, ITerminalProcessExtHostRequest, ITerminalDimensions, EXT_HOST_CREATION_DELAY, IShellDefinition } from 'vs/workbench/contrib/terminal/common/terminal';
import { ITerminalService, ITerminalInstance, IShellLaunchConfig, ITerminalProcessExtHostProxy, ITerminalProcessExtHostRequest, ITerminalDimensions, EXT_HOST_CREATION_DELAY } from 'vs/workbench/contrib/terminal/common/terminal';
import { ExtHostContext, ExtHostTerminalServiceShape, MainThreadTerminalServiceShape, MainContext, IExtHostContext, ShellLaunchConfigDto } from 'vs/workbench/api/common/extHost.protocol';
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
import { UriComponents, URI } from 'vs/base/common/uri';
......@@ -46,11 +46,14 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
this._toDispose.push(_terminalService.onActiveInstanceChanged(instance => this._onActiveTerminalChanged(instance ? instance.id : null)));
this._toDispose.push(_terminalService.onInstanceTitleChanged(instance => this._onTitleChanged(instance.id, instance.title)));
this._toDispose.push(_terminalService.configHelper.onWorkspacePermissionsChanged(isAllowed => this._onWorkspacePermissionsChanged(isAllowed)));
this._toDispose.push(_terminalService.onRequestAvailableShells(r => this._onRequestAvailableShells(r)));
this._toDispose.push(_terminalService.onRequestAvailableShells(r => this._proxy.$requestAvailableShells().then(e => r(e))));
// ITerminalInstanceService listeners
if (terminalInstanceService.onRequestDefaultShell) {
this._toDispose.push(terminalInstanceService.onRequestDefaultShell(r => this._onRequestDefaultShell(r)));
this._toDispose.push(terminalInstanceService.onRequestDefaultShell(r => this._proxy.$requestDefaultShell().then(e => r(e))));
}
if (terminalInstanceService.onRequestDefaultShellAndArgs) {
this._toDispose.push(terminalInstanceService.onRequestDefaultShellAndArgs(r => this._proxy.$requestDefaultShellAndArgs().then(e => r(e.shell, e.args))));
}
// Set initial ext host state
......@@ -285,12 +288,4 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
}
this._terminalProcesses[terminalId].emitLatency(sum / COUNT);
}
private _onRequestAvailableShells(resolve: (shells: IShellDefinition[]) => void): void {
this._proxy.$requestAvailableShells().then(e => resolve(e));
}
private _onRequestDefaultShell(resolve: (defaultShell: string) => void): void {
this._proxy.$requestDefaultShell().then(e => resolve(e));
}
}
......@@ -1111,6 +1111,11 @@ export interface IShellDefinitionDto {
path: string;
}
export interface IShellAndArgsDto {
shell: string;
args: string[] | string | undefined;
}
export interface ExtHostTerminalServiceShape {
$acceptTerminalClosed(id: number): void;
$acceptTerminalOpened(id: number, name: string): void;
......@@ -1130,6 +1135,7 @@ export interface ExtHostTerminalServiceShape {
$acceptWorkspacePermissionsChanged(isAllowed: boolean): void;
$requestAvailableShells(): Promise<IShellDefinitionDto[]>;
$requestDefaultShell(): Promise<string>;
$requestDefaultShellAndArgs(): Promise<IShellAndArgsDto>;
}
export interface ExtHostSCMShape {
......
......@@ -10,7 +10,7 @@ import { URI, UriComponents } from 'vs/base/common/uri';
import * as platform from 'vs/base/common/platform';
import * as terminalEnvironment from 'vs/workbench/contrib/terminal/common/terminalEnvironment';
import { Event, Emitter } from 'vs/base/common/event';
import { ExtHostTerminalServiceShape, MainContext, MainThreadTerminalServiceShape, IMainContext, ShellLaunchConfigDto, IShellDefinitionDto } from 'vs/workbench/api/common/extHost.protocol';
import { ExtHostTerminalServiceShape, MainContext, MainThreadTerminalServiceShape, IMainContext, ShellLaunchConfigDto, IShellDefinitionDto, IShellAndArgsDto } from 'vs/workbench/api/common/extHost.protocol';
import { ExtHostConfiguration, ExtHostConfigProvider } from 'vs/workbench/api/common/extHostConfiguration';
import { ILogService } from 'vs/platform/log/common/log';
import { EXT_HOST_CREATION_DELAY, IShellLaunchConfig, ITerminalEnvironment } from 'vs/workbench/contrib/terminal/common/terminal';
......@@ -20,7 +20,7 @@ import { ExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { ExtHostVariableResolverService } from 'vs/workbench/api/node/extHostDebugService';
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
import { getDefaultShell, detectAvailableShells } from 'vs/workbench/contrib/terminal/node/terminal';
import { getSystemShell, detectAvailableShells } from 'vs/workbench/contrib/terminal/node/terminal';
const RENDERER_NO_PROCESS_ID = -1;
......@@ -338,12 +338,22 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
return terminalEnvironment.getDefaultShell(
fetchSetting,
this._isWorkspaceShellAllowed,
getDefaultShell(platform.platform),
getSystemShell(platform.platform),
process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432'),
process.env.windir
);
}
private _getDefaultShellArgs(configProvider: ExtHostConfigProvider): string[] | string | undefined {
const fetchSetting = (key: string) => {
const setting = configProvider
.getConfiguration(key.substr(0, key.lastIndexOf('.')))
.inspect<string | string[]>(key.substr(key.lastIndexOf('.') + 1));
return this._apiInspectConfigToPlain<string | string[]>(setting);
};
return terminalEnvironment.getDefaultShellArgs(fetchSetting, this._isWorkspaceShellAllowed);
}
public async resolveTerminalRenderer(id: number): Promise<vscode.TerminalRenderer> {
// Check to see if the extension host already knows about this terminal.
for (const terminalRenderer of this._terminalRenderers) {
......@@ -495,7 +505,7 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
shellLaunchConfig,
fetchSetting,
isWorkspaceShellAllowed || false,
getDefaultShell(platform.platform),
getSystemShell(platform.platform),
process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432'),
process.env.windir
);
......@@ -579,8 +589,17 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
return detectAvailableShells();
}
// TODO: Remove this once requestDefaultShellAndArgs is working
public $requestDefaultShell(): Promise<string> {
return Promise.resolve(getDefaultShell(platform.platform));
return Promise.resolve(getSystemShell(platform.platform));
}
public async $requestDefaultShellAndArgs(): Promise<IShellAndArgsDto> {
const configProvider = await this._extHostConfiguration.getConfigProvider();
return Promise.resolve({
shell: this.getDefaultShell(configProvider),
args: this._getDefaultShellArgs(configProvider)
});
}
private _onProcessExit(id: number, exitCode: number): void {
......
......@@ -10,7 +10,7 @@ import * as pfs from 'vs/base/node/pfs';
import { assign } from 'vs/base/common/objects';
import { ITerminalLauncher, ITerminalSettings } from 'vs/workbench/contrib/debug/common/debug';
import { getPathFromAmdModule } from 'vs/base/common/amd';
import { getDefaultShell } from 'vs/workbench/contrib/terminal/node/terminal';
import { getSystemShell } from 'vs/workbench/contrib/terminal/node/terminal';
const TERMINAL_TITLE = nls.localize('console.title', "VS Code Console");
......@@ -315,13 +315,13 @@ export function prepareCommand(args: DebugProtocol.RunInTerminalRequestArguments
let shell: string;
const shell_config = config.integrated.shell;
if (env.isWindows) {
shell = shell_config.windows || getDefaultShell(env.Platform.Windows);
shell = shell_config.windows || getSystemShell(env.Platform.Windows);
shellType = ShellType.cmd;
} else if (env.isLinux) {
shell = shell_config.linux || getDefaultShell(env.Platform.Linux);
shell = shell_config.linux || getSystemShell(env.Platform.Linux);
shellType = ShellType.bash;
} else if (env.isMacintosh) {
shell = shell_config.osx || getDefaultShell(env.Platform.Mac);
shell = shell_config.osx || getSystemShell(env.Platform.Mac);
shellType = ShellType.bash;
} else {
throw new Error('Unknown platform');
......
......@@ -778,8 +778,8 @@ export class TerminalTaskSystem implements ITaskSystem {
let terminalName = this.createTerminalName(task);
let originalCommand = task.command.name;
if (isShellCommand) {
shellLaunchConfig = { name: terminalName, executable: undefined, args: undefined, waitOnExit };
this.terminalInstanceService.mergeDefaultShellPathAndArgs(shellLaunchConfig, await this.terminalInstanceService.getDefaultShell(), this.terminalService.configHelper, platform);
const defaultConfig = await this.terminalInstanceService.getDefaultShellAndArgs();
shellLaunchConfig = { name: terminalName, executable: defaultConfig.shell, args: defaultConfig.args, waitOnExit };
let shellSpecified: boolean = false;
let shellOptions: ShellConfiguration | undefined = task.command.options && task.command.options.shell;
if (shellOptions) {
......
......@@ -6,7 +6,7 @@
import { Terminal as XTermTerminal } from 'xterm';
import { WebLinksAddon as XTermWebLinksAddon } from 'xterm-addon-web-links';
import { SearchAddon as XTermSearchAddon } from 'xterm-addon-search';
import { ITerminalInstance, IWindowsShellHelper, ITerminalConfigHelper, ITerminalChildProcess, IShellLaunchConfig } from 'vs/workbench/contrib/terminal/common/terminal';
import { ITerminalInstance, IWindowsShellHelper, ITerminalConfigHelper, ITerminalChildProcess, IShellLaunchConfig, IDefaultShellAndArgsRequest } from 'vs/workbench/contrib/terminal/common/terminal';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IProcessEnvironment, Platform } from 'vs/base/common/platform';
import { Event } from 'vs/base/common/event';
......@@ -22,6 +22,7 @@ export interface ITerminalInstanceService {
_serviceBrand: any;
onRequestDefaultShell?: Event<(defaultShell: string) => void>;
onRequestDefaultShellAndArgs?: Event<IDefaultShellAndArgsRequest>;
getXtermConstructor(): Promise<typeof XTermTerminal>;
getXtermWebLinksConstructor(): Promise<typeof XTermWebLinksAddon>;
......@@ -34,6 +35,7 @@ export interface ITerminalInstanceService {
mergeDefaultShellPathAndArgs(shell: IShellLaunchConfig, defaultShell: string, configHelper: ITerminalConfigHelper, platformOverride?: Platform): void;
getDefaultShell(): Promise<string>;
getDefaultShellAndArgs(): Promise<{ shell: string, args: string[] | string | undefined }>;
getMainProcessParentEnv(): Promise<IProcessEnvironment>;
}
......
......@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal';
import { IWindowsShellHelper, ITerminalChildProcess } from 'vs/workbench/contrib/terminal/common/terminal';
import { IWindowsShellHelper, ITerminalChildProcess, IDefaultShellAndArgsRequest } from 'vs/workbench/contrib/terminal/common/terminal';
import { Terminal as XTermTerminal } from 'xterm';
import { WebLinksAddon as XTermWebLinksAddon } from 'xterm-addon-web-links';
import { SearchAddon as XTermSearchAddon } from 'xterm-addon-search';
......@@ -20,6 +20,8 @@ export class TerminalInstanceService implements ITerminalInstanceService {
private readonly _onRequestDefaultShell = new Emitter<(defaultShell: string) => void>();
public get onRequestDefaultShell(): Event<(defaultShell: string) => void> { return this._onRequestDefaultShell.event; }
private readonly _onRequestDefaultShellAndArgs = new Emitter<IDefaultShellAndArgsRequest>();
public get onRequestDefaultShellAndArgs(): Event<IDefaultShellAndArgsRequest> { return this._onRequestDefaultShellAndArgs.event; }
constructor() { }
......@@ -56,6 +58,10 @@ export class TerminalInstanceService implements ITerminalInstanceService {
return new Promise(r => this._onRequestDefaultShell.fire(r));
}
public getDefaultShellAndArgs(): Promise<{ shell: string, args: string[] | string | undefined }> {
return new Promise(r => this._onRequestDefaultShellAndArgs.fire((shell, args) => r({ shell, args })));
}
public async getMainProcessParentEnv(): Promise<IProcessEnvironment> {
return {};
}
......
......@@ -163,7 +163,9 @@ export class TerminalProcessManager implements ITerminalProcessManager {
private async _launchProcess(shellLaunchConfig: IShellLaunchConfig, cols: number, rows: number): Promise<ITerminalChildProcess> {
if (!shellLaunchConfig.executable) {
this._terminalInstanceService.mergeDefaultShellPathAndArgs(shellLaunchConfig, await this._terminalInstanceService.getDefaultShell(), this._configHelper);
const defaultConfig = await this._terminalInstanceService.getDefaultShellAndArgs();
shellLaunchConfig.executable = defaultConfig.shell;
shellLaunchConfig.args = defaultConfig.args;
}
const activeWorkspaceRootUri = this._historyService.getLastActiveWorkspaceRoot(Schemas.file);
......
......@@ -789,4 +789,8 @@ export interface ITerminalChildProcess {
getInitialCwd(): Promise<string>;
getCwd(): Promise<string>;
getLatency(): Promise<number>;
}
export interface IDefaultShellAndArgsRequest {
(shell: string, args: string[] | string | undefined): void;
}
\ No newline at end of file
......@@ -192,7 +192,7 @@ export function getDefaultShell(
return executable;
}
function getDefaultShellArgs(
export function getDefaultShellArgs(
fetchSetting: (key: string) => { user: string | string[] | undefined, value: string | string[] | undefined, default: string | string[] | undefined },
isWorkspaceShellAllowed: boolean,
platformOverride: platform.Platform = platform.platform
......@@ -203,6 +203,7 @@ function getDefaultShellArgs(
return args;
}
// TODO: Remove this?
export function mergeDefaultShellPathAndArgs(
shell: IShellLaunchConfig,
fetchSetting: (key: string) => { user: string | string[] | undefined, value: string | string[] | undefined, default: string | string[] | undefined },
......
......@@ -6,11 +6,11 @@
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal';
import { TerminalInstanceService } from 'vs/workbench/contrib/terminal/electron-browser/terminalInstanceService';
import { getDefaultShell } from 'vs/workbench/contrib/terminal/node/terminal';
import { getSystemShell } from 'vs/workbench/contrib/terminal/node/terminal';
import { registerShellConfiguration } from 'vs/workbench/contrib/terminal/common/terminalShellConfig';
import { TerminalNativeService } from 'vs/workbench/contrib/terminal/electron-browser/terminalNativeService';
import { ITerminalNativeService } from 'vs/workbench/contrib/terminal/common/terminal';
registerShellConfiguration(getDefaultShell);
registerShellConfiguration(getSystemShell);
registerSingleton(ITerminalNativeService, TerminalNativeService, true);
registerSingleton(ITerminalInstanceService, TerminalInstanceService, true);
......@@ -9,14 +9,14 @@ import { WindowsShellHelper } from 'vs/workbench/contrib/terminal/node/windowsSh
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IProcessEnvironment, Platform, isLinux, isMacintosh, isWindows, OperatingSystem, platform } from 'vs/base/common/platform';
import { TerminalProcess } from 'vs/workbench/contrib/terminal/node/terminalProcess';
import { getDefaultShell } from 'vs/workbench/contrib/terminal/node/terminal';
import { getSystemShell } from 'vs/workbench/contrib/terminal/node/terminal';
import { Terminal as XTermTerminal } from 'xterm';
import { WebLinksAddon as XTermWebLinksAddon } from 'xterm-addon-web-links';
import { SearchAddon as XTermSearchAddon } from 'xterm-addon-search';
import { readFile } from 'vs/base/node/pfs';
import { basename } from 'vs/base/common/path';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { mergeDefaultShellPathAndArgs } from 'vs/workbench/contrib/terminal/common/terminalEnvironment';
import { mergeDefaultShellPathAndArgs, getDefaultShell, getDefaultShellArgs } from 'vs/workbench/contrib/terminal/common/terminalEnvironment';
let Terminal: typeof XTermTerminal;
let WebLinksAddon: typeof XTermWebLinksAddon;
......@@ -78,7 +78,24 @@ export class TerminalInstanceService implements ITerminalInstanceService {
public getDefaultShell(): Promise<string> {
// Don't go via ext host as that would delay terminal start up until after the extension
// host is ready.
return Promise.resolve(getDefaultShell(platform));
return Promise.resolve(getSystemShell(platform));
}
public getDefaultShellAndArgs(): Promise<{ shell: string, args: string[] | string | undefined }> {
// TODO: Pull the workspace shell permissions setting
const isWorkspaceShellAllowed = false; // configHelper.checkWorkspaceShellPermissions(platform);
const shell = getDefaultShell(
(key) => this._configurationService.inspect(key),
isWorkspaceShellAllowed,
getSystemShell(platform),
process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432'),
process.env.windir
);
const args = getDefaultShellArgs(
(key) => this._configurationService.inspect(key),
isWorkspaceShellAllowed
);
return Promise.resolve({ shell, args });
}
public async getMainProcessParentEnv(): Promise<IProcessEnvironment> {
......
......@@ -11,10 +11,15 @@ import { LinuxDistro, IShellDefinition } from 'vs/workbench/contrib/terminal/com
import { coalesce } from 'vs/base/common/arrays';
import { normalize, basename } from 'vs/base/common/path';
export function getDefaultShell(p: platform.Platform): string {
/**
* Gets the detected default shell for the _system_, not to be confused with VS Code's _default_
* shell that the terminal uses by default.
* @param p The platform to detect the shell of.
*/
export function getSystemShell(p: platform.Platform): string {
if (p === platform.Platform.Windows) {
if (platform.isWindows) {
return getTerminalDefaultShellWindows();
return getSystemShellWindows();
}
// Don't detect Windows shell when not on Windows
return processes.getWindowsShell();
......@@ -23,11 +28,11 @@ export function getDefaultShell(p: platform.Platform): string {
if (platform.isLinux && p === platform.Platform.Mac || platform.isMacintosh && p === platform.Platform.Linux) {
return '/bin/bash';
}
return getTerminalDefaultShellUnixLike();
return getSystemShellUnixLike();
}
let _TERMINAL_DEFAULT_SHELL_UNIX_LIKE: string | null = null;
function getTerminalDefaultShellUnixLike(): string {
function getSystemShellUnixLike(): string {
if (!_TERMINAL_DEFAULT_SHELL_UNIX_LIKE) {
let unixLikeTerminal = 'sh';
if (!platform.isWindows && process.env.SHELL) {
......@@ -46,7 +51,7 @@ function getTerminalDefaultShellUnixLike(): string {
}
let _TERMINAL_DEFAULT_SHELL_WINDOWS: string | null = null;
function getTerminalDefaultShellWindows(): string {
function getSystemShellWindows(): string {
if (!_TERMINAL_DEFAULT_SHELL_WINDOWS) {
const isAtLeastWindows10 = platform.isWindows && parseFloat(os.release()) >= 10;
const is32ProcessOn64Windows = process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432');
......
......@@ -8,6 +8,7 @@ import { OperatingSystem } from 'vs/base/common/platform';
import { TerminalLinkHandler, LineColumnInfo } from 'vs/workbench/contrib/terminal/browser/terminalLinkHandler';
import * as strings from 'vs/base/common/strings';
import { ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal';
import { Event } from 'vs/base/common/event';
class TestTerminalLinkHandler extends TerminalLinkHandler {
public get localLinkRegex(): RegExp {
......@@ -30,6 +31,10 @@ class TestXterm {
}
class MockTerminalInstanceService implements ITerminalInstanceService {
onRequestDefaultShellAndArgs?: Event<any> | undefined;
getDefaultShellAndArgs(): Promise<{ shell: string; args: string | string[] | undefined; }> {
throw new Error('Method not implemented.');
}
onRequestDefaultShell: any;
getDefaultShell(): Promise<string> {
throw new Error('Method not implemented.');
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册