Files
bare-operating-system/packages/bare-os-booter/lib/shell-tokenizer.js
T
Raven Scott aa81fbff5b Close the BareOS shell + Fish REPL roadmap tracker and ship the remaining
shell surfaces in-tree.
Roadmap / CI
- docs/data/shell-roadmap-features.json: all shell-001…shell-100 rows and
  P1–P8 phases marked implemented; note documents closure date and pointers.
- scripts/verify-shell-roadmap.mjs: validate JSON (schema 1, 8 phases,
  100 implemented items) plus existing source needles; wire npm run
  verify:shell-roadmap into root pretest (package.json).
- scripts/README.md: document verifier behavior.
Lexer & expansion (packages/bare-os-booter/lib)
- shell-lex.js: central lexShellLine; ANSI-C $'…' via decodeBareOsDollarQuote;
  keep diagnostics/tokenizer aligned with execution tokenizer.
- shell.js: stray reserved words at statement start → syntax error exit 2;
  optional [[ … ]] when BARE_OS_SHELL_DOUBLE_BRACKET=1 (==, !=);
  alias expansion before function dispatch (ordering tests);
  expandWordWithCmdSubst: balanced $(…) vs skipped $((…)); backtick
  command substitution when BARE_OS_SHELL_CMDSUBST; default ctx.execLine for
  nested cmdsubst when unset; index passthrough for DOUBLE_BRACKET env.
- shell-glob.js: ~login → HOME when USER matches, else /home/login (bounded
  login pattern); tests for pathname + execShellLine.
- shell-tokenizer.js: align with shell-lex detailed spans/modes where needed.
Completion / REPL
- completion-engine.js: completion depth / collectors per shell program work.
- packages/bare-os-booter/index.js: small wiring for shell env passthrough.
/bin/sh front-end
- packages/bare-os-coreutils/src/sh.js; kernel/bin/sh; seeder copies: stay in
  sync with shell behavior and env flags.
Tests
- packages/bare-os-booter/test.js: coverage for misplaced reserved words,
  gated [[ ]], alias vs function, ~user/~~ paths, $'…', cmdsubst $(…) and
  backticks, and related regressions.
Documentation
- docs/reference/shell-grammar.md: $'…', $(…) / backticks vs $((…)).
- handbook/09-posix-utilities-shell-and-vfs.md, environment appendix,
  shell-troubleshooting / shell-unsupported-behavior, release checklist,
  docs/reference/README.md: shell behavior and operator surfaces.
- developer-guide/19-how-to-fish-keybinding-completer.md: Fish keybinding /
  completer how-to (new).
Generated / synced artifacts
- kernel/lib/bare/manifest.json, kernel/share/man/man.json,
  kernel/lib/bare/shell-completion.json, posix_utilities.json,
  docs/audit/bundle-health.json: regenerated or synced with tooling.
- scripts/bench-shell-phases.mjs: bench script touch.
2026-04-27 00:41:06 -04:00

46 lines
1.6 KiB
JavaScript

/**
* Shell tokenizer slice (diagnostics / trace); planner and executor use {@link ./shell-lex.js}.
*/
import { lexShellLine } from './shell-lex.js'
export function tokenizeBareShellLineForDiagnostics(line) {
const toks = tokenizeBareShellLineDetailed(line)
return toks.map((t) => ({ type: 'word', value: t.value }))
}
/**
* Structured token stream for diagnostics and grammar development.
* @param {string} line
* @returns {{ type: 'word', value: string, mode: 'normal'|'single'|'double'|'arith'|'heredoc'|'op', start: number, end: number }[]}
*/
export function tokenizeBareShellLineDetailed(line) {
const raw = lexShellLine(String(line || ''))
/** @type {{ type: 'word', value: string, mode: 'normal'|'single'|'double'|'arith'|'heredoc'|'op', start: number, end: number }[]} */
const out = []
for (const t of raw) {
const st = t.start ?? 0
const en = t.end ?? st
if (t.type === 'op') {
const v = t.value
let mode = /** @type {'normal'|'heredoc'} */ ('normal')
if (v === '<<' || v === '<<-' || v === '<<<') mode = 'heredoc'
out.push({ type: 'word', value: v, mode, start: st, end: en })
continue
}
const parts = t.parts || []
const joined = parts.map((p) => p.t).join('')
let mode = /** @type {'normal'|'single'|'double'|'arith'} */ ('normal')
if (parts.length === 1 && parts[0].q === 's') mode = 'single'
else if (parts.length === 1 && parts[0].q === 'd') mode = 'double'
if (/\$\(\(/.test(joined)) mode = 'arith'
out.push({
type: 'word',
value: t.value,
mode,
start: st,
end: en
})
}
return out
}