terminalService.ts 4.5 KB
Newer Older
D
Daniel Imms 已提交
1 2 3 4 5
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

6 7 8 9 10 11
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';
D
Daniel Imms 已提交
12
import {IPanelService} from 'vs/workbench/services/panel/common/panelService';
13
import {IPartService} from 'vs/workbench/services/part/common/partService';
14 15 16 17 18
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';
19
import {TerminalPanel} from 'vs/workbench/parts/terminal/electron-browser/terminalPanel';
D
Daniel Imms 已提交
20 21 22 23

export class TerminalService implements ITerminalService {
	public serviceId = ITerminalService;

24 25 26
	private terminalProcesses: ITerminalProcess[];
	private configHelper: TerminalConfigHelper;

D
Daniel Imms 已提交
27
	constructor(
28
		@IPanelService private panelService: IPanelService,
29 30 31
		@IPartService private partService: IPartService,
		@IConfigurationService private configurationService: IConfigurationService,
		@IWorkspaceContextService private contextService: IWorkspaceContextService
D
Daniel Imms 已提交
32 33 34
	) {
	}

D
Daniel Imms 已提交
35 36 37 38
	public focus(): TPromise<any> {
		return this.panelService.openPanel(TERMINAL_PANEL_ID, true);
	}

39 40
	public focusNext(): TPromise<any> {
		return this.focus().then(() => {
41 42 43
			return this.toggleAndGetTerminalPanel().then((terminalPanel) => {
				terminalPanel.focusNext();
			});
44 45 46 47 48
		});
	}

	public focusPrevious(): TPromise<any> {
		return this.focus().then(() => {
49 50 51
			return this.toggleAndGetTerminalPanel().then((terminalPanel) => {
				terminalPanel.focusPrevious();
			});
52 53 54
		});
	}

55
	public toggle(): TPromise<any> {
56 57 58 59 60 61 62
		const panel = this.panelService.getActivePanel();
		if (panel && panel.getId() === TERMINAL_PANEL_ID) {
			this.partService.setPanelHidden(true);

			return TPromise.as(null);
		}

D
Daniel Imms 已提交
63 64
		return this.panelService.openPanel(TERMINAL_PANEL_ID, true);
	}
65 66

	public createNew(): TPromise<any> {
67 68 69
		return this.toggleAndGetTerminalPanel().then((terminalPanel) => {
			terminalPanel.createNewTerminalInstance();
		});
70
	}
D
Daniel Imms 已提交
71 72

	public close(): TPromise<any> {
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
		return this.toggleAndGetTerminalPanel().then((terminalPanel) => {
			terminalPanel.closeActiveTerminal();
		});
	}

	private toggleAndGetTerminalPanel(): TPromise<TerminalPanel> {
		return new TPromise<TerminalPanel>((complete) => {
			let panel = this.panelService.getActivePanel();
			if (!panel || panel.getId() !== TERMINAL_PANEL_ID) {
				this.toggle().then(() => {
					panel = this.panelService.getActivePanel();
					complete(<TerminalPanel>panel);
				});
			}
			complete(<TerminalPanel>panel);
		});
D
Daniel Imms 已提交
89
	}
90

91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
	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];
130
		});
131 132
		return newEnv;
	}
D
Daniel Imms 已提交
133
}