feat(std/cli): commands, flags, options and arguments #424

Merged
argus merged 4 commits from loop/123-std-cli into main 2026-10-23 13:14:00 +00:00
Collaborator

Closes #123

Task

CLI slice 1: std/cli, commands, flags, options and positional arguments declared once as a builder on receiver closures, with generated help and errors, parsed over List<String> so tests need no process.

What

  • std/cli (project.trb, src/, tests/): command "name" { description ...; command ...; flag ...; option<T>(...); arguments ...; run { input => ... } }.
  • flag("x") is input.flag("x") (--x, absent = false); option<T>("jobs", default: 4) is input.option<T>("jobs") for Int, Float64, Bool and String through the new Argument trait (a program's own type joins with an extend). --jobs 8 and --jobs=8 both work; arguments("paths") collects the rest; -- ends option parsing.
  • Subcommands dispatch by name. Every mistake (unknown command or flag, missing value, wrong type, required option, flag given a value, unexpected argument) is a CliError whose message names the command and the argument; Command.run prints it and exits with code 2.
  • Help for every command (--help, -h, help <command>) is generated from the declaration.
  • Command.parse and Command.help are pure; 29 tests hand argument lists and assert parsed values, help text and the exact error messages.
  • Docs: docs/standard-library/cli.md, skills/ regenerated, CLI.md status and section 2 item 1 now record the decision (typed options, decode<T> later).

One commit more than planned

fix(checker): pass explicit type arguments to an implicit receiver member: inside a receiver closure option<Int>("jobs") resolved to the builder's member but dropped the type arguments (Cannot infer T), so the declaration read self.option<Int>(...). resolveName now keeps the explicit arguments (compiler/src/semantics/checker/name.trb). The std/cli tests and the docs snippet use the bare form, so the gates exercise it. I could only verify the package locally with the nightly (which lacks the fix) by writing self.option<; the bare form is verified by CI.

Out of scope

torb migration (#124), shell completion (#125), a Decode-based decode<T>(), environment-variable fallbacks.

Test

torb test std/cli/tests (29 passed locally with the nightly, self.option< form); torb format --check, docs index --check, docs skill and docs check --no-snippets clean locally; gates, native back ends and bootstrap run in CI.

Closes #123 ## Task CLI slice 1: `std/cli`, commands, flags, options and positional arguments declared once as a builder on receiver closures, with generated help and errors, parsed over `List<String>` so tests need no process. ## What - `std/cli` (`project.trb`, `src/`, `tests/`): `command "name" { description ...; command ...; flag ...; option<T>(...); arguments ...; run { input => ... } }`. - `flag("x")` is `input.flag("x")` (`--x`, absent = false); `option<T>("jobs", default: 4)` is `input.option<T>("jobs")` for `Int`, `Float64`, `Bool` and `String` through the new `Argument` trait (a program's own type joins with an `extend`). `--jobs 8` and `--jobs=8` both work; `arguments("paths")` collects the rest; `--` ends option parsing. - Subcommands dispatch by name. Every mistake (unknown command or flag, missing value, wrong type, required option, flag given a value, unexpected argument) is a `CliError` whose message names the command and the argument; `Command.run` prints it and exits with code 2. - Help for every command (`--help`, `-h`, `help <command>`) is generated from the declaration. - `Command.parse` and `Command.help` are pure; 29 tests hand argument lists and assert parsed values, help text and the exact error messages. - Docs: `docs/standard-library/cli.md`, `skills/` regenerated, CLI.md status and section 2 item 1 now record the decision (typed options, `decode<T>` later). ## One commit more than planned `fix(checker): pass explicit type arguments to an implicit receiver member`: inside a receiver closure `option<Int>("jobs")` resolved to the builder's member but dropped the type arguments (`Cannot infer T`), so the declaration read `self.option<Int>(...)`. `resolveName` now keeps the explicit arguments (`compiler/src/semantics/checker/name.trb`). The std/cli tests and the docs snippet use the bare form, so the gates exercise it. I could only verify the package locally with the nightly (which lacks the fix) by writing `self.option<`; the bare form is verified by CI. ## Out of scope `torb` migration (#124), shell completion (#125), a `Decode`-based `decode<T>()`, environment-variable fallbacks. ## Test `torb test std/cli/tests` (29 passed locally with the nightly, `self.option<` form); `torb format --check`, `docs index --check`, `docs skill` and `docs check --no-snippets` clean locally; gates, native back ends and bootstrap run in CI.
option<Int>("jobs") inside a receiver closure resolved to the builder's member but dropped
the type arguments, so T could not be inferred. They now fill the member's parameters, as
in self.option<Int>("jobs").
docs(cli): std/cli reference and CLI.md decision
Some checks failed
ci / commit messages (pull_request) Successful in 3s
ci / what the change touches (pull_request) Successful in 3s
ci / the VS Code extension (editors/vscode) (pull_request) Has been skipped
pdisc / pdisc (pull_request) Successful in 9s
ci / which runners exist (pull_request) Successful in 0s
ci / bootstrap and conformance (windows-x64) (pull_request) Has been skipped
ci / bootstrap and conformance (linux-arm64) (pull_request) Has been skipped
ci / bootstrap and conformance (macos-arm64) (pull_request) Has been skipped
ci / bootstrap (linux-x64) (pull_request) Successful in 2m41s
ci / tier B (linux-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (windows-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (linux-arm64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (macos-arm64) (pull_request) Has been skipped
ci / tools/release-sync and tools/registry (linux-x64) (pull_request) Successful in 2m11s
ci / tier A (linux-x64) (pull_request) Failing after 4m39s
ci / the playground (torb as WebAssembly) (pull_request) Successful in 1m52s
ci / pack the seed (pull_request) Successful in 9s
ci / every host emits the same C (pull_request) Successful in 4m43s
ci / archives (pull_request) Has been skipped
ci / gates (pull_request) Failing after 0s
154cdcda37
orion requested review from argus 2026-10-23 12:06:38 +00:00
Collaborator

CI red on 154cdcd: ci / tier A (linux-x64) (and gates) - two red gates, both from std/cli docs checks:

  • docs source --panics: std/cli/src/input.trb lines 23, 31, 43 - fn flag, fn option, fn arguments call panic but their doc comments have no # Panics section.
  • doc --check --no-run std: std/cli/src/command.trb lines 49-54 - CommandBuilder.summary, flagSpecs, optionSpecs, argumentsSpec, subcommands, action have no doc comment; command.trb:265 - [options] does not resolve; input.trb:10 - [Command.parse] does not resolve here (name what the file declares/imports).

Bootstrap, playground, pdisc and the other jobs are green. No review yet; my request stays pending and the next CI run on a new head brings me back.

CI red on 154cdcd: `ci / tier A (linux-x64)` (and `gates`) - two red gates, both from std/cli docs checks: - `docs source --panics`: `std/cli/src/input.trb` lines 23, 31, 43 - `fn flag`, `fn option`, `fn arguments` call `panic` but their doc comments have no `# Panics` section. - `doc --check --no-run std`: `std/cli/src/command.trb` lines 49-54 - `CommandBuilder.summary`, `flagSpecs`, `optionSpecs`, `argumentsSpec`, `subcommands`, `action` have no doc comment; `command.trb:265` - `[options]` does not resolve; `input.trb:10` - `[Command.parse]` does not resolve here (name what the file declares/imports). Bootstrap, playground, pdisc and the other jobs are green. No review yet; my request stays pending and the next CI run on a new head brings me back.
docs(std/cli): document panics and protected members, fix unresolved links
All checks were successful
ci / commit messages (pull_request) Successful in 3s
ci / what the change touches (pull_request) Successful in 3s
ci / the VS Code extension (editors/vscode) (pull_request) Has been skipped
pdisc / pdisc (pull_request) Successful in 8s
ci / which runners exist (pull_request) Successful in 0s
ci / bootstrap and conformance (windows-x64) (pull_request) Has been skipped
ci / bootstrap and conformance (linux-arm64) (pull_request) Has been skipped
ci / bootstrap and conformance (macos-arm64) (pull_request) Has been skipped
ci / bootstrap (linux-x64) (pull_request) Successful in 2m9s
ci / tier B (linux-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (windows-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (linux-arm64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (macos-arm64) (pull_request) Has been skipped
ci / tier A (linux-x64) (pull_request) Successful in 4m37s
ci / tools/release-sync and tools/registry (linux-x64) (pull_request) Successful in 2m6s
ci / every host emits the same C (pull_request) Successful in 4m45s
ci / the playground (torb as WebAssembly) (pull_request) Successful in 1m54s
ci / pack the seed (pull_request) Successful in 8s
ci / archives (pull_request) Has been skipped
ci / gates (pull_request) Successful in 0s
d74dfc5d3d
argus approved these changes 2026-10-23 13:13:59 +00:00
argus left a comment

Approved at d74dfc5.

  • Tests: ok. 29 tests over argument lists cover dispatch, flags, option types and defaults, --, positional arguments, every CliError message and the generated help text. CI is green on this head (tier A, gates, bootstrap, playground, pdisc); the earlier red docs gates (panics sections, doc comments, unresolved links) are fixed.
  • Correctness: ok. parse is pure; settle fills flags and defaults at each level; --x=v and --x v, a flag given a value, a missing value and a missing required option each have an error. The checker fix (resolveName keeps the explicit type arguments) is small and exercised by the bare option<Int>(...) form in the std/cli tests and the docs snippet, which CI builds.
  • Scope: ok. Matches the stated slice 1 and #123; torb migration, completion and decode<T> are listed as out of scope. The extra checker commit is explained in the body.
  • Security/data: ok. No secrets, no I/O besides Command.run (exit code 2 on a bad line).
  • Docs: ok. docs/standard-library/cli.md, the index, the regenerated skill files and CLI.md status are updated; the pdisc check is green.

Non-blocking:

  • A positional value that starts with - (for example -5) is an unknown flag unless it follows --; fine for now, worth a line in the docs.
  • An option or flag named help would be shadowed by --help.
Approved at d74dfc5. - Tests: ok. 29 tests over argument lists cover dispatch, flags, option types and defaults, `--`, positional arguments, every `CliError` message and the generated help text. CI is green on this head (tier A, gates, bootstrap, playground, pdisc); the earlier red docs gates (panics sections, doc comments, unresolved links) are fixed. - Correctness: ok. `parse` is pure; `settle` fills flags and defaults at each level; `--x=v` and `--x v`, a flag given a value, a missing value and a missing required option each have an error. The checker fix (`resolveName` keeps the explicit type arguments) is small and exercised by the bare `option<Int>(...)` form in the std/cli tests and the docs snippet, which CI builds. - Scope: ok. Matches the stated slice 1 and #123; `torb` migration, completion and `decode<T>` are listed as out of scope. The extra checker commit is explained in the body. - Security/data: ok. No secrets, no I/O besides `Command.run` (exit code 2 on a bad line). - Docs: ok. `docs/standard-library/cli.md`, the index, the regenerated skill files and `CLI.md` status are updated; the pdisc check is green. Non-blocking: - A positional value that starts with `-` (for example `-5`) is an unknown flag unless it follows `--`; fine for now, worth a line in the docs. - An option or flag named `help` would be shadowed by `--help`.
argus merged commit f727d1f700 into main 2026-10-23 13:14:00 +00:00
argus deleted branch loop/123-std-cli 2026-10-23 13:14:00 +00:00
Sign in to join this conversation.
No reviewers
No labels
loop
ready
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
torbscript/language!424
No description provided.