mirror of
https://github.com/Microsoft/vscode
synced 2024-10-16 08:22:51 +00:00
parent
c62e57fed1
commit
87e16500d2
|
@ -9,6 +9,7 @@ import { ExtHostContext, ExtHostTerminalServiceShape, MainThreadTerminalServiceS
|
|||
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
import { UriComponents, URI } from 'vs/base/common/uri';
|
||||
import { StopWatch } from 'vs/base/common/stopwatch';
|
||||
import { ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
|
||||
@extHostNamedCustomer(MainContext.MainThreadTerminalService)
|
||||
export class MainThreadTerminalService implements MainThreadTerminalServiceShape {
|
||||
|
@ -22,10 +23,13 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
|||
|
||||
constructor(
|
||||
extHostContext: IExtHostContext,
|
||||
@ITerminalService private readonly _terminalService: ITerminalService
|
||||
@ITerminalService private readonly _terminalService: ITerminalService,
|
||||
@ITerminalInstanceService readonly terminalInstanceService: ITerminalInstanceService
|
||||
) {
|
||||
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostTerminalService);
|
||||
this._remoteAuthority = extHostContext.remoteAuthority;
|
||||
|
||||
// ITerminalService listeners
|
||||
this._toDispose.push(_terminalService.onInstanceCreated((instance) => {
|
||||
// Delay this message so the TerminalInstance constructor has a chance to finish and
|
||||
// return the ID normally to the extension host. The ID that is passed here will be used
|
||||
|
@ -44,6 +48,11 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
|||
this._toDispose.push(_terminalService.configHelper.onWorkspacePermissionsChanged(isAllowed => this._onWorkspacePermissionsChanged(isAllowed)));
|
||||
this._toDispose.push(_terminalService.onRequestAvailableShells(r => this._onRequestAvailableShells(r)));
|
||||
|
||||
// ITerminalInstanceService listeners
|
||||
if (terminalInstanceService.onRequestDefaultShell) {
|
||||
this._toDispose.push(terminalInstanceService.onRequestDefaultShell(r => this._onRequestDefaultShell(r)));
|
||||
}
|
||||
|
||||
// Set initial ext host state
|
||||
this._terminalService.terminalInstances.forEach(t => {
|
||||
this._onTerminalOpened(t);
|
||||
|
@ -278,6 +287,10 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
|||
}
|
||||
|
||||
private _onRequestAvailableShells(resolve: (shells: IShellDefinition[]) => void): void {
|
||||
this._proxy.$requestAvailableShells().then(shells => resolve(shells));
|
||||
this._proxy.$requestAvailableShells().then(e => resolve(e));
|
||||
}
|
||||
|
||||
private _onRequestDefaultShell(resolve: (defaultShell: string) => void): void {
|
||||
this._proxy.$requestDefaultShell().then(e => resolve(e));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1129,6 +1129,7 @@ export interface ExtHostTerminalServiceShape {
|
|||
$acceptProcessRequestLatency(id: number): number;
|
||||
$acceptWorkspacePermissionsChanged(isAllowed: boolean): void;
|
||||
$requestAvailableShells(): Promise<IShellDefinitionDto[]>;
|
||||
$requestDefaultShell(): Promise<string>;
|
||||
}
|
||||
|
||||
export interface ExtHostSCMShape {
|
||||
|
|
|
@ -579,6 +579,10 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
|||
return detectAvailableShells();
|
||||
}
|
||||
|
||||
public $requestDefaultShell(): Promise<string> {
|
||||
return Promise.resolve(getDefaultShell(platform.platform));
|
||||
}
|
||||
|
||||
private _onProcessExit(id: number, exitCode: number): void {
|
||||
// Remove listeners
|
||||
this._terminalProcesses[id].dispose();
|
||||
|
|
|
@ -763,25 +763,6 @@ export class TerminalTaskSystem implements ITaskSystem {
|
|||
return nls.localize('TerminalTaskSystem.terminalName', 'Task - {0}', needsFolderQualification ? task.getQualifiedLabel() : task.configurationProperties.name);
|
||||
}
|
||||
|
||||
private getDefaultShell(platform: Platform.Platform): string {
|
||||
let defaultShell: string | undefined = undefined;
|
||||
try {
|
||||
defaultShell = this.terminalInstanceService.getDefaultShell(platform);
|
||||
} catch {
|
||||
// Do nothing
|
||||
}
|
||||
if (!defaultShell) {
|
||||
// Make up a guess for the default shell.
|
||||
if (platform === Platform.Platform.Windows) {
|
||||
defaultShell = 'cmd.exe';
|
||||
} else {
|
||||
defaultShell = 'bash';
|
||||
}
|
||||
console.warn('Cannot get the default shell.');
|
||||
}
|
||||
return defaultShell;
|
||||
}
|
||||
|
||||
private async getUserHome(): Promise<URI> {
|
||||
const env = await this.remoteAgentService.getEnvironment();
|
||||
if (env) {
|
||||
|
@ -798,7 +779,7 @@ export class TerminalTaskSystem implements ITaskSystem {
|
|||
let originalCommand = task.command.name;
|
||||
if (isShellCommand) {
|
||||
shellLaunchConfig = { name: terminalName, executable: undefined, args: undefined, waitOnExit };
|
||||
this.terminalInstanceService.mergeDefaultShellPathAndArgs(shellLaunchConfig, this.getDefaultShell(platform), this.terminalService.configHelper, platform);
|
||||
this.terminalInstanceService.mergeDefaultShellPathAndArgs(shellLaunchConfig, await this.terminalInstanceService.getDefaultShell(), this.terminalService.configHelper, platform);
|
||||
let shellSpecified: boolean = false;
|
||||
let shellOptions: ShellConfiguration | undefined = task.command.options && task.command.options.shell;
|
||||
if (shellOptions) {
|
||||
|
|
|
@ -9,6 +9,7 @@ import { SearchAddon as XTermSearchAddon } from 'xterm-addon-search';
|
|||
import { ITerminalInstance, IWindowsShellHelper, ITerminalConfigHelper, ITerminalChildProcess, IShellLaunchConfig } 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';
|
||||
|
||||
export const ITerminalInstanceService = createDecorator<ITerminalInstanceService>('terminalInstanceService');
|
||||
|
||||
|
@ -20,16 +21,19 @@ export const ITerminalInstanceService = createDecorator<ITerminalInstanceService
|
|||
export interface ITerminalInstanceService {
|
||||
_serviceBrand: any;
|
||||
|
||||
onRequestDefaultShell?: Event<(defaultShell: string) => void>;
|
||||
|
||||
getXtermConstructor(): Promise<typeof XTermTerminal>;
|
||||
getXtermWebLinksConstructor(): Promise<typeof XTermWebLinksAddon>;
|
||||
getXtermSearchConstructor(): Promise<typeof XTermSearchAddon>;
|
||||
createWindowsShellHelper(shellProcessId: number, instance: ITerminalInstance, xterm: XTermTerminal): IWindowsShellHelper;
|
||||
createTerminalProcess(shellLaunchConfig: IShellLaunchConfig, cwd: string, cols: number, rows: number, env: IProcessEnvironment, windowsEnableConpty: boolean): ITerminalChildProcess;
|
||||
getDefaultShell(p: Platform): string;
|
||||
/**
|
||||
* Merges the default shell path and args into the provided launch configuration
|
||||
*/
|
||||
mergeDefaultShellPathAndArgs(shell: IShellLaunchConfig, defaultShell: string, configHelper: ITerminalConfigHelper, platformOverride?: Platform): void;
|
||||
|
||||
getDefaultShell(): Promise<string>;
|
||||
getMainProcessParentEnv(): Promise<IProcessEnvironment>;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,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 { IProcessEnvironment } from 'vs/base/common/platform';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
|
||||
let Terminal: typeof XTermTerminal;
|
||||
let WebLinksAddon: typeof XTermWebLinksAddon;
|
||||
|
@ -17,6 +18,9 @@ let SearchAddon: typeof XTermSearchAddon;
|
|||
export class TerminalInstanceService implements ITerminalInstanceService {
|
||||
public _serviceBrand: any;
|
||||
|
||||
private readonly _onRequestDefaultShell = new Emitter<(defaultShell: string) => void>();
|
||||
public get onRequestDefaultShell(): Event<(defaultShell: string) => void> { return this._onRequestDefaultShell.event; }
|
||||
|
||||
constructor() { }
|
||||
|
||||
public async getXtermConstructor(): Promise<typeof XTermTerminal> {
|
||||
|
@ -48,8 +52,8 @@ export class TerminalInstanceService implements ITerminalInstanceService {
|
|||
throw new Error('Not implemented');
|
||||
}
|
||||
|
||||
public getDefaultShell(): string {
|
||||
throw new Error('Not implemented');
|
||||
public getDefaultShell(): Promise<string> {
|
||||
return new Promise(r => this._onRequestDefaultShell.fire(r));
|
||||
}
|
||||
|
||||
public async getMainProcessParentEnv(): Promise<IProcessEnvironment> {
|
||||
|
|
|
@ -163,7 +163,7 @@ export class TerminalProcessManager implements ITerminalProcessManager {
|
|||
|
||||
private async _launchProcess(shellLaunchConfig: IShellLaunchConfig, cols: number, rows: number): Promise<ITerminalChildProcess> {
|
||||
if (!shellLaunchConfig.executable) {
|
||||
this._terminalInstanceService.mergeDefaultShellPathAndArgs(shellLaunchConfig, this._terminalInstanceService.getDefaultShell(platform.platform), this._configHelper);
|
||||
this._terminalInstanceService.mergeDefaultShellPathAndArgs(shellLaunchConfig, await this._terminalInstanceService.getDefaultShell(), this._configHelper);
|
||||
}
|
||||
|
||||
const activeWorkspaceRootUri = this._historyService.getLastActiveWorkspaceRoot(Schemas.file);
|
||||
|
|
|
@ -62,10 +62,6 @@ export class TerminalInstanceService implements ITerminalInstanceService {
|
|||
return this._instantiationService.createInstance(TerminalProcess, shellLaunchConfig, cwd, cols, rows, env, windowsEnableConpty);
|
||||
}
|
||||
|
||||
public getDefaultShell(p: Platform): string {
|
||||
return getDefaultShell(p);
|
||||
}
|
||||
|
||||
public mergeDefaultShellPathAndArgs(shell: IShellLaunchConfig, defaultShell: string, configHelper: ITerminalConfigHelper, platformOverride: Platform = platform): void {
|
||||
const isWorkspaceShellAllowed = configHelper.checkWorkspaceShellPermissions(platformOverride === Platform.Windows ? OperatingSystem.Windows : (platformOverride === Platform.Mac ? OperatingSystem.Macintosh : OperatingSystem.Linux));
|
||||
mergeDefaultShellPathAndArgs(
|
||||
|
@ -79,6 +75,12 @@ 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));
|
||||
}
|
||||
|
||||
public async getMainProcessParentEnv(): Promise<IProcessEnvironment> {
|
||||
if (this._mainProcessParentEnv) {
|
||||
return this._mainProcessParentEnv;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { Platform, OperatingSystem } from 'vs/base/common/platform';
|
||||
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';
|
||||
|
@ -30,6 +30,10 @@ class TestXterm {
|
|||
}
|
||||
|
||||
class MockTerminalInstanceService implements ITerminalInstanceService {
|
||||
onRequestDefaultShell: any;
|
||||
getDefaultShell(): Promise<string> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
mergeDefaultShellPathAndArgs(): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
@ -49,9 +53,6 @@ class MockTerminalInstanceService implements ITerminalInstanceService {
|
|||
createTerminalProcess(): any {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
getDefaultShell(p: Platform): string {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
getMainProcessParentEnv(): any {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue