Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 22 additions & 6 deletions PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -665,13 +665,25 @@ feature list is not an exhaustive audit.
or a flattened Args wrapper; their targeted diagnostic explains the named
`#[usage(flatten)]` rewrite instead of reporting a generic unsupported
shape. Facade tests exercise unit roots and nested unit Args commands.
- [ ] **Relationships through flatten and positional IDs.** Positional
- [x] **Post-binding relationships through flatten and positional IDs.** Positional
relationships are already a general gap above. The fleet exposed the
second half: a field cannot name a flag contributed by a flattened Args
type because validation runs against the declaring struct before the
command is assembled. aube lost statically declared relationships and hk
and fnox needed runtime conflict checks. Validate selectors against the
composed command and carry stable IDs for both flags and positionals.
and fnox needed runtime conflict checks. Derived `CommandArgs` now expose
selector-stable presence and value lookup across flattened boundaries, so
parent conflicts, requirements, conditional requirements/defaults, and
required-if/unless rules resolve against the composed command without a
dynamic command graph or allocation. Flags use every accepted spelling and
positionals use their stable field identity. Binding-time `overrides` remains
a separate gap below and is rejected when it names a flattened field rather
than compiling into a no-op.
- [ ] **Binding-time overrides across flatten boundaries.** `overrides` is
last-token-wins and therefore cannot be implemented by the post-binding
presence/value lookup used for conflicts and requirements. Add a composed
displacement hook that can reset an opaque flattened partial, preserve the
losing field's default/env suppression, and handle either token order before
allowing a parent selector to name a flattened target.
- [ ] **Flattened help topology.** clap's `next_help_heading` and flattened flag
groups preserve meaningful sections in aube's long help. usage flattens the
fields but discards that struct-level heading, so a migration can preserve
Expand Down Expand Up @@ -1170,9 +1182,13 @@ repeated here.
subcommand variant selects the shared `CommandArgs` table independently.
The same facade regression covers the fnox full-command shape; mise's
flattened `ConfigLs` reuse remains covered by the fleet shadow.
- [ ] **Relationships across a flatten boundary.** A flag in the parent
conflicting with a flag in the flattened group has no spelling; hk and
aube both hit it and enforce post-bind by hand.
- [x] **Post-binding relationships across a flatten boundary.** A parent flag can name a flag
or positional contributed by a flattened group. The nested partial answers
selector lookup through `CommandArgs`, preserving the same argv/env/default
presence semantics as relationships declared inside one struct. hk and aube
can remove their post-bind conflict checks when repinned to this stack tip.
Binding-time `overrides` is tracked separately and rejected across the
boundary until composed displacement exists.
- [x] **Checked-in specs vs release automation.** `SpecView::omit_version()`
removes the runtime version from a cold emitted metadata view without
changing the base derived spec or built-in `--version` behavior. tak uses
Expand Down
28 changes: 28 additions & 0 deletions argv/src/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2112,6 +2112,17 @@ pub const fn concat_bindings<const N: usize>(
joined
}

/// Presence information exposed across a flattened [`CommandArgs`] boundary.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ArgumentState {
/// The canonical name used in diagnostics.
pub name: &'static str,
/// Whether argv or an environment fallback supplied the argument.
pub given: bool,
/// Whether the argument is satisfied, including an unconditional default.
pub satisfied: bool,
}

pub trait CommandArgs: Sized {
/// Values collected so far. Partly-filled by construction, since a parse can
/// stop early.
Expand Down Expand Up @@ -2182,6 +2193,23 @@ pub trait CommandArgs: Sized {
None
}

/// Find an argument by any selector it accepts.
///
/// Parents use this to enforce a relationship declared beside a flattened
/// argument group. The default keeps hand-written implementations source compatible.
fn argument_state(partial: &Self::Partial, selector: &str) -> Option<ArgumentState> {
let _ = (partial, selector);
None
}

/// Whether a selected argument has an explicitly supplied value.
///
/// This is the value-aware half needed by conditional defaults and requirements.
fn argument_matches(partial: &Self::Partial, selector: &str, value: &[u8]) -> Option<bool> {
let _ = (partial, selector, value);
None
}

/// Fill fields in this command from their declared defaults.
///
/// Kept separate from [`CommandArgs::check`] so a parent can preserve defaults in a
Expand Down
Loading
Loading