Skip to content
This repository has been archived by the owner on Jul 19, 2019. It is now read-only.

Implement terminal exit #27

Merged
merged 9 commits into from
Dec 13, 2018
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
**********************************************************************/

import { injectable } from 'inversify';
import { TerminalWatcher } from '@theia/terminal/lib/common/terminal-watcher';
import { IBaseTerminalClient, IBaseTerminalExitEvent, IBaseTerminalErrorEvent } from '@theia/terminal/lib/common/base-terminal-protocol';
import { JsonRpcProxy } from '@theia/core';
import { Emitter, Event } from '@theia/core/lib/common/event';

export const TERMINAL_SERVER_TYPE = 'terminal';
export const CONNECT_TERMINAL_SEGMENT = 'connect';
Expand Down Expand Up @@ -50,18 +50,49 @@ export interface RemoteTerminalServer {
export const RemoteTerminalServerProxy = Symbol('RemoteTerminalServerProxy');
export type RemoteTerminalServerProxy = JsonRpcProxy<RemoteTerminalServer>;

/**
* For now this class it's a stub. Real implementation depends on
* https://github.com/eclipse/che-machine-exec/issues/5
*/
// Terminal exec exit event
export class ExecExitEvent {
id: number;
}

// Terminal exec error event
export class ExecErrorEvent {
id: number;
stack: string;
}

// Terminal exec client
export interface TerminalExecClient {
onExecExit(event: ExecExitEvent): void;
onExecError(event: ExecErrorEvent): void;
}

@injectable()
export class RemoteTerminaWatcher extends TerminalWatcher {
getTerminalClient(): IBaseTerminalClient {
export class RemoteTerminalWatcher {

private onRemoteTerminalExitEmitter = new Emitter<ExecExitEvent>();
private onRemoteTerminalErrorEmitter = new Emitter<ExecErrorEvent>();

getTerminalExecClient(): TerminalExecClient {

const exitEmitter = this.onRemoteTerminalExitEmitter;
const errorEmitter = this.onRemoteTerminalErrorEmitter;

return {
onTerminalExitChanged(event: IBaseTerminalExitEvent) {
onExecExit(event: ExecExitEvent) {
exitEmitter.fire(event);
},
onTerminalError(event: IBaseTerminalErrorEvent) {
onExecError(event: ExecErrorEvent) {
errorEmitter.fire(event);
}
};
}

get onTerminalExecExit(): Event<ExecExitEvent> {
return this.onRemoteTerminalExitEmitter.event;
}

get onTerminalExecError(): Event<ExecErrorEvent> {
return this.onRemoteTerminalErrorEmitter.event;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

import { injectable, inject } from 'inversify';
import { RemoteWebSocketConnectionProvider, } from './remote-connection';
import { CONNECT_TERMINAL_SEGMENT, RemoteTerminalServerProxy, RemoteTerminalServer } from './base-terminal-protocol';
import { CONNECT_TERMINAL_SEGMENT, RemoteTerminalServerProxy, RemoteTerminalServer, RemoteTerminalWatcher } from './remote-terminal-protocol';
import URI from '@theia/core/lib/common/uri';

export type TerminalApiEndPointProvider = () => Promise<string | undefined>;
Expand All @@ -20,13 +20,19 @@ export type TerminalProxyCreatorProvider = () => Promise<TerminalProxyCreator>;
@injectable()
export class TerminalProxyCreator {

private remoteTermServer: RemoteTerminalServerProxy;

constructor(@inject(RemoteWebSocketConnectionProvider) protected readonly connProvider: RemoteWebSocketConnectionProvider,
@inject('term-api-end-point') protected readonly apiEndPoint: string,
@inject(RemoteTerminalWatcher) protected readonly terminalWatcher: RemoteTerminalWatcher,
) {
}

create(): RemoteTerminalServerProxy {
const url = new URI(this.apiEndPoint).resolve(CONNECT_TERMINAL_SEGMENT);
return this.connProvider.createProxy<RemoteTerminalServer>(url.toString());
if (!this.remoteTermServer) {
const url = new URI(this.apiEndPoint).resolve(CONNECT_TERMINAL_SEGMENT);
this.remoteTermServer = this.connProvider.createProxy<RemoteTerminalServer>(url.toString(), this.terminalWatcher.getTerminalExecClient());
}
return this.remoteTermServer;
}
}
6 changes: 4 additions & 2 deletions che-theia-terminal/src/browser/terminal-frontend-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { TerminalService } from '@theia/terminal/lib/browser/base/terminal-servi
import { TerminalWidget, TerminalWidgetOptions } from '@theia/terminal/lib/browser/base/terminal-widget';
import { RemoteTerminalWidget } from './terminal-widget/remote-terminal-widget';
import { RemoteTerminaActiveKeybingContext } from './contribution/keybinding-context';
import { RemoteTerminalServerProxy, RemoteTerminalServer } from './server-definition/base-terminal-protocol';
import { RemoteTerminalServerProxy, RemoteTerminalServer, RemoteTerminalWatcher } from './server-definition/remote-terminal-protocol';

export default new ContainerModule((bind: interfaces.Bind, unbind: interfaces.Unbind, isBound: interfaces.IsBound, rebind: interfaces.Rebind) => {
bind(KeybindingContext).to(RemoteTerminaActiveKeybingContext).inSingletonScope();
Expand All @@ -42,6 +42,8 @@ export default new ContainerModule((bind: interfaces.Bind, unbind: interfaces.Un

bind(RemoteTerminalServer).toService(RemoteTerminalServerProxy);

bind(RemoteTerminalWatcher).toSelf().inSingletonScope();

let terminalNum = 0;
bind(WidgetFactory).toDynamicValue(ctx => ({
id: REMOTE_TERMINAL_WIDGET_FACTORY_ID,
Expand Down Expand Up @@ -102,7 +104,7 @@ export default new ContainerModule((bind: interfaces.Bind, unbind: interfaces.Un
}
return reject('Unabel to find che-machine-exec server.');
}).catch(err => {
console.log('Failed get terminal proxy. Cause: ', err);
console.log('Failed to get terminal proxy. Cause: ', err);
return reject(err);
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
// Copied from 'terminal-widget.ts' with some modifications, CQ: https://dev.eclipse.org/ipzilla/show_bug.cgi?id=16269
/* tslint:enable */

import { injectable, inject } from 'inversify';
import { injectable, inject, postConstruct } from 'inversify';
import { TerminalWidgetImpl } from '@theia/terminal/lib/browser/terminal-widget-impl';
import { IBaseTerminalServer } from '@theia/terminal/lib/common/base-terminal-protocol';
import { TerminalProxyCreator, TerminalProxyCreatorProvider } from '../server-definition/terminal-proxy-creator';
import { ATTACH_TERMINAL_SEGMENT, RemoteTerminalServerProxy } from '../server-definition/base-terminal-protocol';
import { ATTACH_TERMINAL_SEGMENT, RemoteTerminalServerProxy, RemoteTerminalWatcher } from '../server-definition/remote-terminal-protocol';
import { RemoteWebSocketConnectionProvider } from '../server-definition/remote-connection';
import { Deferred } from '@theia/core/lib/common/promise-util';
import { Disposable } from 'vscode-jsonrpc';
Expand Down Expand Up @@ -43,9 +43,30 @@ export class RemoteTerminalWidget extends TerminalWidgetImpl {
@inject(RemoteWebSocketConnectionProvider)
protected readonly remoteWebSocketConnectionProvider: RemoteWebSocketConnectionProvider;

@inject(RemoteTerminalWatcher)
protected readonly remoteTerminalWatcher: RemoteTerminalWatcher;

@inject(RemoteTerminalWidgetOptions)
options: RemoteTerminalWidgetOptions;

@postConstruct()
protected init(): void {
super.init();

this.toDispose.push(this.remoteTerminalWatcher.onTerminalExecExit(exitEvent => {
if (this.terminalId === exitEvent.id) {
this.dispose();
}
}));

this.toDispose.push(this.remoteTerminalWatcher.onTerminalExecError(errEvent => {
if (this.terminalId === errEvent.id) {
this.dispose();
this.logger.error(`Terminal error: ${errEvent.stack}`);
}
}));
}

async start(id?: number): Promise<number> {
try {
if (!this.termServer) {
Expand Down
2 changes: 1 addition & 1 deletion che-theia-terminal/src/node/workspace-service-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { injectable, inject } from 'inversify';
import WorkspaceClient, { IRemoteAPI, IWorkspace, IServer, IMachine, IRequestError, IRestAPIConfig } from '@eclipse-che/workspace-client';
import { EnvVariablesServer } from '@theia/core/lib/common/env-variables';
import { CHEWorkspaceService } from '../common/workspace-service';
import { TERMINAL_SERVER_TYPE } from '../browser/server-definition/base-terminal-protocol';
import { TERMINAL_SERVER_TYPE } from '../browser/server-definition/remote-terminal-protocol';

const TYPE: string = 'type';
const EDITOR_SERVER_TYPE: string = 'ide';
Expand Down