提交 4e4ac630 编写于 作者: D Daniel Imms

Use a factory to create terminal processes

上级 44688558
......@@ -14,9 +14,6 @@ export const TERMINAL_PANEL_ID = 'workbench.panel.terminal';
export const TERMINAL_SERVICE_ID = 'terminalService';
export const TERMINAL_DEFAULT_SHELL_LINUX = !platform.isWindows ? (process.env.SHELL || 'sh') : 'sh';
export const TERMINAL_DEFAULT_SHELL_OSX = !platform.isWindows ? (process.env.SHELL || 'sh') : 'sh';
export const TERMINAL_DEFAULT_RIGHT_CLICK_COPY_PASTE = platform.isWindows;
/** A context key that is set when the integrated terminal has focus. */
......
......@@ -11,8 +11,8 @@ import * as platform from 'vs/base/common/platform';
import nls = require('vs/nls');
import { Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry';
import { GlobalQuickOpenAction } from 'vs/workbench/browser/parts/quickopen/quickopen.contribution';
import { ITerminalService, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, TERMINAL_PANEL_ID, TERMINAL_DEFAULT_SHELL_LINUX, TERMINAL_DEFAULT_SHELL_OSX, TERMINAL_DEFAULT_RIGHT_CLICK_COPY_PASTE } from 'vs/workbench/parts/terminal/common/terminal';
import { TERMINAL_DEFAULT_SHELL_WINDOWS } from 'vs/workbench/parts/terminal/electron-browser/terminal';
import { ITerminalService, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, TERMINAL_PANEL_ID, TERMINAL_DEFAULT_RIGHT_CLICK_COPY_PASTE } from 'vs/workbench/parts/terminal/common/terminal';
import { TERMINAL_DEFAULT_SHELL_LINUX, TERMINAL_DEFAULT_SHELL_OSX, TERMINAL_DEFAULT_SHELL_WINDOWS } from 'vs/workbench/parts/terminal/electron-browser/terminal';
import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actionRegistry';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
......
......@@ -5,14 +5,19 @@
'use strict';
import * as os from 'os';
import * as cp from 'child_process';
import platform = require('vs/base/common/platform');
import processes = require('vs/base/node/processes');
const powerShellExePath =
!process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432')
? `${process.env.windir}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`
: `${process.env.windir}\\Sysnative\\WindowsPowerShell\\v1.0\\powershell.exe`;
export const TERMINAL_DEFAULT_SHELL_LINUX = !platform.isWindows ? (process.env.SHELL || 'sh') : 'sh';
export const TERMINAL_DEFAULT_SHELL_OSX = !platform.isWindows ? (process.env.SHELL || 'sh') : 'sh';
const isAtLeastWindows10 = platform.isWindows && parseFloat(os.release()) >= 10;
const is64BitWindows = process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432');
const powerShellPath = `${process.env.windir}\\${is64BitWindows ? 'Sysnative' : 'System32'}\\WindowsPowerShell\\v1.0\\powershell.exe`;
export const TERMINAL_DEFAULT_SHELL_WINDOWS = isAtLeastWindows10 ? powerShellExePath : processes.getWindowsShell();
export const TERMINAL_DEFAULT_SHELL_WINDOWS = isAtLeastWindows10 ? powerShellPath : processes.getWindowsShell();
export interface ITerminalProcessFactory {
create(env: { [key: string]: string }): cp.ChildProcess;
}
......@@ -20,6 +20,7 @@ import { IMessageService, Severity } from 'vs/platform/message/common/message';
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
import { IStringDictionary } from 'vs/base/common/collections';
import { ITerminalInstance, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, TERMINAL_PANEL_ID, IShellLaunchConfig } from 'vs/workbench/parts/terminal/common/terminal';
import { ITerminalProcessFactory } from 'vs/workbench/parts/terminal/electron-browser/terminal';
import { IWorkspace, IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { TabFocus } from 'vs/editor/common/config/commonEditorConfig';
......@@ -28,9 +29,19 @@ import { TerminalConfigHelper } from 'vs/workbench/parts/terminal/electron-brows
/** The amount of time to consider terminal errors to be related to the launch */
const LAUNCHING_DURATION = 500;
class StandardTerminalProcessFactory implements ITerminalProcessFactory {
public create(env: { [key: string]: string }): cp.ChildProcess {
return cp.fork('./terminalProcess', [], {
env,
cwd: URI.parse(path.dirname(require.toUrl('./terminalProcess'))).fsPath
});
}
}
export class TerminalInstance implements ITerminalInstance {
private static readonly EOL_REGEX = /\r?\n/g;
private static _terminalProcessFactory: ITerminalProcessFactory = new StandardTerminalProcessFactory();
private static _idCounter = 1;
private _id: number;
......@@ -338,7 +349,7 @@ export class TerminalInstance implements ITerminalInstance {
return TerminalInstance._sanitizeCwd(cwd);
}
protected _createProcess(workspace: IWorkspace, shell: IShellLaunchConfig) {
protected _createProcess(workspace: IWorkspace, shell: IShellLaunchConfig): void {
const locale = this._configHelper.isSetLocaleVariables() ? platform.locale : undefined;
if (!shell.executable) {
this._configHelper.mergeDefaultShellPathAndArgs(shell);
......@@ -528,4 +539,8 @@ export class TerminalInstance implements ITerminalInstance {
});
}
}
public static setTerminalProcessFactory(factory: ITerminalProcessFactory): void {
this._terminalProcessFactory = factory;
}
}
......@@ -5,17 +5,27 @@
'use strict';
import * as assert from 'assert';
import * as cp from 'child_process';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { TerminalInstance } from 'vs/workbench/parts/terminal/electron-browser/terminalInstance';
import { TerminalService } from 'vs/workbench/parts/terminal/electron-browser/terminalService';
import { TERMINAL_DEFAULT_SHELL_LINUX, TERMINAL_DEFAULT_SHELL_OSX } from 'vs/workbench/parts/terminal/common/terminal';
import { TERMINAL_DEFAULT_SHELL_WINDOWS } from 'vs/workbench/parts/terminal/electron-browser/terminal';
import { ITerminalProcessFactory, TERMINAL_DEFAULT_SHELL_LINUX, TERMINAL_DEFAULT_SHELL_OSX, TERMINAL_DEFAULT_SHELL_WINDOWS } from 'vs/workbench/parts/terminal/electron-browser/terminal';
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
import { TPromise } from 'vs/base/common/winjs.base';
class TestTerminalProcessFactory implements ITerminalProcessFactory {
public create(env: { [key: string]: string }): cp.ChildProcess {
return <any>{};
}
}
TerminalInstance.setTerminalProcessFactory(new TestTerminalProcessFactory());
class TestTerminalService extends TerminalService {
public showPanel(focus?: boolean): TPromise<void> {
return TPromise.as(void 0);
......@@ -50,57 +60,57 @@ suite('Workbench - TerminalService', () => {
});
// TODO@Tyriar: Re-enable these tests after testing them on Windows
// suite('createInstance', () => {
// test('should return the new instance', () => {
// assert.ok(service.createInstance() instanceof TerminalInstance);
// });
// test('should register the new instance on the service', () => {
// const instance = service.createInstance();
// assert.deepEqual(service.terminalInstances, [instance]);
// });
// test('should deregister an instance from the service when it\'s disposed', () => {
// const instance = service.createInstance();
// assert.equal(service.terminalInstances.length, 1);
// instance.dispose();
// assert.equal(service.terminalInstances.length, 0);
// });
// test('should only automatically set the first instance as the active instance', () => {
// const first = service.createInstance();
// assert.equal(service.getActiveInstance(), first);
// service.createInstance();
// assert.equal(service.getActiveInstance(), first);
// });
// });
// suite('onInstancesChanged event', () => {
// test('should fire when an instance is created', () => {
// let count = 0;
// service.onInstancesChanged(() => { count++; });
// service.createInstance();
// assert.equal(count, 1);
// service.createInstance();
// assert.equal(count, 2);
// });
// test('should fire when an instance is disposed', () => {
// let count = 0;
// service.onInstancesChanged(() => { count++; });
// service.createInstance().dispose();
// assert.equal(count, 2);
// });
// });
// suite('onInstanceDisposed event', () => {
// test('should fire when an instance is disposed', () => {
// let count = 0;
// service.onInstanceDisposed(() => { count++; });
// service.createInstance().dispose();
// assert.equal(count, 1);
// });
// });
suite('createInstance', () => {
test('should return the new instance', () => {
assert.ok(service.createInstance() instanceof TerminalInstance);
});
test('should register the new instance on the service', () => {
const instance = service.createInstance();
assert.deepEqual(service.terminalInstances, [instance]);
});
test('should deregister an instance from the service when it\'s disposed', () => {
const instance = service.createInstance();
assert.equal(service.terminalInstances.length, 1);
instance.dispose();
assert.equal(service.terminalInstances.length, 0);
});
test('should only automatically set the first instance as the active instance', () => {
const first = service.createInstance();
assert.equal(service.getActiveInstance(), first);
service.createInstance();
assert.equal(service.getActiveInstance(), first);
});
});
suite('onInstancesChanged event', () => {
test('should fire when an instance is created', () => {
let count = 0;
service.onInstancesChanged(() => { count++; });
service.createInstance();
assert.equal(count, 1);
service.createInstance();
assert.equal(count, 2);
});
test('should fire when an instance is disposed', () => {
let count = 0;
service.onInstancesChanged(() => { count++; });
service.createInstance().dispose();
assert.equal(count, 2);
});
});
suite('onInstanceDisposed event', () => {
test('should fire when an instance is disposed', () => {
let count = 0;
service.onInstanceDisposed(() => { count++; });
service.createInstance().dispose();
assert.equal(count, 1);
});
});
});
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册