/** Plain-text manual formatter (prepended before src/man.js; no import in /bin/man). */ function bareManParseWidth(env) { const raw = env && env.MANWIDTH != null ? String(env.MANWIDTH).trim() : '' const n = raw ? Number.parseInt(raw, 10) : 72 if (!Number.isFinite(n)) return 72 return Math.max(40, Math.min(n, 200)) } function bareManUseAnsi(ctx) { const env = ctx.env || {} if (env.NO_COLOR != null && String(env.NO_COLOR) !== '') return false const out = ctx.stdout return Boolean(out && out.isTTY) } function bareManBold(s, on) { if (!on) return s return '\x1b[1m' + s + '\x1b[0m' } function bareManWrap(text, width) { const words = String(text).replace(/\s+/g, ' ').trim().split(' ') const lines = [] let cur = '' for (const w of words) { const next = cur ? cur + ' ' + w : w if (next.length <= width) cur = next else { if (cur) lines.push(cur) cur = w.length > width ? w.slice(0, width) : w while (cur.length > width) { lines.push(cur.slice(0, width)) cur = cur.slice(width) } } } if (cur) lines.push(cur) return lines } /** Indent fixed-width command lines; hard-wrap only when longer than width. */ function bareManRenderExampleCode(code, width) { const indent = ' ' const max = Math.max(20, width - indent.length) const out = [] for (const line of String(code).split('\n')) { if (line.length <= max) { out.push(indent + line) continue } let rest = line while (rest.length > max) { out.push(indent + rest.slice(0, max)) rest = rest.slice(max) } if (rest) out.push(indent + rest) } return out.join('\n') } /** Keep newlines; hard-wrap long lines only (for handbook / preformatted text). */ function bareManRenderPreserve(text, width) { const indent = ' ' const max = Math.max(20, width - indent.length) const out = [] for (const line of String(text).split('\n')) { if (line === '') { out.push('') continue } let rest = line while (rest.length > max) { out.push(indent + rest.slice(0, max)) rest = rest.slice(max) } out.push(indent + rest) } return out.join('\n') + '\n' } function bareManFlushBlock(lines, width, prefixFirst, prefixRest) { const out = [] let first = true for (const line of lines) { const wrapped = bareManWrap(line, width - (first ? prefixFirst.length : prefixRest.length)) for (let i = 0; i < wrapped.length; i++) { const p = i === 0 && first ? prefixFirst : prefixRest out.push(p + wrapped[i]) first = false } } return out.join('\n') + '\n' } function bareManRenderPage(page, ctx, width) { const ansi = bareManUseAnsi(ctx) const H = (s) => bareManBold(s, ansi) + '\n' let s = '' s += H('NAME') s += page.name + '(' + page.section + ') - ' + page.title + '\n\n' s += H('SYNOPSIS') for (const line of page.synopsis) { s += ' ' + line + '\n' } s += '\n' s += H('DESCRIPTION') if (page.descriptionMode === 'preserve') { s += bareManRenderPreserve(page.description, width) } else { s += bareManFlushBlock([page.description], width, '', ' ') } if (page.options && page.options.length) { s += '\n' + H('OPTIONS') for (const o of page.options) { const head = o.flag + '\t' const rest = o.meaning s += bareManFlushBlock([rest], width, ' ' + head, ' ') } } if (page.examples && page.examples.length) { s += '\n' + H('EXAMPLES') s += bareManFlushBlock( [ 'tl;dr-style snippets (like cheat.sh). Copy, adapt paths; pipelines are shell-simulated on Bare OS.' ], width, '', ' ' ) + '\n' for (const ex of page.examples) { if (ex.caption) { s += bareManFlushBlock( ['# ' + ex.caption], width, '', ' ' ) + '\n' } s += bareManRenderExampleCode(ex.code, width) + '\n\n' } } if (page.environment && page.environment.length) { s += '\n' + H('ENVIRONMENT') for (const e of page.environment) s += ' ' + e + '\n' } if (page.files && page.files.length) { s += '\n' + H('FILES') for (const f of page.files) s += ' ' + f + '\n' } if (page.exitStatus && page.exitStatus.length) { s += '\n' + H('EXIT STATUS') for (const e of page.exitStatus) s += ' ' + e + '\n' } if (page.diagnostics && page.diagnostics.length) { s += '\n' + H('DIAGNOSTICS') for (const d of page.diagnostics) s += ' ' + d + '\n' } if (page.builtins && page.builtins.length) { s += '\n' + H('SHELL BUILTINS') for (const b of page.builtins) { s += '\n' + bareManBold(b.name, ansi) + '\n' if (b.synopsis && b.synopsis.length) { for (const line of b.synopsis) s += ' ' + line + '\n' } s += bareManFlushBlock([b.description], width, ' ', ' ') if (b.options && b.options.length) { for (const o of b.options) { const head = o.flag + '\t' s += bareManFlushBlock([o.meaning], width, ' ' + head, ' ') } } if (b.examples && b.examples.length) { s += '\n' + bareManBold(' Examples', ansi) + '\n' for (const ex of b.examples) { if (ex.caption) { s += bareManFlushBlock( ['# ' + ex.caption], width, ' ', ' ' ) + '\n' } s += bareManRenderExampleCode(ex.code, width) + '\n\n' } } } } if (page.bareOsNotes) { s += '\n' + H('BARE OS NOTES') s += bareManFlushBlock([page.bareOsNotes], width, '', ' ') } if (page.seeAlso && page.seeAlso.length) { s += '\n' + H('SEE ALSO') const parts = page.seeAlso.map((r) => r.name + '(' + r.section + ')') s += ' ' + parts.join(', ') + '\n' } if (page.stub) { s += '\n' + H('STATUS') s += ' This command is a stub or intentionally limited on Bare OS.\n' } return s }