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

Move terminal process to TerminalService

上级 6a353625
......@@ -4,10 +4,11 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import {TPromise} from 'vs/base/common/winjs.base';
import {createDecorator, ServiceIdentifier} from 'vs/platform/instantiation/common/instantiation';
import cp = require('child_process');
import platform = require('vs/base/common/platform');
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';
......@@ -39,6 +40,11 @@ export interface ITerminalConfiguration {
};
}
export interface ITerminalProcess {
title: string;
process: cp.ChildProcess;
}
export interface ITerminalService {
serviceId: ServiceIdentifier<any>;
......@@ -49,5 +55,8 @@ export interface ITerminalService {
focusPrevious(): TPromise<any>;
toggle(): TPromise<any>;
createTerminalProcess(): ITerminalProcess;
//getTerminalInstanceTitles(): TPromise<string[]>;
initConfigHelper(panelElement: HTMLElement): void;
killTerminalProcess(terminalProcess: ITerminalProcess): void;
}
......@@ -3,11 +3,11 @@
* 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 {Action, IAction} from 'vs/base/common/actions';
import {ITerminalService} from 'vs/workbench/parts/terminal/electron-browser/terminal';
import {SelectActionItem} from 'vs/base/browser/ui/actionbar/actionbar';
import {TPromise} from 'vs/base/common/winjs.base';
export class ToggleTerminalAction extends Action {
......
......@@ -3,28 +3,21 @@
* 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 lifecycle = require('vs/base/common/lifecycle');
import platform = require('vs/base/common/platform');
import xterm = require('xterm');
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 {ScrollbarVisibility} from 'vs/base/browser/ui/scrollbar/scrollableElementOptions';
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 {
private processTitle: string = '';
private toDispose: lifecycle.IDisposable[];
private ptyProcess: cp.ChildProcess;
private terminalProcess: ITerminalProcess;
private terminal;
private terminalDomElement: HTMLDivElement;
private wrapperElement: HTMLDivElement;
......@@ -40,7 +33,7 @@ export class TerminalInstance {
this.toDispose = [];
this.wrapperElement = document.createElement('div');
DOM.addClass(this.wrapperElement, 'terminal-wrapper');
this.ptyProcess = this.createTerminalProcess();
this.terminalProcess = this.terminalService.createTerminalProcess();
this.terminalDomElement = document.createElement('div');
let terminalScrollbar = new DomScrollableElement(this.terminalDomElement, {
canUseTranslate3d: false,
......@@ -50,21 +43,22 @@ export class TerminalInstance {
this.toDispose.push(terminalScrollbar);
this.terminal = xterm();
this.ptyProcess.on('message', (message) => {
this.terminalProcess.process.on('message', (message) => {
if (message.type === 'data') {
this.terminal.write(message.content);
} 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.ptyProcess.send({
this.terminalProcess.process.send({
event: 'input',
data: data
});
return false;
});
this.ptyProcess.on('exit', (exitCode) => {
this.terminalProcess.process.on('exit', (exitCode) => {
this.dispose();
if (exitCode) {
console.error('Integrated terminal exited with code ' + exitCode);
......@@ -107,8 +101,8 @@ export class TerminalInstance {
if (this.terminal) {
this.terminal.resize(cols, rows);
}
if (this.ptyProcess.connected) {
this.ptyProcess.send({
if (this.terminalProcess.process.connected) {
this.terminalProcess.process.send({
event: 'resize',
cols: cols,
rows: rows
......@@ -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) {
DOM.toggleClass(this.wrapperElement, 'active', visible);
}
......@@ -163,10 +135,6 @@ export class TerminalInstance {
this.terminal.element.dispatchEvent(event);
}
public getProcessTitle(): string {
return this.processTitle;
}
public dispose(): void {
if (this.wrapperElement) {
this.parentDomElement.removeChild(this.wrapperElement);
......@@ -174,6 +142,6 @@ export class TerminalInstance {
}
this.toDispose = lifecycle.dispose(this.toDispose);
this.terminal.destroy();
this.ptyProcess.kill();
this.terminalService.killTerminalProcess(this.terminalProcess);
}
}
\ No newline at end of file
......@@ -3,23 +3,23 @@
* 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 platform = require('vs/base/common/platform');
import DOM = require('vs/base/browser/dom');
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 {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 {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
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 {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 {TPromise} from 'vs/base/common/winjs.base';
import {TerminalConfigHelper} from 'vs/workbench/parts/terminal/electron-browser/terminalConfigHelper';
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 {
......@@ -80,6 +80,7 @@ export class TerminalPanel extends Panel {
public create(parent: Builder): TPromise<void> {
super.create(parent);
this.parentDomElement = parent.getHTMLElement();
this.terminalService.initConfigHelper(this.parentDomElement);
DOM.addClass(this.parentDomElement, 'integrated-terminal');
this.themeStyleElement = document.createElement('style');
......@@ -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> {
if (visible) {
if (this.terminalInstances.length > 0) {
......
......@@ -3,18 +3,32 @@
* 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 {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';
export class TerminalService implements ITerminalService {
public serviceId = ITerminalService;
private terminalProcesses: ITerminalProcess[];
private configHelper: TerminalConfigHelper;
constructor(
@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 {
});
}
/*public getTerminalInstanceTitles(): TPromise<string[]> {
return this.getTerminalPanel().then((terminalPanel) => {
return terminalPanel.getTerminalInstanceTitles();
public getTerminalInstanceTitles(): string[] {
return this.terminalProcesses.map((process) => process.title);
}
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.
先完成此消息的编辑!
想要评论请 注册