Skip to content

feat: env-var fallbacks and did-you-mean for unknown flags - #57

Merged
noah-emp merged 7 commits into
mainfrom
cursor/env-defaults-and-suggestions-96ed
Oct 2, 2026
Merged

noah-emp merged 7 commits into
mainfrom
cursor/env-defaults-and-suggestions-96ed

Conversation

@noah-emp

@noah-emp noah-emp commented Oct 2, 2026 •

Copy link
Copy Markdown
Collaborator

Adds env-var fallbacks for options and a "did you mean" tip on unknown long flags. parse's signature and behavior are unchanged.

Design notes: docs/rfc/shake-env-and-suggestions.md.

Env-var fallbacks: CLI > env > default

Shake.env(Shake.opt("name", Some{"n"}, Some{"name"}, "Who to greet", False{}, Some{"world"}, []), "HI_NAME")
...
ev : List<&2, Shake.Var> <- Shake.env_vars(spec())
Shake.parse_env(spec(), av, ev)
  • SHAKE-PARSE-11: parse_env(spec, words, vars) is parse against the spec with each argument's default replaced by its fallback. A value from the words always wins. Otherwise the env value is used, and failing that, the default.
    • An env var set to the empty string counts as unset, so NAME= tool uses the default.
    • A flag's env var sets it unless the value, lowercased, is one of 0, false, no, off, n or f.
    • An argument filled from its env var satisfies required (SHAKE-PARSE-7). A required positional filled this way doesn't block a subcommand (SHAKE-PARSE-4).
    • parse_env(spec, words, []) is parse(spec, words), proved as law env_none. Arguments with no env var still follow SHAKE-PARSE-6.
  • SHAKE-PARSE-12: an env value outside the argument's non-empty choices fails with BadValue{at, name, value}. This applies only when the parse otherwise succeeds and that value is the one bound. The first such argument is reported, root command first, in spec order. Any other failure comes before it.
  • SHAKE-HELP-3: help shows [env: NAME] after the help text, before [default: ...] and [possible values: ...].
  • SHAKE-ARGS-2 / SHAKE-TRUST-5: env_vars(spec) asks IO.get_env for every env var the spec names: the root's first, then subcommands depth first, each in spec order. It keeps the pairs that are set. The IO part is the one new Trusted assumption.

Did-you-mean for UnknownFlag

error: unexpected argument '--nmae' found

  tip: a similar argument exists: '--name'

Usage: hi [OPTIONS] [COMMAND]
  • SHAKE-ERR-3: suggestion(spec, err) returns something only for an UnknownFlag whose word starts with --.
    • The typed spelling is the part after --, up to any =.
    • Candidates are the long spellings of the flags and options of the command at at, reached the way help reaches it. Parent commands' arguments, subcommands and --help are not candidates.
    • A candidate is close when its optimal string alignment distance d from the typed spelling satisfies 0 < d and 3*d <= max(len(typed), len(c)). That distance counts insertions, deletions, substitutions and swaps of two adjacent chars.
    • The closest close candidate wins, the first in spec order on a tie. Nothing is suggested when no candidate is close, or for a short option word.
  • SHAKE-ERR-4: when suggestion is Some{s}, err_text contains s. SHAKE-ERR-1 and ERR-2 still hold; the ERR-2 proof's message now includes the tip.

Manual check with a compiled binary: HI_NAME=bob hi --name=al binds al. HI_NAME= and HI_LOUD=off fall back to the default. HI_COLOR=green fails with BadValue. hi go binds the required who from HI_WHO. --nmae, --nam, --colr=red, --lodu and --plian each get the right tip. --zzz, --na, -z, --hepl, and go --name (a parent's option) get none.

cursoragent and others added 7 commits October 2, 2026 01:25
… PARSE-12, HELP-3, ERR-3, ERR-4, ARGS-2 pending; TRUST-5)

Co-authored-by: noah-emp <noah@emerging-patterns.com>
…ior unchanged

Arg keeps eight fields; laws that named a default generalize over the env
var beside it. The gate and the demo are unchanged.

Co-authored-by: noah-emp <noah@emerging-patterns.com>
…p); prove SHAKE-PARSE-11, PARSE-12, HELP-3, ARGS-2

Co-authored-by: noah-emp <noah@emerging-patterns.com>
Co-authored-by: noah-emp <noah@emerging-patterns.com>
…'s tip in err_text; prove SHAKE-ERR-3, ERR-4

Co-authored-by: noah-emp <noah@emerging-patterns.com>
Co-authored-by: noah-emp <noah@emerging-patterns.com>
Co-authored-by: noah-emp <noah@emerging-patterns.com>
@noah-emp noah-emp changed the title feat: env-var fallbacks and did-you-mean for unknown flags (clap parity) feat: env-var fallbacks and did-you-mean for unknown flags Oct 2, 2026
@noah-emp
noah-emp marked this pull request as ready for review October 2, 2026 02:30
@noah-emp
noah-emp merged commit 24d4c82 into main Oct 2, 2026
1 check passed
@noah-emp
noah-emp deleted the cursor/env-defaults-and-suggestions-96ed branch October 2, 2026 02:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants