diff --git a/src/bun/ffi.ts b/src/bun/ffi.ts index 11a1fcb..2f7f07d 100644 --- a/src/bun/ffi.ts +++ b/src/bun/ffi.ts @@ -1 +1,54 @@ // Bun-specific ffi code +import { dlopen, ptr, FFIType, suffix, toArrayBuffer } from "bun:ffi"; +import {STDIN_FILENO, TCSANOW} from "../common/ffi"; + +const termiosArray = new Uint8Array(60); + +const getLib = (name: string) => { + return dlopen( + name, + { + tcgetattr: { + args: ['i32', 'pointer'], + returns: 'i32', + }, + tcsetattr: { + args: ['i32', 'i32', 'pointer'], + returns: 'i32', + }, + cfmakeraw: { + args: ['pointer'], + returns: 'void', + }, + }, + ); +} + +let cStdLib = {symbols: {}}; + +try { + cStdLib = getLib(`libc.${suffix}`); +} catch { + cStdLib = getLib(`libc.${suffix}.6`); +} + +export const enableRawMode = () => { + // Get the current termios settings + const termiosPtr = ptr(termiosArray); + cStdLib.symbols.tcgetattr(STDIN_FILENO, termiosPtr); + + const oldTermios = new Uint8Array(toArrayBuffer(termiosPtr, 0, 60), 0, 60); + console.info(oldTermios); + + // Update termios struct with raw settings + cStdLib.symbols.cfmakeraw(termiosPtr); + + // Actually set the new termios settings + cStdLib.symbols.tcsetattr(STDIN_FILENO, TCSANOW, termiosPtr); + + return () => { + const oldTermiosPtr = ptr(oldTermios); + + cStdLib.symbols.tcsetattr(STDIN_FILENO, TCSANOW, oldTermiosPtr); + } +} diff --git a/src/bun/index.ts b/src/bun/index.ts index b2dfafa..f7c14a8 100644 --- a/src/bun/index.ts +++ b/src/bun/index.ts @@ -1,15 +1,26 @@ /** - * The main entrypoint when using Deno as the runtime + * The main entrypoint when using Bun as the runtime */ + +import {enableRawMode} from './ffi' + export async function main(): Promise { + const disableRawMode = enableRawMode(); + const decoder = new TextDecoder(); for await (const chunk of Bun.stdin.stream()) { const char = String(decoder.decode(chunk)).trim(); if (char === 'q') { + disableRawMode(); return 0; } } + process.on("exit", (code) => { + console.log(`Process exited with code ${code}`); + disableRawMode(); + }); + return -1; } \ No newline at end of file diff --git a/src/common/ffi.ts b/src/common/ffi.ts new file mode 100644 index 0000000..a0fe9c2 --- /dev/null +++ b/src/common/ffi.ts @@ -0,0 +1,4 @@ +export const STDIN_FILENO = 0; +export const STOUT_FILENO = 1; +export const TCSANOW = 0; +export const TCSAFLUSH = 2; \ No newline at end of file diff --git a/src/deno/ffi.ts b/src/deno/ffi.ts index 2799387..1eba0ec 100644 --- a/src/deno/ffi.ts +++ b/src/deno/ffi.ts @@ -11,37 +11,14 @@ switch (Deno.build.os) { libSuffix = 'dylib'; break; default: - libSuffix = 'so'; + libSuffix = 'so.6'; break; } -const cSharedLib = `./libc.${libSuffix}`; +const cSharedLib = `libc.${libSuffix}`; const cStdLib = Deno.dlopen( cSharedLib, { - termios: { - type: { - struct: [ - // c_iflag - 'u32', - // c_oflag - 'u32', - // c_cflag - 'u32', - // c_lflag - 'u32', - // c_cc[20] - 'u8', 'u8', 'u8', 'u8', 'u8', - 'u8', 'u8', 'u8', 'u8', 'u8', - 'u8', 'u8', 'u8', 'u8', 'u8', - 'u8', 'u8', 'u8', 'u8', 'u8', - // __ispeed - 'i32', - // __ospeed - 'i32', - ] - } - }, tcgetattr: { parameters: ['i32', 'pointer'], result: 'i32', @@ -58,7 +35,6 @@ const cStdLib = Deno.dlopen( ); export default cStdLib.symbols; -export const termios = cStdLib.symbols.termios; export const tcgetattr = cStdLib.symbols.tcgetattr; export const tcsetattr = cStdLib.symbols.tcsetattr; export const cfmakeraw = cStdLib.symbols.cfmakeraw;