refactor(cli)!: split the contributor tool out of the ludic CLI
`ludic help` ended with a section titled "contributing to the toolchain itself", listing bootstrap, reseed, docs-gen and release tasks. None of that is available to someone who installed the language — those tasks need the repository — so the shipped tool was advertising work its user cannot do, in a namespace they have to read past to find `new` and `run`. The tasks move to a second program, dev.ludic -> bin/ludic-dev, built from a checkout and excluded from every release artifact. `ludic` keeps the project and package commands and nothing else; `ludic dev …` now explains where the tasks went instead of failing as an unknown command. What this shook out: the two programs share prelude/build/project/pkg, so the helpers each had accreted in whichever file first needed them — cc(), ensure_ludicc, the string functions, title_case, cmd_version — moved to where both can see them. The argument-shift indirection added for the `dev` namespace is gone with the namespace, so commands read argv directly again. `ludic-dev test` asserts the split rather than trusting it: the staged install must build a project, and `ludic dev build` there must fail while naming ludic-dev. install.sh keeps building older tags, whose bootstrap goes through main.ludic. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
f369fbd227
commit
e175619543
46 changed files with 630 additions and 558 deletions
|
|
@ -1,17 +1,17 @@
|
|||
# docgen.ludic — the Ludic documentation-site generator and its guards, ported
|
||||
# off Python (gen.py / check.py / palette.py). Three x subcommands:
|
||||
#
|
||||
# ludic dev docs-palette emit selfhost/backend/stdlib/emit_color.ludic +
|
||||
# ludic-dev docs-palette emit selfhost/backend/stdlib/emit_color.ludic +
|
||||
# docs/language/colors/palette.json from the palette
|
||||
# table below (the named-colour source of truth).
|
||||
# ludic dev docs-gen [--out DIR] parse docs/language/** + docs/site/*, read the asset
|
||||
# ludic-dev docs-gen [--out DIR] parse docs/language/** + docs/site/*, read the asset
|
||||
# templates, emit every page + symbols.json + the
|
||||
# highlighter + .nojekyll into DIR (default build/pages).
|
||||
# ludic dev docs-check [DIR] the coverage/integrity guard over a generated site.
|
||||
# ludic-dev docs-check [DIR] the coverage/integrity guard over a generated site.
|
||||
#
|
||||
# String work is over NUL-terminated byte buffers; helpers here mirror gen.py's
|
||||
# html.escape / json.dumps / front-matter parsing closely enough to reproduce the
|
||||
# Python generator's output byte-for-byte (verified against the oracle in ludic dev test).
|
||||
# Python generator's output byte-for-byte (verified against the oracle in ludic-dev test).
|
||||
|
||||
# ---- a growable byte buffer (avoids O(n^2) string building) ------------------
|
||||
property Sb { data: pointer = null, len: int = 0, cap: int = 0 }
|
||||
|
|
@ -87,40 +87,6 @@ function lstrip_nl(s: pointer) -> pointer {
|
|||
while s[i] == '\n' { i += 1 }
|
||||
return sslice(s, i, slen(s))
|
||||
}
|
||||
# lowercase ASCII A-Z
|
||||
function lower_ascii(s: pointer) -> pointer {
|
||||
let n = slen(s)
|
||||
let b = bytes(n + 1)
|
||||
var i = 0
|
||||
while i < n {
|
||||
var c = s[i]
|
||||
if c >= 'A' and c <= 'Z' { c += 32 }
|
||||
b[i] = c
|
||||
i += 1
|
||||
}
|
||||
b[n] = 0
|
||||
return b
|
||||
}
|
||||
# Python str.title(): capitalise the first letter of each alpha run, lower the rest
|
||||
function title_case(s: pointer) -> pointer {
|
||||
let n = slen(s)
|
||||
let b = bytes(n + 1)
|
||||
var i = 0
|
||||
var prev_alpha = false
|
||||
while i < n {
|
||||
var c = s[i]
|
||||
let al = (c >= 'A' and c <= 'Z') or (c >= 'a' and c <= 'z')
|
||||
if al {
|
||||
if prev_alpha { if c >= 'A' and c <= 'Z' { c += 32 } }
|
||||
else { if c >= 'a' and c <= 'z' { c -= 32 } }
|
||||
}
|
||||
b[i] = c
|
||||
prev_alpha = al
|
||||
i += 1
|
||||
}
|
||||
b[n] = 0
|
||||
return b
|
||||
}
|
||||
# lexicographic byte compare: <0, 0, >0
|
||||
function str_cmp(a: pointer, b: pointer) -> int {
|
||||
var i = 0
|
||||
|
|
@ -563,7 +529,7 @@ function palette_emit_ludic(path: pointer) -> bool {
|
|||
sb_puts(b, "# no allocation, identical codegen to writing the hex by hand. Unknown names are\n")
|
||||
sb_puts(b, "# a compile error (color_lookup returns -1, which emit_expr reports).\n")
|
||||
sb_puts(b, "#\n")
|
||||
sb_puts(b, "# GENERATED by `ludic dev docs-palette` from the single source-of-truth palette table\n")
|
||||
sb_puts(b, "# GENERATED by `ludic-dev docs-palette` from the single source-of-truth palette table\n")
|
||||
sb_puts(b, "# in tools/ludic-cli/docgen.ludic. Edit the palette there and regenerate; do not hand-edit.\n")
|
||||
sb_puts(b, "# ============================================================================\n")
|
||||
sb_puts(b, "\n")
|
||||
|
|
@ -620,11 +586,11 @@ function palette_emit_json(path: pointer) -> bool {
|
|||
return write_file(path, sb_str(b))
|
||||
}
|
||||
|
||||
# `ludic dev docs-palette` rewrites the two tracked outputs; `ludic dev docs-palette --check`
|
||||
# `ludic-dev docs-palette` rewrites the two tracked outputs; `ludic-dev docs-palette --check`
|
||||
# regenerates into scratch files and compares them to the tracked ones instead,
|
||||
# so the drift guard judges the working tree, not git HEAD.
|
||||
function cmd_docs_palette() -> int {
|
||||
let check = arg_total() > 2 and arg_n(2) == "--check"
|
||||
let check = arg_count() > 2 and arg(2) == "--check"
|
||||
palette_init()
|
||||
# guard: duplicate names
|
||||
let seen = new []pointer
|
||||
|
|
@ -640,8 +606,8 @@ function cmd_docs_palette() -> int {
|
|||
if not palette_emit_ludic(ludic_out) { err("cannot write emit_color.ludic\n"); return 1 }
|
||||
if not palette_emit_json(json_out) { err("cannot write palette.json\n"); return 1 }
|
||||
if check {
|
||||
if not shq(`cmp -s {ludic_out} selfhost/backend/stdlib/emit_color.ludic`) { err("emit_color.ludic drifted from the palette table (run: ludic dev docs-palette)\n"); return 1 }
|
||||
if not shq(`cmp -s {json_out} docs/language/colors/palette.json`) { err("palette.json drifted from the palette table (run: ludic dev docs-palette)\n"); return 1 }
|
||||
if not shq(`cmp -s {ludic_out} selfhost/backend/stdlib/emit_color.ludic`) { err("emit_color.ludic drifted from the palette table (run: ludic-dev docs-palette)\n"); return 1 }
|
||||
if not shq(`cmp -s {json_out} docs/language/colors/palette.json`) { err("palette.json drifted from the palette table (run: ludic-dev docs-palette)\n"); return 1 }
|
||||
}
|
||||
print(`OK {string(len(pal_names))} colors`)
|
||||
return 0
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue