velxio/vscode-extension/src/SerialTerminal.ts

78 lines
2.1 KiB
TypeScript

/**
* SerialTerminal — VS Code pseudo-terminal for simulation serial I/O.
*
* Provides a native VS Code terminal that displays serial output from the
* running simulation and sends user input back to the simulated UART.
*/
import * as vscode from 'vscode';
export class SerialTerminal {
private terminal: vscode.Terminal | null = null;
private writeEmitter = new vscode.EventEmitter<string>();
private closeEmitter = new vscode.EventEmitter<number | void>();
private _onInput = new vscode.EventEmitter<string>();
/** Fired when the user types in the terminal */
public readonly onInput = this._onInput.event;
/** Create and show the serial terminal */
open(boardName: string): void {
if (this.terminal) {
this.terminal.show();
return;
}
const pty: vscode.Pseudoterminal = {
onDidWrite: this.writeEmitter.event,
onDidClose: this.closeEmitter.event,
open: () => {
this.writeEmitter.fire(`\x1b[36m--- Velxio Serial Monitor (${boardName}) ---\x1b[0m\r\n`);
},
close: () => {
this.terminal = null;
},
handleInput: (data: string) => {
this._onInput.fire(data);
// Echo input in a dim color
this.writeEmitter.fire(`\x1b[90m${data}\x1b[0m`);
},
};
this.terminal = vscode.window.createTerminal({
name: `Velxio Serial (${boardName})`,
pty,
iconPath: new vscode.ThemeIcon('circuit-board'),
});
this.terminal.show(true); // preserve focus
}
/** Write serial output to the terminal */
write(text: string): void {
if (!this.terminal) return;
// Convert \n to \r\n for terminal display
this.writeEmitter.fire(text.replace(/\n/g, '\r\n'));
}
/** Clear the terminal */
clear(): void {
this.writeEmitter.fire('\x1b[2J\x1b[H'); // ANSI clear + home
}
/** Close the terminal */
close(): void {
if (this.terminal) {
this.closeEmitter.fire();
this.terminal.dispose();
this.terminal = null;
}
}
dispose(): void {
this.close();
this.writeEmitter.dispose();
this.closeEmitter.dispose();
this._onInput.dispose();
}
}