未验证 提交 52a351f8 编写于 作者: D Daniel Imms 提交者: GitHub

Merge pull request #75455 from microsoft/tyriar/75091_default_shell_api

Implement API to get default shell
...@@ -1110,6 +1110,12 @@ declare module 'vscode' { ...@@ -1110,6 +1110,12 @@ declare module 'vscode' {
} }
namespace window { namespace window {
/**
* The detected default shell for the extension host, this is overridden by the
* `terminal.integrated.shell` setting for the extension host's platform.
*/
export const shell: string;
/** /**
* An event which fires when the [dimensions](#Terminal.dimensions) of the terminal change. * An event which fires when the [dimensions](#Terminal.dimensions) of the terminal change.
*/ */
......
...@@ -41,6 +41,7 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape ...@@ -41,6 +41,7 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
this._toDispose.push(terminalService.onInstanceRequestExtHostProcess(request => this._onTerminalRequestExtHostProcess(request))); this._toDispose.push(terminalService.onInstanceRequestExtHostProcess(request => this._onTerminalRequestExtHostProcess(request)));
this._toDispose.push(terminalService.onActiveInstanceChanged(instance => this._onActiveTerminalChanged(instance ? instance.id : null))); 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.onInstanceTitleChanged(instance => this._onTitleChanged(instance.id, instance.title)));
this._toDispose.push(terminalService.configHelper.onWorkspacePermissionsChanged(isAllowed => this._onWorkspacePermissionsChanged(isAllowed)));
// Set initial ext host state // Set initial ext host state
this.terminalService.terminalInstances.forEach(t => { this.terminalService.terminalInstances.forEach(t => {
...@@ -182,6 +183,10 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape ...@@ -182,6 +183,10 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
this._proxy.$acceptTerminalTitleChange(terminalId, name); this._proxy.$acceptTerminalTitleChange(terminalId, name);
} }
private _onWorkspacePermissionsChanged(isAllowed: boolean): void {
this._proxy.$acceptWorkspacePermissionsChanged(isAllowed);
}
private _onTerminalRendererInput(terminalId: number, data: string): void { private _onTerminalRendererInput(terminalId: number, data: string): void {
this._proxy.$acceptTerminalRendererInput(terminalId, data); this._proxy.$acceptTerminalRendererInput(terminalId, data);
} }
......
...@@ -1122,6 +1122,7 @@ export interface ExtHostTerminalServiceShape { ...@@ -1122,6 +1122,7 @@ export interface ExtHostTerminalServiceShape {
$acceptProcessRequestInitialCwd(id: number): void; $acceptProcessRequestInitialCwd(id: number): void;
$acceptProcessRequestCwd(id: number): void; $acceptProcessRequestCwd(id: number): void;
$acceptProcessRequestLatency(id: number): number; $acceptProcessRequestLatency(id: number): number;
$acceptWorkspacePermissionsChanged(isAllowed: boolean): void;
} }
export interface ExtHostSCMShape { export interface ExtHostSCMShape {
......
...@@ -389,6 +389,9 @@ export function createApiFactory( ...@@ -389,6 +389,9 @@ export function createApiFactory(
get terminals() { get terminals() {
return extHostTerminalService.terminals; return extHostTerminalService.terminals;
}, },
get shell() {
return extHostTerminalService.getDefaultShell(configProvider);
},
showTextDocument(documentOrUri: vscode.TextDocument | vscode.Uri, columnOrOptions?: vscode.ViewColumn | vscode.TextDocumentShowOptions, preserveFocus?: boolean): Thenable<vscode.TextEditor> { showTextDocument(documentOrUri: vscode.TextDocument | vscode.Uri, columnOrOptions?: vscode.ViewColumn | vscode.TextDocumentShowOptions, preserveFocus?: boolean): Thenable<vscode.TextEditor> {
let documentPromise: Promise<vscode.TextDocument>; let documentPromise: Promise<vscode.TextDocument>;
if (URI.isUri(documentOrUri)) { if (URI.isUri(documentOrUri)) {
......
...@@ -11,7 +11,7 @@ import * as platform from 'vs/base/common/platform'; ...@@ -11,7 +11,7 @@ import * as platform from 'vs/base/common/platform';
import * as terminalEnvironment from 'vs/workbench/contrib/terminal/common/terminalEnvironment'; import * as terminalEnvironment from 'vs/workbench/contrib/terminal/common/terminalEnvironment';
import { Event, Emitter } from 'vs/base/common/event'; import { Event, Emitter } from 'vs/base/common/event';
import { ExtHostTerminalServiceShape, MainContext, MainThreadTerminalServiceShape, IMainContext, ShellLaunchConfigDto } from 'vs/workbench/api/common/extHost.protocol'; import { ExtHostTerminalServiceShape, MainContext, MainThreadTerminalServiceShape, IMainContext, ShellLaunchConfigDto } from 'vs/workbench/api/common/extHost.protocol';
import { ExtHostConfiguration } from 'vs/workbench/api/common/extHostConfiguration'; import { ExtHostConfiguration, ExtHostConfigProvider } from 'vs/workbench/api/common/extHostConfiguration';
import { ILogService } from 'vs/platform/log/common/log'; import { ILogService } from 'vs/platform/log/common/log';
import { EXT_HOST_CREATION_DELAY, IShellLaunchConfig, ITerminalEnvironment } from 'vs/workbench/contrib/terminal/common/terminal'; import { EXT_HOST_CREATION_DELAY, IShellLaunchConfig, ITerminalEnvironment } from 'vs/workbench/contrib/terminal/common/terminal';
import { TerminalProcess } from 'vs/workbench/contrib/terminal/node/terminalProcess'; import { TerminalProcess } from 'vs/workbench/contrib/terminal/node/terminalProcess';
...@@ -278,6 +278,9 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape { ...@@ -278,6 +278,9 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
private _terminalRenderers: ExtHostTerminalRenderer[] = []; private _terminalRenderers: ExtHostTerminalRenderer[] = [];
private _getTerminalPromises: { [id: number]: Promise<ExtHostTerminal> } = {}; private _getTerminalPromises: { [id: number]: Promise<ExtHostTerminal> } = {};
// TODO: Pull this from main side
private _isWorkspaceShellAllowed: boolean = false;
public get activeTerminal(): ExtHostTerminal | undefined { return this._activeTerminal; } public get activeTerminal(): ExtHostTerminal | undefined { return this._activeTerminal; }
public get terminals(): ExtHostTerminal[] { return this._terminals; } public get terminals(): ExtHostTerminal[] { return this._terminals; }
...@@ -325,6 +328,16 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape { ...@@ -325,6 +328,16 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
return renderer; return renderer;
} }
public getDefaultShell(configProvider: ExtHostConfigProvider): string {
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.getDefaultShell(fetchSetting, this._isWorkspaceShellAllowed, getDefaultShell(platform.platform));
}
public async resolveTerminalRenderer(id: number): Promise<vscode.TerminalRenderer> { public async resolveTerminalRenderer(id: number): Promise<vscode.TerminalRenderer> {
// Check to see if the extension host already knows about this terminal. // Check to see if the extension host already knows about this terminal.
for (const terminalRenderer of this._terminalRenderers) { for (const terminalRenderer of this._terminalRenderers) {
...@@ -612,6 +625,10 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape { ...@@ -612,6 +625,10 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
}); });
return index; return index;
} }
public $acceptWorkspacePermissionsChanged(isAllowed: boolean): void {
this._isWorkspaceShellAllowed = isAllowed;
}
} }
class ApiRequest { class ApiRequest {
......
...@@ -14,6 +14,7 @@ import { Terminal as XTermTerminal } from 'xterm'; ...@@ -14,6 +14,7 @@ import { Terminal as XTermTerminal } from 'xterm';
import { INotificationService } from 'vs/platform/notification/common/notification'; import { INotificationService } from 'vs/platform/notification/common/notification';
import { IBrowserTerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminal'; import { IBrowserTerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminal';
import { mergeDefaultShellPathAndArgs } from 'vs/workbench/contrib/terminal/common/terminalEnvironment'; import { mergeDefaultShellPathAndArgs } from 'vs/workbench/contrib/terminal/common/terminalEnvironment';
import { Emitter, Event } from 'vs/base/common/event';
const MINIMUM_FONT_SIZE = 6; const MINIMUM_FONT_SIZE = 6;
const MAXIMUM_FONT_SIZE = 25; const MAXIMUM_FONT_SIZE = 25;
...@@ -29,6 +30,9 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper { ...@@ -29,6 +30,9 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper {
private _lastFontMeasurement: ITerminalFont; private _lastFontMeasurement: ITerminalFont;
public config: ITerminalConfiguration; public config: ITerminalConfiguration;
private readonly _onWorkspacePermissionsChanged = new Emitter<boolean>();
public get onWorkspacePermissionsChanged(): Event<boolean> { return this._onWorkspacePermissionsChanged.event; }
public constructor( public constructor(
private readonly _linuxDistro: LinuxDistro, private readonly _linuxDistro: LinuxDistro,
@IConfigurationService private readonly _configurationService: IConfigurationService, @IConfigurationService private readonly _configurationService: IConfigurationService,
...@@ -160,6 +164,7 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper { ...@@ -160,6 +164,7 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper {
} }
public setWorkspaceShellAllowed(isAllowed: boolean): void { public setWorkspaceShellAllowed(isAllowed: boolean): void {
this._onWorkspacePermissionsChanged.fire(isAllowed);
this._storageService.store(IS_WORKSPACE_SHELL_ALLOWED_STORAGE_KEY, isAllowed, StorageScope.WORKSPACE); this._storageService.store(IS_WORKSPACE_SHELL_ALLOWED_STORAGE_KEY, isAllowed, StorageScope.WORKSPACE);
} }
......
...@@ -109,6 +109,9 @@ export interface ITerminalConfiguration { ...@@ -109,6 +109,9 @@ export interface ITerminalConfiguration {
export interface ITerminalConfigHelper { export interface ITerminalConfigHelper {
config: ITerminalConfiguration; config: ITerminalConfiguration;
onWorkspacePermissionsChanged: Event<boolean>;
configFontIsMonospace(): boolean; configFontIsMonospace(): boolean;
getFont(): ITerminalFont; getFont(): ITerminalFont;
/** /**
...@@ -210,6 +213,9 @@ export interface ITerminalService { ...@@ -210,6 +213,9 @@ export interface ITerminalService {
activeTabIndex: number; activeTabIndex: number;
configHelper: ITerminalConfigHelper; configHelper: ITerminalConfigHelper;
terminalInstances: ITerminalInstance[];
terminalTabs: ITerminalTab[];
onActiveTabChanged: Event<void>; onActiveTabChanged: Event<void>;
onTabDisposed: Event<ITerminalTab>; onTabDisposed: Event<ITerminalTab>;
onInstanceCreated: Event<ITerminalInstance>; onInstanceCreated: Event<ITerminalInstance>;
...@@ -220,8 +226,6 @@ export interface ITerminalService { ...@@ -220,8 +226,6 @@ export interface ITerminalService {
onInstancesChanged: Event<void>; onInstancesChanged: Event<void>;
onInstanceTitleChanged: Event<ITerminalInstance>; onInstanceTitleChanged: Event<ITerminalInstance>;
onActiveInstanceChanged: Event<ITerminalInstance | undefined>; onActiveInstanceChanged: Event<ITerminalInstance | undefined>;
terminalInstances: ITerminalInstance[];
terminalTabs: ITerminalTab[];
/** /**
* Creates a terminal. * Creates a terminal.
......
...@@ -161,34 +161,55 @@ export function escapeNonWindowsPath(path: string): string { ...@@ -161,34 +161,55 @@ export function escapeNonWindowsPath(path: string): string {
return newPath; return newPath;
} }
export function mergeDefaultShellPathAndArgs( export function getDefaultShell(
shell: IShellLaunchConfig,
fetchSetting: (key: string) => { user: string | string[] | undefined, value: string | string[] | undefined, default: string | string[] | undefined }, fetchSetting: (key: string) => { user: string | string[] | undefined, value: string | string[] | undefined, default: string | string[] | undefined },
isWorkspaceShellAllowed: boolean, isWorkspaceShellAllowed: boolean,
defaultShell: string, defaultShell: string,
platformOverride: platform.Platform = platform.platform platformOverride: platform.Platform = platform.platform
): void { ): string {
const platformKey = platformOverride === platform.Platform.Windows ? 'windows' : platformOverride === platform.Platform.Mac ? 'osx' : 'linux'; const platformKey = platformOverride === platform.Platform.Windows ? 'windows' : platformOverride === platform.Platform.Mac ? 'osx' : 'linux';
const shellConfigValue = fetchSetting(`terminal.integrated.shell.${platformKey}`); const shellConfigValue = fetchSetting(`terminal.integrated.shell.${platformKey}`);
const shellArgsConfigValue = fetchSetting(`terminal.integrated.shellArgs.${platformKey}`); let executable = (isWorkspaceShellAllowed ? <string>shellConfigValue.value : <string>shellConfigValue.user) || (<string | null>shellConfigValue.default || defaultShell);
shell.executable = (isWorkspaceShellAllowed ? <string>shellConfigValue.value : <string>shellConfigValue.user) || (<string | null>shellConfigValue.default || defaultShell);
shell.args = (isWorkspaceShellAllowed ? <string[]>shellArgsConfigValue.value : <string[]>shellArgsConfigValue.user) || <string[]>shellArgsConfigValue.default;
// Change Sysnative to System32 if the OS is Windows but NOT WoW64. It's // Change Sysnative to System32 if the OS is Windows but NOT WoW64. It's
// safe to assume that this was used by accident as Sysnative does not // safe to assume that this was used by accident as Sysnative does not
// exist and will break the terminal in non-WoW64 environments. // exist and will break the terminal in non-WoW64 environments.
if ((platformOverride === platform.Platform.Windows) && !process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432') && process.env.windir) { if ((platformOverride === platform.Platform.Windows) && !process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432') && process.env.windir) {
const sysnativePath = path.join(process.env.windir, 'Sysnative').toLowerCase(); const sysnativePath = path.join(process.env.windir, 'Sysnative').toLowerCase();
if (shell.executable && shell.executable.toLowerCase().indexOf(sysnativePath) === 0) { if (executable && executable.toLowerCase().indexOf(sysnativePath) === 0) {
shell.executable = path.join(process.env.windir, 'System32', shell.executable.substr(sysnativePath.length)); executable = path.join(process.env.windir, 'System32', executable.substr(sysnativePath.length));
} }
} }
// Convert / to \ on Windows for convenience // Convert / to \ on Windows for convenience
if (shell.executable && platformOverride === platform.Platform.Windows) { if (executable && platformOverride === platform.Platform.Windows) {
shell.executable = shell.executable.replace(/\//g, '\\'); executable = executable.replace(/\//g, '\\');
} }
return executable;
}
function getDefaultShellArgs(
fetchSetting: (key: string) => { user: string | string[] | undefined, value: string | string[] | undefined, default: string | string[] | undefined },
isWorkspaceShellAllowed: boolean,
defaultShell: string,
platformOverride: platform.Platform = platform.platform
): string[] {
const platformKey = platformOverride === platform.Platform.Windows ? 'windows' : platformOverride === platform.Platform.Mac ? 'osx' : 'linux';
const shellArgsConfigValue = fetchSetting(`terminal.integrated.shellArgs.${platformKey}`);
const args = (isWorkspaceShellAllowed ? <string[]>shellArgsConfigValue.value : <string[]>shellArgsConfigValue.user) || <string[]>shellArgsConfigValue.default;
return args;
}
export function mergeDefaultShellPathAndArgs(
shell: IShellLaunchConfig,
fetchSetting: (key: string) => { user: string | string[] | undefined, value: string | string[] | undefined, default: string | string[] | undefined },
isWorkspaceShellAllowed: boolean,
defaultShell: string,
platformOverride: platform.Platform = platform.platform
): void {
shell.executable = getDefaultShell(fetchSetting, isWorkspaceShellAllowed, defaultShell, platformOverride);
shell.args = getDefaultShellArgs(fetchSetting, isWorkspaceShellAllowed, defaultShell, platformOverride);
} }
export function createTerminalEnvironment( export function createTerminalEnvironment(
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册