From 331da82ad57e11b87f625bf52c83c2109bdeea4a Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 18 Jun 2019 11:28:30 -0700 Subject: [PATCH] Enable shell selector outside Windows Fixes #75718 --- .../api/browser/mainThreadTerminalService.ts | 6 +++--- .../workbench/api/common/extHost.protocol.ts | 2 +- .../api/node/extHostTerminalService.ts | 9 +++------ .../terminal/browser/terminal.contribution.ts | 3 --- .../terminal/browser/terminalActions.ts | 11 +++-------- .../contrib/terminal/common/terminal.ts | 2 +- .../contrib/terminal/common/terminalService.ts | 6 +++--- .../contrib/terminal/node/terminal.ts | 18 ++++++++++++++++-- 8 files changed, 30 insertions(+), 27 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadTerminalService.ts b/src/vs/workbench/api/browser/mainThreadTerminalService.ts index 2d9fba053ce..c37b7c685f0 100644 --- a/src/vs/workbench/api/browser/mainThreadTerminalService.ts +++ b/src/vs/workbench/api/browser/mainThreadTerminalService.ts @@ -42,7 +42,7 @@ 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.onRequestWindowsShells(r => this._onRequestDetectWindowsShell(r))); + this._toDispose.push(_terminalService.onRequestAvailableShells(r => this._onRequestAvailableShells(r))); // Set initial ext host state this._terminalService.terminalInstances.forEach(t => { @@ -277,7 +277,7 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape this._terminalProcesses[terminalId].emitLatency(sum / COUNT); } - private _onRequestDetectWindowsShell(resolve: (shells: IShellDefinition[]) => void): void { - this._proxy.$requestWindowsShells().then(shells => resolve(shells)); + private _onRequestAvailableShells(resolve: (shells: IShellDefinition[]) => void): void { + this._proxy.$requestAvailableShells().then(shells => resolve(shells)); } } diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index d21659ce49c..bcd55cea583 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -1128,7 +1128,7 @@ export interface ExtHostTerminalServiceShape { $acceptProcessRequestCwd(id: number): void; $acceptProcessRequestLatency(id: number): number; $acceptWorkspacePermissionsChanged(isAllowed: boolean): void; - $requestWindowsShells(): Promise; + $requestAvailableShells(): Promise; } export interface ExtHostSCMShape { diff --git a/src/vs/workbench/api/node/extHostTerminalService.ts b/src/vs/workbench/api/node/extHostTerminalService.ts index 6274c89b139..878127edcc5 100644 --- a/src/vs/workbench/api/node/extHostTerminalService.ts +++ b/src/vs/workbench/api/node/extHostTerminalService.ts @@ -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, detectWindowsShells } from 'vs/workbench/contrib/terminal/node/terminal'; +import { getDefaultShell, detectAvailableShells } from 'vs/workbench/contrib/terminal/node/terminal'; const RENDERER_NO_PROCESS_ID = -1; @@ -575,11 +575,8 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape { return id; } - public $requestWindowsShells(): Promise { - if (!platform.isWindows) { - throw new Error('Can only detect Windows shells on Windows'); - } - return detectWindowsShells(); + public $requestAvailableShells(): Promise { + return detectAvailableShells(); } private _onProcessExit(id: number, exitCode: number): void { diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts b/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts index db127081d5d..8a62400e086 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts @@ -370,10 +370,7 @@ actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ClearTerminalAct primary: 0, mac: { primary: KeyMod.CtrlCmd | KeyCode.KEY_K } }, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KeybindingWeight.WorkbenchContrib + 1), 'Terminal: Clear', category); -// TODO: This should be the remote OS -// if (platform.isWindows) { actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(SelectDefaultShellWindowsTerminalAction, SelectDefaultShellWindowsTerminalAction.ID, SelectDefaultShellWindowsTerminalAction.LABEL), 'Terminal: Select Default Shell', category); -// } actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(AllowWorkspaceShellTerminalCommand, AllowWorkspaceShellTerminalCommand.ID, AllowWorkspaceShellTerminalCommand.LABEL), 'Terminal: Allow Workspace Shell Configuration', category); actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(DisallowWorkspaceShellTerminalCommand, DisallowWorkspaceShellTerminalCommand.ID, DisallowWorkspaceShellTerminalCommand.LABEL), 'Terminal: Disallow Workspace Shell Configuration', category); actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(RenameTerminalAction, RenameTerminalAction.ID, RenameTerminalAction.LABEL), 'Terminal: Rename', category); diff --git a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts index 199d6b2183b..0e01b387a47 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts @@ -35,7 +35,6 @@ import { Schemas } from 'vs/base/common/network'; import { URI } from 'vs/base/common/uri'; import { isWindows } from 'vs/base/common/platform'; import { withNullAsUndefined } from 'vs/base/common/types'; -import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; export const TERMINAL_PICKER_PREFIX = 'term '; @@ -743,8 +742,7 @@ export class SwitchTerminalActionViewItem extends SelectActionViewItem { action: IAction, @ITerminalService private readonly terminalService: ITerminalService, @IThemeService themeService: IThemeService, - @IContextViewService contextViewService: IContextViewService, - @IWorkbenchEnvironmentService private workbenchEnvironmentService: IWorkbenchEnvironmentService + @IContextViewService contextViewService: IContextViewService ) { super(null, action, terminalService.getTabLabels().map(label => { text: label }), terminalService.activeTabIndex, contextViewService, { ariaLabel: nls.localize('terminals', 'Open Terminals.') }); @@ -756,11 +754,8 @@ export class SwitchTerminalActionViewItem extends SelectActionViewItem { private _updateItems(): void { const items = this.terminalService.getTabLabels().map(label => { text: label }); - let enableSelectDefaultShell = this.workbenchEnvironmentService.configuration.remoteAuthority ? false : isWindows; - if (enableSelectDefaultShell) { - items.push({ text: SwitchTerminalActionViewItem.SEPARATOR }); - items.push({ text: SelectDefaultShellWindowsTerminalAction.LABEL }); - } + items.push({ text: SwitchTerminalActionViewItem.SEPARATOR }); + items.push({ text: SelectDefaultShellWindowsTerminalAction.LABEL }); this.setOptions(items, this.terminalService.activeTabIndex); } } diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index 614d4de28d9..be1202ac526 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -222,7 +222,7 @@ export interface ITerminalService { onInstancesChanged: Event; onInstanceTitleChanged: Event; onActiveInstanceChanged: Event; - onRequestWindowsShells: Event<(shells: IShellDefinition[]) => void>; + onRequestAvailableShells: Event<(shells: IShellDefinition[]) => void>; /** * Creates a terminal. diff --git a/src/vs/workbench/contrib/terminal/common/terminalService.ts b/src/vs/workbench/contrib/terminal/common/terminalService.ts index 6af9cfc7bb3..2dd2c47180c 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalService.ts @@ -65,8 +65,8 @@ export abstract class TerminalService implements ITerminalService { public get onActiveInstanceChanged(): Event { return this._onActiveInstanceChanged.event; } protected readonly _onTabDisposed = new Emitter(); public get onTabDisposed(): Event { return this._onTabDisposed.event; } - protected readonly _onRequestWindowsShells = new Emitter<(shells: IShellDefinition[]) => void>(); - public get onRequestWindowsShells(): Event<(shells: IShellDefinition[]) => void> { return this._onRequestWindowsShells.event; } + protected readonly _onRequestAvailableShells = new Emitter<(shells: IShellDefinition[]) => void>(); + public get onRequestAvailableShells(): Event<(shells: IShellDefinition[]) => void> { return this._onRequestAvailableShells.event; } public abstract get configHelper(): ITerminalConfigHelper; @@ -553,6 +553,6 @@ export abstract class TerminalService implements ITerminalService { } private _detectWindowsShells(): Promise { - return new Promise(r => this._onRequestWindowsShells.fire(r)); + return new Promise(r => this._onRequestAvailableShells.fire(r)); } } diff --git a/src/vs/workbench/contrib/terminal/node/terminal.ts b/src/vs/workbench/contrib/terminal/node/terminal.ts index 979a359e8b5..195879eb52f 100644 --- a/src/vs/workbench/contrib/terminal/node/terminal.ts +++ b/src/vs/workbench/contrib/terminal/node/terminal.ts @@ -9,7 +9,7 @@ import * as processes from 'vs/base/node/processes'; import { readFile, fileExists, stat } from 'vs/base/node/pfs'; import { LinuxDistro, IShellDefinition } from 'vs/workbench/contrib/terminal/common/terminal'; import { coalesce } from 'vs/base/common/arrays'; -import { normalize } from 'vs/base/common/path'; +import { normalize, basename } from 'vs/base/common/path'; export function getDefaultShell(p: platform.Platform): string { if (p === platform.Platform.Windows) { @@ -85,7 +85,11 @@ export function getWindowsBuildNumber(): number { return buildNumber; } -export async function detectWindowsShells(): Promise { +export function detectAvailableShells(): Promise { + return platform.isWindows ? detectAvailableWindowsShells() : detectAvailableUnixShells(); +} + +async function detectAvailableWindowsShells(): Promise { // Determine the correct System32 path. We want to point to Sysnative // when the 32-bit version of VS Code is running on a 64-bit machine. // The reason for this is because PowerShell's important PSReadline @@ -118,6 +122,16 @@ export async function detectWindowsShells(): Promise { return Promise.all(promises).then(coalesce); } +async function detectAvailableUnixShells(): Promise { + const contents = await readFile('/etc/shells', 'utf8'); + const shells = contents.split('\n').filter(e => e.trim().indexOf('#') !== 0 && e.trim().length > 0); + return shells.map(e => { + return { + label: basename(e), + path: e + }; + }); +} function validateShellPaths(label: string, potentialPaths: string[]): Promise { if (potentialPaths.length === 0) { -- GitLab