more ExternalTerminalService cleanup

This commit is contained in:
Andre Weinand 2019-07-04 17:03:14 +02:00
parent a57a43de01
commit 13940e60ec
2 changed files with 64 additions and 92 deletions

View file

@ -17,42 +17,32 @@ import { IConfigurationRegistry, Extensions, ConfigurationScope } from 'vs/platf
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { Registry } from 'vs/platform/registry/common/platform';
import { ITerminalSettings } from 'vs/workbench/contrib/debug/common/debug';
import { optional } from 'vs/platform/instantiation/common/instantiation';
const TERMINAL_TITLE = nls.localize('console.title', "VS Code Console");
export const DEFAULT_TERMINAL_OSX = 'Terminal.app';
enum WinSpawnType {
CMD,
CMDER
}
export class WindowsExternalTerminalService implements IExternalTerminalService {
public _serviceBrand: any;
private static readonly CMD = 'cmd.exe';
constructor(
@IConfigurationService private readonly _configurationService: IConfigurationService
@optional(IConfigurationService) private readonly _configurationService: IConfigurationService
) {
}
public openTerminal(cwd?: string): void {
const configuration = this._configurationService.getValue<IExternalTerminalConfiguration>();
this.spawnTerminal(cp, configuration, processes.getWindowsShell(), cwd);
if (this._configurationService) {
const configuration = this._configurationService.getValue<IExternalTerminalConfiguration>();
this.spawnTerminal(cp, configuration, processes.getWindowsShell(), cwd);
}
}
/*
public runInTerminal(title: string, dir: string, args: string[], envVars: env.IProcessEnvironment): Promise<number | undefined> {
const configuration = this._configurationService.getValue<IExternalTerminalConfiguration>();
return this.runInTerminal0(title, dir, args, envVars, configuration.terminal);
}
*/
public runInTerminal(title: string, dir: string, args: string[], envVars: env.IProcessEnvironment, configuration: ITerminalSettings): Promise<number | undefined> {
const exec = configuration.external.windowsExec || getDefaultTerminalWindows();
const exec = configuration.external.windowsExec || WindowsExternalTerminalService.getDefaultTerminalWindows();
return new Promise<number | undefined>((resolve, reject) => {
@ -86,8 +76,7 @@ export class WindowsExternalTerminalService implements IExternalTerminalService
private spawnTerminal(spawner: typeof cp, configuration: IExternalTerminalConfiguration, command: string, cwd?: string): Promise<void> {
const terminalConfig = configuration.terminal.external;
const exec = terminalConfig.windowsExec || getDefaultTerminalWindows();
const spawnType = this.getSpawnType(exec);
const exec = terminalConfig.windowsExec || WindowsExternalTerminalService.getDefaultTerminalWindows();
// Make the drive letter uppercase on Windows (see #9448)
if (cwd && cwd[1] === ':') {
@ -96,7 +85,8 @@ export class WindowsExternalTerminalService implements IExternalTerminalService
// cmder ignores the environment cwd and instead opts to always open in %USERPROFILE%
// unless otherwise specified
if (spawnType === WinSpawnType.CMDER) {
const basename = path.basename(exec).toLowerCase();
if (basename === 'cmder' || basename === 'cmder.exe') {
spawner.spawn(exec, cwd ? [cwd] : undefined);
return Promise.resolve(undefined);
}
@ -117,12 +107,14 @@ export class WindowsExternalTerminalService implements IExternalTerminalService
});
}
private getSpawnType(exec: string): WinSpawnType {
const basename = path.basename(exec).toLowerCase();
if (basename === 'cmder' || basename === 'cmder.exe') {
return WinSpawnType.CMDER;
private static _DEFAULT_TERMINAL_WINDOWS: string;
public static getDefaultTerminalWindows(): string {
if (!WindowsExternalTerminalService._DEFAULT_TERMINAL_WINDOWS) {
const isWoW64 = !!process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432');
WindowsExternalTerminalService._DEFAULT_TERMINAL_WINDOWS = `${process.env.windir ? process.env.windir : 'C:\\Windows'}\\${isWoW64 ? 'Sysnative' : 'System32'}\\cmd.exe`;
}
return WinSpawnType.CMD;
return WindowsExternalTerminalService._DEFAULT_TERMINAL_WINDOWS;
}
}
@ -132,22 +124,16 @@ export class MacExternalTerminalService implements IExternalTerminalService {
private static readonly OSASCRIPT = '/usr/bin/osascript'; // osascript is the AppleScript interpreter on OS X
constructor(
@IConfigurationService private readonly _configurationService: IConfigurationService
@optional(IConfigurationService) private readonly _configurationService: IConfigurationService
) { }
public openTerminal(cwd?: string): void {
const configuration = this._configurationService.getValue<IExternalTerminalConfiguration>();
this.spawnTerminal(cp, configuration, cwd);
if (this._configurationService) {
const configuration = this._configurationService.getValue<IExternalTerminalConfiguration>();
this.spawnTerminal(cp, configuration, cwd);
}
}
/*
public runInTerminal(title: string, dir: string, args: string[], envVars: env.IProcessEnvironment): Promise<number | undefined> {
const configuration = this._configurationService.getValue<IExternalTerminalConfiguration>();
return this.runInTerminal0(title, dir, args, envVars, configuration.terminal);
}
*/
public runInTerminal(title: string, dir: string, args: string[], envVars: env.IProcessEnvironment, configuration: ITerminalSettings): Promise<number | undefined> {
const terminalApp = configuration.external.osxExec || DEFAULT_TERMINAL_OSX;
@ -234,26 +220,20 @@ export class LinuxExternalTerminalService implements IExternalTerminalService {
private static readonly WAIT_MESSAGE = nls.localize('press.any.key', "Press any key to continue...");
constructor(
@IConfigurationService private readonly _configurationService: IConfigurationService
@optional(IConfigurationService) private readonly _configurationService: IConfigurationService
) { }
public openTerminal(cwd?: string): void {
const configuration = this._configurationService.getValue<IExternalTerminalConfiguration>();
this.spawnTerminal(cp, configuration, cwd);
if (this._configurationService) {
const configuration = this._configurationService.getValue<IExternalTerminalConfiguration>();
this.spawnTerminal(cp, configuration, cwd);
}
}
/*
public runInTerminal(title: string, dir: string, args: string[], envVars: env.IProcessEnvironment): Promise<number | undefined> {
const configuration = this._configurationService.getValue<IExternalTerminalConfiguration>();
return this.runInTerminal0(title, dir, args, envVars, configuration.terminal);
}
*/
public runInTerminal(title: string, dir: string, args: string[], envVars: env.IProcessEnvironment, configuration: ITerminalSettings): Promise<number | undefined> {
const terminalConfig = configuration.external;
const execPromise = terminalConfig.linuxExec ? Promise.resolve(terminalConfig.linuxExec) : getDefaultTerminalLinuxReady();
const execPromise = terminalConfig.linuxExec ? Promise.resolve(terminalConfig.linuxExec) : LinuxExternalTerminalService.getDefaultTerminalLinuxReady();
return new Promise<number | undefined>((resolve, reject) => {
@ -309,7 +289,7 @@ export class LinuxExternalTerminalService implements IExternalTerminalService {
private spawnTerminal(spawner: typeof cp, configuration: IExternalTerminalConfiguration, cwd?: string): Promise<void> {
const terminalConfig = configuration.terminal.external;
const execPromise = terminalConfig.linuxExec ? Promise.resolve(terminalConfig.linuxExec) : getDefaultTerminalLinuxReady();
const execPromise = terminalConfig.linuxExec ? Promise.resolve(terminalConfig.linuxExec) : LinuxExternalTerminalService.getDefaultTerminalLinuxReady();
return new Promise<void>((c, e) => {
execPromise.then(exec => {
@ -320,6 +300,36 @@ export class LinuxExternalTerminalService implements IExternalTerminalService {
});
});
}
private static _DEFAULT_TERMINAL_LINUX_READY: Promise<string>;
public static getDefaultTerminalLinuxReady(): Promise<string> {
if (!LinuxExternalTerminalService._DEFAULT_TERMINAL_LINUX_READY) {
LinuxExternalTerminalService._DEFAULT_TERMINAL_LINUX_READY = new Promise<string>(c => {
if (env.isLinux) {
Promise.all([pfs.exists('/etc/debian_version'), process.lazyEnv || Promise.resolve(undefined)]).then(([isDebian]) => {
if (isDebian) {
c('x-terminal-emulator');
} else if (process.env.DESKTOP_SESSION === 'gnome' || process.env.DESKTOP_SESSION === 'gnome-classic') {
c('gnome-terminal');
} else if (process.env.DESKTOP_SESSION === 'kde-plasma') {
c('konsole');
} else if (process.env.COLORTERM) {
c(process.env.COLORTERM);
} else if (process.env.TERM) {
c(process.env.TERM);
} else {
c('xterm');
}
});
return;
}
c('xterm');
});
}
return LinuxExternalTerminalService._DEFAULT_TERMINAL_LINUX_READY;
}
}
/**
@ -348,44 +358,6 @@ function quote(args: string[]): string {
return r;
}
let _DEFAULT_TERMINAL_WINDOWS: string | null = null;
export function getDefaultTerminalWindows(): string {
if (!_DEFAULT_TERMINAL_WINDOWS) {
const isWoW64 = !!process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432');
_DEFAULT_TERMINAL_WINDOWS = `${process.env.windir ? process.env.windir : 'C:\\Windows'}\\${isWoW64 ? 'Sysnative' : 'System32'}\\cmd.exe`;
}
return _DEFAULT_TERMINAL_WINDOWS;
}
let _DEFAULT_TERMINAL_LINUX_READY: Promise<string> | null = null;
export function getDefaultTerminalLinuxReady(): Promise<string> {
if (!_DEFAULT_TERMINAL_LINUX_READY) {
_DEFAULT_TERMINAL_LINUX_READY = new Promise<string>(c => {
if (env.isLinux) {
Promise.all([pfs.exists('/etc/debian_version'), process.lazyEnv || Promise.resolve(undefined)]).then(([isDebian]) => {
if (isDebian) {
c('x-terminal-emulator');
} else if (process.env.DESKTOP_SESSION === 'gnome' || process.env.DESKTOP_SESSION === 'gnome-classic') {
c('gnome-terminal');
} else if (process.env.DESKTOP_SESSION === 'kde-plasma') {
c('konsole');
} else if (process.env.COLORTERM) {
c(process.env.COLORTERM);
} else if (process.env.TERM) {
c(process.env.TERM);
} else {
c('xterm');
}
});
return;
}
c('xterm');
});
}
return _DEFAULT_TERMINAL_LINUX_READY;
}
if (env.isWindows) {
registerSingleton(IExternalTerminalService, WindowsExternalTerminalService, true);
} else if (env.isMacintosh) {
@ -394,7 +366,7 @@ if (env.isWindows) {
registerSingleton(IExternalTerminalService, LinuxExternalTerminalService, true);
}
getDefaultTerminalLinuxReady().then(defaultTerminalLinux => {
LinuxExternalTerminalService.getDefaultTerminalLinuxReady().then(defaultTerminalLinux => {
let configurationRegistry = Registry.as<IConfigurationRegistry>(Extensions.Configuration);
configurationRegistry.registerConfiguration({
id: 'externalTerminal',
@ -418,7 +390,7 @@ getDefaultTerminalLinuxReady().then(defaultTerminalLinux => {
'terminal.external.windowsExec': {
type: 'string',
description: nls.localize('terminal.external.windowsExec', "Customizes which terminal to run on Windows."),
default: getDefaultTerminalWindows(),
default: WindowsExternalTerminalService.getDefaultTerminalWindows(),
scope: ConfigurationScope.APPLICATION
},
'terminal.external.osxExec': {

View file

@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { deepEqual, equal } from 'assert';
import { WindowsExternalTerminalService, LinuxExternalTerminalService, MacExternalTerminalService, DEFAULT_TERMINAL_OSX, getDefaultTerminalWindows, getDefaultTerminalLinuxReady } from 'vs/workbench/contrib/externalTerminal/node/externalTerminalService';
import { WindowsExternalTerminalService, LinuxExternalTerminalService, MacExternalTerminalService, DEFAULT_TERMINAL_OSX } from 'vs/workbench/contrib/externalTerminal/node/externalTerminalService';
suite('ExternalTerminalService', () => {
let mockOnExit: Function;
@ -58,7 +58,7 @@ suite('ExternalTerminalService', () => {
let mockSpawner = {
spawn: (command: any, args: any, opts: any) => {
// assert
equal(args[args.length - 1], getDefaultTerminalWindows(), 'terminal should equal expected');
equal(args[args.length - 1], WindowsExternalTerminalService.getDefaultTerminalWindows(), 'terminal should equal expected');
done();
return {
on: (evt: any) => evt
@ -194,7 +194,7 @@ suite('ExternalTerminalService', () => {
});
test(`LinuxTerminalService - uses default terminal when configuration.terminal.external.linuxExec is undefined`, done => {
getDefaultTerminalLinuxReady().then(defaultTerminalLinux => {
LinuxExternalTerminalService.getDefaultTerminalLinuxReady().then(defaultTerminalLinux => {
let testCwd = 'path/to/workspace';
let mockSpawner = {
spawn: (command: any, args: any, opts: any) => {