Skip to content

Commit

Permalink
Implement vscode.Terminal.processId
Browse files Browse the repository at this point in the history
Fixes #11919
  • Loading branch information
Tyriar committed Sep 19, 2016
1 parent 1cc8b7c commit 7236f59
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 2 deletions.
7 changes: 7 additions & 0 deletions src/vs/vscode.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3012,6 +3012,13 @@ declare namespace vscode {
*/
name: string;

/**
* The process ID of the shell process.
*
* @readonly
*/
processId: Thenable<number>;

/**
* Send text to the terminal. The text is written to the stdin of the underlying pty process
* (shell) of the terminal.
Expand Down
1 change: 1 addition & 0 deletions src/vs/workbench/api/node/extHost.protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ export abstract class ExtHostQuickOpenShape {

export abstract class ExtHostTerminalServiceShape {
$acceptTerminalClosed(id: number): void { throw ni(); }
$acceptTerminalProcessId(id: number, processId: number): void { throw ni(); }
}

// --- proxy identifiers
Expand Down
26 changes: 26 additions & 0 deletions src/vs/workbench/api/node/extHostTerminalService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export class ExtHostTerminal implements vscode.Terminal {

private _name: string;
private _id: number;
private _processId: number;
private _proxy: MainThreadTerminalServiceShape;
private _disposed: boolean;
private _queuedRequests: ApiRequest[];
Expand All @@ -34,6 +35,16 @@ export class ExtHostTerminal implements vscode.Terminal {
return this._name;
}

public get processId(): Thenable<number> {
this._checkDisposed();
if (this._processId) {
return Promise.resolve<number>(this._processId);
}
setTimeout(() => {
return this.processId;
}, 200);
}

public sendText(text: string, addNewLine: boolean = true): void {
this._checkDisposed();
this._queueApiRequest(this._proxy.$sendText, [text, addNewLine]);
Expand All @@ -56,6 +67,10 @@ export class ExtHostTerminal implements vscode.Terminal {
}
}

public setProcessId(processId: number): void {
this._processId = processId;
}

private _queueApiRequest(callback: (...args: any[]) => void, args: any[]) {
let request: ApiRequest = new ApiRequest(callback, args);
if (!this._id) {
Expand Down Expand Up @@ -104,6 +119,16 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
this._onDidCloseTerminal.fire(terminal);
}

public $acceptTerminalProcessId(id: number, processId: number): void {
let terminal = this._getTerminalById(id);
terminal.setProcessId(processId);
}

private _getTerminalById(id: number): ExtHostTerminal {
let index = this._getTerminalIndexById(id);
return index !== null ? this._terminals[index] : null;
}

private _getTerminalIndexById(id: number): number {
let index: number = null;
this._terminals.some((terminal, i) => {
Expand All @@ -118,6 +143,7 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
}

class ApiRequest {

private _callback: (...args: any[]) => void;
private _args: any[];

Expand Down
5 changes: 5 additions & 0 deletions src/vs/workbench/api/node/mainThreadTerminalService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export class MainThreadTerminalService extends MainThreadTerminalServiceShape {
this._proxy = threadService.get(ExtHostContext.ExtHostTerminalService);
this._toDispose = [];
this._toDispose.push(terminalService.onInstanceDisposed((terminalInstance) => this._onTerminalDisposed(terminalInstance)));
this._toDispose.push(terminalService.onInstanceProcessIdReady((terminalInstance) => this._onTerminalProcessIdReady(terminalInstance)));
}

public dispose(): void {
Expand Down Expand Up @@ -68,4 +69,8 @@ export class MainThreadTerminalService extends MainThreadTerminalServiceShape {
private _onTerminalDisposed(terminalInstance: ITerminalInstance): void {
this._proxy.$acceptTerminalClosed(terminalInstance.id);
}

private _onTerminalProcessIdReady(terminalInstance: ITerminalInstance): void {
this._proxy.$acceptTerminalProcessId(terminalInstance.id, terminalInstance.processId);
}
}
6 changes: 6 additions & 0 deletions src/vs/workbench/parts/terminal/electron-browser/terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export interface ITerminalService {
configHelper: TerminalConfigHelper;
onActiveInstanceChanged: Event<string>;
onInstanceDisposed: Event<ITerminalInstance>;
onInstanceProcessIdReady: Event<ITerminalInstance>;
onInstancesChanged: Event<string>;
onInstanceTitleChanged: Event<string>;
terminalInstances: ITerminalInstance[];
Expand All @@ -85,6 +86,11 @@ export interface ITerminalInstance {
*/
id: number;

/**
* The process ID of the shell process.
*/
processId: number;

/**
* An event that fires when the terminal instance's title changes.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@ export class TerminalInstance implements ITerminalInstance {
private _isExiting: boolean;
private _isVisible: boolean;
private _onDisposed: Emitter<TerminalInstance>;
private _onProcessIdReady: Emitter<TerminalInstance>;
private _onTitleChanged: Emitter<string>;
private _process: cp.ChildProcess;
private _processId: number;
private _skipTerminalKeybindings: Keybinding[];
private _title: string;
private _toDispose: lifecycle.IDisposable[];
Expand All @@ -44,7 +46,9 @@ export class TerminalInstance implements ITerminalInstance {
private _xtermElement: HTMLDivElement;

public get id(): number { return this._id; }
public get processId(): number { return this._processId; }
public get onClosed(): Event<TerminalInstance> { return this._onDisposed.event; }
public get onProcessIdReady(): Event<TerminalInstance> { return this._onProcessIdReady.event; }
public get onTitleChanged(): Event<string> { return this._onTitleChanged.event; }
public get title(): string { return this._title; }

Expand All @@ -64,8 +68,9 @@ export class TerminalInstance implements ITerminalInstance {
this._isVisible = false;
this._id = TerminalInstance._idCounter++;

this._onTitleChanged = new Emitter<string>();
this._onDisposed = new Emitter<TerminalInstance>();
this._onProcessIdReady = new Emitter<TerminalInstance>();
this._onTitleChanged = new Emitter<string>();

this._createProcess(_workspace, name, shell);

Expand Down Expand Up @@ -94,6 +99,9 @@ export class TerminalInstance implements ITerminalInstance {
this._process.on('message', (message) => {
if (message.type === 'data') {
this._xterm.write(message.content);
} else if (message.type === 'pid') {
this._processId = message.content;
this._onProcessIdReady.fire(this);
}
});
this._xterm.on('data', (data) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ process.on('message', function (message) {
}
});

sendProcessId();
setupTitlePolling();

function getArgs() {
Expand Down Expand Up @@ -91,6 +92,13 @@ function setupPlanB(parentPid) {
}, 5000);
}

function sendProcessId() {
process.send({
type: 'pid',
content: ptyProcess.pid
});
}

function setupTitlePolling() {
sendProcessTitle();
setInterval(function () {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export class TerminalService implements ITerminalService {
private _configHelper: TerminalConfigHelper;
private _onActiveInstanceChanged: Emitter<string>;
private _onInstanceDisposed: Emitter<ITerminalInstance>;
private _onInstanceProcessIdReady: Emitter<ITerminalInstance>;
private _onInstanceTitleChanged: Emitter<string>;
private _onInstancesChanged: Emitter<string>;
private _terminalContainer: HTMLElement;
Expand All @@ -34,6 +35,7 @@ export class TerminalService implements ITerminalService {
public get configHelper(): TerminalConfigHelper { return this._configHelper; }
public get onActiveInstanceChanged(): Event<string> { return this._onActiveInstanceChanged.event; }
public get onInstanceDisposed(): Event<ITerminalInstance> { return this._onInstanceDisposed.event; }
public get onInstanceProcessIdReady(): Event<ITerminalInstance> { return this._onInstanceProcessIdReady.event; }
public get onInstanceTitleChanged(): Event<string> { return this._onInstanceTitleChanged.event; }
public get onInstancesChanged(): Event<string> { return this._onInstancesChanged.event; }
public get terminalInstances(): ITerminalInstance[] { return this._terminalInstances; }
Expand All @@ -51,8 +53,9 @@ export class TerminalService implements ITerminalService {

this._onActiveInstanceChanged = new Emitter<string>();
this._onInstanceDisposed = new Emitter<ITerminalInstance>();
this._onInstancesChanged = new Emitter<string>();
this._onInstanceProcessIdReady = new Emitter<ITerminalInstance>();
this._onInstanceTitleChanged = new Emitter<string>();
this._onInstancesChanged = new Emitter<string>();

this._terminalFocusContextKey = KEYBINDING_CONTEXT_TERMINAL_FOCUS.bindTo(this._contextKeyService);
this._configHelper = <TerminalConfigHelper>this._instantiationService.createInstance(TerminalConfigHelper, platform.platform);
Expand All @@ -73,6 +76,7 @@ export class TerminalService implements ITerminalService {
shell);
terminalInstance.addDisposable(terminalInstance.onTitleChanged(this._onInstanceTitleChanged.fire, this._onInstanceTitleChanged));
terminalInstance.addDisposable(terminalInstance.onClosed(this._onInstanceDisposed.fire, this._onInstanceDisposed));
terminalInstance.addDisposable(terminalInstance.onProcessIdReady(this._onInstanceProcessIdReady.fire, this._onInstanceProcessIdReady));
this.terminalInstances.push(terminalInstance);
if (this.terminalInstances.length === 1) {
// It's the first instance so it should be made active automatically
Expand Down

0 comments on commit 7236f59

Please sign in to comment.