import * as vscode from 'vscode'; import * as shell from './Shell'; import * as childprocess from 'child_process'; import * as logchannel from '../logging/LogChannel'; export class LocalShell implements shell.Shell{ private _stdout: vscode.EventEmitter = new vscode.EventEmitter(); public stdout: vscode.Event; private _stderr: vscode.EventEmitter = new vscode.EventEmitter(); public stderr: vscode.Event; private _err: vscode.EventEmitter = new vscode.EventEmitter(); public err: vscode.Event; private _close: vscode.EventEmitter = new vscode.EventEmitter(); public close: vscode.Event; private shell: childprocess.ChildProcessWithoutNullStreams | undefined; private logChannel: logchannel.LogChannel; constructor(name: string){ this.stdout = this._stdout.event; this.stderr = this._stderr.event; this.err = this._err.event; this.close = this._close.event; this.logChannel = new logchannel.LogChannel(name); } public async exec(cmd: string, args: string[], cwd: vscode.Uri | undefined): Promise { this.shell = childprocess.spawn( cmd, args, {cwd: cwd?.fsPath, shell: true }); this.shell.stdout.on("data", data => { this.logChannel.appendLog(data, false, true); this._stdout.fire(data); }); this.shell.stderr.on("data", data => { this.logChannel.appendLog(data, false, true); this._stderr.fire(data); }); this.shell.on('error', (error: Error) => { this.logChannel.appendLog(error.message, false, true); this._err.fire(error); this.shell?.kill(); }); this.shell.on("close", code => { this.logChannel.appendLog("Exit code: " + code, false, true); this._close.fire(code); this.shell?.kill(); }); this.shell.on("exit", code => { this.logChannel.appendLog("Exit code: " + code, false, true); this._close.fire(code); this.shell?.kill(); }); } public async stdin(text: string): Promise { this.shell?.send(text); } public kill() { this.shell?.kill(); } }