pub fn select_leaf<'a>(
schema: &'a ToolSchema,
args: &[Arg],
) -> Result<&'a ToolSchema>Expand description
Extract parameter types from a tool schema.
Returns a map from param name → param type (e.g., “verbose” → “bool”, “output” → “string”). Build a map from flag name → (canonical param name, param type).
Includes both primary names and aliases (with dashes stripped).
For short flags like -n aliased to lines, maps "n" → ("lines", "int", 1).
The third tuple slot is consumes: how many positionals the flag pulls
per occurrence (1 for standard --flag value, 2 for jq’s --arg NAME VAL).
Positional params (positional: true) are excluded — they’re not flags,
and including them would mis-route cat --paths foo.txt from positional
to named, regressing builtins that read from args.positional.
Walk leading positionals to select the active subcommand leaf of a schema.
A flat tool (schema.subcommands empty) returns the root immediately —
today’s single-leaf behavior. For a subcommand-aware tool each leading
positional, in order, must name a child (by name or a command-level
alias) to descend; the first positional that names no child is the leaf’s
own argument, and selection stops there. Multi-level trees fall out by
construction (block edit insert → two descents).
Routing is literal-only: a subcommand selector must be a bareword or
quoted string (both parse to Expr::Literal(Value::String)). A computed
positional ($(…), $VAR, a glob) sitting where a subcommand is required
is an error, not a silent guess — kaish can’t see its value at parse
time, so picking a leaf from it would misroute the flags that bind against
the leaf’s params. The fix is to spell the subcommand out, or use the
--flag=value form (which binds without any schema lookup).
Returned leaf borrows from schema, so its params/subcommands outlive
any schema_param_lookup taken from it.
Global value flags. A space-form value flag declared on the root
(e.g. kj’s global --confirm <nonce>) can legitimately precede the
subcommand path. Its value is a positional in the AST, so routing must not
mistake it for a subcommand selector — select_leaf skips the value of any
root-declared non-bool flag it sees. Leaf-specific value flags can’t precede
their own subcommand by construction, so only the root’s flags need this.