scroll/src/bun/terminal_io.ts

61 lines
1.7 KiB
JavaScript
Raw Normal View History

/**
* Wrap the runtime-specific hook into stdin
*/
import {
defaultTerminalSize,
ITerminal,
ITerminalSize,
} from '../common/mod.ts';
2023-11-13 15:33:56 -05:00
import Ansi from '../common/ansi.ts';
2023-11-13 15:33:56 -05:00
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) : [],
2023-11-08 18:07:34 -05:00
inputLoop: async function* inputLoop() {
for await (const chunk of Bun.stdin.stream()) {
yield chunk;
}
},
getTerminalSize: async function getTerminalSize(): Promise<ITerminalSize> {
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(';');
2023-11-16 16:00:03 -05:00
const rows = parseInt(srows, 10) ?? 24;
const cols = parseInt(scols, 10) ?? 80;
// Clear the screen
await write(Ansi.ClearScreen + Ansi.ResetCursor);
return {
rows,
cols,
};
}
2023-11-16 16:00:03 -05:00
return defaultTerminalSize;
2023-11-08 18:07:34 -05:00
},
2023-11-13 15:33:56 -05:00
writeStdout: async function write(s: string): Promise<void> {
2023-11-08 18:07:34 -05:00
const buffer = new TextEncoder().encode(s);
2023-11-08 18:07:34 -05:00
await Bun.write(Bun.stdout, buffer);
},
};
export default BunTerminalIO;