155 lines
3.9 KiB
JavaScript
155 lines
3.9 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Standalone TTY repro for fish-style readline (lone `>`, missing `[user@host:path]`).
|
|
*
|
|
* Run in a real terminal (not piped):
|
|
* cd packages/bare-os-booter && node scripts/fish-tty-repro.js
|
|
* # or: npm run repro:fish-tty -w bare-os-booter
|
|
*
|
|
* Automated PTY (drains stdout so Node does not block; checks for green prompt):
|
|
* python3 scripts/run-fish-repro-pty.py
|
|
* # or: npm run repro:fish-tty:pty -w bare-os-booter
|
|
*
|
|
* Env:
|
|
* BARE_OS_REPRO_SKIP_STDERR=1 — omit stderr preamble (isolates stdout/stderr ordering).
|
|
* BARE_OS_REPRO_SKIP_PREAMBLE=1 — skip fake kernel lines; only fish prompt.
|
|
* BARE_OS_FISH_RESYNC_LINE=0 — disable leading newline before each prompt (default is on).
|
|
* DEBUG=1 — verbose fish/TTY logs on the same terminal as the shell (debug-repl.js).
|
|
*
|
|
* Type a few commands; use `exit` or Ctrl+D to quit. Compare first prompt vs after ^C.
|
|
*/
|
|
|
|
import b4a from 'b4a'
|
|
import { bindReplDebugStream, unbindReplDebugStream } from '../lib/debug-repl.js'
|
|
import {
|
|
createFishReadLine,
|
|
disableFishRawMode,
|
|
releaseFishStdin
|
|
} from '../lib/fish-readline.js'
|
|
|
|
function mockCtx() {
|
|
return {
|
|
vfs: {
|
|
getcwd: () => '/home/user',
|
|
resolveLogical: (p) => (p === '' ? '/' : p),
|
|
async readdir() {
|
|
return []
|
|
}
|
|
},
|
|
drive: {
|
|
readdir() {
|
|
async function* empty() {
|
|
/* no /bin entries */
|
|
}
|
|
return empty()
|
|
}
|
|
},
|
|
personalDrive: {
|
|
async get() {
|
|
return null
|
|
},
|
|
async put() {}
|
|
},
|
|
b4a,
|
|
env: {
|
|
HOME: '/home/user',
|
|
USER: 'user',
|
|
HOSTNAME: 'bare-os',
|
|
PATH: '/bin',
|
|
PWD: '/home/user'
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Same idea as executeKernel writeScreen (TTY clear hook). */
|
|
function makeWriteScreen(stdout) {
|
|
return (chunk) => {
|
|
const s = typeof chunk === 'string' ? chunk : String(chunk)
|
|
stdout.write(s)
|
|
}
|
|
}
|
|
|
|
function kernelPreambleToStdout(stdout) {
|
|
const lines = [
|
|
'NAME="BareOS"',
|
|
'VERSION="0.1.0"',
|
|
'VARIANT="hyperdrive-only"',
|
|
'',
|
|
'Bare operating system — POSIX-ish shell: cd, export, exit, quit | try: help, ls /bin, pwd'
|
|
]
|
|
for (const line of lines) stdout.write(line + '\n')
|
|
}
|
|
|
|
async function main() {
|
|
const stdin = process.stdin
|
|
const stdout = process.stdout
|
|
|
|
if (!stdin.isTTY || typeof stdin.setRawMode !== 'function') {
|
|
process.stderr.write(
|
|
'fish-tty-repro: need a TTY with setRawMode (run in a terminal, not a pipe).\n'
|
|
)
|
|
process.exit(1)
|
|
}
|
|
|
|
const skipStderr = process.env.BARE_OS_REPRO_SKIP_STDERR === '1'
|
|
const skipPreamble = process.env.BARE_OS_REPRO_SKIP_PREAMBLE === '1'
|
|
|
|
if (!skipStderr) {
|
|
process.stderr.write(
|
|
'\x1b[0m[bare-os-booter] Fish-style TTY line editor active\n'
|
|
)
|
|
}
|
|
|
|
const ctx = mockCtx()
|
|
const writeScreen = makeWriteScreen(stdout)
|
|
|
|
if (process.env.DEBUG === '1') bindReplDebugStream(stdout)
|
|
|
|
const fishRead = await createFishReadLine(ctx, {
|
|
stdin,
|
|
stdout,
|
|
writeScreen
|
|
})
|
|
|
|
if (!fishRead) {
|
|
process.stderr.write('createFishReadLine returned null.\n')
|
|
process.exit(1)
|
|
}
|
|
|
|
if (!skipPreamble) {
|
|
kernelPreambleToStdout(stdout)
|
|
}
|
|
|
|
const readLine = (prompt) => fishRead(prompt)
|
|
|
|
process.stderr.write(
|
|
'\n--- repro ready: first prompts should show full [user@bare-os:~] > if healthy ---\n'
|
|
)
|
|
|
|
try {
|
|
while (true) {
|
|
const line = await readLine('repro> ')
|
|
if (line == null) {
|
|
stdout.write('\n')
|
|
break
|
|
}
|
|
const t = line.trim()
|
|
if (t === 'exit' || t === 'quit') break
|
|
if (t === 'cls' || t === 'clear') {
|
|
writeScreen('\x1b[H\x1b[2J\x1b[3J')
|
|
continue
|
|
}
|
|
if (t) stdout.write(`(cmd) ${t}\n`)
|
|
}
|
|
} finally {
|
|
disableFishRawMode(stdin)
|
|
releaseFishStdin(stdin)
|
|
unbindReplDebugStream()
|
|
}
|
|
}
|
|
|
|
main().catch((err) => {
|
|
process.stderr.write(String(err?.stack || err) + '\n')
|
|
process.exit(1)
|
|
})
|