Conversation
added 16 commits
August 25, 2026 18:54
Introduces brush_core::args with the contract 'words -> T or ArgsError': builtins will consume only this trait while argument-parsing engines provide implementations. ArgsError distinguishes usage failures from help/version requests. Includes a transitional blanket implementation (clap::Parser types satisfy FromArgs automatically) so existing builtins keep working unchanged during migration; it is removed once migration completes. Assisted-by: ox-alpha (opencode)
Replaces the clap::Parser supertrait on builtins::Command with the new brush_core::args::FromArgs contract, and neutralizes Command::new's error type to ArgsError (usage failure vs help request). Transitional scaffolding, all removable per-builtin as migration proceeds: - blanket impl: clap-derived types satisfy FromArgs unchanged - clap_content helper + one-line get_content impls preserve current help rendering from clap metadata - the four builtins overriding new() (echo/getopts/set/test) keep their '--' workaround via try_parse_known Behavior is unchanged; compat suite: 1854 passed / 0 failed. Assisted-by: ox-alpha (opencode)
echo becomes the reference for the converted shape: - echo.rs holds only the plain argument struct and execute logic; no engine types or derives - args/clap.rs (per-engine module) owns word binding via FromArgs and the mirror type carrying option/help metadata, preserving current output byte-for-byte including the '--' workaround - other engines add their own module (args/bpaf.rs, args/usage.rs) implementing the same FromArgs impls Compat suite: 1854 passed / 0 failed. Assisted-by: ox-alpha (opencode)
… types Per review feedback: instead of mirror structs + conversions, builtin argument structs carry the selected engine's instrumentation directly via cfg_attr, and the parser-clap/parser-bpaf/parser-usage feature trio (exactly-one guard included) selects which set compiles. Consequence: with clap selected, existing derives already satisfy the FromArgs contract through the blanket impl — no per-builtin binding code remains for simple builtins. Only genuine shell quirks (echo's '--' workaround) keep engine-specific overrides, now feature-gated. Help rendering stays on the transitional clap_content path, gated per engine until brush grows its own help model. Selecting an engine without bindings (e.g. parser-bpaf today) fails the build loudly, listing the builtins still lacking support. Assisted-by: ox-alpha (opencode)
Adopts the reviewed layout: each builtin keeps its logic in {builtin}.rs
and its engine-specific instrumented structs (plus any impls) in sibling
{builtin}/{clap,bpaf,usage}.rs files. A small arg_impl!(TheType) macro
declares the engine-gated sibling modules and re-exports the selected
engine's type, so builtin code and factory registrations stay
engine-agnostic.
With clap selected, blanket FromArgs covers plain derives; only shell
quirks (echo's '--' handling) live as overrides inside the engine file.
Other engines will provide their own struct instrumentation and quirk
handling in their own files.
Assisted-by: ox-alpha (opencode)
Completes the bulk migration to the reviewed layout: each builtin's
logic lives in {builtin}.rs with only pure command behavior, while the
engine-instrumented argument struct, trait impls, and any shell-quirk
overrides live in {builtin}/clap.rs behind parser-clap. arg_impl!
selects the module set and re-exports the type so factory registrations
stay unchanged.
Notable non-mechanical cases:
- declare/export/set/umask: clap-flag helper structs generated by
macros (minus_or_plus_flag_arg etc.) move into the engine module
- bind/complete/unset: shared arg types referenced from logic gain
explicit cross-module imports; fields exposed pub(super)
- exec/popd/pushd: cross-builtin invocation switches to UFCS
builtins::Command::execute
- history/bind: unit tests follow their execute implementations
SimpleCommand-style builtins (colon/true/false) have no arguments and
remain single-file.
Compat suite: 1854 passed / 0 failed. Workspace clippy/fmt clean.
(interactive suspend test failure is pre-existing on main)
Assisted-by: ox-alpha (opencode)
Infrastructure complete: args support module (BpafArgs trait, runner, splitter, help rendering), optional bpaf dep wired to parser-bpaf, generated modules for 45 structurally-matching builtins plus hand-written cd/pwd/getopts/set adapters. Remaining known issues tracked for next session: complete/bpaf needs FromStr impls + inherent parser impl placement; bind BindError unification; cd mode mapping; set named_option_section construction; assorted import pruning under the bpaf-only feature set. Assisted-by: ox-alpha (opencode)
Resolves the remaining engine-module issues: declaration-command impls transplanted for export/declare/builtin_, tri-state flag structs for the set/declare families via minus_or_plus_flag_bpaf, FromStr for BindKeyMap, per-file import repairs, and cfg-gating of bpaf-only helpers so the clap-default build stays clean. Both cargo configurations now compile: default (parser-clap) and parser-bpaf with all builtin features. Assisted-by: ox-alpha (opencode)
…t green
Ports experiment/usage-parser's #[derive(usage::Cli)] instrumentation
into per-engine {builtin}/usage.rs modules behind parser-usage:
- args/usage_support.rs: UsageArgs trait + impl_usage_parse! macro +
runner + splitter + help rendering (ported from that branch's core)
- generated modules harvest struct instrumentation from the branch
- declaration builtins carry DeclarationCommand impls
Remaining known issues (~45 errors, all mechanical): missing helper-type
imports (declare/set flag structs via minus_or_plus_flag_bpaf, bind
types from clap sibling, complete CommonCompleteCommandArgs placement),
duplicate builtins imports, exit String/i64 set_trailing_args leftover,
read OpenFile::read trait import, unset shape alignment.
Assisted-by: ox-alpha (opencode)
…ors left - ports experiment/usage-parser's 4-arg minus_or_plus_flag_arg macro (usage::Args derive) as usage_minus_or_plus_flag_arg!, wired into set/declare usage modules with accumulated -o/+o SetOption fixes - args/usage_support: correct 6.1.1 error/help rendering - builtin modules exposed pub(crate) so engine modules can reach shared helper types; import dedup across generated files Remaining 9 errors documented in /tmp capture: complete CommonArgs placement + duplicates, bind enum copies, command duplicate inherent, factory bounds following from those. Assisted-by: ox-alpha (opencode)
Assisted-by: ox-alpha (opencode)
Remaining errors are concentrated in three files: bind/usage.rs (BindKeyMap needs usage ValueEnum derive + BindError ownership), command/usage.rs (duplicate inherent 'command' fn), complete/usage.rs (CommonCompleteCommandArgs + CompGen/CompOpt definitions). Fix pattern is proven from unset: shared types move to the parent module pub(crate), engines import them. Assisted-by: ox-alpha (opencode)
- command.rs: cross-builtin .command() helper restored in each engine module; stale renamed method removed from parent - complete/usage.rs: CommonCompleteCommandArgs struct + CompGen/CompOpt definitions added with usage::Cli derives parser-usage still has ~15 architectural errors (ValueEnum impls needed for core types, derive-macro-vs-trait confusion in spec() calls) that require design decisions about type ownership across engines. Assisted-by: ox-alpha (opencode)
Completes the usage-rs engine port: - completion.rs types instrumented via cfg_attr per parser feature (no standalone modules needed — cfg_attr suffices for type-level derives) - brush-core gains parser-clap/bpaf/usage features with optional deps, forwarding from brush-builtins - clap-only code paths in core gated behind parser-clap - bind/usage.rs: BindKeyMap with usage::ValueEnum derive + variant attrs - command/usage.rs: fields pub(crate) for cross-builtin access; inherent helper renamed first_arg to avoid derive collision - complete/usage.rs: CommonCompleteCommandArgs + CompGen/CompOpt with usage::Cli derives, execute bodies transplanted from experiment branch All three configurations build with zero errors: cargo check -p brush-builtins # parser-clap cargo check -p brush-builtins --no-default-features --features parser-bpaf,$FEATS # parser-bpaf cargo check -p brush-builtins --no-default-features --features parser-usage,$FEATS # parser-usage Assisted-by: ox-alpha (opencode)
Assisted-by: ox-alpha (opencode)
Public API changes for crate: brush-coreAdded itemsChanged itemsPerformance Benchmark Report
Code Coverage Report: Only Changed Files listed
Minimum allowed coverage is |
Contributor
Author
|
Closing — premature. Will reopen once all three engine configurations build green. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Decouples builtin argument parsing from the underlying parsing engine. Each builtin declares its arguments as a plain struct; per-engine modules provide the instrumentation. A cargo feature selects which engine compiles — downstream enables exactly one.
Architecture
arg_impl!(TheType)macro in lib.rs: declares gated sibling modules, re-exports selected typebrush_core::args::FromArgs: engine-neutral contract (words → T or ArgsError)compile_error!guardEngines
parser-clap(default)parser-bpafparser-usageBenchmark (config-lint.sh, 30 runs)
The contract layer adds no measurable overhead vs each native implementation.
What's included
FromArgstrait inbrush_core::args{builtin}.rs+{builtin}/clap.rslayoutcfg_attr-based type instrumentation for core types (completion.rs)What needs work
clap_contentshim)Design notes for review
arg_impl!macro: expands to cfg-gatedmod clap/bpaf/usagedeclarations plus an internalimpnamespace re-exporting whichever compiled. Factory registrations stay unchanged.impl<T: clap::Parser> FromArgs for Tcovers unconverted builtins; removed once migration completes.clap_content::<T>shim: renders help from clap metadata for converted builtins until brush grows its own engine-neutral help model.#[expect(dead_code)]markers: on transplanted helpers awaiting full wiring.Closes #1302 (supersedes as multi-engine approach).
Assisted-by: ox-alpha (opencode)