From 88bf3da4e7b07131c01b083381dc312768435dfb Mon Sep 17 00:00:00 2001 From: "Timothy J. Warren" Date: Tue, 9 Jul 2024 10:23:25 -0400 Subject: [PATCH] Use Tsx/node implementation for file/terminal_io in Bun runtime --- src/bun/file_io.ts | 18 --------- src/bun/mod.ts | 8 ++-- src/bun/terminal_io.ts | 85 ------------------------------------------ src/common/runtime.ts | 39 +++++++++++++++++++ src/tsx/test_base.ts | 3 +- 5 files changed, 44 insertions(+), 109 deletions(-) delete mode 100644 src/bun/file_io.ts delete mode 100644 src/bun/terminal_io.ts diff --git a/src/bun/file_io.ts b/src/bun/file_io.ts deleted file mode 100644 index 20d8297..0000000 --- a/src/bun/file_io.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { IFileIO } from '../common/runtime.ts'; -import { appendFile } from 'node:fs/promises'; - -const BunFileIO: IFileIO = { - openFile: async (path: string): Promise => { - const file = await Bun.file(path); - return await file.text(); - }, - appendFile: async function (path: string, contents: string): Promise { - return await appendFile(path, contents); - }, - saveFile: async function (path: string, contents: string): Promise { - await Bun.write(path, contents); - return; - }, -}; - -export default BunFileIO; diff --git a/src/bun/mod.ts b/src/bun/mod.ts index 64ea653..1084bb8 100644 --- a/src/bun/mod.ts +++ b/src/bun/mod.ts @@ -3,8 +3,8 @@ */ import { IRuntime, RunTimeType } from '../common/runtime.ts'; -import BunTerminalIO from './terminal_io.ts'; -import BunFileIO from './file_io.ts'; +import TerminalIO from '../tsx/terminal_io.ts'; +import FileIO from '../tsx/file_io.ts'; import process from 'node:process'; @@ -13,8 +13,8 @@ import process from 'node:process'; */ const BunRuntime: IRuntime = { name: RunTimeType.Bun, - file: BunFileIO, - term: BunTerminalIO, + file: FileIO, + term: TerminalIO, onEvent: (eventName: string, handler) => process.on(eventName, handler), onExit: (cb: () => void): void => { process.on('beforeExit', cb); diff --git a/src/bun/terminal_io.ts b/src/bun/terminal_io.ts deleted file mode 100644 index 74965ca..0000000 --- a/src/bun/terminal_io.ts +++ /dev/null @@ -1,85 +0,0 @@ -/** - * Wrap the runtime-specific hook into stdin - */ -import process from 'node:process'; -import Ansi from '../common/ansi.ts'; -import { defaultTerminalSize } from '../common/config.ts'; -import { readKey } from '../common/fns.ts'; -import { ITerminal, ITerminalSize } from '../common/types.ts'; - -const encoder = new TextEncoder(); - -async function _getTerminalSizeFromAnsi(): Promise { - // 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 BunTerminalIO.writeStdout( - Ansi.moveCursorForward(999) + Ansi.moveCursorDown(999), - ); - - // Ask where the cursor is - await BunTerminalIO.writeStdout(Ansi.GetCursorLocation); - - // Get the first chunk from stdin - // The response is \x1b[(rows);(cols)R.. - const chunk = await BunTerminalIO.readStdinRaw(); - if (chunk === null) { - return defaultTerminalSize; - } - - 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 BunTerminalIO.writeStdout(Ansi.ClearScreen + Ansi.ResetCursor); - - return { - rows, - cols, - }; -} - -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() { - yield (await BunTerminalIO.readStdinRaw()) ?? new Uint8Array(0); - - return null; - }, - /** - * Get the size of the terminal window via ANSI codes - * @see https://viewsourcecode.org/snaptoken/kilo/03.rawInputAndOutput.html#window-size-the-hard-way - */ - getTerminalSize: function getTerminalSize(): Promise { - const [cols, rows] = process.stdout.getWindowSize(); - - return Promise.resolve({ - rows, - cols, - }); - }, - readStdin: async function (): Promise { - const raw = await BunTerminalIO.readStdinRaw(); - return readKey(raw ?? new Uint8Array(0)); - }, - readStdinRaw: function (): Promise { - return new Promise((resolve) => { - process.stdin.resume().once('data', (buffer: Uint8Array) => { - resolve(buffer); - }); - }); - }, - writeStdout: async function write(s: string): Promise { - const buffer = encoder.encode(s); - - await Bun.write(Bun.stdout, buffer); - }, -}; - -export default BunTerminalIO; diff --git a/src/common/runtime.ts b/src/common/runtime.ts index 36b89ac..ce2cbf6 100644 --- a/src/common/runtime.ts +++ b/src/common/runtime.ts @@ -35,6 +35,45 @@ let scrollRuntime: IRuntime | null = null; // Misc runtime functions // ---------------------------------------------------------------------------- +/** + * Get the size of the terminal window via ANSI codes + * @see https://viewsourcecode.org/snaptoken/kilo/03.rawInputAndOutput.html#window-size-the-hard-way + */ +async function _getTerminalSizeFromAnsi(): Promise { + const { term } = await getRuntime(); + + // 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 term.writeStdout( + Ansi.moveCursorForward(999) + Ansi.moveCursorDown(999), + ); + + // Ask where the cursor is + await term.writeStdout(Ansi.GetCursorLocation); + + // Get the first chunk from stdin + // The response is \x1b[(rows);(cols)R.. + const chunk = await term.readStdinRaw(); + if (chunk === null) { + return defaultTerminalSize; + } + + 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 term.writeStdout(Ansi.ClearScreen + Ansi.ResetCursor); + + return { + rows, + cols, + }; +} + export function log(s: unknown, level: LogLevel = LogLevel.Notice): void { getRuntime().then(({ file }) => { const raw = JSON.stringify(s, null, 2); diff --git a/src/tsx/test_base.ts b/src/tsx/test_base.ts index 2bb3ab0..a51a1ac 100644 --- a/src/tsx/test_base.ts +++ b/src/tsx/test_base.ts @@ -1,13 +1,12 @@ +// @ts-nocheck: Bun is used for typescript checks, bun does not have 'node:assert' or 'node:test' /** * Adapt the node test interface to the shared testing interface */ -// @ts-ignore: Only in newer versions of node import { deepStrictEqual, notStrictEqual, strictEqual, } from 'node:assert/strict'; -// @ts-ignore: Only in newer versions of node import { describe, it } from 'node:test'; import { ITestBase } from '../common/types.ts';