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 { IRuntime, RunTimeType } from '../common/runtime.ts';
|
||||||
import BunTerminalIO from './terminal_io.ts';
|
import TerminalIO from '../tsx/terminal_io.ts';
|
||||||
import BunFileIO from './file_io.ts';
|
import FileIO from '../tsx/file_io.ts';
|
||||||
|
|
||||||
import process from 'node:process';
|
import process from 'node:process';
|
||||||
|
|
||||||
@ -13,8 +13,8 @@ import process from 'node:process';
|
|||||||
*/
|
*/
|
||||||
const BunRuntime: IRuntime = {
|
const BunRuntime: IRuntime = {
|
||||||
name: RunTimeType.Bun,
|
name: RunTimeType.Bun,
|
||||||
file: BunFileIO,
|
file: FileIO,
|
||||||
term: BunTerminalIO,
|
term: TerminalIO,
|
||||||
onEvent: (eventName: string, handler) => process.on(eventName, handler),
|
onEvent: (eventName: string, handler) => process.on(eventName, handler),
|
||||||
onExit: (cb: () => void): void => {
|
onExit: (cb: () => void): void => {
|
||||||
process.on('beforeExit', cb);
|
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
|
// 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 {
|
export function log(s: unknown, level: LogLevel = LogLevel.Notice): void {
|
||||||
getRuntime().then(({ file }) => {
|
getRuntime().then(({ file }) => {
|
||||||
const raw = JSON.stringify(s, null, 2);
|
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
|
* Adapt the node test interface to the shared testing interface
|
||||||
*/
|
*/
|
||||||
// @ts-ignore: Only in newer versions of node
|
|
||||||
import {
|
import {
|
||||||
deepStrictEqual,
|
deepStrictEqual,
|
||||||
notStrictEqual,
|
notStrictEqual,
|
||||||
strictEqual,
|
strictEqual,
|
||||||
} from 'node:assert/strict';
|
} from 'node:assert/strict';
|
||||||
// @ts-ignore: Only in newer versions of node
|
|
||||||
import { describe, it } from 'node:test';
|
import { describe, it } from 'node:test';
|
||||||
import { ITestBase } from '../common/types.ts';
|
import { ITestBase } from '../common/types.ts';
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user