Use Tsx/node implementation for file/terminal_io in Bun runtime
Some checks failed
timw4mail/scroll/pipeline/head There was a failure building this commit
Some checks failed
timw4mail/scroll/pipeline/head There was a failure building this commit
This commit is contained in:
parent
0148561240
commit
88bf3da4e7
@ -1,18 +0,0 @@
|
||||
import { IFileIO } from '../common/runtime.ts';
|
||||
import { appendFile } from 'node:fs/promises';
|
||||
|
||||
const BunFileIO: IFileIO = {
|
||||
openFile: async (path: string): Promise<string> => {
|
||||
const file = await Bun.file(path);
|
||||
return await file.text();
|
||||
},
|
||||
appendFile: async function (path: string, contents: string): Promise<void> {
|
||||
return await appendFile(path, contents);
|
||||
},
|
||||
saveFile: async function (path: string, contents: string): Promise<void> {
|
||||
await Bun.write(path, contents);
|
||||
return;
|
||||
},
|
||||
};
|
||||
|
||||
export default BunFileIO;
|
@ -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);
|
||||
|
@ -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<ITerminalSize> {
|
||||
// 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<ITerminalSize> {
|
||||
const [cols, rows] = process.stdout.getWindowSize();
|
||||
|
||||
return Promise.resolve({
|
||||
rows,
|
||||
cols,
|
||||
});
|
||||
},
|
||||
readStdin: async function (): Promise<string | null> {
|
||||
const raw = await BunTerminalIO.readStdinRaw();
|
||||
return readKey(raw ?? new Uint8Array(0));
|
||||
},
|
||||
readStdinRaw: function (): Promise<Uint8Array | null> {
|
||||
return new Promise((resolve) => {
|
||||
process.stdin.resume().once('data', (buffer: Uint8Array) => {
|
||||
resolve(buffer);
|
||||
});
|
||||
});
|
||||
},
|
||||
writeStdout: async function write(s: string): Promise<void> {
|
||||
const buffer = encoder.encode(s);
|
||||
|
||||
await Bun.write(Bun.stdout, buffer);
|
||||
},
|
||||
};
|
||||
|
||||
export default BunTerminalIO;
|
@ -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<ITerminalSize> {
|
||||
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);
|
||||
|
@ -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';
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user