#[non_exhaustive]pub struct ToolArgs {
pub positional: Vec<Value>,
pub named: BTreeMap<String, Value>,
pub flags: HashSet<String>,
pub words: Option<Vec<Value>>,
}Expand description
Parsed arguments ready for tool execution.
Fields (Non-exhaustive)§
This struct is marked as non-exhaustive
Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.positional: Vec<Value>Positional arguments in order.
named: BTreeMap<String, Value>Named arguments by key.
flags: HashSet<String>Boolean flags (e.g., -l, –force).
words: Option<Vec<Value>>Every word after the tool name, in source order, post-expansion —
Some only for an ArgBinding::Verbatim tool, None for every
other tool.
A text word arrives as Value::String; a heredoc- or pipe-bound word
keeps its Value::Bytes. positional and named are empty when this
is Some; flags holds only the global flags the binder lifted out
(today just json), so has_flag("json") still answers.
Render it to a clap argv with ToolArgs::words_argv.
Implementations§
Source§impl ToolArgs
impl ToolArgs
Sourcepub fn words_argv(&self) -> Vec<String>
pub fn words_argv(&self) -> Vec<String>
Render words into argv tokens for a verbatim tool’s
own parser. Empty when the tool is not verbatim.
A Value::Bytes word renders as an inert placeholder token, as
to_argv does for a binary positional; the real bytes
stay at the matching index in words.
Sourcepub fn get_positional(&self, index: usize) -> Option<&Value>
pub fn get_positional(&self, index: usize) -> Option<&Value>
Get a positional argument by index.
Sourcepub fn get(&self, name: &str, positional_index: usize) -> Option<&Value>
pub fn get(&self, name: &str, positional_index: usize) -> Option<&Value>
Get a named argument or positional fallback.
Useful for tools that accept both cat file.txt and cat path=file.txt.
Sourcepub fn get_string(&self, name: &str, positional_index: usize) -> Option<String>
pub fn get_string(&self, name: &str, positional_index: usize) -> Option<String>
Get a string value from args.
Sourcepub fn get_bool(&self, name: &str, positional_index: usize) -> Option<bool>
pub fn get_bool(&self, name: &str, positional_index: usize) -> Option<bool>
Get a boolean value from args.
Sourcepub fn has_flag(&self, name: &str) -> bool
pub fn has_flag(&self, name: &str) -> bool
Check if a flag is set (in flags set, or named bool).
Sourcepub fn flagify_bool_named(&mut self, schema: &ToolSchema)
pub fn flagify_bool_named(&mut self, schema: &ToolSchema)
Move bool entries from named into the appropriate set so a downstream
clap parser (with #[arg(...)] field: bool) accepts them.
Tests routinely seed args.named.insert(K, Value::Bool(true)) for the
schema-pre-clap path; to_argv() would emit those as --K=true, which
clap rejects for bool fields. Promote to:
Bool(true)→ presence inflags(clap sees--K).Bool(false)→ dropped (clap treats absent flag and explicit false the same; preserving it would only resurface as--K=falseand break the same parser).
A Value::Bool parked under a key the schema declares as a value-taking
flag is the flag’s literal value, not a bare bool flag — spawn --command true binds command = Bool(true). Those keys are left in named so
to_argv() renders --command=true and clap’s Option<String> field
accepts it; collapsing them to a bare --command drops the value and
makes clap error “a value is required”.
Idempotent. Non-bool named entries are left alone.
Sourcepub fn to_argv(&self) -> Result<Vec<String>, ToolArgvError>
pub fn to_argv(&self) -> Result<Vec<String>, ToolArgvError>
Reconstruct a clap-friendly argv vector from already-parsed ToolArgs.
kaish has already done shell parsing (variables expanded, globs expanded,
$(...) substituted, schema-driven flag/value splitting). to_argv
rebuilds a flat token stream suitable for Parser::parse_from(std::iter::once("<tool>").chain(args.to_argv()?)).
Layout: flags first (as --<name>), then named values (as
--<name>=<value>), then positionals — separated from earlier sections
by -- so trailing-passthrough builtins still see them as positionals
even if a value happens to begin with -.
§Errors
Returns ToolArgvError when a named/flag value is
Value::Bytes — binary can’t cross the argv/text stringification
boundary (GH #164, closing the root cause behind GH #120’s stringified
[binary: N bytes] placeholder). A positional Value::Bytes does
NOT error here; see value_to_argv_token’s doc comment for why.
See the clap builtin pattern in CLAUDE.md (Contributor conventions).
Equivalent to to_argv_excluding(&[]) —
same rendering path, nothing excluded.
Sourcepub fn to_argv_excluding(
&self,
exclude: &[&str],
) -> Result<Vec<String>, ToolArgvError>
pub fn to_argv_excluding( &self, exclude: &[&str], ) -> Result<Vec<String>, ToolArgvError>
Like to_argv, but skips the given named keys
entirely — neither the key’s flag token nor its value appears in the
rendered argv, and (crucially) a Value::Bytes under an excluded key
is never passed to render_named_value, so it can never trip
ToolArgvError::BinaryNamedValue.
Use this when a builtin deliberately reads one of its own named
parameters raw off ToolArgs (e.g. args.named.get("content"))
instead of the clap-parsed field, specifically to preserve a
typed/binary value that must not cross the argv/text stringification
boundary — while still wanting the rest of its arguments bound
through the normal clap path. write’s content param is the
motivating case (GH #218, a follow-up from the GH #164 / #215
review): before this helper, the builtin cloned the whole ToolArgs
and called named.remove("content") by hand, which silently stops
covering a second Bytes-capable named param the moment one is added.
Naming the excluded keys here instead makes the exemption a
greppable, drift-resistant idiom.
Only named keys are excludable — not flags or positionals, by
design. A bool flag carries no value to protect, so there is nothing
to exempt. A positional’s clap-reflected field is already a
validation-only sink nobody reads (see CLAUDE.md’s clap-builtin
convention), so a positional Value::Bytes never needed an
exemption in the first place — value_to_argv_token renders it as
an inert placeholder rather than erroring. If a future case needs to
exclude a flag or positional too, that is new design, not an
extension of this helper.
Trait Implementations§
Source§impl<'de> Deserialize<'de> for ToolArgs
impl<'de> Deserialize<'de> for ToolArgs
Source§fn deserialize<__D>(
__deserializer: __D,
) -> Result<ToolArgs, <__D as Deserializer<'de>>::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(
__deserializer: __D,
) -> Result<ToolArgs, <__D as Deserializer<'de>>::Error>where
__D: Deserializer<'de>,
Source§impl Serialize for ToolArgs
impl Serialize for ToolArgs
Source§fn serialize<__S>(
&self,
__serializer: __S,
) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>where
__S: Serializer,
fn serialize<__S>(
&self,
__serializer: __S,
) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>where
__S: Serializer,
Auto Trait Implementations§
impl Freeze for ToolArgs
impl RefUnwindSafe for ToolArgs
impl Send for ToolArgs
impl Sync for ToolArgs
impl Unpin for ToolArgs
impl UnsafeUnpin for ToolArgs
impl UnwindSafe for ToolArgs
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<T> FutureExt for T
impl<T> FutureExt for T
Source§fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
Source§fn with_current_context(self) -> WithContext<Self> ⓘ
fn with_current_context(self) -> WithContext<Self> ⓘ
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
impl<T> OrderedSeq<'_, T> for Twhere
T: Clone,
Source§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<'p, T> Seq<'p, T> for Twhere
T: Clone,
impl<'p, T> Seq<'p, T> for Twhere
T: Clone,
Source§impl<T, S> SpanWrap<S> for Twhere
S: WrappingSpan<T>,
impl<T, S> SpanWrap<S> for Twhere
S: WrappingSpan<T>,
Source§fn with_span(self, span: S) -> <S as WrappingSpan<Self>>::Spanned
fn with_span(self, span: S) -> <S as WrappingSpan<Self>>::Spanned
WrappingSpan::make_wrapped to wrap an AST node in a span.