提交 3465f184 编写于 作者: D Daniel Imms

Get terminal renderers working with name, onData

上级 ed5b3d5a
......@@ -353,7 +353,7 @@ declare module 'vscode' {
// Setting to undefined will reset to use the maximum available
// dimensions: TerminalDimensions;
// Write to xterm.js
// Write to the terminal emulator
write(data: string): void; // out
// key press, or sendText was triggered by an extension on the terminal
......
......@@ -17,6 +17,7 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
private _toDispose: IDisposable[] = [];
private _terminalProcesses: { [id: number]: ITerminalProcessExtHostProxy } = {};
private _dataListeners: { [id: number]: IDisposable } = {};
private _rendererDataListeners: { [id: number]: IDisposable } = {};
constructor(
extHostContext: IExtHostContext,
......@@ -85,13 +86,28 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
}
}
public $write(terminalId: number, text: string): void {
public $terminalRendererWrite(terminalId: number, text: string): void {
const terminalInstance = this.terminalService.getInstanceFromId(terminalId);
if (terminalInstance && terminalInstance.shellLaunchConfig.isRendererOnly) {
terminalInstance.write(text);
}
}
public $terminalRendererSetName(terminalId: number, name: string): void {
const terminalInstance = this.terminalService.getInstanceFromId(terminalId);
if (terminalInstance && terminalInstance.shellLaunchConfig.isRendererOnly) {
terminalInstance.setTitle(name, false);
}
}
public $terminalRendererRegisterOnDataListener(terminalId: number): void {
const terminalInstance = this.terminalService.getInstanceFromId(terminalId);
if (terminalInstance) {
this._rendererDataListeners[terminalId] = terminalInstance.onRendererData(data => this._onTerminalRendererData(terminalId, data));
terminalInstance.onDisposed(() => delete this._dataListeners[terminalId]);
}
}
public $sendText(terminalId: number, text: string, addNewLine: boolean): void {
const terminalInstance = this.terminalService.getInstanceFromId(terminalId);
if (terminalInstance) {
......@@ -103,7 +119,7 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
const terminalInstance = this.terminalService.getInstanceFromId(terminalId);
if (terminalInstance) {
this._dataListeners[terminalId] = terminalInstance.onData(data => this._onTerminalData(terminalId, data));
terminalInstance.onDisposed(instance => delete this._dataListeners[terminalId]);
terminalInstance.onDisposed(() => delete this._dataListeners[terminalId]);
}
}
......@@ -111,6 +127,10 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
this._proxy.$acceptTerminalProcessData(terminalId, data);
}
private _onTerminalRendererData(terminalId: number, data: string): void {
this._proxy.$acceptTerminalRendererData(terminalId, data);
}
private _onTerminalDisposed(terminalInstance: ITerminalInstance): void {
this._proxy.$acceptTerminalClosed(terminalInstance.id);
}
......
......@@ -328,14 +328,19 @@ export interface MainThreadTerminalServiceShape extends IDisposable {
$dispose(terminalId: number): void;
$hide(terminalId: number): void;
$sendText(terminalId: number, text: string, addNewLine: boolean): void;
$write(terminalId: number, text: string): void;
$show(terminalId: number, preserveFocus: boolean): void;
$registerOnDataListener(terminalId: number): void;
// Process
$sendProcessTitle(terminalId: number, title: string): void;
$sendProcessData(terminalId: number, data: string): void;
$sendProcessPid(terminalId: number, pid: number): void;
$sendProcessExit(terminalId: number, exitCode: number): void;
// Renderer
$terminalRendererSetName(terminalId: number, name: string): void;
$terminalRendererWrite(terminalId: number, text: string): void;
$terminalRendererRegisterOnDataListener(terminalId: number): void;
}
export interface TransferQuickPickItems extends IQuickPickItem {
......@@ -837,6 +842,7 @@ export interface ExtHostTerminalServiceShape {
$acceptTerminalOpened(id: number, name: string): void;
$acceptTerminalProcessId(id: number, processId: number): void;
$acceptTerminalProcessData(id: number, data: string): void;
$acceptTerminalRendererData(id: number, data: string): void;
$createProcess(id: number, shellLaunchConfig: ShellLaunchConfigDto, cols: number, rows: number): void;
$acceptProcessInput(id: number, data: string): void;
$acceptProcessResize(id: number, cols: number, rows: number): void;
......
......@@ -132,12 +132,21 @@ export class ExtHostTerminal extends BaseExtHostTerminal implements vscode.Termi
export class ExtHostTerminalRenderer extends BaseExtHostTerminal implements vscode.TerminalRenderer {
public get name(): string { return this._name; }
public set name(newName: string) {
this._name = newName;
this._checkDisposed();
this._queueApiRequest(this._proxy.$terminalRendererSetName, [this._name]);
}
private readonly _onData: Emitter<string> = new Emitter<string>();
public get onData(): Event<string> {
this._checkDisposed();
this._queueApiRequest(this._proxy.$terminalRendererRegisterOnDataListener, [this._id]);
// TODO: This is not firing on renderers as ExtHostTerminalService doesn't track them currently
console.log('TerminalRenderer.onData id: ', this._id);
// TODO: This needs to fire for keystrokes and sendText only for renderers
// Tell the main side to start sending data if it's not already
this._proxy.$registerOnDataListener(this._id);
// this._proxy.$terminalRendererRegisterOnDataListener(this._id);
return this._onData && this._onData.event;
}
......@@ -153,7 +162,11 @@ export class ExtHostTerminalRenderer extends BaseExtHostTerminal implements vsco
public write(data: string): void {
this._checkDisposed();
this._queueApiRequest(this._proxy.$write, [data]);
this._queueApiRequest(this._proxy.$terminalRendererWrite, [data]);
}
public _fireOnData(data: string): void {
this._onData.fire(data);
}
}
......@@ -161,6 +174,7 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
private _proxy: MainThreadTerminalServiceShape;
private _terminals: ExtHostTerminal[] = [];
private _terminalProcesses: { [id: number]: cp.ChildProcess } = {};
private _terminalRenderers: ExtHostTerminalRenderer[] = [];
public get terminals(): ExtHostTerminal[] { return this._terminals; }
......@@ -192,9 +206,10 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
}
public createTerminalRenderer(name: string): vscode.TerminalRenderer {
const terminalRenderer = new ExtHostTerminalRenderer(this._proxy, name);
const renderer = new ExtHostTerminalRenderer(this._proxy, name);
console.log('Creating new terminal renderer');
return terminalRenderer;
this._terminalRenderers.push(renderer);
return renderer;
}
public $acceptTerminalProcessData(id: number, data: string): void {
......@@ -206,6 +221,15 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
terminal._fireOnData(data);
}
public $acceptTerminalRendererData(id: number, data: string): void {
const index = this._getTerminalRendererIndexById(id);
if (index === null) {
return;
}
const renderer = this._terminalRenderers[index];
renderer._fireOnData(data);
}
public $acceptTerminalClosed(id: number): void {
const index = this._getTerminalIndexById(id);
if (index === null) {
......@@ -345,6 +369,21 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
});
return index;
}
// TODO: Factor out common bits
private _getTerminalRendererIndexById(id: number): number {
let index: number = null;
this._terminalRenderers.some((renderer, i) => {
// TODO: This shouldn't be cas
const thisId = (<any>renderer)._id;
if (thisId === id) {
index = i;
return true;
}
return false;
});
return index;
}
}
class ApiRequest {
......
......@@ -467,11 +467,18 @@ export interface ITerminalInstance {
/**
* Attach a listener to the raw data stream coming from the pty, including ANSI escape
* sequecnes.
* sequences.
* @param listener The listener function.
*/
onData(listener: (data: string) => void): IDisposable;
/**
* Attach a listener to the "renderer" data event, this event fires for terminal renderers on
* keystrokes and when the Terminal.sendText extension API is used.
* @param listener The listener function.
*/
onRendererData(listener: (data: string) => void): IDisposable;
/**
* Attach a listener to listen for new lines added to this terminal instance.
*
......
......@@ -130,6 +130,8 @@ export class TerminalInstance implements ITerminalInstance {
this._initDimensions();
if (!this.shellLaunchConfig.isRendererOnly) {
this._createProcess();
} else {
this.setTitle(this._shellLaunchConfig.name, false);
}
this._xtermReadyPromise = this._createXterm();
......@@ -799,9 +801,25 @@ export class TerminalInstance implements ITerminalInstance {
}
public onData(listener: (data: string) => void): lifecycle.IDisposable {
// TODO: This should still work for renderers
if (!this._processManager) {
return null;
}
return this._processManager.onProcessData(data => listener(data));
}
public onRendererData(listener: (data: string) => void): lifecycle.IDisposable {
if (this._processManager) {
throw new Error('onRendererData attempted to be used on a regular terminal');
}
// For terminal renderers onData fires on keystrokes and when sendText is called.
// TODO: Handle sendText case
this._xterm.on('data', listener);
return {
dispose: () => this._xterm.off('data', listener)
};
}
public onLineData(listener: (lineData: string) => void): lifecycle.IDisposable {
this._onLineDataListeners.push(listener);
return {
......
......@@ -92,6 +92,7 @@ export class TerminalService extends AbstractTerminalService implements ITermina
}
public createTerminalRenderer(name: string): ITerminalInstance {
console.log('createTerminalRenderer', name);
return this.createTerminal({ name, isRendererOnly: true });
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册