From 378acb553ca422610032893ca473abf5f391a1b9 Mon Sep 17 00:00:00 2001 From: default <216188+jdx@users.noreply.github.com> Date: Mon, 17 Aug 2026 13:17:30 +0000 Subject: [PATCH 1/7] feat(go): render a failure as something a person can act on MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `argv.Render` turns a binding failure into what a CLI prints to stderr: what went wrong, the usage line for the command the user was actually in, and what to try next. error: unknown flag `--wat` Usage: ex run [-f --force] For more information, try `--help`. This is the one part of the module with **no reference to match**, and saying so is the point. usage-lib prints a one-line message inside miette's frame; usage-argv renders through miette as well, underlining the offending token in the command line. Neither travels — miette is a Rust library, and a Go CLI drawing the same ASCII art would be imitating a diagnostic format rather than sharing one. Every other renderer here is measured against usage-lib byte for byte, and this one cannot be, so it is judged on a different standard: does the message say what went wrong, where, and what to do about it. Tested that way too. Every code renders something specific — a failure falling through to "could not be parsed" tells a user nothing, so the test is that none of them does — and the usage line names the command in scope rather than the program, which is the part that makes the message actionable on a nested command. `missing_flag_value` says the likeliest cause out loud, because the rule behind it is not guessable: a flag-like token after a flag is refused as its value, and the attached form is how to force it. Help and version render nothing. They arrive as errors because a parse that stops to print a page has produced no value, but a caller that renders one of them as a failure has made two mistakes at once. Co-Authored-By: Claude Opus 5 --- go/README.md | 22 ++++++- go/argv/render.go | 134 +++++++++++++++++++++++++++++++++++++++++ go/argv/render_test.go | 92 ++++++++++++++++++++++++++++ 3 files changed, 245 insertions(+), 3 deletions(-) create mode 100644 go/argv/render.go create mode 100644 go/argv/render_test.go diff --git a/go/README.md b/go/README.md index b4db65200..2dee4f860 100644 --- a/go/README.md +++ b/go/README.md @@ -156,6 +156,25 @@ rules drift, so both are run over mise's real spec and compared — the same che Two implementations checked against one oracle beats two checked against each other. +## Errors + +`argv.Render` turns a failure into what a CLI should print to stderr: + +``` +error: unknown flag `--wat` + +Usage: ex run [-f --force] + +For more information, try `--help`. +``` + +The one part of this module with **no reference to match**. usage-lib prints a +one-line message inside miette's frame and usage-argv renders through miette too; +neither travels, because miette is a Rust library and a Go CLI drawing the same +ASCII art would be imitating a diagnostic format rather than sharing one. So this +is judged on whether the message says what went wrong, where, and what to try — +and tested by asserting those rather than by comparing bytes. + ## Conformance The [corpus](../corpus) is the definition of correct, and it is plain JSON so that @@ -191,9 +210,6 @@ claim is measured at real scale rather than against a fixture with four flags: - **Typed values.** Binding collects text. Something still has to turn `"8"` into an `int` and `"1m"` into a `time.Duration`, and report the ones that will not convert. -- **Errors worth reading.** `Error()` returns `unknown flag: --wat`, which names - the problem and helps nobody fix it. usage-argv renders these through miette - with the offending token underlined. - **Completions.** The Rust side serves these from the parser's own scope rules so that what is offered and what is accepted cannot disagree; the hooks for it (`Collecting`, `PendingArg`, `FlagsInScope`, `CommandStart`) are already here. diff --git a/go/argv/render.go b/go/argv/render.go new file mode 100644 index 000000000..9872acd33 --- /dev/null +++ b/go/argv/render.go @@ -0,0 +1,134 @@ +package argv + +import "strings" + +// Turning a binding failure into something a person can act on. +// +// Unlike everything else in this package, there is no reference to match. usage-lib +// prints a one-line message inside miette's frame; usage-argv renders through +// miette too, with the offending token underlined in the command line. Neither +// travels: miette is a Rust library, and a Go CLI drawing ASCII art around an +// error would be imitating a diagnostic format rather than sharing one. +// +// So this is judged on a different standard — whether the message says what went +// wrong, where, and what to do about it — and it is tested by asserting those +// three things rather than by comparing bytes. The shape is clap's, which is what +// a Go user will have seen before: +// +// error: unknown flag `--wat` +// +// Usage: ex [-f --force] +// +// For more information, try `--help`. + +// Render turns a failure into the text a CLI should print to stderr. +// +// `path` and `chain` are the command as invoked, as for [ShortHelp], so the usage +// line names the command the user was actually in rather than the program. +// +// Help and version are not failures and render as nothing: a caller that gets +// [CodeHelp] should print the page, not this. +func Render(err *Error, path []string, chain []*Command, help HelpTable) string { + if err == nil || err.Code == CodeHelp || err.Code == CodeVersion { + return "" + } + + var out strings.Builder + out.WriteString("error: " + explain(err, help) + "\n") + + if len(chain) > 0 { + out.WriteString("\nUsage: " + UsageLine(path, chain[len(chain)-1], help) + "\n") + } + out.WriteString("\nFor more information, try `--help`.\n") + return out.String() +} + +// explain is the one-line summary: what went wrong, naming the thing it went +// wrong with. +// +// Backticks around anything the user typed or could type, so a flag reads as a +// flag rather than as part of the sentence — `unknown flag --for` is ambiguous +// about where the name ends in a way that “unknown flag `--for` “ is not. +func explain(err *Error, help HelpTable) string { + switch err.Code { + case CodeUnknownFlag: + return "unknown flag `" + err.Token + "`" + case CodeMissingFlagValue: + name := "a flag" + if err.Flag != nil { + name = "`--" + primaryLong(err.Flag) + "`" + } + // The likeliest cause, said out loud: a flag-like token following the flag + // is refused as its value, and the attached form is how to force it. + return "missing value for " + name + + " (a value beginning with `-` has to be attached: `--flag=-x`)" + case CodeUnexpectedArg: + return "unexpected argument `" + err.Token + "`" + case CodeArgRequiresDoubleDash: + name := "that argument" + if err.Arg != nil { + name = "`" + err.Arg.Name + "`" + } + return name + " is only read after a `--` separator" + case CodeTooDeep: + return "the command tree is nested deeper than this parser will go" + case CodeMissingRequiredFlag: + return "missing required flag `--" + err.Name + "`" + case CodeMissingRequiredArg: + return "missing required argument `" + err.Name + "`" + case CodeInvalidChoice: + msg := "`" + err.Name + "` does not accept that value" + if len(err.Choices) > 0 { + msg += " (expected one of: " + strings.Join(err.Choices, ", ") + ")" + } + return msg + case CodeVarTooFew: + return "`" + err.Name + "` needs at least " + plural(int(err.Bound), "value") + + ", got " + itoa(err.Got) + case CodeVarTooMany: + return "`" + err.Name + "` accepts at most " + plural(int(err.Bound), "time") + + ", given " + itoa(err.Got) + case CodeConflictingFlags: + other := err.Other + if other == "" { + return "`--" + err.Name + "` cannot be given with another flag it conflicts with" + } + return "`--" + err.Name + "` and `--" + other + "` cannot be given together" + } + return "the command line could not be parsed" +} + +// primaryLong is the spelling to name a flag by: its first long form, or its name +// where it has none. +func primaryLong(f *Flag) string { + if len(f.Longs) > 0 { + return f.Longs[0] + } + return f.Name +} + +func plural(n int, noun string) string { + if n == 1 { + return "1 " + noun + } + return itoa(n) + " " + noun + "s" +} + +func itoa(n int) string { + if n == 0 { + return "0" + } + neg := n < 0 + if neg { + n = -n + } + var digits []byte + for n > 0 { + digits = append([]byte{byte('0' + n%10)}, digits...) + n /= 10 + } + if neg { + return "-" + string(digits) + } + return string(digits) +} diff --git a/go/argv/render_test.go b/go/argv/render_test.go new file mode 100644 index 000000000..c656be071 --- /dev/null +++ b/go/argv/render_test.go @@ -0,0 +1,92 @@ +package argv + +import ( + "strings" + "testing" +) + +// A rendered failure is judged on three things rather than on bytes: it says what +// went wrong, it shows the command the user was actually in, and it says what to +// try next. There is no reference to match here — see render.go. +func TestRenderSaysWhatWentWrongAndWhatToTry(t *testing.T) { + sub := &Command{Name: "run", Key: 2, Flags: []*Flag{ + {Key: 3, Name: "force", Longs: []string{"force"}, Shorts: []byte{'f'}}, + }} + root := &Command{Name: "ex", Key: 1, Subcommands: []*Command{sub}} + help := HelpTable{{Key: 1}, {Key: 2}, {Key: 3}} + path, chain := []string{"ex", "run"}, []*Command{root, sub} + + got := Render(&Error{Code: CodeUnknownFlag, Token: "--wat"}, path, chain, help) + + for _, want := range []string{ + "error: unknown flag `--wat`", + // The command the user was in, not the program. + "Usage: ex run [-f --force]", + "try `--help`", + } { + if !strings.Contains(got, want) { + t.Errorf("missing %q in:\n%s", want, got) + } + } +} + +// Every code renders something specific. A failure that falls through to "could +// not be parsed" tells the user nothing, so the test is that none of them does. +func TestEveryCodeRendersSomethingSpecific(t *testing.T) { + flag := &Flag{Key: 1, Name: "jobs", Longs: []string{"jobs"}} + arg := &Arg{Key: 2, Name: "FILE"} + cases := []*Error{ + {Code: CodeUnknownFlag, Token: "--wat"}, + {Code: CodeMissingFlagValue, Flag: flag}, + {Code: CodeUnexpectedArg, Token: "extra"}, + {Code: CodeArgRequiresDoubleDash, Arg: arg}, + {Code: CodeTooDeep}, + {Code: CodeMissingRequiredFlag, Name: "file"}, + {Code: CodeMissingRequiredArg, Name: "FILE"}, + {Code: CodeInvalidChoice, Name: "shell", Choices: []string{"bash", "zsh"}}, + {Code: CodeVarTooFew, Name: "files", Bound: 2, Got: 1}, + {Code: CodeVarTooMany, Name: "tag", Bound: 1, Got: 3}, + {Code: CodeConflictingFlags, Name: "file", Other: "stdin"}, + } + for _, e := range cases { + got := explain(e, nil) + if got == "" || strings.Contains(got, "could not be parsed") { + t.Errorf("%v renders nothing useful: %q", e.Code, got) + } + } +} + +// Help and version are not failures. A caller that gets one should print the +// page, and rendering an error for it would be the wrong thing twice over. +func TestHelpAndVersionRenderNothing(t *testing.T) { + for _, code := range []Code{CodeHelp, CodeVersion} { + if got := Render(&Error{Code: code}, nil, nil, nil); got != "" { + t.Errorf("%v should render nothing, got %q", code, got) + } + } + if got := Render(nil, nil, nil, nil); got != "" { + t.Errorf("no error should render nothing, got %q", got) + } +} + +// The messages name things the way a user typed them, which is the whole reason +// for the backticks. +func TestMessagesQuoteWhatTheUserWouldType(t *testing.T) { + for _, c := range []struct { + err *Error + want string + }{ + {&Error{Code: CodeInvalidChoice, Name: "shell", Choices: []string{"bash", "zsh"}}, + "expected one of: bash, zsh"}, + {&Error{Code: CodeConflictingFlags, Name: "file", Other: "stdin"}, + "`--file` and `--stdin` cannot be given together"}, + {&Error{Code: CodeVarTooFew, Name: "files", Bound: 2, Got: 1}, + "at least 2 values, got 1"}, + {&Error{Code: CodeVarTooMany, Name: "tag", Bound: 1, Got: 3}, + "at most 1 time, given 3"}, + } { + if got := explain(c.err, nil); !strings.Contains(got, c.want) { + t.Errorf("want %q in %q", c.want, got) + } + } +} From dad35261696fc843c3e77e1e7a503180ed490d39 Mon Sep 17 00:00:00 2001 From: default <216188+jdx@users.noreply.github.com> Date: Mon, 17 Aug 2026 13:28:59 +0000 Subject: [PATCH 2/7] fix(go): name a flag the way it can be typed, and do not let a value reach the terminal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two review findings on the error text, both about output a user cannot act on. A short-only flag was named `--f`. `primaryLong` fell back to the flag's *name* and everything prefixed `--`, so a flag reachable only as `-f` was reported as something nobody can enter — and the advice that comes with a missing value was worse than useless, telling someone with `-j` to write `--j=-1`, which is an unknown flag. Flags are spelled from their forms now: first long, else first short, and the attachment example follows the same spelling. The post-binding failures carry only a name, because they judge an entry rather than a token and no flag reaches them. A one-character name is taken to be a short, which is a guess and the right one nearly always: a flag's name is its long form wherever it has one. Printing `--f` for something typeable only as `-f` is the alternative. And a value quoted back into an error is escaped. What the user typed can contain control characters, and an escape sequence in an argument would otherwise reach the terminal through the message — where it can recolour the output, move the cursor, or forge lines that look like the program wrote them. Rendering a rejected value is not a reason to execute it. The escaping keeps the text legible rather than dropping it, so the user still sees what was refused. Co-Authored-By: Claude Opus 5 --- go/argv/render.go | 83 ++++++++++++++++++++++++++++++++++-------- go/argv/render_test.go | 50 +++++++++++++++++++++++++ 2 files changed, 118 insertions(+), 15 deletions(-) diff --git a/go/argv/render.go b/go/argv/render.go index 9872acd33..9fa8e2256 100644 --- a/go/argv/render.go +++ b/go/argv/render.go @@ -52,18 +52,21 @@ func Render(err *Error, path []string, chain []*Command, help HelpTable) string func explain(err *Error, help HelpTable) string { switch err.Code { case CodeUnknownFlag: - return "unknown flag `" + err.Token + "`" + return "unknown flag `" + safe(err.Token) + "`" case CodeMissingFlagValue: - name := "a flag" - if err.Flag != nil { - name = "`--" + primaryLong(err.Flag) + "`" + if err.Flag == nil { + return "missing value for a flag" } // The likeliest cause, said out loud: a flag-like token following the flag - // is refused as its value, and the attached form is how to force it. - return "missing value for " + name + - " (a value beginning with `-` has to be attached: `--flag=-x`)" + // is refused as its value, and attaching it is how to force it. The + // example is spelled in the form the flag actually has — telling someone + // with a short-only `-j` to write `--j=-1` sends them to an unknown-flag + // error. + spelling := spell(err.Flag) + return "missing value for `" + spelling + "`" + + " (a value beginning with `-` has to be attached: `" + spelling + "=-1`)" case CodeUnexpectedArg: - return "unexpected argument `" + err.Token + "`" + return "unexpected argument `" + safe(err.Token) + "`" case CodeArgRequiresDoubleDash: name := "that argument" if err.Arg != nil { @@ -73,7 +76,7 @@ func explain(err *Error, help HelpTable) string { case CodeTooDeep: return "the command tree is nested deeper than this parser will go" case CodeMissingRequiredFlag: - return "missing required flag `--" + err.Name + "`" + return "missing required flag `" + spellName(err.Name) + "`" case CodeMissingRequiredArg: return "missing required argument `" + err.Name + "`" case CodeInvalidChoice: @@ -91,22 +94,72 @@ func explain(err *Error, help HelpTable) string { case CodeConflictingFlags: other := err.Other if other == "" { - return "`--" + err.Name + "` cannot be given with another flag it conflicts with" + return "`" + spellName(err.Name) + "` cannot be given with another flag it conflicts with" } - return "`--" + err.Name + "` and `--" + other + "` cannot be given together" + return "`" + spellName(err.Name) + "` and `" + spellName(other) + + "` cannot be given together" } return "the command line could not be parsed" } -// primaryLong is the spelling to name a flag by: its first long form, or its name -// where it has none. -func primaryLong(f *Flag) string { +// spell names a flag the way a user would type it: its first long form, else its +// first short. Naming a short-only flag `--f` gives advice that cannot be +// followed. +func spell(f *Flag) string { if len(f.Longs) > 0 { - return f.Longs[0] + return "--" + f.Longs[0] + } + if len(f.Shorts) > 0 { + return "-" + string(f.Shorts[0]) } return f.Name } +// spellName is [spell] for the failures that carry only a name, which is what the +// post-binding rules have: they judge an entry rather than a token, so no [Flag] +// reaches them. +// +// A single-character name is taken to be a short flag, which is a guess — but the +// right one nearly always, since a flag's name is its long form where it has one. +// The alternative is printing `--f` for something only typeable as `-f`. +func spellName(name string) string { + if len([]rune(name)) == 1 { + return "-" + name + } + return "--" + name +} + +// safe makes text from the command line printable. +// +// An error quotes back what the user typed, and what the user typed can contain +// control characters: an escape sequence in an argument would otherwise reach the +// terminal through the error message, where it can recolour the output, move the +// cursor, or forge lines that look like they came from the program. Rendering a +// rejected value is not a reason to execute it. +func safe(s string) string { + var out strings.Builder + for _, r := range s { + switch { + case r == '\t': + out.WriteString("\\t") + case r == '\n': + out.WriteString("\\n") + case r == '\r': + out.WriteString("\\r") + case r < 0x20 || r == 0x7f: + out.WriteString("\\x" + hex(byte(r))) + default: + out.WriteRune(r) + } + } + return out.String() +} + +func hex(b byte) string { + const digits = "0123456789abcdef" + return string([]byte{digits[b>>4], digits[b&0xf]}) +} + func plural(n int, noun string) string { if n == 1 { return "1 " + noun diff --git a/go/argv/render_test.go b/go/argv/render_test.go index c656be071..6936df02d 100644 --- a/go/argv/render_test.go +++ b/go/argv/render_test.go @@ -90,3 +90,53 @@ func TestMessagesQuoteWhatTheUserWouldType(t *testing.T) { } } } + +// A short-only flag is named the way it can be typed. +// +// `--f` is not a flag anybody can enter, and the advice that comes with a missing +// value has to be followable: telling someone with `-j` to write `--j=-1` sends +// them to an unknown-flag error. +func TestAShortOnlyFlagIsNamedAsItIsTyped(t *testing.T) { + short := &Flag{Key: 1, Name: "j", Shorts: []byte{'j'}, TakesValue: true} + got := explain(&Error{Code: CodeMissingFlagValue, Flag: short}, nil) + if strings.Contains(got, "--j") { + t.Errorf("a short-only flag should not be named `--j`: %s", got) + } + for _, want := range []string{"`-j`", "`-j=-1`"} { + if !strings.Contains(got, want) { + t.Errorf("want %s in: %s", want, got) + } + } + + long := &Flag{Key: 2, Name: "jobs", Longs: []string{"jobs"}, Shorts: []byte{'j'}} + if got := explain(&Error{Code: CodeMissingFlagValue, Flag: long}, nil); !strings.Contains(got, "`--jobs`") { + t.Errorf("a flag with a long form is named by it: %s", got) + } + + // The post-binding failures carry a name rather than a flag, so the form is + // inferred from its length — the right guess nearly always, since a name is a + // long form where there is one. + if got := explain(&Error{Code: CodeMissingRequiredFlag, Name: "f"}, nil); !strings.Contains(got, "`-f`") { + t.Errorf("a one-character name reads as a short: %s", got) + } + if got := explain(&Error{Code: CodeMissingRequiredFlag, Name: "file"}, nil); !strings.Contains(got, "`--file`") { + t.Errorf("a longer name reads as a long: %s", got) + } +} + +// An error quotes back what the user typed, and what the user typed can contain +// escape sequences. Rendering a rejected value is not a reason to execute it. +func TestControlCharactersDoNotReachTheTerminal(t *testing.T) { + got := explain(&Error{Code: CodeUnknownFlag, Token: "--x\x1b[31mred\r\nerror: forged"}, nil) + for _, forbidden := range []string{"\x1b", "\r", "\n"} { + if strings.Contains(got, forbidden) { + t.Errorf("a control character survived into %q", got) + } + } + // Still legible: the escaping shows what was there rather than dropping it. + for _, want := range []string{`\x1b`, `\r`, `\n`, "red", "forged"} { + if !strings.Contains(got, want) { + t.Errorf("want %q kept visible in %q", want, got) + } + } +} From 2b1038b71dcc6b965e1e3f7de5d99360a6a9d9f2 Mon Sep 17 00:00:00 2001 From: default <216188+jdx@users.noreply.github.com> Date: Mon, 17 Aug 2026 17:19:25 +0000 Subject: [PATCH 3/7] fix(go): illustrate the attached form with a value that needs it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The missing-value message advised attaching a dash-prefixed value and showed `--jobs=-1`. A negative number is the one dash-prefixed token the parser takes *detached*: `--jobs -1` binds, and `--jobs -x` is the failure being explained. So the example demonstrated the case exempt from the rule it was illustrating — advice that contradicts itself. `-x` now, which is a token that actually triggers it. Checked both ways round rather than reasoned about. Co-Authored-By: Claude Opus 5 --- go/argv/render.go | 15 ++++++++++----- go/argv/render_test.go | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/go/argv/render.go b/go/argv/render.go index 9fa8e2256..bf506600d 100644 --- a/go/argv/render.go +++ b/go/argv/render.go @@ -58,13 +58,18 @@ func explain(err *Error, help HelpTable) string { return "missing value for a flag" } // The likeliest cause, said out loud: a flag-like token following the flag - // is refused as its value, and attaching it is how to force it. The - // example is spelled in the form the flag actually has — telling someone - // with a short-only `-j` to write `--j=-1` sends them to an unknown-flag - // error. + // is refused as its value, and attaching it is how to force it. + // + // The example is `-x` rather than `-1`, because a negative number is the + // one dash-prefixed token the parser *does* take detached — `--jobs -1` + // binds. Illustrating the rule with the case that is exempt from it was + // advice that contradicted itself. + // + // And it is spelled in the form the flag actually has: telling someone + // with a short-only `-j` to write `--j=-x` sends them to an unknown flag. spelling := spell(err.Flag) return "missing value for `" + spelling + "`" + - " (a value beginning with `-` has to be attached: `" + spelling + "=-1`)" + " (a value beginning with `-` has to be attached: `" + spelling + "=-x`)" case CodeUnexpectedArg: return "unexpected argument `" + safe(err.Token) + "`" case CodeArgRequiresDoubleDash: diff --git a/go/argv/render_test.go b/go/argv/render_test.go index 6936df02d..5598be3c1 100644 --- a/go/argv/render_test.go +++ b/go/argv/render_test.go @@ -102,7 +102,7 @@ func TestAShortOnlyFlagIsNamedAsItIsTyped(t *testing.T) { if strings.Contains(got, "--j") { t.Errorf("a short-only flag should not be named `--j`: %s", got) } - for _, want := range []string{"`-j`", "`-j=-1`"} { + for _, want := range []string{"`-j`", "`-j=-x`"} { if !strings.Contains(got, want) { t.Errorf("want %s in: %s", want, got) } From d772b78bce1d5b1ddde4a0575bdfb335a596804d Mon Sep 17 00:00:00 2001 From: default <216188+jdx@users.noreply.github.com> Date: Mon, 17 Aug 2026 17:34:59 +0000 Subject: [PATCH 4/7] fix(go): carry how a flag is typed instead of guessing from its name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `spellName` read a one-character name as a short flag, reasoning that a name is a long form wherever there is one. A long-only `--a` is one character too, so it was rendered `-a` — a form that does not exist, and one that may belong to a *different* flag. Advice naming the wrong flag is worse than advice naming none. The guess is gone. `Meta` carries the spelling, worked out where the forms are visible — first long, else first short — by the table builder and the emitter alike, and the failures that judge an entry carry it through. Both sides of a conflict get their own, since they can be spelled differently. Where nothing is carried the bare name is printed rather than dressed as something the user cannot type. Two notes on the way here, both about tests rather than code. The emitter change silently missed the first time: the pattern was written at the wrong indentation and matched nothing, and the build still passed. The check that caught it was counting `Spelling` entries in mise's regenerated tables — 711 now, 0 then. And five emitter tests broke, all of them asserting a whole rendered row. A row grows a field every time the cold table learns something, so they now assert the part each test is about. That is what they meant all along. Co-Authored-By: Claude Opus 5 --- go/argv/argv.go | 5 + go/argv/post.go | 10 +- go/argv/relationships.go | 21 +- go/argv/render.go | 30 +- go/argv/render_test.go | 43 +- go/internal/shadow/mise/tables.go | 1448 ++++++++--------- go/internal/spec/spec.go | 16 + go/internal/spec/spec_test.go | 23 + lib/src/go/mod.rs | 57 +- .../usage__go__tests__a_whole_cli.snap | 12 +- ...liding_names_get_distinct_identifiers.snap | 4 +- 11 files changed, 872 insertions(+), 797 deletions(-) diff --git a/go/argv/argv.go b/go/argv/argv.go index 079a121c2..20e407eee 100644 --- a/go/argv/argv.go +++ b/go/argv/argv.go @@ -318,6 +318,11 @@ type Error struct { // Name is the flag or argument the post-binding rules rejected, as the spec // spells it. Name string + // Spelling is how the entry is typed, where the rule that raised this knew — + // see [Meta.Spelling]. Empty means only the name is known. + Spelling string + // OtherSpelling is the same for [Error.Other]. + OtherSpelling string // Choices carries the declared list for CodeInvalidChoice, rather than the // offending value: the value is the caller's to render, and it has it. Choices []string diff --git a/go/argv/post.go b/go/argv/post.go index baa72e9d9..eae236c89 100644 --- a/go/argv/post.go +++ b/go/argv/post.go @@ -29,6 +29,14 @@ type Meta struct { Key uint64 // Name is what the spec calls it, for the error. Name string + // Spelling is how a user types it — `--file`, `-f` — for the errors raised + // here, which judge an *entry* and so never see a [Flag]. + // + // Carried rather than derived from the name: a name is a long form wherever + // there is one, but `--a` and `-a` are both one character and guessing + // between them can name a different flag entirely. Empty for an argument, + // which is typed as its value rather than as a form. + Spelling string // Flag distinguishes a missing flag from a missing argument, which the // grammar reports as different classes. Flag bool @@ -175,7 +183,7 @@ func Check(m *Meta, values []string, occurrences int) *Error { if m.Flag { code = CodeMissingRequiredFlag } - return &Error{Code: code, Name: m.Name} + return &Error{Code: code, Name: m.Name, Spelling: m.Spelling} } if len(m.Choices) > 0 { diff --git a/go/argv/relationships.go b/go/argv/relationships.go index 58e3bd35a..556f00623 100644 --- a/go/argv/relationships.go +++ b/go/argv/relationships.go @@ -99,11 +99,12 @@ func CheckRelationships(meta Metadata, entries []uint64, sourceOf func(uint64) S if given(other) { // Both names, because either alone reads as a puzzle: which flag // is unwelcome depends entirely on what else was given. - return &Error{ - Code: CodeConflictingFlags, - Name: m.Name, - Other: nameOf(meta, other), + o := meta.Lookup(other) + e := &Error{Code: CodeConflictingFlags, Name: m.Name, Spelling: m.Spelling} + if o != nil { + e.Other, e.OtherSpelling = o.Name, o.Spelling } + return e } } continue @@ -146,7 +147,7 @@ func missingRequired(m *Meta) *Error { if m.Flag { code = CodeMissingRequiredFlag } - return &Error{Code: code, Name: m.Name} + return &Error{Code: code, Name: m.Name, Spelling: m.Spelling} } func anySet(keys []uint64, isSet func(uint64) bool) bool { @@ -157,13 +158,3 @@ func anySet(keys []uint64, isSet func(uint64) bool) bool { } return false } - -// nameOf renders the other side of a relationship, falling back to nothing rather -// than to a number: an error naming `key 7` is worse than one naming only the -// flag the reader already knows about. -func nameOf(meta Metadata, key uint64) string { - if m := meta.Lookup(key); m != nil { - return m.Name - } - return "" -} diff --git a/go/argv/render.go b/go/argv/render.go index bf506600d..10416c046 100644 --- a/go/argv/render.go +++ b/go/argv/render.go @@ -81,7 +81,7 @@ func explain(err *Error, help HelpTable) string { case CodeTooDeep: return "the command tree is nested deeper than this parser will go" case CodeMissingRequiredFlag: - return "missing required flag `" + spellName(err.Name) + "`" + return "missing required flag `" + typedAs(err.Spelling, err.Name) + "`" case CodeMissingRequiredArg: return "missing required argument `" + err.Name + "`" case CodeInvalidChoice: @@ -99,10 +99,11 @@ func explain(err *Error, help HelpTable) string { case CodeConflictingFlags: other := err.Other if other == "" { - return "`" + spellName(err.Name) + "` cannot be given with another flag it conflicts with" + return "`" + typedAs(err.Spelling, err.Name) + + "` cannot be given with another flag it conflicts with" } - return "`" + spellName(err.Name) + "` and `" + spellName(other) + - "` cannot be given together" + return "`" + typedAs(err.Spelling, err.Name) + "` and `" + + typedAs(err.OtherSpelling, other) + "` cannot be given together" } return "the command line could not be parsed" } @@ -120,18 +121,19 @@ func spell(f *Flag) string { return f.Name } -// spellName is [spell] for the failures that carry only a name, which is what the -// post-binding rules have: they judge an entry rather than a token, so no [Flag] -// reaches them. +// typedAs prefers the spelling the tables carry, and falls back to the bare name. // -// A single-character name is taken to be a short flag, which is a guess — but the -// right one nearly always, since a flag's name is its long form where it has one. -// The alternative is printing `--f` for something only typeable as `-f`. -func spellName(name string) string { - if len([]rune(name)) == 1 { - return "-" + name +// It used to guess: a one-character name was read as a short flag, on the reasoning +// that a name is a long form wherever there is one. That is wrong for a long-only +// `--a`, which it rendered as `-a` — a form that does not exist, and which may +// belong to a *different* flag. So the spelling is carried now, and where it is +// missing the name is printed bare rather than dressed as something the user +// cannot type. +func typedAs(spelling, name string) string { + if spelling != "" { + return spelling } - return "--" + name + return name } // safe makes text from the command line printable. diff --git a/go/argv/render_test.go b/go/argv/render_test.go index 5598be3c1..e6184c266 100644 --- a/go/argv/render_test.go +++ b/go/argv/render_test.go @@ -78,7 +78,8 @@ func TestMessagesQuoteWhatTheUserWouldType(t *testing.T) { }{ {&Error{Code: CodeInvalidChoice, Name: "shell", Choices: []string{"bash", "zsh"}}, "expected one of: bash, zsh"}, - {&Error{Code: CodeConflictingFlags, Name: "file", Other: "stdin"}, + {&Error{Code: CodeConflictingFlags, Name: "file", Spelling: "--file", + Other: "stdin", OtherSpelling: "--stdin"}, "`--file` and `--stdin` cannot be given together"}, {&Error{Code: CodeVarTooFew, Name: "files", Bound: 2, Got: 1}, "at least 2 values, got 1"}, @@ -113,14 +114,13 @@ func TestAShortOnlyFlagIsNamedAsItIsTyped(t *testing.T) { t.Errorf("a flag with a long form is named by it: %s", got) } - // The post-binding failures carry a name rather than a flag, so the form is - // inferred from its length — the right guess nearly always, since a name is a - // long form where there is one. - if got := explain(&Error{Code: CodeMissingRequiredFlag, Name: "f"}, nil); !strings.Contains(got, "`-f`") { - t.Errorf("a one-character name reads as a short: %s", got) + // The post-binding failures never see a flag, so they carry the spelling the + // tables worked out — see TestAOneCharacterLongFormIsNotMistakenForAShort. + if got := explain(&Error{Code: CodeMissingRequiredFlag, Name: "f", Spelling: "-f"}, nil); !strings.Contains(got, "`-f`") { + t.Errorf("the carried spelling should be used: %s", got) } - if got := explain(&Error{Code: CodeMissingRequiredFlag, Name: "file"}, nil); !strings.Contains(got, "`--file`") { - t.Errorf("a longer name reads as a long: %s", got) + if got := explain(&Error{Code: CodeMissingRequiredFlag, Name: "file", Spelling: "--file"}, nil); !strings.Contains(got, "`--file`") { + t.Errorf("the carried spelling should be used: %s", got) } } @@ -140,3 +140,30 @@ func TestControlCharactersDoNotReachTheTerminal(t *testing.T) { } } } + +// The spelling is carried, not guessed. +// +// A one-character *long* form and a short form are both one character, so a +// heuristic on the name renders `--a` as `-a` — a form that does not exist, and +// one that may belong to a different flag. +func TestAOneCharacterLongFormIsNotMistakenForAShort(t *testing.T) { + long := explain(&Error{Code: CodeMissingRequiredFlag, Name: "a", Spelling: "--a"}, nil) + if !strings.Contains(long, "`--a`") { + t.Errorf("want --a, got %s", long) + } + short := explain(&Error{Code: CodeMissingRequiredFlag, Name: "a", Spelling: "-a"}, nil) + if !strings.Contains(short, "`-a`") || strings.Contains(short, "--a") { + t.Errorf("want -a, got %s", short) + } + // Nothing carried: the bare name rather than a form the user cannot type. + bare := explain(&Error{Code: CodeMissingRequiredFlag, Name: "a"}, nil) + if strings.Contains(bare, "-a") { + t.Errorf("no spelling means no prefix invented: %s", bare) + } + // Both sides of a conflict get their own. + both := explain(&Error{Code: CodeConflictingFlags, Name: "a", Spelling: "--a", + Other: "f", OtherSpelling: "-f"}, nil) + if !strings.Contains(both, "`--a`") || !strings.Contains(both, "`-f`") { + t.Errorf("want both spellings, got %s", both) + } +} diff --git a/go/internal/shadow/mise/tables.go b/go/internal/shadow/mise/tables.go index c25051f01..7c979b7d4 100644 --- a/go/internal/shadow/mise/tables.go +++ b/go/internal/shadow/mise/tables.go @@ -3784,49 +3784,49 @@ var cmdWhich = &argv.Command{ // commands take keys too, and have no cold half. var Meta = argv.Metadata{ {}, - {Key: FlagContinueOnError, Name: "continue-on-error", Flag: true}, - {Key: FlagCd, Name: "cd", Flag: true}, - {Key: FlagEnv, Name: "env", Flag: true}, - {Key: FlagForce, Name: "force", Flag: true}, - {Key: FlagJobs, Name: "jobs", Flag: true}, - {Key: FlagDryRun, Name: "dry-run", Flag: true}, - {Key: FlagProfile, Name: "profile", Flag: true}, - {Key: FlagQuiet, Name: "quiet", Flag: true}, - {Key: FlagShell, Name: "shell", Flag: true}, - {Key: FlagTool, Name: "tool", Flag: true}, - {Key: FlagVerbose, Name: "verbose", Flag: true}, - {Key: FlagVersion, Name: "version", Flag: true}, - {Key: FlagYes, Name: "yes", Flag: true}, - {Key: FlagDebug, Name: "debug", Flag: true}, - {Key: FlagLogLevel, Name: "log-level", Flag: true, Choices: []string{"trace", "debug", "info", "warning", "error"}}, - {Key: FlagNoConfig, Name: "no-config", Flag: true}, - {Key: FlagNoEnv, Name: "no-env", Flag: true}, - {Key: FlagNoHooks, Name: "no-hooks", Flag: true}, - {Key: FlagNoTimings, Name: "no-timings", Flag: true}, - {Key: FlagOutput, Name: "output", Flag: true}, - {Key: FlagRaw, Name: "raw", Flag: true}, - {Key: FlagLocked, Name: "locked", Flag: true}, - {Key: FlagSilent, Name: "silent", Flag: true}, - {Key: FlagTimings, Name: "timings", Flag: true}, - {Key: FlagTrace, Name: "trace", Flag: true}, + {Key: FlagContinueOnError, Name: "continue-on-error", Flag: true, Spelling: "--continue-on-error"}, + {Key: FlagCd, Name: "cd", Flag: true, Spelling: "--cd"}, + {Key: FlagEnv, Name: "env", Flag: true, Spelling: "--env"}, + {Key: FlagForce, Name: "force", Flag: true, Spelling: "--force"}, + {Key: FlagJobs, Name: "jobs", Flag: true, Spelling: "--jobs"}, + {Key: FlagDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagProfile, Name: "profile", Flag: true, Spelling: "--profile"}, + {Key: FlagQuiet, Name: "quiet", Flag: true, Spelling: "--quiet"}, + {Key: FlagShell, Name: "shell", Flag: true, Spelling: "--shell"}, + {Key: FlagTool, Name: "tool", Flag: true, Spelling: "--tool"}, + {Key: FlagVerbose, Name: "verbose", Flag: true, Spelling: "--verbose"}, + {Key: FlagVersion, Name: "version", Flag: true, Spelling: "--version"}, + {Key: FlagYes, Name: "yes", Flag: true, Spelling: "--yes"}, + {Key: FlagDebug, Name: "debug", Flag: true, Spelling: "--debug"}, + {Key: FlagLogLevel, Name: "log-level", Flag: true, Spelling: "--log-level", Choices: []string{"trace", "debug", "info", "warning", "error"}}, + {Key: FlagNoConfig, Name: "no-config", Flag: true, Spelling: "--no-config"}, + {Key: FlagNoEnv, Name: "no-env", Flag: true, Spelling: "--no-env"}, + {Key: FlagNoHooks, Name: "no-hooks", Flag: true, Spelling: "--no-hooks"}, + {Key: FlagNoTimings, Name: "no-timings", Flag: true, Spelling: "--no-timings"}, + {Key: FlagOutput, Name: "output", Flag: true, Spelling: "--output"}, + {Key: FlagRaw, Name: "raw", Flag: true, Spelling: "--raw"}, + {Key: FlagLocked, Name: "locked", Flag: true, Spelling: "--locked"}, + {Key: FlagSilent, Name: "silent", Flag: true, Spelling: "--silent"}, + {Key: FlagTimings, Name: "timings", Flag: true, Spelling: "--timings"}, + {Key: FlagTrace, Name: "trace", Flag: true, Spelling: "--trace"}, {Key: ArgTask, Name: "TASK"}, {Key: ArgTaskArgs, Name: "TASK_ARGS"}, {Key: ArgTaskArgsLast, Name: "TASK_ARGS_LAST"}, {}, - {Key: FlagActivateQuiet, Name: "quiet", Flag: true}, - {Key: FlagActivateShell, Name: "shell", Flag: true, Choices: []string{"bash", "elvish", "fish", "nu", "xonsh", "zsh", "pwsh"}}, - {Key: FlagActivateNoHookEnv, Name: "no-hook-env", Flag: true}, - {Key: FlagActivateShims, Name: "shims", Flag: true}, - {Key: FlagActivateStatus, Name: "status", Flag: true}, + {Key: FlagActivateQuiet, Name: "quiet", Flag: true, Spelling: "--quiet"}, + {Key: FlagActivateShell, Name: "shell", Flag: true, Spelling: "--shell", Choices: []string{"bash", "elvish", "fish", "nu", "xonsh", "zsh", "pwsh"}}, + {Key: FlagActivateNoHookEnv, Name: "no-hook-env", Flag: true, Spelling: "--no-hook-env"}, + {Key: FlagActivateShims, Name: "shims", Flag: true, Spelling: "--shims"}, + {Key: FlagActivateStatus, Name: "status", Flag: true, Spelling: "--status"}, {Key: ArgActivateShellType, Name: "SHELL_TYPE", Choices: []string{"bash", "elvish", "fish", "nu", "xonsh", "zsh", "pwsh"}}, {}, - {Key: FlagToolAliasTool, Name: "tool", Flag: true}, - {Key: FlagToolAliasNoHeader, Name: "no-header", Flag: true}, + {Key: FlagToolAliasTool, Name: "tool", Flag: true, Spelling: "--tool"}, + {Key: FlagToolAliasNoHeader, Name: "no-header", Flag: true, Spelling: "--no-header"}, {}, {Key: ArgToolAliasGetTool, Name: "TOOL", Required: true}, {Key: ArgToolAliasGetAlias, Name: "ALIAS", Required: true}, {}, - {Key: FlagToolAliasLsNoHeader, Name: "no-header", Flag: true}, + {Key: FlagToolAliasLsNoHeader, Name: "no-header", Flag: true, Spelling: "--no-header"}, {Key: ArgToolAliasLsTool, Name: "TOOL"}, {}, {Key: ArgToolAliasSetTool, Name: "TOOL", Required: true}, @@ -3840,17 +3840,17 @@ var Meta = argv.Metadata{ {}, {}, {}, - {Key: FlagBinPathsBinNames, Name: "bin-names", Flag: true}, - {Key: FlagBinPathsJson, Name: "json", Flag: true}, + {Key: FlagBinPathsBinNames, Name: "bin-names", Flag: true, Spelling: "--bin-names"}, + {Key: FlagBinPathsJson, Name: "json", Flag: true, Spelling: "--json"}, {Key: ArgBinPathsToolVersion, Name: "TOOL@VERSION"}, {}, - {Key: FlagBootstrapDryRun, Name: "dry-run", Flag: true}, - {Key: FlagBootstrapYes, Name: "yes", Flag: true}, - {Key: FlagBootstrapForceDotfiles, Name: "force-dotfiles", Flag: true}, - {Key: FlagBootstrapOnly, Name: "only", Flag: true, Choices: []string{"plugins", "packages", "accounts", "files", "services", "firewall", "compose", "repos", "dotfiles", "mise-shell-activate", "shell", "macos-defaults", "defaults", "macos-launchd-agents", "launchd", "linux-systemd-units", "systemd", "user", "tools", "task", "final-hook"}}, - {Key: FlagBootstrapPromptSecrets, Name: "prompt-secrets", Flag: true}, - {Key: FlagBootstrapSkip, Name: "skip", Flag: true, Choices: []string{"plugins", "packages", "accounts", "files", "services", "firewall", "compose", "repos", "dotfiles", "mise-shell-activate", "shell", "macos-defaults", "defaults", "macos-launchd-agents", "launchd", "linux-systemd-units", "systemd", "user", "tools", "task", "final-hook"}}, - {Key: FlagBootstrapUpdate, Name: "update", Flag: true}, + {Key: FlagBootstrapDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagBootstrapYes, Name: "yes", Flag: true, Spelling: "--yes"}, + {Key: FlagBootstrapForceDotfiles, Name: "force-dotfiles", Flag: true, Spelling: "--force-dotfiles"}, + {Key: FlagBootstrapOnly, Name: "only", Flag: true, Spelling: "--only", Choices: []string{"plugins", "packages", "accounts", "files", "services", "firewall", "compose", "repos", "dotfiles", "mise-shell-activate", "shell", "macos-defaults", "defaults", "macos-launchd-agents", "launchd", "linux-systemd-units", "systemd", "user", "tools", "task", "final-hook"}}, + {Key: FlagBootstrapPromptSecrets, Name: "prompt-secrets", Flag: true, Spelling: "--prompt-secrets"}, + {Key: FlagBootstrapSkip, Name: "skip", Flag: true, Spelling: "--skip", Choices: []string{"plugins", "packages", "accounts", "files", "services", "firewall", "compose", "repos", "dotfiles", "mise-shell-activate", "shell", "macos-defaults", "defaults", "macos-launchd-agents", "launchd", "linux-systemd-units", "systemd", "user", "tools", "task", "final-hook"}}, + {Key: FlagBootstrapUpdate, Name: "update", Flag: true, Spelling: "--update"}, {}, {}, {}, @@ -3859,264 +3859,264 @@ var Meta = argv.Metadata{ {}, {}, {}, - {Key: FlagBootstrapAccountsApplyDryRun, Name: "dry-run", Flag: true}, - {Key: FlagBootstrapAccountsApplyYes, Name: "yes", Flag: true}, + {Key: FlagBootstrapAccountsApplyDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagBootstrapAccountsApplyYes, Name: "yes", Flag: true, Spelling: "--yes"}, {}, - {Key: FlagBootstrapAccountsStatusJson, Name: "json", Flag: true}, - {Key: FlagBootstrapAccountsStatusMissing, Name: "missing", Flag: true}, + {Key: FlagBootstrapAccountsStatusJson, Name: "json", Flag: true, Spelling: "--json"}, + {Key: FlagBootstrapAccountsStatusMissing, Name: "missing", Flag: true, Spelling: "--missing"}, {}, {}, - {Key: FlagBootstrapComposeApplyDryRun, Name: "dry-run", Flag: true}, - {Key: FlagBootstrapComposeApplyYes, Name: "yes", Flag: true}, + {Key: FlagBootstrapComposeApplyDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagBootstrapComposeApplyYes, Name: "yes", Flag: true, Spelling: "--yes"}, {}, - {Key: FlagBootstrapComposeStatusJson, Name: "json", Flag: true}, - {Key: FlagBootstrapComposeStatusMissing, Name: "missing", Flag: true}, + {Key: FlagBootstrapComposeStatusJson, Name: "json", Flag: true, Spelling: "--json"}, + {Key: FlagBootstrapComposeStatusMissing, Name: "missing", Flag: true, Spelling: "--missing"}, {}, {}, - {Key: FlagBootstrapDotfilesAddForce, Name: "force", Flag: true}, - {Key: FlagBootstrapDotfilesAddGlobal, Name: "global", Flag: true}, - {Key: FlagBootstrapDotfilesAddLocal, Name: "local", Flag: true}, - {Key: FlagBootstrapDotfilesAddMode, Name: "mode", Flag: true}, - {Key: FlagBootstrapDotfilesAddDryRun, Name: "dry-run", Flag: true}, - {Key: FlagBootstrapDotfilesAddNoApply, Name: "no-apply", Flag: true}, - {Key: FlagBootstrapDotfilesAddPath, Name: "path", Flag: true}, - {Key: FlagBootstrapDotfilesAddSource, Name: "source", Flag: true}, - {Key: FlagBootstrapDotfilesAddYes, Name: "yes", Flag: true}, + {Key: FlagBootstrapDotfilesAddForce, Name: "force", Flag: true, Spelling: "--force"}, + {Key: FlagBootstrapDotfilesAddGlobal, Name: "global", Flag: true, Spelling: "--global"}, + {Key: FlagBootstrapDotfilesAddLocal, Name: "local", Flag: true, Spelling: "--local"}, + {Key: FlagBootstrapDotfilesAddMode, Name: "mode", Flag: true, Spelling: "--mode"}, + {Key: FlagBootstrapDotfilesAddDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagBootstrapDotfilesAddNoApply, Name: "no-apply", Flag: true, Spelling: "--no-apply"}, + {Key: FlagBootstrapDotfilesAddPath, Name: "path", Flag: true, Spelling: "--path"}, + {Key: FlagBootstrapDotfilesAddSource, Name: "source", Flag: true, Spelling: "--source"}, + {Key: FlagBootstrapDotfilesAddYes, Name: "yes", Flag: true, Spelling: "--yes"}, {Key: ArgBootstrapDotfilesAddTarget, Name: "TARGET", Required: true}, {}, - {Key: FlagBootstrapDotfilesApplyForce, Name: "force", Flag: true}, - {Key: FlagBootstrapDotfilesApplyDryRun, Name: "dry-run", Flag: true}, - {Key: FlagBootstrapDotfilesApplyYes, Name: "yes", Flag: true}, + {Key: FlagBootstrapDotfilesApplyForce, Name: "force", Flag: true, Spelling: "--force"}, + {Key: FlagBootstrapDotfilesApplyDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagBootstrapDotfilesApplyYes, Name: "yes", Flag: true, Spelling: "--yes"}, {Key: ArgBootstrapDotfilesApplyTarget, Name: "TARGET"}, {}, - {Key: FlagBootstrapDotfilesEditApply, Name: "apply", Flag: true}, - {Key: FlagBootstrapDotfilesEditMode, Name: "mode", Flag: true}, - {Key: FlagBootstrapDotfilesEditSource, Name: "source", Flag: true}, - {Key: FlagBootstrapDotfilesEditYes, Name: "yes", Flag: true}, + {Key: FlagBootstrapDotfilesEditApply, Name: "apply", Flag: true, Spelling: "--apply"}, + {Key: FlagBootstrapDotfilesEditMode, Name: "mode", Flag: true, Spelling: "--mode"}, + {Key: FlagBootstrapDotfilesEditSource, Name: "source", Flag: true, Spelling: "--source"}, + {Key: FlagBootstrapDotfilesEditYes, Name: "yes", Flag: true, Spelling: "--yes"}, {Key: ArgBootstrapDotfilesEditTarget, Name: "TARGET", Required: true}, {}, - {Key: FlagBootstrapDotfilesStatusJson, Name: "json", Flag: true}, - {Key: FlagBootstrapDotfilesStatusMissing, Name: "missing", Flag: true}, + {Key: FlagBootstrapDotfilesStatusJson, Name: "json", Flag: true, Spelling: "--json"}, + {Key: FlagBootstrapDotfilesStatusMissing, Name: "missing", Flag: true, Spelling: "--missing"}, {Key: ArgBootstrapDotfilesStatusTarget, Name: "TARGET"}, {}, - {Key: FlagBootstrapDotfilesUnapplyForce, Name: "force", Flag: true}, - {Key: FlagBootstrapDotfilesUnapplyDryRun, Name: "dry-run", Flag: true}, - {Key: FlagBootstrapDotfilesUnapplyYes, Name: "yes", Flag: true}, + {Key: FlagBootstrapDotfilesUnapplyForce, Name: "force", Flag: true, Spelling: "--force"}, + {Key: FlagBootstrapDotfilesUnapplyDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagBootstrapDotfilesUnapplyYes, Name: "yes", Flag: true, Spelling: "--yes"}, {Key: ArgBootstrapDotfilesUnapplyTarget, Name: "TARGET"}, {}, {}, - {Key: FlagBootstrapFilesApplyDryRun, Name: "dry-run", Flag: true}, - {Key: FlagBootstrapFilesApplyYes, Name: "yes", Flag: true}, - {Key: FlagBootstrapFilesApplyPromptSecrets, Name: "prompt-secrets", Flag: true}, + {Key: FlagBootstrapFilesApplyDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagBootstrapFilesApplyYes, Name: "yes", Flag: true, Spelling: "--yes"}, + {Key: FlagBootstrapFilesApplyPromptSecrets, Name: "prompt-secrets", Flag: true, Spelling: "--prompt-secrets"}, {}, - {Key: FlagBootstrapFilesStatusJson, Name: "json", Flag: true}, - {Key: FlagBootstrapFilesStatusMissing, Name: "missing", Flag: true}, - {Key: FlagBootstrapFilesStatusPromptSecrets, Name: "prompt-secrets", Flag: true}, + {Key: FlagBootstrapFilesStatusJson, Name: "json", Flag: true, Spelling: "--json"}, + {Key: FlagBootstrapFilesStatusMissing, Name: "missing", Flag: true, Spelling: "--missing"}, + {Key: FlagBootstrapFilesStatusPromptSecrets, Name: "prompt-secrets", Flag: true, Spelling: "--prompt-secrets"}, {}, {}, - {Key: FlagBootstrapFirewallApplyDryRun, Name: "dry-run", Flag: true}, - {Key: FlagBootstrapFirewallApplyYes, Name: "yes", Flag: true}, + {Key: FlagBootstrapFirewallApplyDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagBootstrapFirewallApplyYes, Name: "yes", Flag: true, Spelling: "--yes"}, {}, - {Key: FlagBootstrapFirewallStatusJson, Name: "json", Flag: true}, - {Key: FlagBootstrapFirewallStatusMissing, Name: "missing", Flag: true}, + {Key: FlagBootstrapFirewallStatusJson, Name: "json", Flag: true, Spelling: "--json"}, + {Key: FlagBootstrapFirewallStatusMissing, Name: "missing", Flag: true, Spelling: "--missing"}, {}, {}, - {Key: FlagBootstrapLaunchdApplyDryRun, Name: "dry-run", Flag: true}, - {Key: FlagBootstrapLaunchdApplyYes, Name: "yes", Flag: true}, + {Key: FlagBootstrapLaunchdApplyDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagBootstrapLaunchdApplyYes, Name: "yes", Flag: true, Spelling: "--yes"}, {}, - {Key: FlagBootstrapLaunchdStatusJson, Name: "json", Flag: true}, - {Key: FlagBootstrapLaunchdStatusMissing, Name: "missing", Flag: true}, + {Key: FlagBootstrapLaunchdStatusJson, Name: "json", Flag: true, Spelling: "--json"}, + {Key: FlagBootstrapLaunchdStatusMissing, Name: "missing", Flag: true, Spelling: "--missing"}, {}, {}, {}, - {Key: FlagBootstrapLinuxSystemdUnitsApplyDryRun, Name: "dry-run", Flag: true}, - {Key: FlagBootstrapLinuxSystemdUnitsApplyYes, Name: "yes", Flag: true}, + {Key: FlagBootstrapLinuxSystemdUnitsApplyDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagBootstrapLinuxSystemdUnitsApplyYes, Name: "yes", Flag: true, Spelling: "--yes"}, {}, - {Key: FlagBootstrapLinuxSystemdUnitsStatusJson, Name: "json", Flag: true}, - {Key: FlagBootstrapLinuxSystemdUnitsStatusMissing, Name: "missing", Flag: true}, + {Key: FlagBootstrapLinuxSystemdUnitsStatusJson, Name: "json", Flag: true, Spelling: "--json"}, + {Key: FlagBootstrapLinuxSystemdUnitsStatusMissing, Name: "missing", Flag: true, Spelling: "--missing"}, {}, {}, {}, - {Key: FlagBootstrapMacosDefaultsApplyDryRun, Name: "dry-run", Flag: true}, - {Key: FlagBootstrapMacosDefaultsApplyYes, Name: "yes", Flag: true}, + {Key: FlagBootstrapMacosDefaultsApplyDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagBootstrapMacosDefaultsApplyYes, Name: "yes", Flag: true, Spelling: "--yes"}, {}, - {Key: FlagBootstrapMacosDefaultsStatusJson, Name: "json", Flag: true}, - {Key: FlagBootstrapMacosDefaultsStatusMissing, Name: "missing", Flag: true}, + {Key: FlagBootstrapMacosDefaultsStatusJson, Name: "json", Flag: true, Spelling: "--json"}, + {Key: FlagBootstrapMacosDefaultsStatusMissing, Name: "missing", Flag: true, Spelling: "--missing"}, {}, {}, - {Key: FlagBootstrapMacosLaunchdAgentsApplyDryRun, Name: "dry-run", Flag: true}, - {Key: FlagBootstrapMacosLaunchdAgentsApplyYes, Name: "yes", Flag: true}, + {Key: FlagBootstrapMacosLaunchdAgentsApplyDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagBootstrapMacosLaunchdAgentsApplyYes, Name: "yes", Flag: true, Spelling: "--yes"}, {}, - {Key: FlagBootstrapMacosLaunchdAgentsStatusJson, Name: "json", Flag: true}, - {Key: FlagBootstrapMacosLaunchdAgentsStatusMissing, Name: "missing", Flag: true}, + {Key: FlagBootstrapMacosLaunchdAgentsStatusJson, Name: "json", Flag: true, Spelling: "--json"}, + {Key: FlagBootstrapMacosLaunchdAgentsStatusMissing, Name: "missing", Flag: true, Spelling: "--missing"}, {}, {}, - {Key: FlagBootstrapMacosDefaultsApplyDryRun2, Name: "dry-run", Flag: true}, - {Key: FlagBootstrapMacosDefaultsApplyYes2, Name: "yes", Flag: true}, + {Key: FlagBootstrapMacosDefaultsApplyDryRun2, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagBootstrapMacosDefaultsApplyYes2, Name: "yes", Flag: true, Spelling: "--yes"}, {}, - {Key: FlagBootstrapMacosDefaultsStatusJson2, Name: "json", Flag: true}, - {Key: FlagBootstrapMacosDefaultsStatusMissing2, Name: "missing", Flag: true}, + {Key: FlagBootstrapMacosDefaultsStatusJson2, Name: "json", Flag: true, Spelling: "--json"}, + {Key: FlagBootstrapMacosDefaultsStatusMissing2, Name: "missing", Flag: true, Spelling: "--missing"}, {}, {}, - {Key: FlagBootstrapMiseShellActivateApplyDryRun, Name: "dry-run", Flag: true}, - {Key: FlagBootstrapMiseShellActivateApplyYes, Name: "yes", Flag: true}, + {Key: FlagBootstrapMiseShellActivateApplyDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagBootstrapMiseShellActivateApplyYes, Name: "yes", Flag: true, Spelling: "--yes"}, {}, - {Key: FlagBootstrapMiseShellActivateStatusJson, Name: "json", Flag: true}, - {Key: FlagBootstrapMiseShellActivateStatusMissing, Name: "missing", Flag: true}, + {Key: FlagBootstrapMiseShellActivateStatusJson, Name: "json", Flag: true, Spelling: "--json"}, + {Key: FlagBootstrapMiseShellActivateStatusMissing, Name: "missing", Flag: true, Spelling: "--missing"}, {}, {}, - {Key: FlagBootstrapPackagesApplyManager, Name: "manager", Flag: true}, - {Key: FlagBootstrapPackagesApplyDryRun, Name: "dry-run", Flag: true}, - {Key: FlagBootstrapPackagesApplyYes, Name: "yes", Flag: true}, - {Key: FlagBootstrapPackagesApplyUpdate, Name: "update", Flag: true}, + {Key: FlagBootstrapPackagesApplyManager, Name: "manager", Flag: true, Spelling: "--manager"}, + {Key: FlagBootstrapPackagesApplyDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagBootstrapPackagesApplyYes, Name: "yes", Flag: true, Spelling: "--yes"}, + {Key: FlagBootstrapPackagesApplyUpdate, Name: "update", Flag: true, Spelling: "--update"}, {Key: ArgBootstrapPackagesApplyPackage, Name: "PACKAGE"}, {}, {}, - {Key: FlagBootstrapPackagesBrewTapLocal, Name: "local", Flag: true}, - {Key: FlagBootstrapPackagesBrewTapDryRun, Name: "dry-run", Flag: true}, - {Key: FlagBootstrapPackagesBrewTapPath, Name: "path", Flag: true}, + {Key: FlagBootstrapPackagesBrewTapLocal, Name: "local", Flag: true, Spelling: "--local"}, + {Key: FlagBootstrapPackagesBrewTapDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagBootstrapPackagesBrewTapPath, Name: "path", Flag: true, Spelling: "--path"}, {Key: ArgBootstrapPackagesBrewTapTap, Name: "TAP", Required: true}, {Key: ArgBootstrapPackagesBrewTapUrl, Name: "URL"}, {}, - {Key: FlagBootstrapPackagesBrewUntapLocal, Name: "local", Flag: true}, - {Key: FlagBootstrapPackagesBrewUntapDryRun, Name: "dry-run", Flag: true}, - {Key: FlagBootstrapPackagesBrewUntapPath, Name: "path", Flag: true}, + {Key: FlagBootstrapPackagesBrewUntapLocal, Name: "local", Flag: true, Spelling: "--local"}, + {Key: FlagBootstrapPackagesBrewUntapDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagBootstrapPackagesBrewUntapPath, Name: "path", Flag: true, Spelling: "--path"}, {Key: ArgBootstrapPackagesBrewUntapTaps, Name: "TAPS", Required: true}, {}, - {Key: FlagBootstrapPackagesImportEnv, Name: "env", Flag: true}, - {Key: FlagBootstrapPackagesImportGlobal, Name: "global", Flag: true}, - {Key: FlagBootstrapPackagesImportManager, Name: "manager", Flag: true, Choices: []string{"brew"}, Default: []string{"brew"}}, - {Key: FlagBootstrapPackagesImportAll, Name: "all", Flag: true}, - {Key: FlagBootstrapPackagesImportDryRun, Name: "dry-run", Flag: true}, - {Key: FlagBootstrapPackagesImportPath, Name: "path", Flag: true}, + {Key: FlagBootstrapPackagesImportEnv, Name: "env", Flag: true, Spelling: "--env"}, + {Key: FlagBootstrapPackagesImportGlobal, Name: "global", Flag: true, Spelling: "--global"}, + {Key: FlagBootstrapPackagesImportManager, Name: "manager", Flag: true, Spelling: "--manager", Choices: []string{"brew"}, Default: []string{"brew"}}, + {Key: FlagBootstrapPackagesImportAll, Name: "all", Flag: true, Spelling: "--all"}, + {Key: FlagBootstrapPackagesImportDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagBootstrapPackagesImportPath, Name: "path", Flag: true, Spelling: "--path"}, {}, - {Key: FlagBootstrapPackagesPruneManager, Name: "manager", Flag: true, Choices: []string{"brew"}, Default: []string{"brew"}}, - {Key: FlagBootstrapPackagesPruneDryRun, Name: "dry-run", Flag: true}, - {Key: FlagBootstrapPackagesPruneYes, Name: "yes", Flag: true}, + {Key: FlagBootstrapPackagesPruneManager, Name: "manager", Flag: true, Spelling: "--manager", Choices: []string{"brew"}, Default: []string{"brew"}}, + {Key: FlagBootstrapPackagesPruneDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagBootstrapPackagesPruneYes, Name: "yes", Flag: true, Spelling: "--yes"}, {}, - {Key: FlagBootstrapPackagesStatusJson, Name: "json", Flag: true}, - {Key: FlagBootstrapPackagesStatusMissing, Name: "missing", Flag: true}, + {Key: FlagBootstrapPackagesStatusJson, Name: "json", Flag: true, Spelling: "--json"}, + {Key: FlagBootstrapPackagesStatusMissing, Name: "missing", Flag: true, Spelling: "--missing"}, {}, - {Key: FlagBootstrapPackagesUpgradeManager, Name: "manager", Flag: true}, - {Key: FlagBootstrapPackagesUpgradeDryRun, Name: "dry-run", Flag: true}, - {Key: FlagBootstrapPackagesUpgradeYes, Name: "yes", Flag: true}, + {Key: FlagBootstrapPackagesUpgradeManager, Name: "manager", Flag: true, Spelling: "--manager"}, + {Key: FlagBootstrapPackagesUpgradeDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagBootstrapPackagesUpgradeYes, Name: "yes", Flag: true, Spelling: "--yes"}, {Key: ArgBootstrapPackagesUpgradePackage, Name: "PACKAGE"}, {}, - {Key: FlagBootstrapPackagesUseEnv, Name: "env", Flag: true}, - {Key: FlagBootstrapPackagesUseGlobal, Name: "global", Flag: true}, - {Key: FlagBootstrapPackagesUseDryRun, Name: "dry-run", Flag: true}, - {Key: FlagBootstrapPackagesUsePath, Name: "path", Flag: true}, - {Key: FlagBootstrapPackagesUseYes, Name: "yes", Flag: true}, + {Key: FlagBootstrapPackagesUseEnv, Name: "env", Flag: true, Spelling: "--env"}, + {Key: FlagBootstrapPackagesUseGlobal, Name: "global", Flag: true, Spelling: "--global"}, + {Key: FlagBootstrapPackagesUseDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagBootstrapPackagesUsePath, Name: "path", Flag: true, Spelling: "--path"}, + {Key: FlagBootstrapPackagesUseYes, Name: "yes", Flag: true, Spelling: "--yes"}, {Key: ArgBootstrapPackagesUsePackage, Name: "PACKAGE", Required: true}, {}, - {Key: FlagBootstrapPlanJson, Name: "json", Flag: true}, - {Key: FlagBootstrapPlanDetailedExitcode, Name: "detailed-exitcode", Flag: true}, - {Key: FlagBootstrapPlanPromptSecrets, Name: "prompt-secrets", Flag: true}, - {}, - {}, - {Key: FlagBootstrapPluginsApplyDryRun, Name: "dry-run", Flag: true}, - {}, - {Key: FlagBootstrapPluginsStatusMissing, Name: "missing", Flag: true}, - {}, - {Key: FlagBootstrapRemoteAll, Name: "all", Flag: true}, - {Key: FlagBootstrapRemoteBootstrapCommand, Name: "bootstrap-command", Flag: true}, - {Key: FlagBootstrapRemoteConnectTimeout, Name: "connect-timeout", Flag: true, Default: []string{"10"}}, - {Key: FlagBootstrapRemoteExclude, Name: "exclude", Flag: true}, - {Key: FlagBootstrapRemoteFailFast, Name: "fail-fast", Flag: true}, - {Key: FlagBootstrapRemoteForceDotfiles, Name: "force-dotfiles", Flag: true}, - {Key: FlagBootstrapRemoteHost, Name: "host", Flag: true}, - {Key: FlagBootstrapRemoteIdentityFile, Name: "identity-file", Flag: true}, - {Key: FlagBootstrapRemoteDryRun, Name: "dry-run", Flag: true}, - {Key: FlagBootstrapRemoteKeepStaging, Name: "keep-staging", Flag: true}, - {Key: FlagBootstrapRemoteMiseBin, Name: "mise-bin", Flag: true}, - {Key: FlagBootstrapRemoteOnly, Name: "only", Flag: true, Choices: []string{"plugins", "packages", "accounts", "files", "services", "firewall", "compose", "repos", "dotfiles", "mise-shell-activate", "shell", "macos-defaults", "defaults", "macos-launchd-agents", "launchd", "linux-systemd-units", "systemd", "user", "tools", "task", "final-hook"}}, - {Key: FlagBootstrapRemotePort, Name: "port", Flag: true}, - {Key: FlagBootstrapRemotePromptSecrets, Name: "prompt-secrets", Flag: true}, - {Key: FlagBootstrapRemoteRemoteMise, Name: "remote-mise", Flag: true}, - {Key: FlagBootstrapRemoteSkip, Name: "skip", Flag: true, Choices: []string{"plugins", "packages", "accounts", "files", "services", "firewall", "compose", "repos", "dotfiles", "mise-shell-activate", "shell", "macos-defaults", "defaults", "macos-launchd-agents", "launchd", "linux-systemd-units", "systemd", "user", "tools", "task", "final-hook"}}, - {Key: FlagBootstrapRemoteSource, Name: "source", Flag: true}, - {Key: FlagBootstrapRemoteSshOption, Name: "ssh-option", Flag: true}, - {Key: FlagBootstrapRemoteTag, Name: "tag", Flag: true}, - {Key: FlagBootstrapRemoteUpdate, Name: "update", Flag: true}, - {Key: FlagBootstrapRemoteYes, Name: "yes", Flag: true}, + {Key: FlagBootstrapPlanJson, Name: "json", Flag: true, Spelling: "--json"}, + {Key: FlagBootstrapPlanDetailedExitcode, Name: "detailed-exitcode", Flag: true, Spelling: "--detailed-exitcode"}, + {Key: FlagBootstrapPlanPromptSecrets, Name: "prompt-secrets", Flag: true, Spelling: "--prompt-secrets"}, + {}, + {}, + {Key: FlagBootstrapPluginsApplyDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {}, + {Key: FlagBootstrapPluginsStatusMissing, Name: "missing", Flag: true, Spelling: "--missing"}, + {}, + {Key: FlagBootstrapRemoteAll, Name: "all", Flag: true, Spelling: "--all"}, + {Key: FlagBootstrapRemoteBootstrapCommand, Name: "bootstrap-command", Flag: true, Spelling: "--bootstrap-command"}, + {Key: FlagBootstrapRemoteConnectTimeout, Name: "connect-timeout", Flag: true, Spelling: "--connect-timeout", Default: []string{"10"}}, + {Key: FlagBootstrapRemoteExclude, Name: "exclude", Flag: true, Spelling: "--exclude"}, + {Key: FlagBootstrapRemoteFailFast, Name: "fail-fast", Flag: true, Spelling: "--fail-fast"}, + {Key: FlagBootstrapRemoteForceDotfiles, Name: "force-dotfiles", Flag: true, Spelling: "--force-dotfiles"}, + {Key: FlagBootstrapRemoteHost, Name: "host", Flag: true, Spelling: "--host"}, + {Key: FlagBootstrapRemoteIdentityFile, Name: "identity-file", Flag: true, Spelling: "--identity-file"}, + {Key: FlagBootstrapRemoteDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagBootstrapRemoteKeepStaging, Name: "keep-staging", Flag: true, Spelling: "--keep-staging"}, + {Key: FlagBootstrapRemoteMiseBin, Name: "mise-bin", Flag: true, Spelling: "--mise-bin"}, + {Key: FlagBootstrapRemoteOnly, Name: "only", Flag: true, Spelling: "--only", Choices: []string{"plugins", "packages", "accounts", "files", "services", "firewall", "compose", "repos", "dotfiles", "mise-shell-activate", "shell", "macos-defaults", "defaults", "macos-launchd-agents", "launchd", "linux-systemd-units", "systemd", "user", "tools", "task", "final-hook"}}, + {Key: FlagBootstrapRemotePort, Name: "port", Flag: true, Spelling: "--port"}, + {Key: FlagBootstrapRemotePromptSecrets, Name: "prompt-secrets", Flag: true, Spelling: "--prompt-secrets"}, + {Key: FlagBootstrapRemoteRemoteMise, Name: "remote-mise", Flag: true, Spelling: "--remote-mise"}, + {Key: FlagBootstrapRemoteSkip, Name: "skip", Flag: true, Spelling: "--skip", Choices: []string{"plugins", "packages", "accounts", "files", "services", "firewall", "compose", "repos", "dotfiles", "mise-shell-activate", "shell", "macos-defaults", "defaults", "macos-launchd-agents", "launchd", "linux-systemd-units", "systemd", "user", "tools", "task", "final-hook"}}, + {Key: FlagBootstrapRemoteSource, Name: "source", Flag: true, Spelling: "--source"}, + {Key: FlagBootstrapRemoteSshOption, Name: "ssh-option", Flag: true, Spelling: "--ssh-option"}, + {Key: FlagBootstrapRemoteTag, Name: "tag", Flag: true, Spelling: "--tag"}, + {Key: FlagBootstrapRemoteUpdate, Name: "update", Flag: true, Spelling: "--update"}, + {Key: FlagBootstrapRemoteYes, Name: "yes", Flag: true, Spelling: "--yes"}, {Key: ArgBootstrapRemoteTarget, Name: "TARGET"}, {}, {}, - {Key: FlagBootstrapReposApplyDryRun, Name: "dry-run", Flag: true}, - {Key: FlagBootstrapReposApplyYes, Name: "yes", Flag: true}, + {Key: FlagBootstrapReposApplyDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagBootstrapReposApplyYes, Name: "yes", Flag: true, Spelling: "--yes"}, {}, - {Key: FlagBootstrapReposExecContinueOnError, Name: "continue-on-error", Flag: true}, - {Key: FlagBootstrapReposExecDryRun, Name: "dry-run", Flag: true}, + {Key: FlagBootstrapReposExecContinueOnError, Name: "continue-on-error", Flag: true, Spelling: "--continue-on-error"}, + {Key: FlagBootstrapReposExecDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, {Key: ArgBootstrapReposExecPath, Name: "PATH"}, {Key: ArgBootstrapReposExecCommand, Name: "COMMAND", Required: true}, {}, - {Key: FlagBootstrapReposStatusJson, Name: "json", Flag: true}, - {Key: FlagBootstrapReposStatusMissing, Name: "missing", Flag: true}, + {Key: FlagBootstrapReposStatusJson, Name: "json", Flag: true, Spelling: "--json"}, + {Key: FlagBootstrapReposStatusMissing, Name: "missing", Flag: true, Spelling: "--missing"}, {}, - {Key: FlagBootstrapReposUpdateDryRun, Name: "dry-run", Flag: true}, - {Key: FlagBootstrapReposUpdateYes, Name: "yes", Flag: true}, + {Key: FlagBootstrapReposUpdateDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagBootstrapReposUpdateYes, Name: "yes", Flag: true, Spelling: "--yes"}, {Key: ArgBootstrapReposUpdatePath, Name: "PATH"}, {}, {}, - {Key: FlagBootstrapSecretsStatusJson, Name: "json", Flag: true}, - {Key: FlagBootstrapSecretsStatusMissing, Name: "missing", Flag: true}, + {Key: FlagBootstrapSecretsStatusJson, Name: "json", Flag: true, Spelling: "--json"}, + {Key: FlagBootstrapSecretsStatusMissing, Name: "missing", Flag: true, Spelling: "--missing"}, {}, {}, - {Key: FlagBootstrapServicesApplyDryRun, Name: "dry-run", Flag: true}, - {Key: FlagBootstrapServicesApplyYes, Name: "yes", Flag: true}, + {Key: FlagBootstrapServicesApplyDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagBootstrapServicesApplyYes, Name: "yes", Flag: true, Spelling: "--yes"}, {}, - {Key: FlagBootstrapServicesStatusJson, Name: "json", Flag: true}, - {Key: FlagBootstrapServicesStatusMissing, Name: "missing", Flag: true}, + {Key: FlagBootstrapServicesStatusJson, Name: "json", Flag: true, Spelling: "--json"}, + {Key: FlagBootstrapServicesStatusMissing, Name: "missing", Flag: true, Spelling: "--missing"}, {}, - {Key: FlagBootstrapStatusJson, Name: "json", Flag: true}, - {Key: FlagBootstrapStatusMissing, Name: "missing", Flag: true}, - {Key: FlagBootstrapStatusPromptSecrets, Name: "prompt-secrets", Flag: true}, + {Key: FlagBootstrapStatusJson, Name: "json", Flag: true, Spelling: "--json"}, + {Key: FlagBootstrapStatusMissing, Name: "missing", Flag: true, Spelling: "--missing"}, + {Key: FlagBootstrapStatusPromptSecrets, Name: "prompt-secrets", Flag: true, Spelling: "--prompt-secrets"}, {}, {}, - {Key: FlagBootstrapSystemdApplyDryRun, Name: "dry-run", Flag: true}, - {Key: FlagBootstrapSystemdApplyYes, Name: "yes", Flag: true}, + {Key: FlagBootstrapSystemdApplyDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagBootstrapSystemdApplyYes, Name: "yes", Flag: true, Spelling: "--yes"}, {}, - {Key: FlagBootstrapSystemdStatusJson, Name: "json", Flag: true}, - {Key: FlagBootstrapSystemdStatusMissing, Name: "missing", Flag: true}, + {Key: FlagBootstrapSystemdStatusJson, Name: "json", Flag: true, Spelling: "--json"}, + {Key: FlagBootstrapSystemdStatusMissing, Name: "missing", Flag: true, Spelling: "--missing"}, {}, {}, - {Key: FlagBootstrapUserApplyDryRun, Name: "dry-run", Flag: true}, - {Key: FlagBootstrapUserApplyYes, Name: "yes", Flag: true}, + {Key: FlagBootstrapUserApplyDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagBootstrapUserApplyYes, Name: "yes", Flag: true, Spelling: "--yes"}, {}, - {Key: FlagBootstrapUserStatusJson, Name: "json", Flag: true}, - {Key: FlagBootstrapUserStatusMissing, Name: "missing", Flag: true}, + {Key: FlagBootstrapUserStatusJson, Name: "json", Flag: true, Spelling: "--json"}, + {Key: FlagBootstrapUserStatusMissing, Name: "missing", Flag: true, Spelling: "--missing"}, {}, {}, - {Key: FlagCacheClearOutdate, Name: "outdate", Flag: true}, - {Key: FlagCacheClearTask, Name: "task", Flag: true}, + {Key: FlagCacheClearOutdate, Name: "outdate", Flag: true, Spelling: "--outdate"}, + {Key: FlagCacheClearTask, Name: "task", Flag: true, Spelling: "--task"}, {Key: ArgCacheClearTool, Name: "TOOL"}, {}, {}, - {Key: FlagCachePruneVerbose, Name: "verbose", Flag: true}, - {Key: FlagCachePruneDryRun, Name: "dry-run", Flag: true}, + {Key: FlagCachePruneVerbose, Name: "verbose", Flag: true, Spelling: "--verbose"}, + {Key: FlagCachePruneDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, {Key: ArgCachePruneTool, Name: "TOOL"}, {}, - {Key: FlagCacheTaskJson, Name: "json", Flag: true}, + {Key: FlagCacheTaskJson, Name: "json", Flag: true, Spelling: "--json"}, {Key: ArgCacheTaskTask, Name: "TASK", Required: true}, {}, - {Key: FlagCompletionShell, Name: "shell", Flag: true, Choices: []string{"bash", "fish", "powershell", "zsh"}}, - {Key: FlagCompletionIncludeBashCompletionLib, Name: "include-bash-completion-lib", Flag: true}, - {Key: FlagCompletionUsage, Name: "usage", Flag: true}, + {Key: FlagCompletionShell, Name: "shell", Flag: true, Spelling: "--shell", Choices: []string{"bash", "fish", "powershell", "zsh"}}, + {Key: FlagCompletionIncludeBashCompletionLib, Name: "include-bash-completion-lib", Flag: true, Spelling: "--include-bash-completion-lib"}, + {Key: FlagCompletionUsage, Name: "usage", Flag: true, Spelling: "--usage"}, {Key: ArgCompletionShell, Name: "SHELL", Choices: []string{"bash", "fish", "powershell", "zsh"}}, {}, - {Key: FlagConfigJson, Name: "json", Flag: true}, - {Key: FlagConfigNoHeader, Name: "no-header", Flag: true}, - {Key: FlagConfigTrackedConfigs, Name: "tracked-configs", Flag: true}, + {Key: FlagConfigJson, Name: "json", Flag: true, Spelling: "--json"}, + {Key: FlagConfigNoHeader, Name: "no-header", Flag: true, Spelling: "--no-header"}, + {Key: FlagConfigTrackedConfigs, Name: "tracked-configs", Flag: true, Spelling: "--tracked-configs"}, {}, - {Key: FlagConfigGetFile, Name: "file", Flag: true}, + {Key: FlagConfigGetFile, Name: "file", Flag: true, Spelling: "--file"}, {Key: ArgConfigGetKey, Name: "KEY"}, {}, - {Key: FlagConfigLsJson, Name: "json", Flag: true}, - {Key: FlagConfigLsNoHeader, Name: "no-header", Flag: true}, - {Key: FlagConfigLsTrackedConfigs, Name: "tracked-configs", Flag: true}, + {Key: FlagConfigLsJson, Name: "json", Flag: true, Spelling: "--json"}, + {Key: FlagConfigLsNoHeader, Name: "no-header", Flag: true, Spelling: "--no-header"}, + {Key: FlagConfigLsTrackedConfigs, Name: "tracked-configs", Flag: true, Spelling: "--tracked-configs"}, {}, - {Key: FlagConfigSetFile, Name: "file", Flag: true}, - {Key: FlagConfigSetType, Name: "type", Flag: true, Choices: []string{"infer", "string", "integer", "float", "bool", "list", "set"}, Default: []string{"infer"}}, + {Key: FlagConfigSetFile, Name: "file", Flag: true, Spelling: "--file"}, + {Key: FlagConfigSetType, Name: "type", Flag: true, Spelling: "--type", Choices: []string{"infer", "string", "integer", "float", "bool", "list", "set"}, Default: []string{"infer"}}, {Key: ArgConfigSetKey, Name: "KEY", Required: true}, {Key: ArgConfigSetValue, Name: "VALUE"}, {}, @@ -4128,444 +4128,444 @@ var Meta = argv.Metadata{ {}, {}, {}, - {Key: FlagDotfilesAddForce, Name: "force", Flag: true}, - {Key: FlagDotfilesAddGlobal, Name: "global", Flag: true}, - {Key: FlagDotfilesAddLocal, Name: "local", Flag: true}, - {Key: FlagDotfilesAddMode, Name: "mode", Flag: true}, - {Key: FlagDotfilesAddDryRun, Name: "dry-run", Flag: true}, - {Key: FlagDotfilesAddNoApply, Name: "no-apply", Flag: true}, - {Key: FlagDotfilesAddPath, Name: "path", Flag: true}, - {Key: FlagDotfilesAddSource, Name: "source", Flag: true}, - {Key: FlagDotfilesAddYes, Name: "yes", Flag: true}, + {Key: FlagDotfilesAddForce, Name: "force", Flag: true, Spelling: "--force"}, + {Key: FlagDotfilesAddGlobal, Name: "global", Flag: true, Spelling: "--global"}, + {Key: FlagDotfilesAddLocal, Name: "local", Flag: true, Spelling: "--local"}, + {Key: FlagDotfilesAddMode, Name: "mode", Flag: true, Spelling: "--mode"}, + {Key: FlagDotfilesAddDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagDotfilesAddNoApply, Name: "no-apply", Flag: true, Spelling: "--no-apply"}, + {Key: FlagDotfilesAddPath, Name: "path", Flag: true, Spelling: "--path"}, + {Key: FlagDotfilesAddSource, Name: "source", Flag: true, Spelling: "--source"}, + {Key: FlagDotfilesAddYes, Name: "yes", Flag: true, Spelling: "--yes"}, {Key: ArgDotfilesAddTarget, Name: "TARGET", Required: true}, {}, - {Key: FlagDotfilesApplyForce, Name: "force", Flag: true}, - {Key: FlagDotfilesApplyDryRun, Name: "dry-run", Flag: true}, - {Key: FlagDotfilesApplyYes, Name: "yes", Flag: true}, + {Key: FlagDotfilesApplyForce, Name: "force", Flag: true, Spelling: "--force"}, + {Key: FlagDotfilesApplyDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagDotfilesApplyYes, Name: "yes", Flag: true, Spelling: "--yes"}, {Key: ArgDotfilesApplyTarget, Name: "TARGET"}, {}, - {Key: FlagDotfilesEditApply, Name: "apply", Flag: true}, - {Key: FlagDotfilesEditMode, Name: "mode", Flag: true}, - {Key: FlagDotfilesEditSource, Name: "source", Flag: true}, - {Key: FlagDotfilesEditYes, Name: "yes", Flag: true}, + {Key: FlagDotfilesEditApply, Name: "apply", Flag: true, Spelling: "--apply"}, + {Key: FlagDotfilesEditMode, Name: "mode", Flag: true, Spelling: "--mode"}, + {Key: FlagDotfilesEditSource, Name: "source", Flag: true, Spelling: "--source"}, + {Key: FlagDotfilesEditYes, Name: "yes", Flag: true, Spelling: "--yes"}, {Key: ArgDotfilesEditTarget, Name: "TARGET", Required: true}, {}, - {Key: FlagDotfilesStatusJson, Name: "json", Flag: true}, - {Key: FlagDotfilesStatusMissing, Name: "missing", Flag: true}, + {Key: FlagDotfilesStatusJson, Name: "json", Flag: true, Spelling: "--json"}, + {Key: FlagDotfilesStatusMissing, Name: "missing", Flag: true, Spelling: "--missing"}, {Key: ArgDotfilesStatusTarget, Name: "TARGET"}, {}, - {Key: FlagDotfilesUnapplyForce, Name: "force", Flag: true}, - {Key: FlagDotfilesUnapplyDryRun, Name: "dry-run", Flag: true}, - {Key: FlagDotfilesUnapplyYes, Name: "yes", Flag: true}, + {Key: FlagDotfilesUnapplyForce, Name: "force", Flag: true, Spelling: "--force"}, + {Key: FlagDotfilesUnapplyDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagDotfilesUnapplyYes, Name: "yes", Flag: true, Spelling: "--yes"}, {Key: ArgDotfilesUnapplyTarget, Name: "TARGET"}, {}, - {Key: FlagDoctorJson, Name: "json", Flag: true}, + {Key: FlagDoctorJson, Name: "json", Flag: true, Spelling: "--json"}, {}, - {Key: FlagDoctorPathFull, Name: "full", Flag: true}, + {Key: FlagDoctorPathFull, Name: "full", Flag: true, Spelling: "--full"}, {}, - {Key: FlagEnShell, Name: "shell", Flag: true}, + {Key: FlagEnShell, Name: "shell", Flag: true, Spelling: "--shell"}, {Key: ArgEnDir, Name: "DIR", Default: []string{"."}}, {}, - {Key: FlagEnvDotenv, Name: "dotenv", Flag: true}, - {Key: FlagEnvJson, Name: "json", Flag: true}, - {Key: FlagEnvShell, Name: "shell", Flag: true, Choices: []string{"bash", "elvish", "fish", "nu", "xonsh", "zsh", "pwsh"}}, - {Key: FlagEnvJsonExtended, Name: "json-extended", Flag: true}, - {Key: FlagEnvRedacted, Name: "redacted", Flag: true}, - {Key: FlagEnvValues, Name: "values", Flag: true}, + {Key: FlagEnvDotenv, Name: "dotenv", Flag: true, Spelling: "--dotenv"}, + {Key: FlagEnvJson, Name: "json", Flag: true, Spelling: "--json"}, + {Key: FlagEnvShell, Name: "shell", Flag: true, Spelling: "--shell", Choices: []string{"bash", "elvish", "fish", "nu", "xonsh", "zsh", "pwsh"}}, + {Key: FlagEnvJsonExtended, Name: "json-extended", Flag: true, Spelling: "--json-extended"}, + {Key: FlagEnvRedacted, Name: "redacted", Flag: true, Spelling: "--redacted"}, + {Key: FlagEnvValues, Name: "values", Flag: true, Spelling: "--values"}, {Key: ArgEnvToolVersion, Name: "TOOL@VERSION"}, {}, - {Key: FlagExecCommand, Name: "command", Flag: true}, - {Key: FlagExecJobs, Name: "jobs", Flag: true}, - {Key: FlagExecAllowEnv, Name: "allow-env", Flag: true}, - {Key: FlagExecAllowNet, Name: "allow-net", Flag: true}, - {Key: FlagExecAllowRead, Name: "allow-read", Flag: true}, - {Key: FlagExecAllowWrite, Name: "allow-write", Flag: true}, - {Key: FlagExecDenyAll, Name: "deny-all", Flag: true}, - {Key: FlagExecDenyEnv, Name: "deny-env", Flag: true}, - {Key: FlagExecDenyNet, Name: "deny-net", Flag: true}, - {Key: FlagExecDenyRead, Name: "deny-read", Flag: true}, - {Key: FlagExecDenyWrite, Name: "deny-write", Flag: true}, - {Key: FlagExecFreshEnv, Name: "fresh-env", Flag: true}, - {Key: FlagExecNoDeps, Name: "no-deps", Flag: true}, - {Key: FlagExecRaw, Name: "raw", Flag: true}, + {Key: FlagExecCommand, Name: "command", Flag: true, Spelling: "--command"}, + {Key: FlagExecJobs, Name: "jobs", Flag: true, Spelling: "--jobs"}, + {Key: FlagExecAllowEnv, Name: "allow-env", Flag: true, Spelling: "--allow-env"}, + {Key: FlagExecAllowNet, Name: "allow-net", Flag: true, Spelling: "--allow-net"}, + {Key: FlagExecAllowRead, Name: "allow-read", Flag: true, Spelling: "--allow-read"}, + {Key: FlagExecAllowWrite, Name: "allow-write", Flag: true, Spelling: "--allow-write"}, + {Key: FlagExecDenyAll, Name: "deny-all", Flag: true, Spelling: "--deny-all"}, + {Key: FlagExecDenyEnv, Name: "deny-env", Flag: true, Spelling: "--deny-env"}, + {Key: FlagExecDenyNet, Name: "deny-net", Flag: true, Spelling: "--deny-net"}, + {Key: FlagExecDenyRead, Name: "deny-read", Flag: true, Spelling: "--deny-read"}, + {Key: FlagExecDenyWrite, Name: "deny-write", Flag: true, Spelling: "--deny-write"}, + {Key: FlagExecFreshEnv, Name: "fresh-env", Flag: true, Spelling: "--fresh-env"}, + {Key: FlagExecNoDeps, Name: "no-deps", Flag: true, Spelling: "--no-deps"}, + {Key: FlagExecRaw, Name: "raw", Flag: true, Spelling: "--raw"}, {Key: ArgExecToolVersion, Name: "TOOL@VERSION"}, {Key: ArgExecCommand, Name: "COMMAND"}, {}, - {Key: FlagFmtAll, Name: "all", Flag: true}, - {Key: FlagFmtCheck, Name: "check", Flag: true}, - {Key: FlagFmtStdin, Name: "stdin", Flag: true}, + {Key: FlagFmtAll, Name: "all", Flag: true, Spelling: "--all"}, + {Key: FlagFmtCheck, Name: "check", Flag: true, Spelling: "--check"}, + {Key: FlagFmtStdin, Name: "stdin", Flag: true, Spelling: "--stdin"}, {}, {}, - {Key: FlagGenerateBootstrapLocalize, Name: "localize", Flag: true}, - {Key: FlagGenerateBootstrapVersion, Name: "version", Flag: true}, - {Key: FlagGenerateBootstrapWrite, Name: "write", Flag: true}, - {Key: FlagGenerateBootstrapLocalizedDir, Name: "localized-dir", Flag: true, Default: []string{".mise"}}, + {Key: FlagGenerateBootstrapLocalize, Name: "localize", Flag: true, Spelling: "--localize"}, + {Key: FlagGenerateBootstrapVersion, Name: "version", Flag: true, Spelling: "--version"}, + {Key: FlagGenerateBootstrapWrite, Name: "write", Flag: true, Spelling: "--write"}, + {Key: FlagGenerateBootstrapLocalizedDir, Name: "localized-dir", Flag: true, Spelling: "--localized-dir", Default: []string{".mise"}}, {}, - {Key: FlagGenerateConfigGlobal, Name: "global", Flag: true}, - {Key: FlagGenerateConfigDryRun, Name: "dry-run", Flag: true}, - {Key: FlagGenerateConfigToolVersions, Name: "tool-versions", Flag: true}, + {Key: FlagGenerateConfigGlobal, Name: "global", Flag: true, Spelling: "--global"}, + {Key: FlagGenerateConfigDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagGenerateConfigToolVersions, Name: "tool-versions", Flag: true, Spelling: "--tool-versions"}, {Key: ArgGenerateConfigPath, Name: "PATH"}, {}, - {Key: FlagGenerateDevcontainerImage, Name: "image", Flag: true}, - {Key: FlagGenerateDevcontainerMountMiseData, Name: "mount-mise-data", Flag: true}, - {Key: FlagGenerateDevcontainerName, Name: "name", Flag: true}, - {Key: FlagGenerateDevcontainerWrite, Name: "write", Flag: true}, - {}, - {Key: FlagGenerateGitPreCommitTask, Name: "task", Flag: true, Default: []string{"pre-commit"}}, - {Key: FlagGenerateGitPreCommitWrite, Name: "write", Flag: true}, - {Key: FlagGenerateGitPreCommitHook, Name: "hook", Flag: true, Default: []string{"pre-commit"}}, - {}, - {Key: FlagGenerateGithubActionTask, Name: "task", Flag: true, Default: []string{"ci"}}, - {Key: FlagGenerateGithubActionWrite, Name: "write", Flag: true}, - {Key: FlagGenerateGithubActionName, Name: "name", Flag: true, Default: []string{"ci"}}, - {}, - {Key: FlagGenerateTaskDocsInject, Name: "inject", Flag: true}, - {Key: FlagGenerateTaskDocsIndex, Name: "index", Flag: true}, - {Key: FlagGenerateTaskDocsMulti, Name: "multi", Flag: true}, - {Key: FlagGenerateTaskDocsOutput, Name: "output", Flag: true}, - {Key: FlagGenerateTaskDocsRoot, Name: "root", Flag: true}, - {Key: FlagGenerateTaskDocsStyle, Name: "style", Flag: true, Choices: []string{"simple", "detailed"}, Default: []string{"simple"}}, - {}, - {Key: FlagGenerateTaskStubsDir, Name: "dir", Flag: true, Default: []string{"bin"}}, - {Key: FlagGenerateTaskStubsMiseBin, Name: "mise-bin", Flag: true, Default: []string{"mise"}}, - {}, - {Key: FlagGenerateToolStubBin, Name: "bin", Flag: true}, - {Key: FlagGenerateToolStubBootstrap, Name: "bootstrap", Flag: true}, - {Key: FlagGenerateToolStubBootstrapVersion, Name: "bootstrap-version", Flag: true}, - {Key: FlagGenerateToolStubFetch, Name: "fetch", Flag: true}, - {Key: FlagGenerateToolStubHttp, Name: "http", Flag: true, Default: []string{"http"}}, - {Key: FlagGenerateToolStubLock, Name: "lock", Flag: true}, - {Key: FlagGenerateToolStubPlatformBin, Name: "platform-bin", Flag: true}, - {Key: FlagGenerateToolStubPlatformUrl, Name: "platform-url", Flag: true}, - {Key: FlagGenerateToolStubSkipDownload, Name: "skip-download", Flag: true}, - {Key: FlagGenerateToolStubUrl, Name: "url", Flag: true}, - {Key: FlagGenerateToolStubVersion, Name: "version", Flag: true, Default: []string{"latest"}}, + {Key: FlagGenerateDevcontainerImage, Name: "image", Flag: true, Spelling: "--image"}, + {Key: FlagGenerateDevcontainerMountMiseData, Name: "mount-mise-data", Flag: true, Spelling: "--mount-mise-data"}, + {Key: FlagGenerateDevcontainerName, Name: "name", Flag: true, Spelling: "--name"}, + {Key: FlagGenerateDevcontainerWrite, Name: "write", Flag: true, Spelling: "--write"}, + {}, + {Key: FlagGenerateGitPreCommitTask, Name: "task", Flag: true, Spelling: "--task", Default: []string{"pre-commit"}}, + {Key: FlagGenerateGitPreCommitWrite, Name: "write", Flag: true, Spelling: "--write"}, + {Key: FlagGenerateGitPreCommitHook, Name: "hook", Flag: true, Spelling: "--hook", Default: []string{"pre-commit"}}, + {}, + {Key: FlagGenerateGithubActionTask, Name: "task", Flag: true, Spelling: "--task", Default: []string{"ci"}}, + {Key: FlagGenerateGithubActionWrite, Name: "write", Flag: true, Spelling: "--write"}, + {Key: FlagGenerateGithubActionName, Name: "name", Flag: true, Spelling: "--name", Default: []string{"ci"}}, + {}, + {Key: FlagGenerateTaskDocsInject, Name: "inject", Flag: true, Spelling: "--inject"}, + {Key: FlagGenerateTaskDocsIndex, Name: "index", Flag: true, Spelling: "--index"}, + {Key: FlagGenerateTaskDocsMulti, Name: "multi", Flag: true, Spelling: "--multi"}, + {Key: FlagGenerateTaskDocsOutput, Name: "output", Flag: true, Spelling: "--output"}, + {Key: FlagGenerateTaskDocsRoot, Name: "root", Flag: true, Spelling: "--root"}, + {Key: FlagGenerateTaskDocsStyle, Name: "style", Flag: true, Spelling: "--style", Choices: []string{"simple", "detailed"}, Default: []string{"simple"}}, + {}, + {Key: FlagGenerateTaskStubsDir, Name: "dir", Flag: true, Spelling: "--dir", Default: []string{"bin"}}, + {Key: FlagGenerateTaskStubsMiseBin, Name: "mise-bin", Flag: true, Spelling: "--mise-bin", Default: []string{"mise"}}, + {}, + {Key: FlagGenerateToolStubBin, Name: "bin", Flag: true, Spelling: "--bin"}, + {Key: FlagGenerateToolStubBootstrap, Name: "bootstrap", Flag: true, Spelling: "--bootstrap"}, + {Key: FlagGenerateToolStubBootstrapVersion, Name: "bootstrap-version", Flag: true, Spelling: "--bootstrap-version"}, + {Key: FlagGenerateToolStubFetch, Name: "fetch", Flag: true, Spelling: "--fetch"}, + {Key: FlagGenerateToolStubHttp, Name: "http", Flag: true, Spelling: "--http", Default: []string{"http"}}, + {Key: FlagGenerateToolStubLock, Name: "lock", Flag: true, Spelling: "--lock"}, + {Key: FlagGenerateToolStubPlatformBin, Name: "platform-bin", Flag: true, Spelling: "--platform-bin"}, + {Key: FlagGenerateToolStubPlatformUrl, Name: "platform-url", Flag: true, Spelling: "--platform-url"}, + {Key: FlagGenerateToolStubSkipDownload, Name: "skip-download", Flag: true, Spelling: "--skip-download"}, + {Key: FlagGenerateToolStubUrl, Name: "url", Flag: true, Spelling: "--url"}, + {Key: FlagGenerateToolStubVersion, Name: "version", Flag: true, Spelling: "--version", Default: []string{"latest"}}, {Key: ArgGenerateToolStubOutput, Name: "OUTPUT", Required: true}, {}, {}, - {Key: FlagGithubTokenOauth, Name: "oauth", Flag: true}, - {Key: FlagGithubTokenRaw, Name: "raw", Flag: true}, - {Key: FlagGithubTokenRefresh, Name: "refresh", Flag: true}, - {Key: FlagGithubTokenUnmask, Name: "unmask", Flag: true}, + {Key: FlagGithubTokenOauth, Name: "oauth", Flag: true, Spelling: "--oauth"}, + {Key: FlagGithubTokenRaw, Name: "raw", Flag: true, Spelling: "--raw"}, + {Key: FlagGithubTokenRefresh, Name: "refresh", Flag: true, Spelling: "--refresh"}, + {Key: FlagGithubTokenUnmask, Name: "unmask", Flag: true, Spelling: "--unmask"}, {Key: ArgGithubTokenHost, Name: "HOST", Default: []string{"github.com"}}, {}, - {Key: FlagGlobalFuzzy, Name: "fuzzy", Flag: true}, - {Key: FlagGlobalPath, Name: "path", Flag: true}, - {Key: FlagGlobalPin, Name: "pin", Flag: true}, - {Key: FlagGlobalRemove, Name: "remove", Flag: true}, + {Key: FlagGlobalFuzzy, Name: "fuzzy", Flag: true, Spelling: "--fuzzy"}, + {Key: FlagGlobalPath, Name: "path", Flag: true, Spelling: "--path"}, + {Key: FlagGlobalPin, Name: "pin", Flag: true, Spelling: "--pin"}, + {Key: FlagGlobalRemove, Name: "remove", Flag: true, Spelling: "--remove"}, {Key: ArgGlobalToolVersion, Name: "TOOL@VERSION"}, {}, - {Key: FlagHookEnvForce, Name: "force", Flag: true}, - {Key: FlagHookEnvQuiet, Name: "quiet", Flag: true}, - {Key: FlagHookEnvShell, Name: "shell", Flag: true, Choices: []string{"bash", "elvish", "fish", "nu", "xonsh", "zsh", "pwsh"}}, - {Key: FlagHookEnvReason, Name: "reason", Flag: true, Choices: []string{"precmd", "chpwd"}}, - {Key: FlagHookEnvStatus, Name: "status", Flag: true}, + {Key: FlagHookEnvForce, Name: "force", Flag: true, Spelling: "--force"}, + {Key: FlagHookEnvQuiet, Name: "quiet", Flag: true, Spelling: "--quiet"}, + {Key: FlagHookEnvShell, Name: "shell", Flag: true, Spelling: "--shell", Choices: []string{"bash", "elvish", "fish", "nu", "xonsh", "zsh", "pwsh"}}, + {Key: FlagHookEnvReason, Name: "reason", Flag: true, Spelling: "--reason", Choices: []string{"precmd", "chpwd"}}, + {Key: FlagHookEnvStatus, Name: "status", Flag: true, Spelling: "--status"}, {}, - {Key: FlagHookNotFoundShell, Name: "shell", Flag: true, Choices: []string{"bash", "elvish", "fish", "nu", "xonsh", "zsh", "pwsh"}}, + {Key: FlagHookNotFoundShell, Name: "shell", Flag: true, Spelling: "--shell", Choices: []string{"bash", "elvish", "fish", "nu", "xonsh", "zsh", "pwsh"}}, {Key: ArgHookNotFoundBin, Name: "BIN", Required: true}, {}, - {Key: FlagImplodeDryRun, Name: "dry-run", Flag: true}, - {Key: FlagImplodeConfig, Name: "config", Flag: true}, + {Key: FlagImplodeDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagImplodeConfig, Name: "config", Flag: true, Spelling: "--config"}, {}, - {Key: FlagEditGlobal, Name: "global", Flag: true}, - {Key: FlagEditDryRun, Name: "dry-run", Flag: true}, - {Key: FlagEditToolVersions, Name: "tool-versions", Flag: true}, + {Key: FlagEditGlobal, Name: "global", Flag: true, Spelling: "--global"}, + {Key: FlagEditDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagEditToolVersions, Name: "tool-versions", Flag: true, Spelling: "--tool-versions"}, {Key: ArgEditPath, Name: "PATH"}, {}, - {Key: FlagInstallForce, Name: "force", Flag: true}, - {Key: FlagInstallJobs, Name: "jobs", Flag: true}, - {Key: FlagInstallDryRun, Name: "dry-run", Flag: true}, - {Key: FlagInstallVerbose, Name: "verbose", Flag: true}, - {Key: FlagInstallDryRunCode, Name: "dry-run-code", Flag: true}, - {Key: FlagInstallMinimumReleaseAge, Name: "minimum-release-age", Flag: true}, - {Key: FlagInstallMonorepo, Name: "monorepo", Flag: true}, - {Key: FlagInstallRaw, Name: "raw", Flag: true}, - {Key: FlagInstallShared, Name: "shared", Flag: true}, - {Key: FlagInstallSystem, Name: "system", Flag: true}, + {Key: FlagInstallForce, Name: "force", Flag: true, Spelling: "--force"}, + {Key: FlagInstallJobs, Name: "jobs", Flag: true, Spelling: "--jobs"}, + {Key: FlagInstallDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagInstallVerbose, Name: "verbose", Flag: true, Spelling: "--verbose"}, + {Key: FlagInstallDryRunCode, Name: "dry-run-code", Flag: true, Spelling: "--dry-run-code"}, + {Key: FlagInstallMinimumReleaseAge, Name: "minimum-release-age", Flag: true, Spelling: "--minimum-release-age"}, + {Key: FlagInstallMonorepo, Name: "monorepo", Flag: true, Spelling: "--monorepo"}, + {Key: FlagInstallRaw, Name: "raw", Flag: true, Spelling: "--raw"}, + {Key: FlagInstallShared, Name: "shared", Flag: true, Spelling: "--shared"}, + {Key: FlagInstallSystem, Name: "system", Flag: true, Spelling: "--system"}, {Key: ArgInstallToolVersion, Name: "TOOL@VERSION"}, {}, {Key: ArgInstallIntoToolVersion, Name: "TOOL@VERSION", Required: true}, {Key: ArgInstallIntoPath, Name: "PATH", Required: true}, {}, - {Key: FlagLatestInstalled, Name: "installed", Flag: true}, - {Key: FlagLatestMinimumReleaseAge, Name: "minimum-release-age", Flag: true}, + {Key: FlagLatestInstalled, Name: "installed", Flag: true, Spelling: "--installed"}, + {Key: FlagLatestMinimumReleaseAge, Name: "minimum-release-age", Flag: true, Spelling: "--minimum-release-age"}, {Key: ArgLatestToolVersion, Name: "TOOL@VERSION", Required: true}, {Key: ArgLatestAsdfVersion, Name: "ASDF_VERSION"}, {}, - {Key: FlagLinkForce, Name: "force", Flag: true}, + {Key: FlagLinkForce, Name: "force", Flag: true, Spelling: "--force"}, {Key: ArgLinkToolVersion, Name: "TOOL@VERSION", Required: true}, {Key: ArgLinkPath, Name: "PATH", Required: true}, {}, - {Key: FlagLocalParent, Name: "parent", Flag: true}, - {Key: FlagLocalFuzzy, Name: "fuzzy", Flag: true}, - {Key: FlagLocalPath, Name: "path", Flag: true}, - {Key: FlagLocalPin, Name: "pin", Flag: true}, - {Key: FlagLocalRemove, Name: "remove", Flag: true}, + {Key: FlagLocalParent, Name: "parent", Flag: true, Spelling: "--parent"}, + {Key: FlagLocalFuzzy, Name: "fuzzy", Flag: true, Spelling: "--fuzzy"}, + {Key: FlagLocalPath, Name: "path", Flag: true, Spelling: "--path"}, + {Key: FlagLocalPin, Name: "pin", Flag: true, Spelling: "--pin"}, + {Key: FlagLocalRemove, Name: "remove", Flag: true, Spelling: "--remove"}, {Key: ArgLocalToolVersion, Name: "TOOL@VERSION"}, {}, - {Key: FlagLockGlobal, Name: "global", Flag: true}, - {Key: FlagLockJobs, Name: "jobs", Flag: true}, - {Key: FlagLockDryRun, Name: "dry-run", Flag: true}, - {Key: FlagLockPlatform, Name: "platform", Flag: true}, - {Key: FlagLockBump, Name: "bump", Flag: true}, - {Key: FlagLockJson, Name: "json", Flag: true}, - {Key: FlagLockLocal, Name: "local", Flag: true}, - {Key: FlagLockMinimumReleaseAge, Name: "minimum-release-age", Flag: true}, + {Key: FlagLockGlobal, Name: "global", Flag: true, Spelling: "--global"}, + {Key: FlagLockJobs, Name: "jobs", Flag: true, Spelling: "--jobs"}, + {Key: FlagLockDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagLockPlatform, Name: "platform", Flag: true, Spelling: "--platform"}, + {Key: FlagLockBump, Name: "bump", Flag: true, Spelling: "--bump"}, + {Key: FlagLockJson, Name: "json", Flag: true, Spelling: "--json"}, + {Key: FlagLockLocal, Name: "local", Flag: true, Spelling: "--local"}, + {Key: FlagLockMinimumReleaseAge, Name: "minimum-release-age", Flag: true, Spelling: "--minimum-release-age"}, {Key: ArgLockTool, Name: "TOOL"}, {}, - {Key: FlagLsCurrent, Name: "current", Flag: true}, - {Key: FlagLsGlobal, Name: "global", Flag: true}, - {Key: FlagLsInstalled, Name: "installed", Flag: true}, - {Key: FlagLsJson, Name: "json", Flag: true}, - {Key: FlagLsLocal, Name: "local", Flag: true}, - {Key: FlagLsMissing, Name: "missing", Flag: true}, - {Key: FlagLsOffline, Name: "offline", Flag: true}, - {Key: FlagLsPlugin, Name: "plugin", Flag: true}, - {Key: FlagLsAllSources, Name: "all-sources", Flag: true}, - {Key: FlagLsMonorepo, Name: "monorepo", Flag: true}, - {Key: FlagLsNoHeader, Name: "no-header", Flag: true}, - {Key: FlagLsOutdated, Name: "outdated", Flag: true}, - {Key: FlagLsPrefix, Name: "prefix", Flag: true}, - {Key: FlagLsPrunable, Name: "prunable", Flag: true}, + {Key: FlagLsCurrent, Name: "current", Flag: true, Spelling: "--current"}, + {Key: FlagLsGlobal, Name: "global", Flag: true, Spelling: "--global"}, + {Key: FlagLsInstalled, Name: "installed", Flag: true, Spelling: "--installed"}, + {Key: FlagLsJson, Name: "json", Flag: true, Spelling: "--json"}, + {Key: FlagLsLocal, Name: "local", Flag: true, Spelling: "--local"}, + {Key: FlagLsMissing, Name: "missing", Flag: true, Spelling: "--missing"}, + {Key: FlagLsOffline, Name: "offline", Flag: true, Spelling: "--offline"}, + {Key: FlagLsPlugin, Name: "plugin", Flag: true, Spelling: "--plugin"}, + {Key: FlagLsAllSources, Name: "all-sources", Flag: true, Spelling: "--all-sources"}, + {Key: FlagLsMonorepo, Name: "monorepo", Flag: true, Spelling: "--monorepo"}, + {Key: FlagLsNoHeader, Name: "no-header", Flag: true, Spelling: "--no-header"}, + {Key: FlagLsOutdated, Name: "outdated", Flag: true, Spelling: "--outdated"}, + {Key: FlagLsPrefix, Name: "prefix", Flag: true, Spelling: "--prefix"}, + {Key: FlagLsPrunable, Name: "prunable", Flag: true, Spelling: "--prunable"}, {Key: ArgLsInstalledTool, Name: "INSTALLED_TOOL"}, {}, - {Key: FlagLsRemoteAll, Name: "all", Flag: true}, - {Key: FlagLsRemoteMinimumReleaseAge, Name: "minimum-release-age", Flag: true}, - {Key: FlagLsRemoteJson, Name: "json", Flag: true}, - {Key: FlagLsRemoteNoVersionsHost, Name: "no-versions-host", Flag: true}, - {Key: FlagLsRemotePrerelease, Name: "prerelease", Flag: true}, - {Key: FlagLsRemoteStrictMetadata, Name: "strict-metadata", Flag: true}, + {Key: FlagLsRemoteAll, Name: "all", Flag: true, Spelling: "--all"}, + {Key: FlagLsRemoteMinimumReleaseAge, Name: "minimum-release-age", Flag: true, Spelling: "--minimum-release-age"}, + {Key: FlagLsRemoteJson, Name: "json", Flag: true, Spelling: "--json"}, + {Key: FlagLsRemoteNoVersionsHost, Name: "no-versions-host", Flag: true, Spelling: "--no-versions-host"}, + {Key: FlagLsRemotePrerelease, Name: "prerelease", Flag: true, Spelling: "--prerelease"}, + {Key: FlagLsRemoteStrictMetadata, Name: "strict-metadata", Flag: true, Spelling: "--strict-metadata"}, {Key: ArgLsRemoteToolVersion, Name: "TOOL@VERSION"}, {Key: ArgLsRemotePrefix, Name: "PREFIX"}, {}, {}, {}, - {Key: FlagOciBuildCopy, Name: "copy", Flag: true}, - {Key: FlagOciBuildOutput, Name: "output", Flag: true, Default: []string{"./mise-oci"}}, - {Key: FlagOciBuildFrom, Name: "from", Flag: true}, - {Key: FlagOciBuildIncludeGlobal, Name: "include-global", Flag: true}, - {Key: FlagOciBuildTag, Name: "tag", Flag: true}, - {Key: FlagOciBuildMountPoint, Name: "mount-point", Flag: true}, - {Key: FlagOciBuildNoMise, Name: "no-mise", Flag: true}, - {Key: FlagOciBuildOwner, Name: "owner", Flag: true}, - {}, - {Key: FlagOciPushCacheFrom, Name: "cache-from", Flag: true}, - {Key: FlagOciPushFrom, Name: "from", Flag: true}, - {Key: FlagOciPushImageDir, Name: "image-dir", Flag: true}, - {Key: FlagOciPushIncludeGlobal, Name: "include-global", Flag: true}, - {Key: FlagOciPushMountPoint, Name: "mount-point", Flag: true}, - {Key: FlagOciPushNoCache, Name: "no-cache", Flag: true}, - {Key: FlagOciPushNoMise, Name: "no-mise", Flag: true}, - {Key: FlagOciPushOwner, Name: "owner", Flag: true}, - {Key: FlagOciPushUpdateIndex, Name: "update-index", Flag: true}, + {Key: FlagOciBuildCopy, Name: "copy", Flag: true, Spelling: "--copy"}, + {Key: FlagOciBuildOutput, Name: "output", Flag: true, Spelling: "--output", Default: []string{"./mise-oci"}}, + {Key: FlagOciBuildFrom, Name: "from", Flag: true, Spelling: "--from"}, + {Key: FlagOciBuildIncludeGlobal, Name: "include-global", Flag: true, Spelling: "--include-global"}, + {Key: FlagOciBuildTag, Name: "tag", Flag: true, Spelling: "--tag"}, + {Key: FlagOciBuildMountPoint, Name: "mount-point", Flag: true, Spelling: "--mount-point"}, + {Key: FlagOciBuildNoMise, Name: "no-mise", Flag: true, Spelling: "--no-mise"}, + {Key: FlagOciBuildOwner, Name: "owner", Flag: true, Spelling: "--owner"}, + {}, + {Key: FlagOciPushCacheFrom, Name: "cache-from", Flag: true, Spelling: "--cache-from"}, + {Key: FlagOciPushFrom, Name: "from", Flag: true, Spelling: "--from"}, + {Key: FlagOciPushImageDir, Name: "image-dir", Flag: true, Spelling: "--image-dir"}, + {Key: FlagOciPushIncludeGlobal, Name: "include-global", Flag: true, Spelling: "--include-global"}, + {Key: FlagOciPushMountPoint, Name: "mount-point", Flag: true, Spelling: "--mount-point"}, + {Key: FlagOciPushNoCache, Name: "no-cache", Flag: true, Spelling: "--no-cache"}, + {Key: FlagOciPushNoMise, Name: "no-mise", Flag: true, Spelling: "--no-mise"}, + {Key: FlagOciPushOwner, Name: "owner", Flag: true, Spelling: "--owner"}, + {Key: FlagOciPushUpdateIndex, Name: "update-index", Flag: true, Spelling: "--update-index"}, {Key: ArgOciPushRef, Name: "REF", Required: true}, {}, - {Key: FlagOciRunEngine, Name: "engine", Flag: true, Choices: []string{"auto", "podman", "docker"}, Default: []string{"auto"}}, - {Key: FlagOciRunFrom, Name: "from", Flag: true}, - {Key: FlagOciRunImageDir, Name: "image-dir", Flag: true}, - {Key: FlagOciRunIncludeGlobal, Name: "include-global", Flag: true}, - {Key: FlagOciRunKeep, Name: "keep", Flag: true}, - {Key: FlagOciRunMountPoint, Name: "mount-point", Flag: true}, - {Key: FlagOciRunNoMise, Name: "no-mise", Flag: true}, - {Key: FlagOciRunOwner, Name: "owner", Flag: true}, - {Key: FlagOciRunVolume, Name: "volume", Flag: true}, - {Key: FlagOciRunEnv, Name: "env", Flag: true}, - {Key: FlagOciRunInteractive, Name: "interactive", Flag: true}, - {Key: FlagOciRunTty, Name: "tty", Flag: true}, - {Key: FlagOciRunWorkdir, Name: "workdir", Flag: true}, + {Key: FlagOciRunEngine, Name: "engine", Flag: true, Spelling: "--engine", Choices: []string{"auto", "podman", "docker"}, Default: []string{"auto"}}, + {Key: FlagOciRunFrom, Name: "from", Flag: true, Spelling: "--from"}, + {Key: FlagOciRunImageDir, Name: "image-dir", Flag: true, Spelling: "--image-dir"}, + {Key: FlagOciRunIncludeGlobal, Name: "include-global", Flag: true, Spelling: "--include-global"}, + {Key: FlagOciRunKeep, Name: "keep", Flag: true, Spelling: "--keep"}, + {Key: FlagOciRunMountPoint, Name: "mount-point", Flag: true, Spelling: "--mount-point"}, + {Key: FlagOciRunNoMise, Name: "no-mise", Flag: true, Spelling: "--no-mise"}, + {Key: FlagOciRunOwner, Name: "owner", Flag: true, Spelling: "--owner"}, + {Key: FlagOciRunVolume, Name: "volume", Flag: true, Spelling: "--volume"}, + {Key: FlagOciRunEnv, Name: "env", Flag: true, Spelling: "--env"}, + {Key: FlagOciRunInteractive, Name: "interactive", Flag: true, Spelling: "--interactive"}, + {Key: FlagOciRunTty, Name: "tty", Flag: true, Spelling: "--tty"}, + {Key: FlagOciRunWorkdir, Name: "workdir", Flag: true, Spelling: "--workdir"}, {Key: ArgOciRunCmd, Name: "CMD"}, {}, - {Key: FlagOutdatedJson, Name: "json", Flag: true}, - {Key: FlagOutdatedBump, Name: "bump", Flag: true}, - {Key: FlagOutdatedInactive, Name: "inactive", Flag: true}, - {Key: FlagOutdatedLocal, Name: "local", Flag: true}, - {Key: FlagOutdatedMonorepo, Name: "monorepo", Flag: true}, - {Key: FlagOutdatedNoHeader, Name: "no-header", Flag: true}, + {Key: FlagOutdatedJson, Name: "json", Flag: true, Spelling: "--json"}, + {Key: FlagOutdatedBump, Name: "bump", Flag: true, Spelling: "--bump"}, + {Key: FlagOutdatedInactive, Name: "inactive", Flag: true, Spelling: "--inactive"}, + {Key: FlagOutdatedLocal, Name: "local", Flag: true, Spelling: "--local"}, + {Key: FlagOutdatedMonorepo, Name: "monorepo", Flag: true, Spelling: "--monorepo"}, + {Key: FlagOutdatedNoHeader, Name: "no-header", Flag: true, Spelling: "--no-header"}, {Key: ArgOutdatedToolVersion, Name: "TOOL@VERSION"}, {}, - {Key: FlagPatronsJson, Name: "json", Flag: true}, - {Key: FlagPatronsRefresh, Name: "refresh", Flag: true}, + {Key: FlagPatronsJson, Name: "json", Flag: true, Spelling: "--json"}, + {Key: FlagPatronsRefresh, Name: "refresh", Flag: true, Spelling: "--refresh"}, {}, - {Key: FlagPluginsAll, Name: "all", Flag: true}, - {Key: FlagPluginsCore, Name: "core", Flag: true}, - {Key: FlagPluginsUrls, Name: "urls", Flag: true}, - {Key: FlagPluginsRefs, Name: "refs", Flag: true}, - {Key: FlagPluginsUser, Name: "user", Flag: true}, + {Key: FlagPluginsAll, Name: "all", Flag: true, Spelling: "--all"}, + {Key: FlagPluginsCore, Name: "core", Flag: true, Spelling: "--core"}, + {Key: FlagPluginsUrls, Name: "urls", Flag: true, Spelling: "--urls"}, + {Key: FlagPluginsRefs, Name: "refs", Flag: true, Spelling: "--refs"}, + {Key: FlagPluginsUser, Name: "user", Flag: true, Spelling: "--user"}, {}, - {Key: FlagPluginsInstallAll, Name: "all", Flag: true}, - {Key: FlagPluginsInstallForce, Name: "force", Flag: true}, - {Key: FlagPluginsInstallJobs, Name: "jobs", Flag: true}, - {Key: FlagPluginsInstallVerbose, Name: "verbose", Flag: true}, + {Key: FlagPluginsInstallAll, Name: "all", Flag: true, Spelling: "--all"}, + {Key: FlagPluginsInstallForce, Name: "force", Flag: true, Spelling: "--force"}, + {Key: FlagPluginsInstallJobs, Name: "jobs", Flag: true, Spelling: "--jobs"}, + {Key: FlagPluginsInstallVerbose, Name: "verbose", Flag: true, Spelling: "--verbose"}, {Key: ArgPluginsInstallNewPlugin, Name: "NEW_PLUGIN"}, {Key: ArgPluginsInstallGitUrl, Name: "GIT_URL"}, {Key: ArgPluginsInstallRest, Name: "REST"}, {}, - {Key: FlagPluginsLinkForce, Name: "force", Flag: true}, + {Key: FlagPluginsLinkForce, Name: "force", Flag: true, Spelling: "--force"}, {Key: ArgPluginsLinkName, Name: "NAME", Required: true}, {Key: ArgPluginsLinkDir, Name: "DIR"}, {}, - {Key: FlagPluginsLsAll, Name: "all", Flag: true}, - {Key: FlagPluginsLsCore, Name: "core", Flag: true}, - {Key: FlagPluginsLsOutdated, Name: "outdated", Flag: true}, - {Key: FlagPluginsLsUrls, Name: "urls", Flag: true}, - {Key: FlagPluginsLsRefs, Name: "refs", Flag: true}, - {Key: FlagPluginsLsUser, Name: "user", Flag: true}, + {Key: FlagPluginsLsAll, Name: "all", Flag: true, Spelling: "--all"}, + {Key: FlagPluginsLsCore, Name: "core", Flag: true, Spelling: "--core"}, + {Key: FlagPluginsLsOutdated, Name: "outdated", Flag: true, Spelling: "--outdated"}, + {Key: FlagPluginsLsUrls, Name: "urls", Flag: true, Spelling: "--urls"}, + {Key: FlagPluginsLsRefs, Name: "refs", Flag: true, Spelling: "--refs"}, + {Key: FlagPluginsLsUser, Name: "user", Flag: true, Spelling: "--user"}, {}, - {Key: FlagPluginsLsRemoteUrls, Name: "urls", Flag: true}, - {Key: FlagPluginsLsRemoteOnlyNames, Name: "only-names", Flag: true}, + {Key: FlagPluginsLsRemoteUrls, Name: "urls", Flag: true, Spelling: "--urls"}, + {Key: FlagPluginsLsRemoteOnlyNames, Name: "only-names", Flag: true, Spelling: "--only-names"}, {}, - {Key: FlagPluginsUninstallAll, Name: "all", Flag: true}, - {Key: FlagPluginsUninstallPurge, Name: "purge", Flag: true}, + {Key: FlagPluginsUninstallAll, Name: "all", Flag: true, Spelling: "--all"}, + {Key: FlagPluginsUninstallPurge, Name: "purge", Flag: true, Spelling: "--purge"}, {Key: ArgPluginsUninstallPlugin, Name: "PLUGIN"}, {}, - {Key: FlagPluginsUpdateJobs, Name: "jobs", Flag: true}, + {Key: FlagPluginsUpdateJobs, Name: "jobs", Flag: true, Spelling: "--jobs"}, {Key: ArgPluginsUpdatePlugin, Name: "PLUGIN"}, {}, - {Key: FlagDepsExplain, Name: "explain", Flag: true}, - {Key: FlagDepsForce, Name: "force", Flag: true}, - {Key: FlagDepsDryRun, Name: "dry-run", Flag: true}, - {Key: FlagDepsList, Name: "list", Flag: true}, - {Key: FlagDepsMonorepo, Name: "monorepo", Flag: true}, - {Key: FlagDepsOnly, Name: "only", Flag: true}, - {Key: FlagDepsSkip, Name: "skip", Flag: true}, + {Key: FlagDepsExplain, Name: "explain", Flag: true, Spelling: "--explain"}, + {Key: FlagDepsForce, Name: "force", Flag: true, Spelling: "--force"}, + {Key: FlagDepsDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagDepsList, Name: "list", Flag: true, Spelling: "--list"}, + {Key: FlagDepsMonorepo, Name: "monorepo", Flag: true, Spelling: "--monorepo"}, + {Key: FlagDepsOnly, Name: "only", Flag: true, Spelling: "--only"}, + {Key: FlagDepsSkip, Name: "skip", Flag: true, Spelling: "--skip"}, {Key: ArgDepsProvider, Name: "PROVIDER"}, {}, - {Key: FlagDepsAddDev, Name: "dev", Flag: true}, + {Key: FlagDepsAddDev, Name: "dev", Flag: true, Spelling: "--dev"}, {Key: ArgDepsAddPackages, Name: "PACKAGES", Required: true}, {}, - {Key: FlagDepsInstallExplain, Name: "explain", Flag: true}, - {Key: FlagDepsInstallForce, Name: "force", Flag: true}, - {Key: FlagDepsInstallDryRun, Name: "dry-run", Flag: true}, - {Key: FlagDepsInstallList, Name: "list", Flag: true}, - {Key: FlagDepsInstallMonorepo, Name: "monorepo", Flag: true}, - {Key: FlagDepsInstallOnly, Name: "only", Flag: true}, - {Key: FlagDepsInstallSkip, Name: "skip", Flag: true}, + {Key: FlagDepsInstallExplain, Name: "explain", Flag: true, Spelling: "--explain"}, + {Key: FlagDepsInstallForce, Name: "force", Flag: true, Spelling: "--force"}, + {Key: FlagDepsInstallDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagDepsInstallList, Name: "list", Flag: true, Spelling: "--list"}, + {Key: FlagDepsInstallMonorepo, Name: "monorepo", Flag: true, Spelling: "--monorepo"}, + {Key: FlagDepsInstallOnly, Name: "only", Flag: true, Spelling: "--only"}, + {Key: FlagDepsInstallSkip, Name: "skip", Flag: true, Spelling: "--skip"}, {Key: ArgDepsInstallProvider, Name: "PROVIDER"}, {}, {Key: ArgDepsRemovePackages, Name: "PACKAGES", Required: true}, {}, - {Key: FlagPruneDryRun, Name: "dry-run", Flag: true}, - {Key: FlagPruneConfigs, Name: "configs", Flag: true}, - {Key: FlagPruneDryRunCode, Name: "dry-run-code", Flag: true}, - {Key: FlagPruneMonorepo, Name: "monorepo", Flag: true}, - {Key: FlagPruneTools, Name: "tools", Flag: true}, + {Key: FlagPruneDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagPruneConfigs, Name: "configs", Flag: true, Spelling: "--configs"}, + {Key: FlagPruneDryRunCode, Name: "dry-run-code", Flag: true, Spelling: "--dry-run-code"}, + {Key: FlagPruneMonorepo, Name: "monorepo", Flag: true, Spelling: "--monorepo"}, + {Key: FlagPruneTools, Name: "tools", Flag: true, Spelling: "--tools"}, {Key: ArgPruneInstalledTool, Name: "INSTALLED_TOOL"}, {}, - {Key: FlagRegistryBackend, Name: "backend", Flag: true}, - {Key: FlagRegistryComplete, Name: "complete", Flag: true}, - {Key: FlagRegistryHideAliased, Name: "hide-aliased", Flag: true}, - {Key: FlagRegistryJson, Name: "json", Flag: true}, - {Key: FlagRegistrySecurity, Name: "security", Flag: true}, + {Key: FlagRegistryBackend, Name: "backend", Flag: true, Spelling: "--backend"}, + {Key: FlagRegistryComplete, Name: "complete", Flag: true, Spelling: "--complete"}, + {Key: FlagRegistryHideAliased, Name: "hide-aliased", Flag: true, Spelling: "--hide-aliased"}, + {Key: FlagRegistryJson, Name: "json", Flag: true, Spelling: "--json"}, + {Key: FlagRegistrySecurity, Name: "security", Flag: true, Spelling: "--security"}, {Key: ArgRegistryName, Name: "NAME"}, {}, {}, - {Key: FlagReshimForce, Name: "force", Flag: true}, + {Key: FlagReshimForce, Name: "force", Flag: true, Spelling: "--force"}, {Key: ArgReshimTool, Name: "TOOL"}, {Key: ArgReshimVersion, Name: "VERSION"}, {}, - {Key: FlagRunAffected, Name: "affected", Flag: true}, - {Key: FlagRunAffectedBase, Name: "affected-base", Flag: true}, - {Key: FlagRunAffectedExplain, Name: "affected-explain", Flag: true}, - {Key: FlagRunAffectedHead, Name: "affected-head", Flag: true}, - {Key: FlagRunAffectedJson, Name: "affected-json", Flag: true}, - {Key: FlagRunContinueOnError, Name: "continue-on-error", Flag: true}, - {Key: FlagRunCd, Name: "cd", Flag: true}, - {Key: FlagRunForce, Name: "force", Flag: true}, - {Key: FlagRunJobs, Name: "jobs", Flag: true}, - {Key: FlagRunDryRun, Name: "dry-run", Flag: true}, - {Key: FlagRunOutput, Name: "output", Flag: true}, - {Key: FlagRunQuiet, Name: "quiet", Flag: true}, - {Key: FlagRunRaw, Name: "raw", Flag: true}, - {Key: FlagRunShell, Name: "shell", Flag: true}, - {Key: FlagRunSilent, Name: "silent", Flag: true}, - {Key: FlagRunTool, Name: "tool", Flag: true}, - {Key: FlagRunAllowEnv, Name: "allow-env", Flag: true}, - {Key: FlagRunAllowNet, Name: "allow-net", Flag: true}, - {Key: FlagRunAllowRead, Name: "allow-read", Flag: true}, - {Key: FlagRunAllowWrite, Name: "allow-write", Flag: true}, - {Key: FlagRunDenyAll, Name: "deny-all", Flag: true}, - {Key: FlagRunDenyEnv, Name: "deny-env", Flag: true}, - {Key: FlagRunDenyNet, Name: "deny-net", Flag: true}, - {Key: FlagRunDenyRead, Name: "deny-read", Flag: true}, - {Key: FlagRunDenyWrite, Name: "deny-write", Flag: true}, - {Key: FlagRunFreshEnv, Name: "fresh-env", Flag: true}, - {Key: FlagRunNoCache, Name: "no-cache", Flag: true}, - {Key: FlagRunNoDeps, Name: "no-deps", Flag: true}, - {Key: FlagRunNoTimings, Name: "no-timings", Flag: true}, - {Key: FlagRunSkipDeps, Name: "skip-deps", Flag: true}, - {Key: FlagRunSkipTools, Name: "skip-tools", Flag: true}, - {Key: FlagRunTaskCache, Name: "task-cache", Flag: true, Choices: []string{"read-write", "read-only", "write-only", "off", "local-only"}, Default: []string{"read-write"}}, - {Key: FlagRunTaskCacheExplain, Name: "task-cache-explain", Flag: true}, - {Key: FlagRunTaskCacheExplainJson, Name: "task-cache-explain-json", Flag: true}, - {Key: FlagRunTaskCacheStats, Name: "task-cache-stats", Flag: true}, - {Key: FlagRunTimeout, Name: "timeout", Flag: true}, - {Key: FlagRunTimings, Name: "timings", Flag: true}, - {}, - {Key: FlagSearchInteractive, Name: "interactive", Flag: true}, - {Key: FlagSearchMatchType, Name: "match-type", Flag: true, Choices: []string{"equal", "contains", "fuzzy"}, Default: []string{"fuzzy"}}, - {Key: FlagSearchNoHeader, Name: "no-header", Flag: true}, + {Key: FlagRunAffected, Name: "affected", Flag: true, Spelling: "--affected"}, + {Key: FlagRunAffectedBase, Name: "affected-base", Flag: true, Spelling: "--affected-base"}, + {Key: FlagRunAffectedExplain, Name: "affected-explain", Flag: true, Spelling: "--affected-explain"}, + {Key: FlagRunAffectedHead, Name: "affected-head", Flag: true, Spelling: "--affected-head"}, + {Key: FlagRunAffectedJson, Name: "affected-json", Flag: true, Spelling: "--affected-json"}, + {Key: FlagRunContinueOnError, Name: "continue-on-error", Flag: true, Spelling: "--continue-on-error"}, + {Key: FlagRunCd, Name: "cd", Flag: true, Spelling: "--cd"}, + {Key: FlagRunForce, Name: "force", Flag: true, Spelling: "--force"}, + {Key: FlagRunJobs, Name: "jobs", Flag: true, Spelling: "--jobs"}, + {Key: FlagRunDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagRunOutput, Name: "output", Flag: true, Spelling: "--output"}, + {Key: FlagRunQuiet, Name: "quiet", Flag: true, Spelling: "--quiet"}, + {Key: FlagRunRaw, Name: "raw", Flag: true, Spelling: "--raw"}, + {Key: FlagRunShell, Name: "shell", Flag: true, Spelling: "--shell"}, + {Key: FlagRunSilent, Name: "silent", Flag: true, Spelling: "--silent"}, + {Key: FlagRunTool, Name: "tool", Flag: true, Spelling: "--tool"}, + {Key: FlagRunAllowEnv, Name: "allow-env", Flag: true, Spelling: "--allow-env"}, + {Key: FlagRunAllowNet, Name: "allow-net", Flag: true, Spelling: "--allow-net"}, + {Key: FlagRunAllowRead, Name: "allow-read", Flag: true, Spelling: "--allow-read"}, + {Key: FlagRunAllowWrite, Name: "allow-write", Flag: true, Spelling: "--allow-write"}, + {Key: FlagRunDenyAll, Name: "deny-all", Flag: true, Spelling: "--deny-all"}, + {Key: FlagRunDenyEnv, Name: "deny-env", Flag: true, Spelling: "--deny-env"}, + {Key: FlagRunDenyNet, Name: "deny-net", Flag: true, Spelling: "--deny-net"}, + {Key: FlagRunDenyRead, Name: "deny-read", Flag: true, Spelling: "--deny-read"}, + {Key: FlagRunDenyWrite, Name: "deny-write", Flag: true, Spelling: "--deny-write"}, + {Key: FlagRunFreshEnv, Name: "fresh-env", Flag: true, Spelling: "--fresh-env"}, + {Key: FlagRunNoCache, Name: "no-cache", Flag: true, Spelling: "--no-cache"}, + {Key: FlagRunNoDeps, Name: "no-deps", Flag: true, Spelling: "--no-deps"}, + {Key: FlagRunNoTimings, Name: "no-timings", Flag: true, Spelling: "--no-timings"}, + {Key: FlagRunSkipDeps, Name: "skip-deps", Flag: true, Spelling: "--skip-deps"}, + {Key: FlagRunSkipTools, Name: "skip-tools", Flag: true, Spelling: "--skip-tools"}, + {Key: FlagRunTaskCache, Name: "task-cache", Flag: true, Spelling: "--task-cache", Choices: []string{"read-write", "read-only", "write-only", "off", "local-only"}, Default: []string{"read-write"}}, + {Key: FlagRunTaskCacheExplain, Name: "task-cache-explain", Flag: true, Spelling: "--task-cache-explain"}, + {Key: FlagRunTaskCacheExplainJson, Name: "task-cache-explain-json", Flag: true, Spelling: "--task-cache-explain-json"}, + {Key: FlagRunTaskCacheStats, Name: "task-cache-stats", Flag: true, Spelling: "--task-cache-stats"}, + {Key: FlagRunTimeout, Name: "timeout", Flag: true, Spelling: "--timeout"}, + {Key: FlagRunTimings, Name: "timings", Flag: true, Spelling: "--timings"}, + {}, + {Key: FlagSearchInteractive, Name: "interactive", Flag: true, Spelling: "--interactive"}, + {Key: FlagSearchMatchType, Name: "match-type", Flag: true, Spelling: "--match-type", Choices: []string{"equal", "contains", "fuzzy"}, Default: []string{"fuzzy"}}, + {Key: FlagSearchNoHeader, Name: "no-header", Flag: true, Spelling: "--no-header"}, {Key: ArgSearchName, Name: "NAME"}, {}, - {Key: FlagSelfUpdateForce, Name: "force", Flag: true}, - {Key: FlagSelfUpdateYes, Name: "yes", Flag: true}, - {Key: FlagSelfUpdateNoPlugins, Name: "no-plugins", Flag: true}, + {Key: FlagSelfUpdateForce, Name: "force", Flag: true, Spelling: "--force"}, + {Key: FlagSelfUpdateYes, Name: "yes", Flag: true, Spelling: "--yes"}, + {Key: FlagSelfUpdateNoPlugins, Name: "no-plugins", Flag: true, Spelling: "--no-plugins"}, {Key: ArgSelfUpdateVersion, Name: "VERSION"}, {}, - {Key: FlagSetEnv, Name: "env", Flag: true}, - {Key: FlagSetGlobal, Name: "global", Flag: true}, - {Key: FlagSetAgeEncrypt, Name: "age-encrypt", Flag: true}, - {Key: FlagSetAgeKeyFile, Name: "age-key-file", Flag: true}, - {Key: FlagSetAgeRecipient, Name: "age-recipient", Flag: true}, - {Key: FlagSetAgeSshRecipient, Name: "age-ssh-recipient", Flag: true}, - {Key: FlagSetComplete, Name: "complete", Flag: true}, - {Key: FlagSetFile, Name: "file", Flag: true}, - {Key: FlagSetNoRedact, Name: "no-redact", Flag: true}, - {Key: FlagSetPrompt, Name: "prompt", Flag: true}, - {Key: FlagSetRemove, Name: "remove", Flag: true}, - {Key: FlagSetStdin, Name: "stdin", Flag: true}, + {Key: FlagSetEnv, Name: "env", Flag: true, Spelling: "--env"}, + {Key: FlagSetGlobal, Name: "global", Flag: true, Spelling: "--global"}, + {Key: FlagSetAgeEncrypt, Name: "age-encrypt", Flag: true, Spelling: "--age-encrypt"}, + {Key: FlagSetAgeKeyFile, Name: "age-key-file", Flag: true, Spelling: "--age-key-file"}, + {Key: FlagSetAgeRecipient, Name: "age-recipient", Flag: true, Spelling: "--age-recipient"}, + {Key: FlagSetAgeSshRecipient, Name: "age-ssh-recipient", Flag: true, Spelling: "--age-ssh-recipient"}, + {Key: FlagSetComplete, Name: "complete", Flag: true, Spelling: "--complete"}, + {Key: FlagSetFile, Name: "file", Flag: true, Spelling: "--file"}, + {Key: FlagSetNoRedact, Name: "no-redact", Flag: true, Spelling: "--no-redact"}, + {Key: FlagSetPrompt, Name: "prompt", Flag: true, Spelling: "--prompt"}, + {Key: FlagSetRemove, Name: "remove", Flag: true, Spelling: "--remove"}, + {Key: FlagSetStdin, Name: "stdin", Flag: true, Spelling: "--stdin"}, {Key: ArgSetEnvVar, Name: "ENV_VAR"}, {}, - {Key: FlagSettingsAll, Name: "all", Flag: true}, - {Key: FlagSettingsJson, Name: "json", Flag: true}, - {Key: FlagSettingsLocal, Name: "local", Flag: true}, - {Key: FlagSettingsToml, Name: "toml", Flag: true}, - {Key: FlagSettingsComplete, Name: "complete", Flag: true}, - {Key: FlagSettingsJsonExtended, Name: "json-extended", Flag: true}, + {Key: FlagSettingsAll, Name: "all", Flag: true, Spelling: "--all"}, + {Key: FlagSettingsJson, Name: "json", Flag: true, Spelling: "--json"}, + {Key: FlagSettingsLocal, Name: "local", Flag: true, Spelling: "--local"}, + {Key: FlagSettingsToml, Name: "toml", Flag: true, Spelling: "--toml"}, + {Key: FlagSettingsComplete, Name: "complete", Flag: true, Spelling: "--complete"}, + {Key: FlagSettingsJsonExtended, Name: "json-extended", Flag: true, Spelling: "--json-extended"}, {Key: ArgSettingsSetting, Name: "SETTING"}, {Key: ArgSettingsValue, Name: "VALUE"}, {}, - {Key: FlagSettingsAddLocal, Name: "local", Flag: true}, + {Key: FlagSettingsAddLocal, Name: "local", Flag: true, Spelling: "--local"}, {Key: ArgSettingsAddSetting, Name: "SETTING", Required: true}, {Key: ArgSettingsAddValue, Name: "VALUE"}, {}, - {Key: FlagSettingsGetLocal, Name: "local", Flag: true}, + {Key: FlagSettingsGetLocal, Name: "local", Flag: true, Spelling: "--local"}, {Key: ArgSettingsGetSetting, Name: "SETTING", Required: true}, {}, - {Key: FlagSettingsLsAll, Name: "all", Flag: true}, - {Key: FlagSettingsLsJson, Name: "json", Flag: true}, - {Key: FlagSettingsLsLocal, Name: "local", Flag: true}, - {Key: FlagSettingsLsToml, Name: "toml", Flag: true}, - {Key: FlagSettingsLsComplete, Name: "complete", Flag: true}, - {Key: FlagSettingsLsJsonExtended, Name: "json-extended", Flag: true}, + {Key: FlagSettingsLsAll, Name: "all", Flag: true, Spelling: "--all"}, + {Key: FlagSettingsLsJson, Name: "json", Flag: true, Spelling: "--json"}, + {Key: FlagSettingsLsLocal, Name: "local", Flag: true, Spelling: "--local"}, + {Key: FlagSettingsLsToml, Name: "toml", Flag: true, Spelling: "--toml"}, + {Key: FlagSettingsLsComplete, Name: "complete", Flag: true, Spelling: "--complete"}, + {Key: FlagSettingsLsJsonExtended, Name: "json-extended", Flag: true, Spelling: "--json-extended"}, {Key: ArgSettingsLsSetting, Name: "SETTING"}, {}, - {Key: FlagSettingsSetLocal, Name: "local", Flag: true}, + {Key: FlagSettingsSetLocal, Name: "local", Flag: true, Spelling: "--local"}, {Key: ArgSettingsSetSetting, Name: "SETTING", Required: true}, {Key: ArgSettingsSetValue, Name: "VALUE"}, {}, - {Key: FlagSettingsUnsetLocal, Name: "local", Flag: true}, + {Key: FlagSettingsUnsetLocal, Name: "local", Flag: true, Spelling: "--local"}, {Key: ArgSettingsUnsetKey, Name: "KEY", Required: true}, {}, - {Key: FlagShellJobs, Name: "jobs", Flag: true}, - {Key: FlagShellUnset, Name: "unset", Flag: true}, - {Key: FlagShellRaw, Name: "raw", Flag: true}, + {Key: FlagShellJobs, Name: "jobs", Flag: true, Spelling: "--jobs"}, + {Key: FlagShellUnset, Name: "unset", Flag: true, Spelling: "--unset"}, + {Key: FlagShellRaw, Name: "raw", Flag: true, Spelling: "--raw"}, {Key: ArgShellToolVersion, Name: "TOOL@VERSION", Required: true}, {}, - {Key: FlagShellAliasNoHeader, Name: "no-header", Flag: true}, + {Key: FlagShellAliasNoHeader, Name: "no-header", Flag: true, Spelling: "--no-header"}, {}, {Key: ArgShellAliasGetShellAlias, Name: "shell_alias", Required: true}, {}, - {Key: FlagShellAliasLsNoHeader, Name: "no-header", Flag: true}, + {Key: FlagShellAliasLsNoHeader, Name: "no-header", Flag: true, Spelling: "--no-header"}, {}, {Key: ArgShellAliasSetShellAlias, Name: "shell_alias", Required: true}, {Key: ArgShellAliasSetCommand, Name: "COMMAND"}, @@ -4574,264 +4574,264 @@ var Meta = argv.Metadata{ {}, {}, {}, - {Key: FlagSyncNodeBrew, Name: "brew", Flag: true}, - {Key: FlagSyncNodeNodenv, Name: "nodenv", Flag: true}, - {Key: FlagSyncNodeNvm, Name: "nvm", Flag: true}, + {Key: FlagSyncNodeBrew, Name: "brew", Flag: true, Spelling: "--brew"}, + {Key: FlagSyncNodeNodenv, Name: "nodenv", Flag: true, Spelling: "--nodenv"}, + {Key: FlagSyncNodeNvm, Name: "nvm", Flag: true, Spelling: "--nvm"}, {}, - {Key: FlagSyncPythonPyenv, Name: "pyenv", Flag: true}, - {Key: FlagSyncPythonUv, Name: "uv", Flag: true}, + {Key: FlagSyncPythonPyenv, Name: "pyenv", Flag: true, Spelling: "--pyenv"}, + {Key: FlagSyncPythonUv, Name: "uv", Flag: true, Spelling: "--uv"}, {}, - {Key: FlagSyncRubyBrew, Name: "brew", Flag: true}, + {Key: FlagSyncRubyBrew, Name: "brew", Flag: true, Spelling: "--brew"}, {}, - {Key: FlagTasksGlobal, Name: "global", Flag: true}, - {Key: FlagTasksJson, Name: "json", Flag: true}, - {Key: FlagTasksLocal, Name: "local", Flag: true}, - {Key: FlagTasksExtended, Name: "extended", Flag: true}, - {Key: FlagTasksAll, Name: "all", Flag: true}, - {Key: FlagTasksComplete, Name: "complete", Flag: true}, - {Key: FlagTasksHidden, Name: "hidden", Flag: true}, - {Key: FlagTasksNameOnly, Name: "name-only", Flag: true}, - {Key: FlagTasksNoHeader, Name: "no-header", Flag: true}, - {Key: FlagTasksSort, Name: "sort", Flag: true, Choices: []string{"name", "alias", "description", "source"}}, - {Key: FlagTasksSortOrder, Name: "sort-order", Flag: true, Choices: []string{"asc", "desc"}}, - {Key: FlagTasksUsage, Name: "usage", Flag: true}, + {Key: FlagTasksGlobal, Name: "global", Flag: true, Spelling: "--global"}, + {Key: FlagTasksJson, Name: "json", Flag: true, Spelling: "--json"}, + {Key: FlagTasksLocal, Name: "local", Flag: true, Spelling: "--local"}, + {Key: FlagTasksExtended, Name: "extended", Flag: true, Spelling: "--extended"}, + {Key: FlagTasksAll, Name: "all", Flag: true, Spelling: "--all"}, + {Key: FlagTasksComplete, Name: "complete", Flag: true, Spelling: "--complete"}, + {Key: FlagTasksHidden, Name: "hidden", Flag: true, Spelling: "--hidden"}, + {Key: FlagTasksNameOnly, Name: "name-only", Flag: true, Spelling: "--name-only"}, + {Key: FlagTasksNoHeader, Name: "no-header", Flag: true, Spelling: "--no-header"}, + {Key: FlagTasksSort, Name: "sort", Flag: true, Spelling: "--sort", Choices: []string{"name", "alias", "description", "source"}}, + {Key: FlagTasksSortOrder, Name: "sort-order", Flag: true, Spelling: "--sort-order", Choices: []string{"asc", "desc"}}, + {Key: FlagTasksUsage, Name: "usage", Flag: true, Spelling: "--usage"}, {Key: ArgTasksTask, Name: "TASK"}, {}, - {Key: FlagTasksAddAlias, Name: "alias", Flag: true}, - {Key: FlagTasksAddDepends, Name: "depends", Flag: true}, - {Key: FlagTasksAddDir, Name: "dir", Flag: true}, - {Key: FlagTasksAddFile, Name: "file", Flag: true}, - {Key: FlagTasksAddHide, Name: "hide", Flag: true}, - {Key: FlagTasksAddQuiet, Name: "quiet", Flag: true}, - {Key: FlagTasksAddRaw, Name: "raw", Flag: true}, - {Key: FlagTasksAddSources, Name: "sources", Flag: true}, - {Key: FlagTasksAddWaitFor, Name: "wait-for", Flag: true}, - {Key: FlagTasksAddDependsPost, Name: "depends-post", Flag: true}, - {Key: FlagTasksAddDescription, Name: "description", Flag: true}, - {Key: FlagTasksAddOutputs, Name: "outputs", Flag: true}, - {Key: FlagTasksAddRunWindows, Name: "run-windows", Flag: true}, - {Key: FlagTasksAddShell, Name: "shell", Flag: true}, - {Key: FlagTasksAddSilent, Name: "silent", Flag: true}, + {Key: FlagTasksAddAlias, Name: "alias", Flag: true, Spelling: "--alias"}, + {Key: FlagTasksAddDepends, Name: "depends", Flag: true, Spelling: "--depends"}, + {Key: FlagTasksAddDir, Name: "dir", Flag: true, Spelling: "--dir"}, + {Key: FlagTasksAddFile, Name: "file", Flag: true, Spelling: "--file"}, + {Key: FlagTasksAddHide, Name: "hide", Flag: true, Spelling: "--hide"}, + {Key: FlagTasksAddQuiet, Name: "quiet", Flag: true, Spelling: "--quiet"}, + {Key: FlagTasksAddRaw, Name: "raw", Flag: true, Spelling: "--raw"}, + {Key: FlagTasksAddSources, Name: "sources", Flag: true, Spelling: "--sources"}, + {Key: FlagTasksAddWaitFor, Name: "wait-for", Flag: true, Spelling: "--wait-for"}, + {Key: FlagTasksAddDependsPost, Name: "depends-post", Flag: true, Spelling: "--depends-post"}, + {Key: FlagTasksAddDescription, Name: "description", Flag: true, Spelling: "--description"}, + {Key: FlagTasksAddOutputs, Name: "outputs", Flag: true, Spelling: "--outputs"}, + {Key: FlagTasksAddRunWindows, Name: "run-windows", Flag: true, Spelling: "--run-windows"}, + {Key: FlagTasksAddShell, Name: "shell", Flag: true, Spelling: "--shell"}, + {Key: FlagTasksAddSilent, Name: "silent", Flag: true, Spelling: "--silent"}, {Key: ArgTasksAddTask, Name: "TASK", Required: true}, {Key: ArgTasksAddRun, Name: "RUN"}, {}, - {Key: FlagTasksDepsCompact, Name: "compact", Flag: true}, - {Key: FlagTasksDepsDot, Name: "dot", Flag: true}, - {Key: FlagTasksDepsHidden, Name: "hidden", Flag: true}, + {Key: FlagTasksDepsCompact, Name: "compact", Flag: true, Spelling: "--compact"}, + {Key: FlagTasksDepsDot, Name: "dot", Flag: true, Spelling: "--dot"}, + {Key: FlagTasksDepsHidden, Name: "hidden", Flag: true, Spelling: "--hidden"}, {Key: ArgTasksDepsTasks, Name: "TASKS"}, {}, - {Key: FlagTasksEditPath, Name: "path", Flag: true}, + {Key: FlagTasksEditPath, Name: "path", Flag: true, Spelling: "--path"}, {Key: ArgTasksEditTask, Name: "TASK", Required: true}, {}, - {Key: FlagTasksGraphJson, Name: "json", Flag: true}, - {Key: FlagTasksGraphExplain, Name: "explain", Flag: true}, - {Key: FlagTasksGraphNoHeader, Name: "no-header", Flag: true}, + {Key: FlagTasksGraphJson, Name: "json", Flag: true, Spelling: "--json"}, + {Key: FlagTasksGraphExplain, Name: "explain", Flag: true, Spelling: "--explain"}, + {Key: FlagTasksGraphNoHeader, Name: "no-header", Flag: true, Spelling: "--no-header"}, {}, - {Key: FlagTasksInfoJson, Name: "json", Flag: true}, + {Key: FlagTasksInfoJson, Name: "json", Flag: true, Spelling: "--json"}, {Key: ArgTasksInfoTask, Name: "TASK", Required: true}, {}, - {Key: FlagTasksLsGlobal, Name: "global", Flag: true}, - {Key: FlagTasksLsJson, Name: "json", Flag: true}, - {Key: FlagTasksLsLocal, Name: "local", Flag: true}, - {Key: FlagTasksLsExtended, Name: "extended", Flag: true}, - {Key: FlagTasksLsAll, Name: "all", Flag: true}, - {Key: FlagTasksLsComplete, Name: "complete", Flag: true}, - {Key: FlagTasksLsHidden, Name: "hidden", Flag: true}, - {Key: FlagTasksLsNameOnly, Name: "name-only", Flag: true}, - {Key: FlagTasksLsNoHeader, Name: "no-header", Flag: true}, - {Key: FlagTasksLsSort, Name: "sort", Flag: true, Choices: []string{"name", "alias", "description", "source"}}, - {Key: FlagTasksLsSortOrder, Name: "sort-order", Flag: true, Choices: []string{"asc", "desc"}}, - {Key: FlagTasksLsUsage, Name: "usage", Flag: true}, - {}, - {Key: FlagTasksRunAffected, Name: "affected", Flag: true}, - {Key: FlagTasksRunAffectedBase, Name: "affected-base", Flag: true}, - {Key: FlagTasksRunAffectedExplain, Name: "affected-explain", Flag: true}, - {Key: FlagTasksRunAffectedHead, Name: "affected-head", Flag: true}, - {Key: FlagTasksRunAffectedJson, Name: "affected-json", Flag: true}, - {Key: FlagTasksRunContinueOnError, Name: "continue-on-error", Flag: true}, - {Key: FlagTasksRunCd, Name: "cd", Flag: true}, - {Key: FlagTasksRunForce, Name: "force", Flag: true}, - {Key: FlagTasksRunJobs, Name: "jobs", Flag: true}, - {Key: FlagTasksRunDryRun, Name: "dry-run", Flag: true}, - {Key: FlagTasksRunOutput, Name: "output", Flag: true}, - {Key: FlagTasksRunQuiet, Name: "quiet", Flag: true}, - {Key: FlagTasksRunRaw, Name: "raw", Flag: true}, - {Key: FlagTasksRunShell, Name: "shell", Flag: true}, - {Key: FlagTasksRunSilent, Name: "silent", Flag: true}, - {Key: FlagTasksRunTool, Name: "tool", Flag: true}, - {Key: FlagTasksRunAllowEnv, Name: "allow-env", Flag: true}, - {Key: FlagTasksRunAllowNet, Name: "allow-net", Flag: true}, - {Key: FlagTasksRunAllowRead, Name: "allow-read", Flag: true}, - {Key: FlagTasksRunAllowWrite, Name: "allow-write", Flag: true}, - {Key: FlagTasksRunDenyAll, Name: "deny-all", Flag: true}, - {Key: FlagTasksRunDenyEnv, Name: "deny-env", Flag: true}, - {Key: FlagTasksRunDenyNet, Name: "deny-net", Flag: true}, - {Key: FlagTasksRunDenyRead, Name: "deny-read", Flag: true}, - {Key: FlagTasksRunDenyWrite, Name: "deny-write", Flag: true}, - {Key: FlagTasksRunFreshEnv, Name: "fresh-env", Flag: true}, - {Key: FlagTasksRunNoCache, Name: "no-cache", Flag: true}, - {Key: FlagTasksRunNoDeps, Name: "no-deps", Flag: true}, - {Key: FlagTasksRunNoTimings, Name: "no-timings", Flag: true}, - {Key: FlagTasksRunSkipDeps, Name: "skip-deps", Flag: true}, - {Key: FlagTasksRunSkipTools, Name: "skip-tools", Flag: true}, - {Key: FlagTasksRunTaskCache, Name: "task-cache", Flag: true, Choices: []string{"read-write", "read-only", "write-only", "off", "local-only"}, Default: []string{"read-write"}}, - {Key: FlagTasksRunTaskCacheExplain, Name: "task-cache-explain", Flag: true}, - {Key: FlagTasksRunTaskCacheExplainJson, Name: "task-cache-explain-json", Flag: true}, - {Key: FlagTasksRunTaskCacheStats, Name: "task-cache-stats", Flag: true}, - {Key: FlagTasksRunTimeout, Name: "timeout", Flag: true}, - {Key: FlagTasksRunTimings, Name: "timings", Flag: true}, + {Key: FlagTasksLsGlobal, Name: "global", Flag: true, Spelling: "--global"}, + {Key: FlagTasksLsJson, Name: "json", Flag: true, Spelling: "--json"}, + {Key: FlagTasksLsLocal, Name: "local", Flag: true, Spelling: "--local"}, + {Key: FlagTasksLsExtended, Name: "extended", Flag: true, Spelling: "--extended"}, + {Key: FlagTasksLsAll, Name: "all", Flag: true, Spelling: "--all"}, + {Key: FlagTasksLsComplete, Name: "complete", Flag: true, Spelling: "--complete"}, + {Key: FlagTasksLsHidden, Name: "hidden", Flag: true, Spelling: "--hidden"}, + {Key: FlagTasksLsNameOnly, Name: "name-only", Flag: true, Spelling: "--name-only"}, + {Key: FlagTasksLsNoHeader, Name: "no-header", Flag: true, Spelling: "--no-header"}, + {Key: FlagTasksLsSort, Name: "sort", Flag: true, Spelling: "--sort", Choices: []string{"name", "alias", "description", "source"}}, + {Key: FlagTasksLsSortOrder, Name: "sort-order", Flag: true, Spelling: "--sort-order", Choices: []string{"asc", "desc"}}, + {Key: FlagTasksLsUsage, Name: "usage", Flag: true, Spelling: "--usage"}, + {}, + {Key: FlagTasksRunAffected, Name: "affected", Flag: true, Spelling: "--affected"}, + {Key: FlagTasksRunAffectedBase, Name: "affected-base", Flag: true, Spelling: "--affected-base"}, + {Key: FlagTasksRunAffectedExplain, Name: "affected-explain", Flag: true, Spelling: "--affected-explain"}, + {Key: FlagTasksRunAffectedHead, Name: "affected-head", Flag: true, Spelling: "--affected-head"}, + {Key: FlagTasksRunAffectedJson, Name: "affected-json", Flag: true, Spelling: "--affected-json"}, + {Key: FlagTasksRunContinueOnError, Name: "continue-on-error", Flag: true, Spelling: "--continue-on-error"}, + {Key: FlagTasksRunCd, Name: "cd", Flag: true, Spelling: "--cd"}, + {Key: FlagTasksRunForce, Name: "force", Flag: true, Spelling: "--force"}, + {Key: FlagTasksRunJobs, Name: "jobs", Flag: true, Spelling: "--jobs"}, + {Key: FlagTasksRunDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagTasksRunOutput, Name: "output", Flag: true, Spelling: "--output"}, + {Key: FlagTasksRunQuiet, Name: "quiet", Flag: true, Spelling: "--quiet"}, + {Key: FlagTasksRunRaw, Name: "raw", Flag: true, Spelling: "--raw"}, + {Key: FlagTasksRunShell, Name: "shell", Flag: true, Spelling: "--shell"}, + {Key: FlagTasksRunSilent, Name: "silent", Flag: true, Spelling: "--silent"}, + {Key: FlagTasksRunTool, Name: "tool", Flag: true, Spelling: "--tool"}, + {Key: FlagTasksRunAllowEnv, Name: "allow-env", Flag: true, Spelling: "--allow-env"}, + {Key: FlagTasksRunAllowNet, Name: "allow-net", Flag: true, Spelling: "--allow-net"}, + {Key: FlagTasksRunAllowRead, Name: "allow-read", Flag: true, Spelling: "--allow-read"}, + {Key: FlagTasksRunAllowWrite, Name: "allow-write", Flag: true, Spelling: "--allow-write"}, + {Key: FlagTasksRunDenyAll, Name: "deny-all", Flag: true, Spelling: "--deny-all"}, + {Key: FlagTasksRunDenyEnv, Name: "deny-env", Flag: true, Spelling: "--deny-env"}, + {Key: FlagTasksRunDenyNet, Name: "deny-net", Flag: true, Spelling: "--deny-net"}, + {Key: FlagTasksRunDenyRead, Name: "deny-read", Flag: true, Spelling: "--deny-read"}, + {Key: FlagTasksRunDenyWrite, Name: "deny-write", Flag: true, Spelling: "--deny-write"}, + {Key: FlagTasksRunFreshEnv, Name: "fresh-env", Flag: true, Spelling: "--fresh-env"}, + {Key: FlagTasksRunNoCache, Name: "no-cache", Flag: true, Spelling: "--no-cache"}, + {Key: FlagTasksRunNoDeps, Name: "no-deps", Flag: true, Spelling: "--no-deps"}, + {Key: FlagTasksRunNoTimings, Name: "no-timings", Flag: true, Spelling: "--no-timings"}, + {Key: FlagTasksRunSkipDeps, Name: "skip-deps", Flag: true, Spelling: "--skip-deps"}, + {Key: FlagTasksRunSkipTools, Name: "skip-tools", Flag: true, Spelling: "--skip-tools"}, + {Key: FlagTasksRunTaskCache, Name: "task-cache", Flag: true, Spelling: "--task-cache", Choices: []string{"read-write", "read-only", "write-only", "off", "local-only"}, Default: []string{"read-write"}}, + {Key: FlagTasksRunTaskCacheExplain, Name: "task-cache-explain", Flag: true, Spelling: "--task-cache-explain"}, + {Key: FlagTasksRunTaskCacheExplainJson, Name: "task-cache-explain-json", Flag: true, Spelling: "--task-cache-explain-json"}, + {Key: FlagTasksRunTaskCacheStats, Name: "task-cache-stats", Flag: true, Spelling: "--task-cache-stats"}, + {Key: FlagTasksRunTimeout, Name: "timeout", Flag: true, Spelling: "--timeout"}, + {Key: FlagTasksRunTimings, Name: "timings", Flag: true, Spelling: "--timings"}, {Key: ArgTasksRunTask, Name: "TASK", Default: []string{"default"}}, {Key: ArgTasksRunArgs, Name: "ARGS"}, {Key: ArgTasksRunArgsLast, Name: "ARGS_LAST"}, {}, - {Key: FlagTasksValidateErrorsOnly, Name: "errors-only", Flag: true}, - {Key: FlagTasksValidateJson, Name: "json", Flag: true}, + {Key: FlagTasksValidateErrorsOnly, Name: "errors-only", Flag: true, Spelling: "--errors-only"}, + {Key: FlagTasksValidateJson, Name: "json", Flag: true, Spelling: "--json"}, {Key: ArgTasksValidateTasks, Name: "TASKS"}, {}, - {Key: FlagTestToolAll, Name: "all", Flag: true}, - {Key: FlagTestToolJobs, Name: "jobs", Flag: true}, - {Key: FlagTestToolAllConfig, Name: "all-config", Flag: true}, - {Key: FlagTestToolIncludeNonDefined, Name: "include-non-defined", Flag: true}, - {Key: FlagTestToolRaw, Name: "raw", Flag: true}, + {Key: FlagTestToolAll, Name: "all", Flag: true, Spelling: "--all"}, + {Key: FlagTestToolJobs, Name: "jobs", Flag: true, Spelling: "--jobs"}, + {Key: FlagTestToolAllConfig, Name: "all-config", Flag: true, Spelling: "--all-config"}, + {Key: FlagTestToolIncludeNonDefined, Name: "include-non-defined", Flag: true, Spelling: "--include-non-defined"}, + {Key: FlagTestToolRaw, Name: "raw", Flag: true, Spelling: "--raw"}, {Key: ArgTestToolTools, Name: "TOOLS"}, {}, {}, - {Key: FlagTokenForgejoUnmask, Name: "unmask", Flag: true}, + {Key: FlagTokenForgejoUnmask, Name: "unmask", Flag: true, Spelling: "--unmask"}, {Key: ArgTokenForgejoHost, Name: "HOST", Default: []string{"codeberg.org"}}, {}, - {Key: FlagTokenGithubOauth, Name: "oauth", Flag: true}, - {Key: FlagTokenGithubRaw, Name: "raw", Flag: true}, - {Key: FlagTokenGithubRefresh, Name: "refresh", Flag: true}, - {Key: FlagTokenGithubUnmask, Name: "unmask", Flag: true}, + {Key: FlagTokenGithubOauth, Name: "oauth", Flag: true, Spelling: "--oauth"}, + {Key: FlagTokenGithubRaw, Name: "raw", Flag: true, Spelling: "--raw"}, + {Key: FlagTokenGithubRefresh, Name: "refresh", Flag: true, Spelling: "--refresh"}, + {Key: FlagTokenGithubUnmask, Name: "unmask", Flag: true, Spelling: "--unmask"}, {Key: ArgTokenGithubHost, Name: "HOST", Default: []string{"github.com"}}, {}, - {Key: FlagTokenGitlabUnmask, Name: "unmask", Flag: true}, + {Key: FlagTokenGitlabUnmask, Name: "unmask", Flag: true, Spelling: "--unmask"}, {Key: ArgTokenGitlabHost, Name: "HOST", Default: []string{"gitlab.com"}}, {}, - {Key: FlagToolJson, Name: "json", Flag: true}, - {Key: FlagToolActive, Name: "active", Flag: true}, - {Key: FlagToolBackend, Name: "backend", Flag: true}, - {Key: FlagToolConfigSource, Name: "config-source", Flag: true}, - {Key: FlagToolDescription, Name: "description", Flag: true}, - {Key: FlagToolInstalled, Name: "installed", Flag: true}, - {Key: FlagToolRequested, Name: "requested", Flag: true}, - {Key: FlagToolToolOptions, Name: "tool-options", Flag: true}, + {Key: FlagToolJson, Name: "json", Flag: true, Spelling: "--json"}, + {Key: FlagToolActive, Name: "active", Flag: true, Spelling: "--active"}, + {Key: FlagToolBackend, Name: "backend", Flag: true, Spelling: "--backend"}, + {Key: FlagToolConfigSource, Name: "config-source", Flag: true, Spelling: "--config-source"}, + {Key: FlagToolDescription, Name: "description", Flag: true, Spelling: "--description"}, + {Key: FlagToolInstalled, Name: "installed", Flag: true, Spelling: "--installed"}, + {Key: FlagToolRequested, Name: "requested", Flag: true, Spelling: "--requested"}, + {Key: FlagToolToolOptions, Name: "tool-options", Flag: true, Spelling: "--tool-options"}, {Key: ArgToolTool, Name: "TOOL", Required: true}, {}, {Key: ArgToolStubFile, Name: "FILE", Required: true}, {Key: ArgToolStubArgs, Name: "ARGS"}, {}, - {Key: FlagTrustAll, Name: "all", Flag: true}, - {Key: FlagTrustIgnore, Name: "ignore", Flag: true}, - {Key: FlagTrustShow, Name: "show", Flag: true}, - {Key: FlagTrustUntrust, Name: "untrust", Flag: true}, + {Key: FlagTrustAll, Name: "all", Flag: true, Spelling: "--all"}, + {Key: FlagTrustIgnore, Name: "ignore", Flag: true, Spelling: "--ignore"}, + {Key: FlagTrustShow, Name: "show", Flag: true, Spelling: "--show"}, + {Key: FlagTrustUntrust, Name: "untrust", Flag: true, Spelling: "--untrust"}, {Key: ArgTrustConfigFile, Name: "CONFIG_FILE"}, {}, - {Key: FlagUninstallAll, Name: "all", Flag: true}, - {Key: FlagUninstallDryRun, Name: "dry-run", Flag: true}, - {Key: FlagUninstallDryRunCode, Name: "dry-run-code", Flag: true}, + {Key: FlagUninstallAll, Name: "all", Flag: true, Spelling: "--all"}, + {Key: FlagUninstallDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagUninstallDryRunCode, Name: "dry-run-code", Flag: true, Spelling: "--dry-run-code"}, {Key: ArgUninstallInstalledToolVersion, Name: "INSTALLED_TOOL@VERSION"}, {}, - {Key: FlagUnsetFile, Name: "file", Flag: true}, - {Key: FlagUnsetGlobal, Name: "global", Flag: true}, + {Key: FlagUnsetFile, Name: "file", Flag: true, Spelling: "--file"}, + {Key: FlagUnsetGlobal, Name: "global", Flag: true, Spelling: "--global"}, {Key: ArgUnsetEnvKey, Name: "ENV_KEY"}, {}, {Key: ArgUntrustConfigFile, Name: "CONFIG_FILE"}, {}, - {Key: FlagUnuseEnv, Name: "env", Flag: true}, - {Key: FlagUnuseGlobal, Name: "global", Flag: true}, - {Key: FlagUnusePath, Name: "path", Flag: true}, - {Key: FlagUnuseNoPrune, Name: "no-prune", Flag: true}, + {Key: FlagUnuseEnv, Name: "env", Flag: true, Spelling: "--env"}, + {Key: FlagUnuseGlobal, Name: "global", Flag: true, Spelling: "--global"}, + {Key: FlagUnusePath, Name: "path", Flag: true, Spelling: "--path"}, + {Key: FlagUnuseNoPrune, Name: "no-prune", Flag: true, Spelling: "--no-prune"}, {Key: ArgUnuseInstalledToolVersion, Name: "INSTALLED_TOOL@VERSION", Required: true}, {}, - {Key: FlagUpgradeInteractive, Name: "interactive", Flag: true}, - {Key: FlagUpgradeJobs, Name: "jobs", Flag: true}, - {Key: FlagUpgradeBump, Name: "bump", Flag: true}, - {Key: FlagUpgradeDryRun, Name: "dry-run", Flag: true}, - {Key: FlagUpgradeExclude, Name: "exclude", Flag: true}, - {Key: FlagUpgradeDryRunCode, Name: "dry-run-code", Flag: true}, - {Key: FlagUpgradeInactive, Name: "inactive", Flag: true}, - {Key: FlagUpgradeLocal, Name: "local", Flag: true}, - {Key: FlagUpgradeMinimumReleaseAge, Name: "minimum-release-age", Flag: true}, - {Key: FlagUpgradeMonorepo, Name: "monorepo", Flag: true}, - {Key: FlagUpgradeNoPrune, Name: "no-prune", Flag: true}, - {Key: FlagUpgradeRaw, Name: "raw", Flag: true}, + {Key: FlagUpgradeInteractive, Name: "interactive", Flag: true, Spelling: "--interactive"}, + {Key: FlagUpgradeJobs, Name: "jobs", Flag: true, Spelling: "--jobs"}, + {Key: FlagUpgradeBump, Name: "bump", Flag: true, Spelling: "--bump"}, + {Key: FlagUpgradeDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagUpgradeExclude, Name: "exclude", Flag: true, Spelling: "--exclude"}, + {Key: FlagUpgradeDryRunCode, Name: "dry-run-code", Flag: true, Spelling: "--dry-run-code"}, + {Key: FlagUpgradeInactive, Name: "inactive", Flag: true, Spelling: "--inactive"}, + {Key: FlagUpgradeLocal, Name: "local", Flag: true, Spelling: "--local"}, + {Key: FlagUpgradeMinimumReleaseAge, Name: "minimum-release-age", Flag: true, Spelling: "--minimum-release-age"}, + {Key: FlagUpgradeMonorepo, Name: "monorepo", Flag: true, Spelling: "--monorepo"}, + {Key: FlagUpgradeNoPrune, Name: "no-prune", Flag: true, Spelling: "--no-prune"}, + {Key: FlagUpgradeRaw, Name: "raw", Flag: true, Spelling: "--raw"}, {Key: ArgUpgradeInstalledToolVersion, Name: "INSTALLED_TOOL@VERSION"}, {}, {}, - {Key: FlagUseEnv, Name: "env", Flag: true}, - {Key: FlagUseForce, Name: "force", Flag: true}, - {Key: FlagUseGlobal, Name: "global", Flag: true}, - {Key: FlagUseJobs, Name: "jobs", Flag: true}, - {Key: FlagUseDryRun, Name: "dry-run", Flag: true}, - {Key: FlagUsePath, Name: "path", Flag: true}, - {Key: FlagUseDryRunCode, Name: "dry-run-code", Flag: true}, - {Key: FlagUseFuzzy, Name: "fuzzy", Flag: true}, - {Key: FlagUseMinimumReleaseAge, Name: "minimum-release-age", Flag: true}, - {Key: FlagUsePin, Name: "pin", Flag: true}, - {Key: FlagUseRaw, Name: "raw", Flag: true}, - {Key: FlagUseRemove, Name: "remove", Flag: true}, + {Key: FlagUseEnv, Name: "env", Flag: true, Spelling: "--env"}, + {Key: FlagUseForce, Name: "force", Flag: true, Spelling: "--force"}, + {Key: FlagUseGlobal, Name: "global", Flag: true, Spelling: "--global"}, + {Key: FlagUseJobs, Name: "jobs", Flag: true, Spelling: "--jobs"}, + {Key: FlagUseDryRun, Name: "dry-run", Flag: true, Spelling: "--dry-run"}, + {Key: FlagUsePath, Name: "path", Flag: true, Spelling: "--path"}, + {Key: FlagUseDryRunCode, Name: "dry-run-code", Flag: true, Spelling: "--dry-run-code"}, + {Key: FlagUseFuzzy, Name: "fuzzy", Flag: true, Spelling: "--fuzzy"}, + {Key: FlagUseMinimumReleaseAge, Name: "minimum-release-age", Flag: true, Spelling: "--minimum-release-age"}, + {Key: FlagUsePin, Name: "pin", Flag: true, Spelling: "--pin"}, + {Key: FlagUseRaw, Name: "raw", Flag: true, Spelling: "--raw"}, + {Key: FlagUseRemove, Name: "remove", Flag: true, Spelling: "--remove"}, {Key: ArgUseToolVersion, Name: "TOOL@VERSION"}, {}, - {Key: FlagVersionJson, Name: "json", Flag: true}, - {}, - {Key: FlagWatchTaskFlag, Name: "task-flag", Flag: true}, - {Key: FlagWatchGlob, Name: "glob", Flag: true}, - {Key: FlagWatchSkipDeps, Name: "skip-deps", Flag: true}, - {Key: FlagWatchWatch, Name: "watch", Flag: true}, - {Key: FlagWatchWatchNonRecursive, Name: "watch-non-recursive", Flag: true}, - {Key: FlagWatchWatchFile, Name: "watch-file", Flag: true}, - {Key: FlagWatchClear, Name: "clear", Flag: true, Choices: []string{"clear", "reset"}}, - {Key: FlagWatchOnBusyUpdate, Name: "on-busy-update", Flag: true, Choices: []string{"queue", "do-nothing", "restart", "signal"}, Default: []string{"do-nothing"}}, - {Key: FlagWatchRestart, Name: "restart", Flag: true}, - {Key: FlagWatchSignal, Name: "signal", Flag: true}, - {Key: FlagWatchStopSignal, Name: "stop-signal", Flag: true}, - {Key: FlagWatchStopTimeout, Name: "stop-timeout", Flag: true, Default: []string{"10s"}}, - {Key: FlagWatchMapSignal, Name: "map-signal", Flag: true}, - {Key: FlagWatchDebounce, Name: "debounce", Flag: true, Default: []string{"50ms"}}, - {Key: FlagWatchStdinQuit, Name: "stdin-quit", Flag: true}, - {Key: FlagWatchNoVcsIgnore, Name: "no-vcs-ignore", Flag: true}, - {Key: FlagWatchNoProjectIgnore, Name: "no-project-ignore", Flag: true}, - {Key: FlagWatchNoGlobalIgnore, Name: "no-global-ignore", Flag: true}, - {Key: FlagWatchNoDefaultIgnore, Name: "no-default-ignore", Flag: true}, - {Key: FlagWatchNoDiscoverIgnore, Name: "no-discover-ignore", Flag: true}, - {Key: FlagWatchIgnoreNothing, Name: "ignore-nothing", Flag: true}, - {Key: FlagWatchPostpone, Name: "postpone", Flag: true}, - {Key: FlagWatchDelayRun, Name: "delay-run", Flag: true}, - {Key: FlagWatchPoll, Name: "poll", Flag: true}, - {Key: FlagWatchShell, Name: "shell", Flag: true}, - {Key: FlagWatchN, Name: "n", Flag: true}, - {Key: FlagWatchEmitEventsTo, Name: "emit-events-to", Flag: true, Choices: []string{"environment", "stdio", "file", "json-stdio", "json-file", "none"}, Default: []string{"none"}}, - {Key: FlagWatchOnlyEmitEvents, Name: "only-emit-events", Flag: true}, - {Key: FlagWatchEnv, Name: "env", Flag: true}, - {Key: FlagWatchWrapProcess, Name: "wrap-process", Flag: true, Choices: []string{"group", "session", "none"}}, - {Key: FlagWatchNotify, Name: "notify", Flag: true}, - {Key: FlagWatchColor, Name: "color", Flag: true, Choices: []string{"auto", "always", "never"}, Default: []string{"auto"}}, - {Key: FlagWatchTimings, Name: "timings", Flag: true}, - {Key: FlagWatchQuiet, Name: "quiet", Flag: true}, - {Key: FlagWatchBell, Name: "bell", Flag: true}, - {Key: FlagWatchProjectOrigin, Name: "project-origin", Flag: true}, - {Key: FlagWatchWorkdir, Name: "workdir", Flag: true}, - {Key: FlagWatchExts, Name: "exts", Flag: true}, - {Key: FlagWatchFilter, Name: "filter", Flag: true}, - {Key: FlagWatchFilterFile, Name: "filter-file", Flag: true}, - {Key: FlagWatchFilterProg, Name: "filter-prog", Flag: true}, - {Key: FlagWatchIgnore, Name: "ignore", Flag: true}, - {Key: FlagWatchIgnoreFile, Name: "ignore-file", Flag: true}, - {Key: FlagWatchFsEvents, Name: "fs-events", Flag: true, Choices: []string{"access", "create", "remove", "rename", "modify", "metadata"}, Default: []string{"create", "remove", "rename", "modify", "metadata"}}, - {Key: FlagWatchNoMeta, Name: "no-meta", Flag: true}, - {Key: FlagWatchPrintEvents, Name: "print-events", Flag: true}, - {Key: FlagWatchManual, Name: "manual", Flag: true}, + {Key: FlagVersionJson, Name: "json", Flag: true, Spelling: "--json"}, + {}, + {Key: FlagWatchTaskFlag, Name: "task-flag", Flag: true, Spelling: "--task-flag"}, + {Key: FlagWatchGlob, Name: "glob", Flag: true, Spelling: "--glob"}, + {Key: FlagWatchSkipDeps, Name: "skip-deps", Flag: true, Spelling: "--skip-deps"}, + {Key: FlagWatchWatch, Name: "watch", Flag: true, Spelling: "--watch"}, + {Key: FlagWatchWatchNonRecursive, Name: "watch-non-recursive", Flag: true, Spelling: "--watch-non-recursive"}, + {Key: FlagWatchWatchFile, Name: "watch-file", Flag: true, Spelling: "--watch-file"}, + {Key: FlagWatchClear, Name: "clear", Flag: true, Spelling: "--clear", Choices: []string{"clear", "reset"}}, + {Key: FlagWatchOnBusyUpdate, Name: "on-busy-update", Flag: true, Spelling: "--on-busy-update", Choices: []string{"queue", "do-nothing", "restart", "signal"}, Default: []string{"do-nothing"}}, + {Key: FlagWatchRestart, Name: "restart", Flag: true, Spelling: "--restart"}, + {Key: FlagWatchSignal, Name: "signal", Flag: true, Spelling: "--signal"}, + {Key: FlagWatchStopSignal, Name: "stop-signal", Flag: true, Spelling: "--stop-signal"}, + {Key: FlagWatchStopTimeout, Name: "stop-timeout", Flag: true, Spelling: "--stop-timeout", Default: []string{"10s"}}, + {Key: FlagWatchMapSignal, Name: "map-signal", Flag: true, Spelling: "--map-signal"}, + {Key: FlagWatchDebounce, Name: "debounce", Flag: true, Spelling: "--debounce", Default: []string{"50ms"}}, + {Key: FlagWatchStdinQuit, Name: "stdin-quit", Flag: true, Spelling: "--stdin-quit"}, + {Key: FlagWatchNoVcsIgnore, Name: "no-vcs-ignore", Flag: true, Spelling: "--no-vcs-ignore"}, + {Key: FlagWatchNoProjectIgnore, Name: "no-project-ignore", Flag: true, Spelling: "--no-project-ignore"}, + {Key: FlagWatchNoGlobalIgnore, Name: "no-global-ignore", Flag: true, Spelling: "--no-global-ignore"}, + {Key: FlagWatchNoDefaultIgnore, Name: "no-default-ignore", Flag: true, Spelling: "--no-default-ignore"}, + {Key: FlagWatchNoDiscoverIgnore, Name: "no-discover-ignore", Flag: true, Spelling: "--no-discover-ignore"}, + {Key: FlagWatchIgnoreNothing, Name: "ignore-nothing", Flag: true, Spelling: "--ignore-nothing"}, + {Key: FlagWatchPostpone, Name: "postpone", Flag: true, Spelling: "--postpone"}, + {Key: FlagWatchDelayRun, Name: "delay-run", Flag: true, Spelling: "--delay-run"}, + {Key: FlagWatchPoll, Name: "poll", Flag: true, Spelling: "--poll"}, + {Key: FlagWatchShell, Name: "shell", Flag: true, Spelling: "--shell"}, + {Key: FlagWatchN, Name: "n", Flag: true, Spelling: "-n"}, + {Key: FlagWatchEmitEventsTo, Name: "emit-events-to", Flag: true, Spelling: "--emit-events-to", Choices: []string{"environment", "stdio", "file", "json-stdio", "json-file", "none"}, Default: []string{"none"}}, + {Key: FlagWatchOnlyEmitEvents, Name: "only-emit-events", Flag: true, Spelling: "--only-emit-events"}, + {Key: FlagWatchEnv, Name: "env", Flag: true, Spelling: "--env"}, + {Key: FlagWatchWrapProcess, Name: "wrap-process", Flag: true, Spelling: "--wrap-process", Choices: []string{"group", "session", "none"}}, + {Key: FlagWatchNotify, Name: "notify", Flag: true, Spelling: "--notify"}, + {Key: FlagWatchColor, Name: "color", Flag: true, Spelling: "--color", Choices: []string{"auto", "always", "never"}, Default: []string{"auto"}}, + {Key: FlagWatchTimings, Name: "timings", Flag: true, Spelling: "--timings"}, + {Key: FlagWatchQuiet, Name: "quiet", Flag: true, Spelling: "--quiet"}, + {Key: FlagWatchBell, Name: "bell", Flag: true, Spelling: "--bell"}, + {Key: FlagWatchProjectOrigin, Name: "project-origin", Flag: true, Spelling: "--project-origin"}, + {Key: FlagWatchWorkdir, Name: "workdir", Flag: true, Spelling: "--workdir"}, + {Key: FlagWatchExts, Name: "exts", Flag: true, Spelling: "--exts"}, + {Key: FlagWatchFilter, Name: "filter", Flag: true, Spelling: "--filter"}, + {Key: FlagWatchFilterFile, Name: "filter-file", Flag: true, Spelling: "--filter-file"}, + {Key: FlagWatchFilterProg, Name: "filter-prog", Flag: true, Spelling: "--filter-prog"}, + {Key: FlagWatchIgnore, Name: "ignore", Flag: true, Spelling: "--ignore"}, + {Key: FlagWatchIgnoreFile, Name: "ignore-file", Flag: true, Spelling: "--ignore-file"}, + {Key: FlagWatchFsEvents, Name: "fs-events", Flag: true, Spelling: "--fs-events", Choices: []string{"access", "create", "remove", "rename", "modify", "metadata"}, Default: []string{"create", "remove", "rename", "modify", "metadata"}}, + {Key: FlagWatchNoMeta, Name: "no-meta", Flag: true, Spelling: "--no-meta"}, + {Key: FlagWatchPrintEvents, Name: "print-events", Flag: true, Spelling: "--print-events"}, + {Key: FlagWatchManual, Name: "manual", Flag: true, Spelling: "--manual"}, {Key: ArgWatchTask, Name: "TASK"}, {Key: ArgWatchArgs, Name: "ARGS"}, {}, {Key: ArgWhereToolVersion, Name: "TOOL@VERSION", Required: true}, {Key: ArgWhereAsdfVersion, Name: "ASDF_VERSION"}, {}, - {Key: FlagWhichTool, Name: "tool", Flag: true}, - {Key: FlagWhichComplete, Name: "complete", Flag: true}, - {Key: FlagWhichPlugin, Name: "plugin", Flag: true}, - {Key: FlagWhichVersion, Name: "version", Flag: true}, + {Key: FlagWhichTool, Name: "tool", Flag: true, Spelling: "--tool"}, + {Key: FlagWhichComplete, Name: "complete", Flag: true, Spelling: "--complete"}, + {Key: FlagWhichPlugin, Name: "plugin", Flag: true, Spelling: "--plugin"}, + {Key: FlagWhichVersion, Name: "version", Flag: true, Spelling: "--version"}, {Key: ArgWhichBinName, Name: "BIN_NAME"}, } diff --git a/go/internal/spec/spec.go b/go/internal/spec/spec.go index 37bdec98a..c8b3adc9a 100644 --- a/go/internal/spec/spec.go +++ b/go/internal/spec/spec.go @@ -198,6 +198,21 @@ type Flag struct { Arg *Arg `json:"arg"` } +// spelling is how a user types a flag: its first long form, else its first short. +// +// Worked out here, where the forms are visible, because the rules that judge an +// entry never see one — and guessing from the name gets `--a` and `-a` the wrong +// way round. +func spelling(f *Flag) string { + if len(f.Long) > 0 { + return "--" + f.Long[0] + } + if len(f.Short) > 0 && f.Short[0] != "" { + return "-" + f.Short[0] + } + return "" +} + // choices for a flag are declared on the value it takes, not on the flag. func (f *Flag) choices() []string { if f.Arg == nil { @@ -659,6 +674,7 @@ func (b *builder) flag(f *Flag) *argv.Flag { b.record(out.Key, argv.Meta{ Name: f.Name, Flag: true, + Spelling: spelling(f), Required: f.Required, Choices: f.choices(), Default: f.defaults(), diff --git a/go/internal/spec/spec_test.go b/go/internal/spec/spec_test.go index 1c44f2c74..fb562c3fc 100644 --- a/go/internal/spec/spec_test.go +++ b/go/internal/spec/spec_test.go @@ -461,3 +461,26 @@ func TestATruncatedSubcommandObjectIsAnError(t *testing.T) { t.Error("a truncated lowering should not decode as a spec") } } + +// The tables carry how a flag is typed, because the rules that judge an entry +// never see one — and a one-character long form and a short form are both one +// character, so guessing from the name renders `--a` as `-a`. +func TestTheTableCarriesHowAFlagIsTyped(t *testing.T) { + root, meta := build(&Spec{ + Name: "ex", Bin: "ex", + Cmd: Cmd{Name: "ex", Flags: []Flag{ + {Name: "a", Long: []string{"a"}}, + {Name: "b", Short: []string{"b"}}, + {Name: "file", Long: []string{"file"}, Short: []string{"f"}}, + }}, + }) + for _, c := range []struct{ name, want string }{ + {"a", "--a"}, // one character, and a long form + {"b", "-b"}, // short only + {"file", "--file"}, // the long form wins where there is one + } { + if got := metaFor(t, meta, root, c.name).Spelling; got != c.want { + t.Errorf("%s: want %q, got %q", c.name, c.want, got) + } + } +} diff --git a/lib/src/go/mod.rs b/lib/src/go/mod.rs index 0cea680d0..33f3ccc19 100644 --- a/lib/src/go/mod.rs +++ b/lib/src/go/mod.rs @@ -454,6 +454,14 @@ impl Emitter<'_> { if flag.required { fields.push("Required: true".to_string()); } + // How a user types it, worked out where the forms are visible: the rules + // that judge an entry never see a flag, and guessing from the name gets a + // one-letter long form and a short the wrong way round. + if let Some(long) = flag.long.first() { + fields.push(format!("Spelling: {}", go_string(&format!("--{long}")))); + } else if let Some(short) = flag.short.first() { + fields.push(format!("Spelling: {}", go_string(&format!("-{short}")))); + } // Written on the value a flag takes, never on the flag. if let Some(choices) = flag.arg.as_ref().and_then(|a| a.choices.as_ref()) { fields.push(format!("Choices: {}", string_slice(&choices.choices))); @@ -1145,6 +1153,16 @@ fn go_byte(c: char) -> String { mod tests { use super::*; + /// The emitted `Meta` line for an entry, so a test can assert about the part + /// it cares about rather than the whole rendered row — which grows a field + /// every time the cold table learns something. + fn entry_of(out: &str, name: &str) -> String { + out.lines() + .find(|l| l.contains(&format!("Name: \"{name}\", Flag: true"))) + .unwrap_or_default() + .to_string() + } + fn go(kdl: &str) -> String { let spec: Spec = kdl.parse().expect("the fixture spec should parse"); generate(&spec, &GoOptions::default()) @@ -1527,19 +1545,13 @@ cmd "run" { } "#); // A negation names the flag it belongs to. - assert!( - out.contains("Name: \"plain\", Flag: true, Conflicts: []uint64{FlagColor}"), - "{out}" - ); + assert!(out.contains("Conflicts: []uint64{FlagColor}"), "{out}"); // An inherited global is in scope from below. - assert!( - out.contains("Name: \"loud\", Flag: true, Conflicts: []uint64{FlagQuiet}"), - "{out}" - ); + assert!(out.contains("Conflicts: []uint64{FlagQuiet}"), "{out}"); // `--plain` is not global, so from a subcommand it names nothing — the // other half, and the one a looser search would get wrong. assert!( - out.contains("{Key: FlagRunSolo, Name: \"solo\", Flag: true},"), + !entry_of(&out, "solo").contains("Conflicts"), "a non-global should not resolve from below:\n{out}" ); } @@ -1560,21 +1572,15 @@ flag "--c" conflicts="-q" flag "--d" conflicts="--color" "#); // `--q` is not a long form of anything, and `-color` is not a short. - assert!( - out.contains("{Key: FlagA, Name: \"a\", Flag: true},"), - "{out}" - ); - assert!( - out.contains("{Key: FlagB, Name: \"b\", Flag: true},"), - "{out}" - ); + assert!(!entry_of(&out, "a").contains("Conflicts"), "{out}"); + assert!(!entry_of(&out, "b").contains("Conflicts"), "{out}"); // The forms the flags actually have. assert!( - out.contains("Name: \"c\", Flag: true, Conflicts: []uint64{FlagQuiet}"), + out.contains("Name: \"c\"") && out.contains("Conflicts: []uint64{FlagQuiet}"), "{out}" ); assert!( - out.contains("Name: \"d\", Flag: true, Conflicts: []uint64{FlagColor}"), + out.contains("Name: \"d\"") && out.contains("Conflicts: []uint64{FlagColor}"), "{out}" ); } @@ -1595,7 +1601,7 @@ flag "--zap" flag "--p" conflicts="--zap" "#); assert!( - out.contains("Name: \"p\", Flag: true, Conflicts: []uint64{FlagZap}"), + out.contains("Name: \"p\"") && out.contains("Conflicts: []uint64{FlagZap}"), "should name the flag `--zap` binds, not the one negating to it:\n{out}" ); } @@ -1611,12 +1617,12 @@ flag "--plain" conflicts="-no-tint" flag "--other" conflicts="--no-tint" "#); assert!( - out.contains("Name: \"plain\", Flag: true, Conflicts: []uint64{FlagTint}"), + out.contains("Name: \"plain\"") && out.contains("Conflicts: []uint64{FlagTint}"), "the exact form should resolve:\n{out}" ); // And the form it was not written as does not. assert!( - out.contains("{Key: FlagOther, Name: \"other\", Flag: true},"), + !entry_of(&out, "other").contains("Conflicts"), "`--no-tint` is not how it was declared:\n{out}" ); } @@ -1633,15 +1639,12 @@ flag "--a" conflicts="--no-color" flag "--b" conflicts="--no-tint" "#); assert!( - out.contains("Name: \"a\", Flag: true, Conflicts: []uint64{FlagColor}"), + out.contains("Name: \"a\"") && out.contains("Conflicts: []uint64{FlagColor}"), "{out}" ); // `--no-tint` is not the form `-no-tint`, so it names nothing — as in // usage-lib, which does not resolve it either. - assert!( - out.contains("{Key: FlagB, Name: \"b\", Flag: true},"), - "{out}" - ); + assert!(!entry_of(&out, "b").contains("Conflicts"), "{out}"); } #[test] diff --git a/lib/src/go/snapshots/usage__go__tests__a_whole_cli.snap b/lib/src/go/snapshots/usage__go__tests__a_whole_cli.snap index 14f063aaf..c6bbe3b69 100644 --- a/lib/src/go/snapshots/usage__go__tests__a_whole_cli.snap +++ b/lib/src/go/snapshots/usage__go__tests__a_whole_cli.snap @@ -93,18 +93,18 @@ var cmdConfigLs = &argv.Command{ // commands take keys too, and have no cold half. var Meta = argv.Metadata{ {}, - {Key: FlagVerbose, Name: "verbose", Flag: true}, - {Key: FlagColor, Name: "color", Flag: true}, - {Key: FlagJobs, Name: "jobs", Flag: true}, - {Key: FlagInclude, Name: "include", Flag: true, VarMax: 3}, + {Key: FlagVerbose, Name: "verbose", Flag: true, Spelling: "--verbose"}, + {Key: FlagColor, Name: "color", Flag: true, Spelling: "--color"}, + {Key: FlagJobs, Name: "jobs", Flag: true, Spelling: "--jobs"}, + {Key: FlagInclude, Name: "include", Flag: true, Spelling: "--include", VarMax: 3}, {Key: ArgFile, Name: "file", Required: true}, {Key: ArgRest, Name: "rest"}, {}, - {Key: FlagInstallForce, Name: "force", Flag: true}, + {Key: FlagInstallForce, Name: "force", Flag: true, Spelling: "--force"}, {Key: ArgInstallPkg, Name: "pkg", Required: true}, {}, {}, - {Key: FlagConfigLsNoHeader, Name: "no-header", Flag: true}, + {Key: FlagConfigLsNoHeader, Name: "no-header", Flag: true, Spelling: "--no-header"}, } // HelpText is the third table, read only when a page is rendered. Neither the diff --git a/lib/src/go/snapshots/usage__go__tests__colliding_names_get_distinct_identifiers.snap b/lib/src/go/snapshots/usage__go__tests__colliding_names_get_distinct_identifiers.snap index 9b0f6a3c7..daa546420 100644 --- a/lib/src/go/snapshots/usage__go__tests__colliding_names_get_distinct_identifiers.snap +++ b/lib/src/go/snapshots/usage__go__tests__colliding_names_get_distinct_identifiers.snap @@ -68,10 +68,10 @@ var cmdMacosDefaults2 = &argv.Command{ var Meta = argv.Metadata{ {}, {}, - {Key: FlagMacosDefaultsApply, Name: "apply", Flag: true}, + {Key: FlagMacosDefaultsApply, Name: "apply", Flag: true, Spelling: "--apply"}, {}, {}, - {Key: FlagMacosDefaultsApply2, Name: "apply", Flag: true}, + {Key: FlagMacosDefaultsApply2, Name: "apply", Flag: true, Spelling: "--apply"}, } // HelpText is the third table, read only when a page is rendered. Neither the From 63b99938d946598fb30eb905a6f709f0ffb7c38a Mon Sep 17 00:00:00 2001 From: default <216188+jdx@users.noreply.github.com> Date: Mon, 17 Aug 2026 18:12:51 +0000 Subject: [PATCH 5/7] fix(go): escape the command line in the error value as well as the page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Render escapes what the user typed before showing it back. `Error()` did not, and it is the string a caller gets from Go's own error interface — logged, wrapped, printed by code that never calls Render. An argument carrying an escape sequence reached the terminal through it, where it can recolour the output or forge a line that looks like the program's. Only the two fields that come from the command line. A flag's name and an argument's are the spec's, written by the author and held in the tables. `safe` returns its input untouched where there is nothing to escape, which is every real failure: a message that allocates once should not also allocate a copy of each token in it. Co-Authored-By: Claude Opus 5 --- go/argv/argv.go | 11 +++++++++-- go/argv/render.go | 6 ++++++ go/argv/render_test.go | 22 ++++++++++++++++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/go/argv/argv.go b/go/argv/argv.go index 20e407eee..0cfe7e97a 100644 --- a/go/argv/argv.go +++ b/go/argv/argv.go @@ -336,14 +336,21 @@ type Error struct { Other string } +// Error is the message Go's own error interface asks for. +// +// The tokens go through `safe` here as they do in [Render]: this string reaches a +// terminal too, by way of whatever logs or prints it, and a rejected argument +// carrying an escape sequence can recolour that output or forge a line in it. +// Where the message quotes the spec — a flag's name, an argument's — there is +// nothing to escape, because the author wrote it and the parse tables hold it. func (e *Error) Error() string { switch e.Code { case CodeUnknownFlag: - return "unknown flag: " + e.Token + return "unknown flag: " + safe(e.Token) case CodeMissingFlagValue: return "missing value for flag: " + e.Flag.Name case CodeUnexpectedArg: - return "unexpected argument: " + e.Token + return "unexpected argument: " + safe(e.Token) case CodeArgRequiresDoubleDash: return "argument requires a -- separator: " + e.Arg.Name case CodeTooDeep: diff --git a/go/argv/render.go b/go/argv/render.go index 10416c046..dcaeadc7e 100644 --- a/go/argv/render.go +++ b/go/argv/render.go @@ -144,6 +144,12 @@ func typedAs(spelling, name string) string { // cursor, or forge lines that look like they came from the program. Rendering a // rejected value is not a reason to execute it. func safe(s string) string { + // The common case is text with nothing to escape, and returning it as it is + // keeps this off the allocation budget: a failure allocates its message, and + // need not also allocate a copy of every token in it. + if !strings.ContainsFunc(s, func(r rune) bool { return r < 0x20 || r == 0x7f }) { + return s + } var out strings.Builder for _, r := range s { switch { diff --git a/go/argv/render_test.go b/go/argv/render_test.go index e6184c266..009389c69 100644 --- a/go/argv/render_test.go +++ b/go/argv/render_test.go @@ -141,6 +141,28 @@ func TestControlCharactersDoNotReachTheTerminal(t *testing.T) { } } +// The same for the message Go's error interface hands out. +// +// Render is the page a CLI prints, but an error is a value: it gets logged, +// wrapped, printed by a caller that never calls Render at all. That string +// reaches a terminal too, and it was quoting the command line raw. +func TestAnErrorValueIsSafeToPrintToo(t *testing.T) { + for _, e := range []*Error{ + {Code: CodeUnknownFlag, Token: "--x\x1b[31m\r\nerror: forged"}, + {Code: CodeUnexpectedArg, Token: "wat\x1b[31m\r\nerror: forged"}, + } { + got := e.Error() + for _, forbidden := range []string{"\x1b", "\r", "\n"} { + if strings.Contains(got, forbidden) { + t.Errorf("a control character survived into %q", got) + } + } + if !strings.Contains(got, "forged") { + t.Errorf("the token should still be shown: %q", got) + } + } +} + // The spelling is carried, not guessed. // // A one-character *long* form and a short form are both one character, so a From 8b0fb121d3ce16bee40b7f560d28fd7cd994164e Mon Sep 17 00:00:00 2001 From: default <216188+jdx@users.noreply.github.com> Date: Mon, 17 Aug 2026 20:09:11 +0000 Subject: [PATCH 6/7] fix(go): name the flag as typed in every failure that names one MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The spelling was carried onto the metadata so that the rules judging an entry after binding could name it the way a user types it — they never see a `*Flag`. Three of the four codes did not pass it on, so an invalid choice, too few values or too many occurrences reported a short-only flag as `j`: not something anyone can type, which is the whole thing this was meant to stop printing. An argument keeps its bare name, because that is what it is called. The emitter's relationship tests are tightened while here. They asserted a name and a `Conflicts` slice as two substrings of the whole file, which passes when the relationship is attached to a different flag entirely — the regression those tests exist to catch. Both halves now come from the same row. Co-Authored-By: Claude Opus 5 --- go/argv/post.go | 9 ++++++--- go/argv/render.go | 8 +++++--- go/argv/render_test.go | 37 +++++++++++++++++++++++++++++++++++++ lib/src/go/mod.rs | 15 ++++++++++----- 4 files changed, 58 insertions(+), 11 deletions(-) diff --git a/go/argv/post.go b/go/argv/post.go index eae236c89..0fe88b83b 100644 --- a/go/argv/post.go +++ b/go/argv/post.go @@ -191,7 +191,8 @@ func Check(m *Meta, values []string, occurrences int) *Error { // and a bad one, and so can a repeatable flag across occurrences. for _, v := range values { if !contains(m.Choices, v) { - return &Error{Code: CodeInvalidChoice, Name: m.Name, Choices: m.Choices} + return &Error{Code: CodeInvalidChoice, Name: m.Name, + Spelling: m.Spelling, Choices: m.Choices} } } } @@ -200,11 +201,13 @@ func Check(m *Meta, values []string, occurrences int) *Error { // its minimum; it simply is not there, and reporting `var_too_few` for it // would make every bounded variadic effectively required. if m.VarMin > 0 && len(values) > 0 && uint32(len(values)) < m.VarMin { - return &Error{Code: CodeVarTooFew, Name: m.Name, Bound: m.VarMin, Got: len(values)} + return &Error{Code: CodeVarTooFew, Name: m.Name, Spelling: m.Spelling, + Bound: m.VarMin, Got: len(values)} } if m.VarMax > 0 && occurrences > int(m.VarMax) { - return &Error{Code: CodeVarTooMany, Name: m.Name, Bound: m.VarMax, Got: occurrences} + return &Error{Code: CodeVarTooMany, Name: m.Name, Spelling: m.Spelling, + Bound: m.VarMax, Got: occurrences} } return nil diff --git a/go/argv/render.go b/go/argv/render.go index dcaeadc7e..2bfad3e99 100644 --- a/go/argv/render.go +++ b/go/argv/render.go @@ -85,16 +85,18 @@ func explain(err *Error, help HelpTable) string { case CodeMissingRequiredArg: return "missing required argument `" + err.Name + "`" case CodeInvalidChoice: - msg := "`" + err.Name + "` does not accept that value" + msg := "`" + typedAs(err.Spelling, err.Name) + "` does not accept that value" if len(err.Choices) > 0 { msg += " (expected one of: " + strings.Join(err.Choices, ", ") + ")" } return msg case CodeVarTooFew: - return "`" + err.Name + "` needs at least " + plural(int(err.Bound), "value") + + return "`" + typedAs(err.Spelling, err.Name) + "` needs at least " + + plural(int(err.Bound), "value") + ", got " + itoa(err.Got) case CodeVarTooMany: - return "`" + err.Name + "` accepts at most " + plural(int(err.Bound), "time") + + return "`" + typedAs(err.Spelling, err.Name) + "` accepts at most " + + plural(int(err.Bound), "time") + ", given " + itoa(err.Got) case CodeConflictingFlags: other := err.Other diff --git a/go/argv/render_test.go b/go/argv/render_test.go index 009389c69..c3c84f0ff 100644 --- a/go/argv/render_test.go +++ b/go/argv/render_test.go @@ -141,6 +141,43 @@ func TestControlCharactersDoNotReachTheTerminal(t *testing.T) { } } +// Every failure that names an entry names it the way it is typed. +// +// The spelling is carried on the metadata, so the rules that judge an entry after +// binding can pass it on — they never see a *Flag. Missing this on three of the +// codes left a short-only flag reported as `j`, which is not something anyone can +// type, and the whole point of carrying it was to stop printing those. +func TestEveryPostBindingFailureNamesTheFlagAsTyped(t *testing.T) { + short := &Meta{Name: "jobs", Flag: true, Spelling: "-j"} + for _, c := range []struct { + what string + err *Error + }{ + {"a choice", Check(&Meta{Name: short.Name, Flag: true, Spelling: short.Spelling, + Choices: []string{"a"}}, []string{"b"}, 1)}, + {"too few", Check(&Meta{Name: short.Name, Flag: true, Spelling: short.Spelling, + VarMin: 2}, []string{"a"}, 1)}, + {"too many", Check(&Meta{Name: short.Name, Flag: true, Spelling: short.Spelling, + VarMax: 1}, []string{"a", "b"}, 2)}, + {"required", Check(&Meta{Name: short.Name, Flag: true, Spelling: short.Spelling, + Required: true}, nil, 0)}, + } { + if c.err == nil { + t.Fatalf("%s should fail", c.what) + } + if got := explain(c.err, nil); !strings.Contains(got, "`-j`") { + t.Errorf("%s should name the flag as `-j`: %s", c.what, got) + } + } + + // An argument has no spelling to carry, and its bare name is what it is + // called: `` is not typed with dashes. + arg := Check(&Meta{Name: "file", Choices: []string{"a"}}, []string{"b"}, 0) + if got := explain(arg, nil); !strings.Contains(got, "`file`") { + t.Errorf("an argument keeps its name: %s", got) + } +} + // The same for the message Go's error interface hands out. // // Render is the page a CLI prints, but an error is a value: it gets logged, diff --git a/lib/src/go/mod.rs b/lib/src/go/mod.rs index 33f3ccc19..f8c605dda 100644 --- a/lib/src/go/mod.rs +++ b/lib/src/go/mod.rs @@ -1156,6 +1156,11 @@ mod tests { /// The emitted `Meta` line for an entry, so a test can assert about the part /// it cares about rather than the whole rendered row — which grows a field /// every time the cold table learns something. + /// + /// Used for what a row *does* say as well as for what it does not. Two + /// substring checks over the whole file — one for the name, one for the + /// relationship — pass when the relationship is attached to a different flag + /// entirely, which is the regression these tests exist to catch. fn entry_of(out: &str, name: &str) -> String { out.lines() .find(|l| l.contains(&format!("Name: \"{name}\", Flag: true"))) @@ -1576,11 +1581,11 @@ flag "--d" conflicts="--color" assert!(!entry_of(&out, "b").contains("Conflicts"), "{out}"); // The forms the flags actually have. assert!( - out.contains("Name: \"c\"") && out.contains("Conflicts: []uint64{FlagQuiet}"), + entry_of(&out, "c").contains("Conflicts: []uint64{FlagQuiet}"), "{out}" ); assert!( - out.contains("Name: \"d\"") && out.contains("Conflicts: []uint64{FlagColor}"), + entry_of(&out, "d").contains("Conflicts: []uint64{FlagColor}"), "{out}" ); } @@ -1601,7 +1606,7 @@ flag "--zap" flag "--p" conflicts="--zap" "#); assert!( - out.contains("Name: \"p\"") && out.contains("Conflicts: []uint64{FlagZap}"), + entry_of(&out, "p").contains("Conflicts: []uint64{FlagZap}"), "should name the flag `--zap` binds, not the one negating to it:\n{out}" ); } @@ -1617,7 +1622,7 @@ flag "--plain" conflicts="-no-tint" flag "--other" conflicts="--no-tint" "#); assert!( - out.contains("Name: \"plain\"") && out.contains("Conflicts: []uint64{FlagTint}"), + entry_of(&out, "plain").contains("Conflicts: []uint64{FlagTint}"), "the exact form should resolve:\n{out}" ); // And the form it was not written as does not. @@ -1639,7 +1644,7 @@ flag "--a" conflicts="--no-color" flag "--b" conflicts="--no-tint" "#); assert!( - out.contains("Name: \"a\"") && out.contains("Conflicts: []uint64{FlagColor}"), + entry_of(&out, "a").contains("Conflicts: []uint64{FlagColor}"), "{out}" ); // `--no-tint` is not the form `-no-tint`, so it names nothing — as in From 2e3c1b50d9cdc03e3978c5b24d993b641bf4c8af Mon Sep 17 00:00:00 2001 From: default <216188+jdx@users.noreply.github.com> Date: Mon, 17 Aug 2026 20:27:42 +0000 Subject: [PATCH 7/7] fix(go): advise the form that was typed, not the flag's first one MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A flag answers to several spellings, and the first is not always the one in front of the user. An inherited `--jobs --workers` whose `--jobs` a nearer command has taken still binds through `--workers` — and the advice for a missing value said `--jobs=-x`, which sets the other flag or fails again. The parser knows which form matched, so it carries it. For a long that costs nothing: with no attached value the token *is* the spelling, and a slice of it is free on a path that must not allocate. The short form is built in the failure branch rather than by the caller, for the same reason — the allocation test caught that on the first attempt. Where nothing was carried the flag's own first form is used, which at least exists. Co-Authored-By: Claude Opus 5 --- go/argv/parser.go | 24 ++++++++++++++++++++---- go/argv/render.go | 9 ++++++--- go/argv/render_test.go | 29 +++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 7 deletions(-) diff --git a/go/argv/parser.go b/go/argv/parser.go index 00905f922..4747f8351 100644 --- a/go/argv/parser.go +++ b/go/argv/parser.go @@ -282,7 +282,10 @@ func (p *Parser) longFlag(token string) bool { if hasAttached { value = attached } else { - v, ok := p.takeDetachedValue(flag) + // `token`, not `--`+name: with no attached value the token is the + // spelling, and slicing it costs nothing on a path that must not + // allocate. + v, ok := p.takeDetachedValue(flag, token, 0) if !ok { return false } @@ -365,7 +368,7 @@ func (p *Parser) shortFlag() bool { var value string switch { case rest == "": - v, ok := p.takeDetachedValue(flag) + v, ok := p.takeDetachedValue(flag, "", b) if !ok { return false } @@ -386,13 +389,26 @@ func (p *Parser) shortFlag() bool { // It refuses a flag-like token: `--jobs --force` is far more likely a forgotten // value than a deliberate one, and the attached form is available for the // deliberate case. The negative-number exception means `--offset -1` still works. -func (p *Parser) takeDetachedValue(flag *Flag) (string, bool) { +func (p *Parser) takeDetachedValue(flag *Flag, long string, short byte) (string, bool) { if p.pos < len(p.argv) && !isFlagLike(p.argv[p.pos]) { v := p.argv[p.pos] p.pos++ return v, true } - p.fail(Error{Code: CodeMissingFlagValue, Flag: flag}) + // The form the user actually wrote, carried so the advice can use it. A flag + // answers to several spellings and the first is not always the one in front of + // them: with an inherited `--jobs --workers` whose `--jobs` a nearer command + // has taken, `--workers` is what bound, and telling them to write `--jobs=…` + // sends them to a different flag. + // + // The long form arrives as a slice of the token, and the short one is built + // here rather than by the caller — this branch is the failure, and the caller + // is the hot path that must not allocate. + typed := long + if typed == "" && short != 0 { + typed = "-" + string(short) + } + p.fail(Error{Code: CodeMissingFlagValue, Flag: flag, Token: typed}) return "", false } diff --git a/go/argv/render.go b/go/argv/render.go index 2bfad3e99..1daf1ac8f 100644 --- a/go/argv/render.go +++ b/go/argv/render.go @@ -65,9 +65,12 @@ func explain(err *Error, help HelpTable) string { // binds. Illustrating the rule with the case that is exempt from it was // advice that contradicted itself. // - // And it is spelled in the form the flag actually has: telling someone - // with a short-only `-j` to write `--j=-x` sends them to an unknown flag. - spelling := spell(err.Flag) + // And it is spelled the way the user wrote it, where the parser said so: + // a flag answers to several forms, and the first one is not always the one + // in front of them — an inherited `--workers` whose `--jobs` a nearer + // command has taken is bound by `--workers` alone. Falling back to the + // flag's own first form, which at least exists, when nothing was carried. + spelling := typedAs(safe(err.Token), spell(err.Flag)) return "missing value for `" + spelling + "`" + " (a value beginning with `-` has to be attached: `" + spelling + "=-x`)" case CodeUnexpectedArg: diff --git a/go/argv/render_test.go b/go/argv/render_test.go index c3c84f0ff..8b72d37db 100644 --- a/go/argv/render_test.go +++ b/go/argv/render_test.go @@ -200,6 +200,35 @@ func TestAnErrorValueIsSafeToPrintToo(t *testing.T) { } } +// The advice names the form the user typed, where the parser knows it. +// +// A flag answers to several spellings, and the first is not always the one in +// front of them: an inherited `--jobs --workers` whose `--jobs` a nearer command +// has taken still binds through `--workers`, and advising `--jobs=-x` there sends +// them to a different flag entirely. +func TestTheAttachedFormIsSpelledTheWayItWasTyped(t *testing.T) { + global := &Flag{Key: 2, Name: "jobs", Longs: []string{"jobs", "workers"}, + TakesValue: true, Global: true} + local := &Flag{Key: 3, Name: "jobs", Longs: []string{"jobs"}} + sub := &Command{Name: "run", Key: 4, Flags: []*Flag{local}} + root := &Command{Name: "ex", Key: 1, Flags: []*Flag{global}, Subcommands: []*Command{sub}} + + p := New(root, []string{"run", "--workers"}) + for p.Next() { + } + err, _ := p.Err().(*Error) + if err == nil || err.Code != CodeMissingFlagValue { + t.Fatalf("a value-taking flag with nothing after it should fail: %v", p.Err()) + } + got := explain(err, nil) + if !strings.Contains(got, "`--workers=-x`") { + t.Errorf("the advice should use the form that bound: %s", got) + } + if strings.Contains(got, "--jobs") { + t.Errorf("`--jobs` is the nearer command's flag here: %s", got) + } +} + // The spelling is carried, not guessed. // // A one-character *long* form and a short form are both one character, so a