提交 dbaeb1f9 编写于 作者: D Daniel Imms

Move terminal process to TerminalService

上级 6a353625
...@@ -4,10 +4,11 @@ ...@@ -4,10 +4,11 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
'use strict'; 'use strict';
import {TPromise} from 'vs/base/common/winjs.base'; import cp = require('child_process');
import {createDecorator, ServiceIdentifier} from 'vs/platform/instantiation/common/instantiation';
import platform = require('vs/base/common/platform'); import platform = require('vs/base/common/platform');
import processes = require('vs/base/node/processes'); import processes = require('vs/base/node/processes');
import {TPromise} from 'vs/base/common/winjs.base';
import {createDecorator, ServiceIdentifier} from 'vs/platform/instantiation/common/instantiation';
export const TERMINAL_PANEL_ID = 'workbench.panel.terminal'; export const TERMINAL_PANEL_ID = 'workbench.panel.terminal';
...@@ -39,6 +40,11 @@ export interface ITerminalConfiguration { ...@@ -39,6 +40,11 @@ export interface ITerminalConfiguration {
}; };
} }
export interface ITerminalProcess {
title: string;
process: cp.ChildProcess;
}
export interface ITerminalService { export interface ITerminalService {
serviceId: ServiceIdentifier<any>; serviceId: ServiceIdentifier<any>;
...@@ -49,5 +55,8 @@ export interface ITerminalService { ...@@ -49,5 +55,8 @@ export interface ITerminalService {
focusPrevious(): TPromise<any>; focusPrevious(): TPromise<any>;
toggle(): TPromise<any>; toggle(): TPromise<any>;
createTerminalProcess(): ITerminalProcess;
//getTerminalInstanceTitles(): TPromise<string[]>; //getTerminalInstanceTitles(): TPromise<string[]>;
initConfigHelper(panelElement: HTMLElement): void;
killTerminalProcess(terminalProcess: ITerminalProcess): void;
} }
...@@ -3,11 +3,11 @@ ...@@ -3,11 +3,11 @@
* Licensed under the MIT License. See License.txt in the project root for license information. * Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import {TPromise} from 'vs/base/common/winjs.base';
import nls = require('vs/nls'); import nls = require('vs/nls');
import {Action, IAction} from 'vs/base/common/actions'; import {Action, IAction} from 'vs/base/common/actions';
import {ITerminalService} from 'vs/workbench/parts/terminal/electron-browser/terminal'; import {ITerminalService} from 'vs/workbench/parts/terminal/electron-browser/terminal';
import {SelectActionItem} from 'vs/base/browser/ui/actionbar/actionbar'; import {SelectActionItem} from 'vs/base/browser/ui/actionbar/actionbar';
import {TPromise} from 'vs/base/common/winjs.base';
export class ToggleTerminalAction extends Action { export class ToggleTerminalAction extends Action {
......
...@@ -3,28 +3,21 @@ ...@@ -3,28 +3,21 @@
* Licensed under the MIT License. See License.txt in the project root for license information. * Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import cp = require('child_process');
import xterm = require('xterm');
import lifecycle = require('vs/base/common/lifecycle');
import os = require('os');
import path = require('path');
import URI from 'vs/base/common/uri';
import DOM = require('vs/base/browser/dom'); import DOM = require('vs/base/browser/dom');
import lifecycle = require('vs/base/common/lifecycle');
import platform = require('vs/base/common/platform'); import platform = require('vs/base/common/platform');
import xterm = require('xterm');
import {Dimension} from 'vs/base/browser/builder'; import {Dimension} from 'vs/base/browser/builder';
import {IStringDictionary} from 'vs/base/common/collections';
import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace';
import {ITerminalService} from 'vs/workbench/parts/terminal/electron-browser/terminal';
import {DomScrollableElement} from 'vs/base/browser/ui/scrollbar/scrollableElement'; import {DomScrollableElement} from 'vs/base/browser/ui/scrollbar/scrollableElement';
import {ScrollbarVisibility} from 'vs/base/browser/ui/scrollbar/scrollableElementOptions';
import {IShell, ITerminalFont} from 'vs/workbench/parts/terminal/electron-browser/terminalConfigHelper'; import {IShell, ITerminalFont} from 'vs/workbench/parts/terminal/electron-browser/terminalConfigHelper';
import {ITerminalProcess, ITerminalService} from 'vs/workbench/parts/terminal/electron-browser/terminal';
import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace';
import {ScrollbarVisibility} from 'vs/base/browser/ui/scrollbar/scrollableElementOptions';
export class TerminalInstance { export class TerminalInstance {
private processTitle: string = '';
private toDispose: lifecycle.IDisposable[]; private toDispose: lifecycle.IDisposable[];
private ptyProcess: cp.ChildProcess; private terminalProcess: ITerminalProcess;
private terminal; private terminal;
private terminalDomElement: HTMLDivElement; private terminalDomElement: HTMLDivElement;
private wrapperElement: HTMLDivElement; private wrapperElement: HTMLDivElement;
...@@ -40,7 +33,7 @@ export class TerminalInstance { ...@@ -40,7 +33,7 @@ export class TerminalInstance {
this.toDispose = []; this.toDispose = [];
this.wrapperElement = document.createElement('div'); this.wrapperElement = document.createElement('div');
DOM.addClass(this.wrapperElement, 'terminal-wrapper'); DOM.addClass(this.wrapperElement, 'terminal-wrapper');
this.ptyProcess = this.createTerminalProcess(); this.terminalProcess = this.terminalService.createTerminalProcess();
this.terminalDomElement = document.createElement('div'); this.terminalDomElement = document.createElement('div');
let terminalScrollbar = new DomScrollableElement(this.terminalDomElement, { let terminalScrollbar = new DomScrollableElement(this.terminalDomElement, {
canUseTranslate3d: false, canUseTranslate3d: false,
...@@ -50,21 +43,22 @@ export class TerminalInstance { ...@@ -50,21 +43,22 @@ export class TerminalInstance {
this.toDispose.push(terminalScrollbar); this.toDispose.push(terminalScrollbar);
this.terminal = xterm(); this.terminal = xterm();
this.ptyProcess.on('message', (message) => { this.terminalProcess.process.on('message', (message) => {
if (message.type === 'data') { if (message.type === 'data') {
this.terminal.write(message.content); this.terminal.write(message.content);
} else if (message.type === 'title') { } else if (message.type === 'title') {
this.processTitle = message.content; // TODO: Should this live in TerminalService?
this.terminalProcess.title = message.content;
} }
}); });
this.terminal.on('data', (data) => { this.terminal.on('data', (data) => {
this.ptyProcess.send({ this.terminalProcess.process.send({
event: 'input', event: 'input',
data: data data: data
}); });
return false; return false;
}); });
this.ptyProcess.on('exit', (exitCode) => { this.terminalProcess.process.on('exit', (exitCode) => {
this.dispose(); this.dispose();
if (exitCode) { if (exitCode) {
console.error('Integrated terminal exited with code ' + exitCode); console.error('Integrated terminal exited with code ' + exitCode);
...@@ -107,8 +101,8 @@ export class TerminalInstance { ...@@ -107,8 +101,8 @@ export class TerminalInstance {
if (this.terminal) { if (this.terminal) {
this.terminal.resize(cols, rows); this.terminal.resize(cols, rows);
} }
if (this.ptyProcess.connected) { if (this.terminalProcess.process.connected) {
this.ptyProcess.send({ this.terminalProcess.process.send({
event: 'resize', event: 'resize',
cols: cols, cols: cols,
rows: rows rows: rows
...@@ -116,28 +110,6 @@ export class TerminalInstance { ...@@ -116,28 +110,6 @@ export class TerminalInstance {
} }
} }
private cloneEnv(): IStringDictionary<string> {
let newEnv: IStringDictionary<string> = Object.create(null);
Object.keys(process.env).forEach((key) => {
newEnv[key] = process.env[key];
});
return newEnv;
}
private createTerminalProcess(): cp.ChildProcess {
let env = this.cloneEnv();
env['PTYPID'] = process.pid.toString();
env['PTYSHELL'] = this.shell.executable;
this.shell.args.forEach((arg, i) => {
env[`PTYSHELLARG${i}`] = arg;
});
env['PTYCWD'] = this.contextService.getWorkspace() ? this.contextService.getWorkspace().resource.fsPath : os.homedir();
return cp.fork('./terminalProcess', [], {
env: env,
cwd: URI.parse(path.dirname(require.toUrl('./terminalProcess'))).fsPath
});
}
public toggleVisibility(visible: boolean) { public toggleVisibility(visible: boolean) {
DOM.toggleClass(this.wrapperElement, 'active', visible); DOM.toggleClass(this.wrapperElement, 'active', visible);
} }
...@@ -163,10 +135,6 @@ export class TerminalInstance { ...@@ -163,10 +135,6 @@ export class TerminalInstance {
this.terminal.element.dispatchEvent(event); this.terminal.element.dispatchEvent(event);
} }
public getProcessTitle(): string {
return this.processTitle;
}
public dispose(): void { public dispose(): void {
if (this.wrapperElement) { if (this.wrapperElement) {
this.parentDomElement.removeChild(this.wrapperElement); this.parentDomElement.removeChild(this.wrapperElement);
...@@ -174,6 +142,6 @@ export class TerminalInstance { ...@@ -174,6 +142,6 @@ export class TerminalInstance {
} }
this.toDispose = lifecycle.dispose(this.toDispose); this.toDispose = lifecycle.dispose(this.toDispose);
this.terminal.destroy(); this.terminal.destroy();
this.ptyProcess.kill(); this.terminalService.killTerminalProcess(this.terminalProcess);
} }
} }
\ No newline at end of file
...@@ -3,23 +3,23 @@ ...@@ -3,23 +3,23 @@
* Licensed under the MIT License. See License.txt in the project root for license information. * Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import DOM = require('vs/base/browser/dom');
import lifecycle = require('vs/base/common/lifecycle'); import lifecycle = require('vs/base/common/lifecycle');
import platform = require('vs/base/common/platform'); import platform = require('vs/base/common/platform');
import DOM = require('vs/base/browser/dom');
import {Action, IAction} from 'vs/base/common/actions'; import {Action, IAction} from 'vs/base/common/actions';
import {IActionItem} from 'vs/base/browser/ui/actionbar/actionbar';
import {TPromise} from 'vs/base/common/winjs.base';
import {Builder, Dimension} from 'vs/base/browser/builder'; import {Builder, Dimension} from 'vs/base/browser/builder';
import {CreateNewTerminalAction, SwitchTerminalInstanceAction, SwitchTerminalInstanceActionItem} from 'vs/workbench/parts/terminal/electron-browser/terminalActions';
import {IActionItem} from 'vs/base/browser/ui/actionbar/actionbar';
import {IConfigurationService} from 'vs/platform/configuration/common/configuration'; import {IConfigurationService} from 'vs/platform/configuration/common/configuration';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry';
import {ITerminalService, TERMINAL_PANEL_ID} from 'vs/workbench/parts/terminal/electron-browser/terminal';
import {IThemeService} from 'vs/workbench/services/themes/common/themeService'; import {IThemeService} from 'vs/workbench/services/themes/common/themeService';
import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace';
import {ITerminalService, TERMINAL_PANEL_ID} from 'vs/workbench/parts/terminal/electron-browser/terminal';
import {Panel} from 'vs/workbench/browser/panel'; import {Panel} from 'vs/workbench/browser/panel';
import {TPromise} from 'vs/base/common/winjs.base';
import {TerminalConfigHelper} from 'vs/workbench/parts/terminal/electron-browser/terminalConfigHelper'; import {TerminalConfigHelper} from 'vs/workbench/parts/terminal/electron-browser/terminalConfigHelper';
import {TerminalInstance} from 'vs/workbench/parts/terminal/electron-browser/terminalInstance'; import {TerminalInstance} from 'vs/workbench/parts/terminal/electron-browser/terminalInstance';
import {CreateNewTerminalAction, SwitchTerminalInstanceAction, SwitchTerminalInstanceActionItem} from 'vs/workbench/parts/terminal/electron-browser/terminalActions';
export class TerminalPanel extends Panel { export class TerminalPanel extends Panel {
...@@ -80,6 +80,7 @@ export class TerminalPanel extends Panel { ...@@ -80,6 +80,7 @@ export class TerminalPanel extends Panel {
public create(parent: Builder): TPromise<void> { public create(parent: Builder): TPromise<void> {
super.create(parent); super.create(parent);
this.parentDomElement = parent.getHTMLElement(); this.parentDomElement = parent.getHTMLElement();
this.terminalService.initConfigHelper(this.parentDomElement);
DOM.addClass(this.parentDomElement, 'integrated-terminal'); DOM.addClass(this.parentDomElement, 'integrated-terminal');
this.themeStyleElement = document.createElement('style'); this.themeStyleElement = document.createElement('style');
...@@ -115,14 +116,6 @@ export class TerminalPanel extends Panel { ...@@ -115,14 +116,6 @@ export class TerminalPanel extends Panel {
}); });
} }
public getTerminalInstanceTitles(): string[] {
let result: string[] = [];
this.terminalInstances.forEach((instance) => {
result.push(instance.getProcessTitle());
});
return result;
}
public setVisible(visible: boolean): TPromise<void> { public setVisible(visible: boolean): TPromise<void> {
if (visible) { if (visible) {
if (this.terminalInstances.length > 0) { if (this.terminalInstances.length > 0) {
......
...@@ -3,18 +3,32 @@ ...@@ -3,18 +3,32 @@
* Licensed under the MIT License. See License.txt in the project root for license information. * Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import {TPromise} from 'vs/base/common/winjs.base'; import URI from 'vs/base/common/uri';
import cp = require('child_process');
import os = require('os');
import path = require('path');
import platform = require('vs/base/common/platform');
import {IConfigurationService} from 'vs/platform/configuration/common/configuration';
import {IPanelService} from 'vs/workbench/services/panel/common/panelService'; import {IPanelService} from 'vs/workbench/services/panel/common/panelService';
import {IPartService} from 'vs/workbench/services/part/common/partService'; import {IPartService} from 'vs/workbench/services/part/common/partService';
import {ITerminalService, TERMINAL_PANEL_ID} from 'vs/workbench/parts/terminal/electron-browser/terminal'; import {IStringDictionary} from 'vs/base/common/collections';
import {ITerminalProcess, ITerminalService, TERMINAL_PANEL_ID} from 'vs/workbench/parts/terminal/electron-browser/terminal';
import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace';
import {TPromise} from 'vs/base/common/winjs.base';
import {TerminalConfigHelper} from 'vs/workbench/parts/terminal/electron-browser/terminalConfigHelper';
import {TerminalPanel} from 'vs/workbench/parts/terminal/electron-browser/terminalPanel'; import {TerminalPanel} from 'vs/workbench/parts/terminal/electron-browser/terminalPanel';
export class TerminalService implements ITerminalService { export class TerminalService implements ITerminalService {
public serviceId = ITerminalService; public serviceId = ITerminalService;
private terminalProcesses: ITerminalProcess[];
private configHelper: TerminalConfigHelper;
constructor( constructor(
@IPanelService private panelService: IPanelService, @IPanelService private panelService: IPanelService,
@IPartService private partService: IPartService @IPartService private partService: IPartService,
@IConfigurationService private configurationService: IConfigurationService,
@IWorkspaceContextService private contextService: IWorkspaceContextService
) { ) {
} }
...@@ -74,9 +88,46 @@ export class TerminalService implements ITerminalService { ...@@ -74,9 +88,46 @@ export class TerminalService implements ITerminalService {
}); });
} }
/*public getTerminalInstanceTitles(): TPromise<string[]> { public getTerminalInstanceTitles(): string[] {
return this.getTerminalPanel().then((terminalPanel) => { return this.terminalProcesses.map((process) => process.title);
return terminalPanel.getTerminalInstanceTitles(); }
public initConfigHelper(panelElement: HTMLElement): void {
if (!this.configHelper) {
this.configHelper = new TerminalConfigHelper(platform.platform, this.configurationService, panelElement);
}
}
public killTerminalProcess(terminalProcess: ITerminalProcess): void {
terminalProcess.process.kill();
// TODO: Be more defensive
this.terminalProcesses.slice(this.terminalProcesses.indexOf(terminalProcess), 1);
}
public createTerminalProcess(): ITerminalProcess {
let env = this.cloneEnv();
let shell = this.configHelper.getShell();
env['PTYPID'] = process.pid.toString();
env['PTYSHELL'] = shell.executable;
shell.args.forEach((arg, i) => {
env[`PTYSHELLARG${i}`] = arg;
});
env['PTYCWD'] = this.contextService.getWorkspace() ? this.contextService.getWorkspace().resource.fsPath : os.homedir();
let terminalProcess = {
title: '',
process: cp.fork('./terminalProcess', [], {
env: env,
cwd: URI.parse(path.dirname(require.toUrl('./terminalProcess'))).fsPath
})
};
return terminalProcess;
}
private cloneEnv(): IStringDictionary<string> {
let newEnv: IStringDictionary<string> = Object.create(null);
Object.keys(process.env).forEach((key) => {
newEnv[key] = process.env[key];
}); });
}*/ return newEnv;
}
} }
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册