Can I use vscode ExtensionTerminal in Theia?

Hello,

I’m trying to get my VS Code extension Calva work in Theia. I’m not fully clear about all things that do not work at the moment, but right now I am focusing on the fact that Theia throws errors about the terminal instance being undefined for custom Task I use for starting and controlling a shell process. So I am trying to not use a task for this, but instead an ExtensionTerminal. This works in VS Code, but in Theia it is as if it just creates a regular terminal and thus my child process is never run.

This is my PseudoTerminal code:

import * as vscode from 'vscode';
import * as child from 'child_process';

export interface  JackInTerminalOptions extends vscode.TerminalOptions {
    name: string,
    cwd: string,
    env: { [key: string]: string },
    executable: string,
    args: string[]
};

export class JackInTerminal implements vscode.Pseudoterminal {
    private writeEmitter = new vscode.EventEmitter<string>();
    onDidWrite: vscode.Event<string> = this.writeEmitter.event;
    private closeEmitter = new vscode.EventEmitter<void>();
    onDidClose: vscode.Event<void> = this.closeEmitter.event;


    private fileWatcher: vscode.FileSystemWatcher | undefined;
    private process: child.ChildProcess;

    constructor(private options: JackInTerminalOptions, private outputChannel: vscode.OutputChannel, private whenStarted: (p: child.ChildProcess) => void) {
    }

    open(initialDimensions: vscode.TerminalDimensions | undefined): void {
        this.outputChannel.appendLine(`Starting Jack-in Terminal: ${this.options.executable} ${this.options.args.join(' ')}`);
        this.startClojureProgram();
    }

    close(): void {
        this.closeEmitter.fire();
    }

    handleInput(data: string) {
        let charCode = data.charCodeAt(0);
        if (data === "\r") {
            this.writeEmitter.fire("\r\n");
        } else if (charCode < 32) {
            this.writeEmitter.fire(`^${String.fromCharCode(charCode + 64)}`);
            if (charCode === 3) {
                this.killProcess();
            }
        } else {
            this.writeEmitter.fire(`${data}`);
        }
    }

    private async startClojureProgram(): Promise<child.ChildProcess> {
        return new Promise<child.ChildProcess>((resolve) => {
            this.writeEmitter.fire(`${this.options.executable} ${this.options.args.join(' ')}\r\n`);
            if (this.process && !this.process.killed) {
                this.process.kill();
            }
            this.process = child.spawn(this.options.executable, this.options.args, {
                env: this.options.env,
                cwd: this.options.cwd,
                shell: true
            });
            this.whenStarted(this.process);
            this.process.on('exit', (status) => {
                this.writeEmitter.fire(`process exited with status: ${status}\r\n`);
            });
            this.process.stdout.on('data', (data) => {
                this.writeEmitter.fire(`${data}\r\n`);
            });
        });
    }

    killProcess(): void {
        if (this.process && !this.process.killed) {
            this.process.kill();
        }
    }
}

I create an instance of that and then create the terminal like so:

    jackInTerminal = (<any>vscode.window).createTerminal({ name: `Calva Jack-in: ${connectSequence.name}`, pty: jackInPTY });

The pseudo terminals are pretty recent in the VS Code Extension API, so maybe Theia does not yet have support?

Hello @PEZ! Thank you for your question.
You’re right, Pseudoterminal API isn’t supported yet in Theia.
There’s a request on GitHub https://github.com/eclipse-theia/theia/issues/6589 where you can describe your use case to give the request more visibility.
BTW, you can track the current status of supporting VS Code compatible Plugin API in Theia on this site https://che-incubator.github.io/vscode-theia-comparator/status.html.

2 Likes