/** * Wrap the runtime-specific hook into stdin */ import Ansi from '../common/ansi.ts'; import { defaultTerminalSize, ITerminal, ITerminalSize, readKey, } from '../common/mod.ts'; const BunTerminalIO: ITerminal = { // Deno only returns arguments passed to the script, so // remove the bun runtime executable, and entry script arguments // to have consistent argument lists argv: (Bun.argv.length > 2) ? Bun.argv.slice(2) : [], inputLoop: async function* inputLoop() { for await (const chunk of Bun.stdin.stream()) { yield readKey(chunk); } }, getTerminalSize: async function getTerminalSize(): Promise { const encoder = new TextEncoder(); const write = (s: string) => Bun.write(Bun.stdout, encoder.encode(s)); // Tell the cursor to move to Row 999 and Column 999 // Since this command specifically doesn't go off the screen // When we ask where the cursor is, we should get the size of the screen await write(Ansi.moveCursorForward(999) + Ansi.moveCursorDown(999)); // Ask where the cursor is await write(Ansi.GetCursorLocation); // Get the first chunk from stdin // The response is \x1b[(rows);(cols)R.. for await (const chunk of Bun.stdin.stream()) { const rawCode = (new TextDecoder()).decode(chunk); const res = rawCode.trim().replace(/^.\[([0-9]+;[0-9]+)R$/, '$1'); const [srows, scols] = res.split(';'); const rows = parseInt(srows, 10) ?? 24; const cols = parseInt(scols, 10) ?? 80; // Clear the screen await write(Ansi.ClearScreen + Ansi.ResetCursor); return { rows, cols, }; } return defaultTerminalSize; }, writeStdout: async function write(s: string): Promise { const buffer = new TextEncoder().encode(s); await Bun.write(Bun.stdout, buffer); }, }; export default BunTerminalIO;