diff --git a/README.md b/README.md index fe3ea42..914c759 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,6 @@ Tiny, simple, but powerful CLI framework for modern Go 🚀 - [Sub Commands](#sub-commands) - [Flags](#flags) - [Arguments](#arguments) - - [Shell Completion](#shell-completion) - [Core Principles](#core-principles) - [😱 Well behaved libraries don't panic](#-well-behaved-libraries-dont-panic) - [🧘🏻 Keep it Simple](#-keep-it-simple) @@ -331,33 +330,6 @@ The types you can currently use for positional args are: > Slice types are not supported (yet), for those you need to use the `cmd.Args()` method to get the arguments manually. I plan to address this but it can be tricky > as slice types will eat up the remainder of the arguments so I need to figure out a good DevEx for this as it could lead to confusing outcomes -### Shell Completion - -`cli` has built-in support for shell completions via [carapace-bin]. Wire in `cli.CompletionSubCommand()` alongside your other subcommands: - -```go -cmd, err := cli.New( - "mytool", - // ... - cli.SubCommands( - buildServeCommand, - buildDeployCommand, - cli.CompletionSubCommand(), // add this - ), -) -``` - -Running `mytool completion` outputs a [carapace-spec] YAML document describing your full command tree — all subcommands, flags, and descriptions. Redirect it once to register completions with [carapace-bin]: - -```shell -mytool completion > ~/.config/carapace/specs/mytool.yaml -``` - -carapace-bin then provides completions across bash, zsh, fish, nushell, PowerShell, and more — no shell-specific scripts required. - -> [!TIP] -> See the [`./examples/completion`](https://github.com/FollowTheProcess/cli/tree/main/examples/completion) example for a working demonstration, and the [carapace-spec] docs for how to extend the generated YAML with semantic completion hints (file paths, environment variables, etc.) - ## Core Principles When designing and implementing `cli`, I had some core goals and guiding principles for implementation. @@ -455,6 +427,14 @@ var delete bool cli.New("demo", cli.Flag(&delete, "delete", cli.NoShortHand, "Delete something")) ``` +## Gaps + +`cli` is new and under active development, so naturally there are some gaps compared to more mature frameworks: + +- No shell completion (yet): I'm thinking about some smart ways to achieve this and haven't made up my mind yet +- Man page generation: Similar to shell completion +- Text wrapping and terminal width detection for `--help` (currently this is on you to format when writing) + ## In the Wild I built `cli` for my own uses really, so I've quickly adopted it across a number of tools. See the following projects for some working examples in real code: @@ -468,5 +448,3 @@ I built `cli` for my own uses really, so I've quickly adopted it across a number [spf13/pflag]: https://github.com/spf13/pflag [urfave/cli]: https://github.com/urfave/cli [functional options]: https://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis -[carapace-bin]: https://github.com/carapace-sh/carapace-bin -[carapace-spec]: https://github.com/carapace-sh/carapace-spec diff --git a/completion.go b/completion.go deleted file mode 100644 index ad41974..0000000 --- a/completion.go +++ /dev/null @@ -1,182 +0,0 @@ -package cli - -import ( - "context" - "fmt" - "slices" - "strings" - - publicflag "go.followtheprocess.codes/cli/flag" - "go.yaml.in/yaml/v4" -) - -const completionLong = ` -Outputs a carapace-spec YAML document describing this command's flags and subcommands. - -Redirect the output to register completions with carapace-bin: - - mytool completion > ~/.config/carapace/specs/mytool.yaml -` - -// CompletionSubCommand returns a [Builder] that constructs a "completion" subcommand. -// -// When run, it outputs a carapace-spec YAML document to stdout describing the full -// command tree, all flags, and all subcommands. -// -// Wire it into your root command: -// -// cli.New("mytool", -// cli.SubCommands(cli.CompletionSubCommand()), -// ... -// ) -// -// Users register completions by running: -// -// mytool completion > ~/.config/carapace/specs/mytool.yaml -// -// carapace-bin then provides completions across bash, zsh, fish, nushell, -// powershell, and more. See https://github.com/carapace-sh/carapace-spec -// for how to extend the generated YAML with semantic completion hints. -func CompletionSubCommand() Builder { - return func() (*Command, error) { - return New( - "completion", - Short("Output a carapace-spec YAML document to stdout"), - Long(completionLong), - Run(func(_ context.Context, cmd *Command) error { - data, err := marshalCompletionSpec(cmd.root()) - if err != nil { - return fmt.Errorf("generating carapace spec: %w", err) - } - - _, err = cmd.Stdout().Write(data) - - return err - }), - ) - } -} - -// specCommand is the internal representation of a carapace-spec YAML command node. -// -// See https://github.com/carapace-sh/carapace-spec for the full schema. -type specCommand struct { - Name string `yaml:"name"` - Description string `yaml:"description,omitempty"` - Flags map[string]string `yaml:"flags,omitempty"` - PersistentFlags map[string]string `yaml:"persistentflags,omitempty"` - Commands []specCommand `yaml:"commands,omitempty"` -} - -// marshalCompletionSpec generates a carapace-spec YAML document for cmd and its -// full subcommand tree. -func marshalCompletionSpec(cmd *Command) ([]byte, error) { - spec := buildSpecTree(cmd) - - // Help and version are on every command; declare them once as persistentflags. - spec.PersistentFlags = persistentFlagsFrom(cmd) - - data, err := yaml.Marshal(spec) - if err != nil { - return nil, fmt.Errorf("marshalling carapace spec: %w", err) - } - - return data, nil -} - -// isSystemFlag reports whether name is an automatically-injected flag. -// These flags appear on every command and are emitted as persistentflags -// on the root rather than repeated in every command's flags map. -func isSystemFlag(name string) bool { - return name == "help" || name == "version" -} - -// buildSpecTree recursively builds a specCommand tree from cmd. -func buildSpecTree(cmd *Command) specCommand { - spec := specCommand{ - Name: cmd.name, - Description: cmd.short, - Flags: specFlagsFrom(cmd), - } - - if len(cmd.subcommands) > 0 { - sorted := make([]*Command, len(cmd.subcommands)) - copy(sorted, cmd.subcommands) - slices.SortFunc(sorted, func(a, b *Command) int { - return strings.Compare(a.name, b.name) - }) - - spec.Commands = make([]specCommand, len(sorted)) - for i, sub := range sorted { - spec.Commands[i] = buildSpecTree(sub) - } - } - - return spec -} - -// specFlagsFrom builds the carapace-spec flags map for cmd, excluding system -// flags (help, version) which are emitted as persistentflags on the root. -func specFlagsFrom(cmd *Command) map[string]string { - flags := make(map[string]string) - - for name, fl := range cmd.flagSet().All() { - if isSystemFlag(name) { - continue - } - - key := specFlagKey(name, fl.Short(), fl.Type(), fl.NoArgValue()) - flags[key] = fl.Usage() - } - - if len(flags) == 0 { - return nil - } - - return flags -} - -// persistentFlagsFrom builds the carapace-spec persistentflags map from the -// system flags (help, version) that are automatically added to every command. -func persistentFlagsFrom(cmd *Command) map[string]string { - flags := make(map[string]string) - - for name, fl := range cmd.flagSet().All() { - if !isSystemFlag(name) { - continue - } - - key := specFlagKey(name, fl.Short(), fl.Type(), fl.NoArgValue()) - flags[key] = fl.Usage() - } - - if len(flags) == 0 { - return nil - } - - return flags -} - -// specFlagKey encodes a flag name, shorthand, and type into a carapace-spec -// flag map key. -func specFlagKey(name string, short rune, typ, noArgValue string) string { - var base string - if short != publicflag.NoShortHand { - base = fmt.Sprintf("-%s, --%s", string(short), name) - } else { - base = "--" + name - } - - switch { - case noArgValue == "": - // Value is required - return base + "=" - case typ == "bool": - return base - case typ == "count": - return base + "*" - default: - // Optional value - return base + "?" - } -} diff --git a/completion_test.go b/completion_test.go deleted file mode 100644 index 02b73a3..0000000 --- a/completion_test.go +++ /dev/null @@ -1,315 +0,0 @@ -package cli_test - -import ( - "bytes" - "context" - "net" - "slices" - "testing" - "time" - - "go.followtheprocess.codes/cli" - "go.followtheprocess.codes/cli/flag" - "go.followtheprocess.codes/snapshot" - "go.followtheprocess.codes/test" -) - -func TestCompletionSpec(t *testing.T) { - tests := []struct { - name string - options []cli.Option - }{ - { - name: "no user flags", - options: []cli.Option{ - cli.Short("My tool"), - cli.OverrideArgs([]string{"completion"}), - cli.SubCommands(cli.CompletionSubCommand()), - }, - }, - { - name: "bool flag", - options: []cli.Option{ - cli.Short("My tool"), - cli.OverrideArgs([]string{"completion"}), - cli.Flag(new(bool), "force", 'f', "Force deletion"), - cli.SubCommands(cli.CompletionSubCommand()), - }, - }, - { - name: "string flag", - options: []cli.Option{ - cli.Short("My tool"), - cli.OverrideArgs([]string{"completion"}), - cli.Flag(new(string), "output", 'o', "Output file"), - cli.SubCommands(cli.CompletionSubCommand()), - }, - }, - { - name: "count flag", - options: []cli.Option{ - cli.Short("My tool"), - cli.OverrideArgs([]string{"completion"}), - cli.Flag(new(flag.Count), "verbose", 'v', "Verbosity level"), - cli.SubCommands(cli.CompletionSubCommand()), - }, - }, - { - name: "long-only flag", - options: []cli.Option{ - cli.Short("My tool"), - cli.OverrideArgs([]string{"completion"}), - cli.Flag(new(bool), "dry-run", flag.NoShortHand, "Dry run mode"), - cli.SubCommands(cli.CompletionSubCommand()), - }, - }, - { - name: "slice flag", - options: []cli.Option{ - cli.Short("My tool"), - cli.OverrideArgs([]string{"completion"}), - cli.Flag(new([]string), "tags", 't', "Tags to apply"), - cli.SubCommands(cli.CompletionSubCommand()), - }, - }, - { - name: "with subcommands", - options: []cli.Option{ - cli.Short("My tool"), - cli.OverrideArgs([]string{"completion"}), - cli.SubCommands( - cli.CompletionSubCommand(), - func() (*cli.Command, error) { - return cli.New("delete", - cli.Short("Delete a resource"), - cli.Run(func(_ context.Context, _ *cli.Command) error { return nil }), - ) - }, - func() (*cli.Command, error) { - return cli.New("get", - cli.Short("Get a resource"), - cli.Run(func(_ context.Context, _ *cli.Command) error { return nil }), - ) - }, - ), - }, - }, - { - name: "nested subcommands", - options: []cli.Option{ - cli.Short("My tool"), - cli.OverrideArgs([]string{"completion"}), - cli.SubCommands( - cli.CompletionSubCommand(), - func() (*cli.Command, error) { - return cli.New("repo", - cli.Short("Repository commands"), - cli.SubCommands( - func() (*cli.Command, error) { - return cli.New("clone", - cli.Short("Clone a repository"), - cli.Flag(new(string), "branch", 'b', "Branch to clone"), - cli.Run(func(_ context.Context, _ *cli.Command) error { return nil }), - ) - }, - ), - ) - }, - ), - }, - }, - { - name: "three level nesting", - options: []cli.Option{ - cli.Short("My tool"), - cli.OverrideArgs([]string{"completion"}), - cli.SubCommands( - cli.CompletionSubCommand(), - func() (*cli.Command, error) { - return cli.New("repo", - cli.Short("Repository commands"), - cli.SubCommands( - func() (*cli.Command, error) { - return cli.New("pr", - cli.Short("Pull request commands"), - cli.SubCommands( - func() (*cli.Command, error) { - return cli.New("create", - cli.Short("Create a pull request"), - cli.Flag(new(string), "title", 't', "PR title"), - cli.Run(func(_ context.Context, _ *cli.Command) error { return nil }), - ) - }, - ), - ) - }, - ), - ) - }, - ), - }, - }, - { - name: "mixed flag types", - options: []cli.Option{ - cli.Short("My tool"), - cli.OverrideArgs([]string{"completion"}), - cli.Flag(new(bool), "force", 'f', "Force the operation"), - cli.Flag(new(string), "output", 'o', "Output file"), - cli.Flag(new(flag.Count), "verbose", 'v', "Verbosity level"), - cli.Flag(new(bool), "dry-run", flag.NoShortHand, "Dry run, make no changes"), - cli.Flag(new(int), "timeout", flag.NoShortHand, "Timeout in seconds"), - cli.Flag(new([]string), "tags", flag.NoShortHand, "Tags to apply"), - cli.SubCommands(cli.CompletionSubCommand()), - }, - }, - { - name: "yaml special chars in usage", - options: []cli.Option{ - cli.Short("My tool"), - cli.OverrideArgs([]string{"completion"}), - // Colons, quotes, and parens in usage strings must be safely marshalled. - cli.Flag(new(bool), "verbose", 'v', "Verbose: show all output"), - cli.Flag(new(string), "config", 'c', `Config file (default: "~/.config.yaml")`), - cli.SubCommands(cli.CompletionSubCommand()), - }, - }, - { - // Subcommands added in non-alphabetical order; output must be sorted. - name: "subcommands sorted alphabetically", - options: []cli.Option{ - cli.Short("My tool"), - cli.OverrideArgs([]string{"completion"}), - cli.SubCommands( - func() (*cli.Command, error) { - return cli.New("repo", - cli.Short("Repository commands"), - cli.Run(func(_ context.Context, _ *cli.Command) error { return nil }), - ) - }, - func() (*cli.Command, error) { - return cli.New("deploy", - cli.Short("Deploy commands"), - cli.Run(func(_ context.Context, _ *cli.Command) error { return nil }), - ) - }, - cli.CompletionSubCommand(), - ), - }, - }, - { - // An intermediate command that has both user flags and its own subcommands. - name: "mid-level command with flags and subcommands", - options: []cli.Option{ - cli.Short("My tool"), - cli.OverrideArgs([]string{"completion"}), - cli.SubCommands( - cli.CompletionSubCommand(), - func() (*cli.Command, error) { - return cli.New("repo", - cli.Short("Repository commands"), - cli.Flag(new(string), "format", flag.NoShortHand, "Output format"), - cli.SubCommands( - func() (*cli.Command, error) { - return cli.New("clone", - cli.Short("Clone a repository"), - cli.Flag(new(string), "branch", 'b', "Branch to clone"), - cli.Run(func(_ context.Context, _ *cli.Command) error { return nil }), - ) - }, - ), - ) - }, - ), - }, - }, - { - // Root has user flags and a deeply nested leaf command also has its own flags. - name: "root flags with nested subcommand flags", - options: []cli.Option{ - cli.Short("My tool"), - cli.OverrideArgs([]string{"completion"}), - cli.Flag(new(bool), "force", 'f', "Force the operation"), - cli.SubCommands( - cli.CompletionSubCommand(), - func() (*cli.Command, error) { - return cli.New("deploy", - cli.Short("Deploy commands"), - cli.SubCommands( - func() (*cli.Command, error) { - return cli.New("prod", - cli.Short("Deploy to production"), - cli.Flag(new(bool), "dry-run", flag.NoShortHand, "Dry run mode"), - cli.Run(func(_ context.Context, _ *cli.Command) error { return nil }), - ) - }, - ), - ) - }, - ), - }, - }, - { - name: "duration flag", - options: []cli.Option{ - cli.Short("My tool"), - cli.OverrideArgs([]string{"completion"}), - cli.Flag(new(time.Duration), "timeout", 't', "Request timeout"), - cli.SubCommands(cli.CompletionSubCommand()), - }, - }, - { - name: "float flag", - options: []cli.Option{ - cli.Short("My tool"), - cli.OverrideArgs([]string{"completion"}), - cli.Flag(new(float64), "threshold", flag.NoShortHand, "Minimum threshold"), - cli.SubCommands(cli.CompletionSubCommand()), - }, - }, - { - name: "ip flag", - options: []cli.Option{ - cli.Short("My tool"), - cli.OverrideArgs([]string{"completion"}), - cli.Flag(new(net.IP), "bind", 'b', "Address to bind"), - cli.SubCommands(cli.CompletionSubCommand()), - }, - }, - { - // A subcommand without an explicit Short inherits the package default description. - name: "subcommand with default description", - options: []cli.Option{ - cli.Short("My tool"), - cli.OverrideArgs([]string{"completion"}), - cli.SubCommands( - cli.CompletionSubCommand(), - func() (*cli.Command, error) { - return cli.New("frobnicate", - cli.Run(func(_ context.Context, _ *cli.Command) error { return nil }), - ) - }, - ), - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - snap := snapshot.New( - t, - snapshot.Update(*update), - ) - - stdout := &bytes.Buffer{} - - cmd, err := cli.New("mytool", slices.Concat([]cli.Option{cli.Stdout(stdout)}, tt.options)...) - test.Ok(t, err) - - err = cmd.Execute(t.Context()) - test.Ok(t, err) - - snap.Snap(stdout.String()) - }) - } -} diff --git a/examples/README.md b/examples/README.md index 6227766..2c854f2 100644 --- a/examples/README.md +++ b/examples/README.md @@ -8,7 +8,6 @@ This directory contains a bunch of example programs built with `cli` to show you - [`./subcommands`](#subcommands) - [`./namedargs`](#namedargs) - [`./cancel`](#cancel) - - [`./completion`](#completion) - [TODO](#todo) ## `./cover` @@ -39,16 +38,6 @@ This examples shows how `cli` requiring you to pass a `context.Context` to your ![cancel](../docs/img/cancel.gif) -## `./completion` - -Demonstrates how to add shell completion support to any CLI by wiring in `cli.CompletionSubCommand()`. Running `mytool completion` outputs a [carapace-spec] YAML document describing the full command tree. Redirect it once to register completions with [carapace-bin]: - -```shell -mytool completion > ~/.config/carapace/specs/mytool.yaml -``` - -carapace-bin then provides completions across bash, zsh, fish, nushell, PowerShell, and more — no shell-specific scripts required. - ### TODO - Replicate one or two well known CLI tools as an example @@ -57,5 +46,3 @@ carapace-bin then provides completions across bash, zsh, fish, nushell, PowerShe [quickstart]: [freeze]: -[carapace-spec]: -[carapace-bin]: diff --git a/examples/completion/cli.go b/examples/completion/cli.go deleted file mode 100644 index b8b6a34..0000000 --- a/examples/completion/cli.go +++ /dev/null @@ -1,92 +0,0 @@ -package main - -import ( - "context" - "fmt" - "strings" - - "go.followtheprocess.codes/cli" - "go.followtheprocess.codes/cli/flag" -) - -// BuildCLI constructs the root command with two subcommands and a completion -// subcommand wired in via [cli.CompletionSubCommand]. -// -// Running "mytool completion" outputs a carapace-spec YAML document that -// describes the full command tree. Redirect it once to register completions -// with carapace-bin: -// -// mytool completion > ~/.config/carapace/specs/mytool.yaml -// -// carapace-bin then provides completions across bash, zsh, fish, nushell, -// PowerShell, and more — no shell-specific scripts required. -func BuildCLI() (*cli.Command, error) { - return cli.New( - "mytool", - cli.Short("An example tool with shell completion support"), - cli.Version("dev"), - cli.Example("Say hello", "mytool hello --name Alice"), - cli.Example("Say goodbye loudly", "mytool goodbye --name Bob --shout"), - cli.Example("Register completions (run once)", "mytool completion > ~/.config/carapace/specs/mytool.yaml"), - cli.SubCommands( - buildHelloCommand, - buildGoodbyeCommand, - cli.CompletionSubCommand(), // wire in completion support - ), - ) -} - -type helloOptions struct { - name string - verbosity flag.Count -} - -func buildHelloCommand() (*cli.Command, error) { - var opts helloOptions - - return cli.New( - "hello", - cli.Short("Greet someone"), - cli.Example("Greet a person", "mytool hello --name Alice"), - cli.Example("Greet verbosely", "mytool hello --name Alice -vvv"), - cli.Flag(&opts.name, "name", 'n', "Name of the person to greet", cli.FlagDefault("World")), - cli.Flag(&opts.verbosity, "verbose", 'v', "Increase output verbosity"), - cli.Run(func(_ context.Context, cmd *cli.Command) error { - fmt.Fprintf(cmd.Stdout(), "Hello, %s!\n", opts.name) - - if opts.verbosity > 0 { - fmt.Fprintf(cmd.Stdout(), "(verbosity level: %d)\n", opts.verbosity) - } - - return nil - }), - ) -} - -type goodbyeOptions struct { - name string - shout bool -} - -func buildGoodbyeCommand() (*cli.Command, error) { - var opts goodbyeOptions - - return cli.New( - "goodbye", - cli.Short("Bid someone farewell"), - cli.Example("Say goodbye", "mytool goodbye --name Bob"), - cli.Example("Say it louder", "mytool goodbye --name Bob --shout"), - cli.Flag(&opts.name, "name", 'n', "Name of the person to farewell", cli.FlagDefault("World")), - cli.Flag(&opts.shout, "shout", 's', "Say the farewell in uppercase"), - cli.Run(func(_ context.Context, cmd *cli.Command) error { - msg := fmt.Sprintf("Goodbye, %s!", opts.name) - if opts.shout { - msg = strings.ToUpper(msg) - } - - fmt.Fprintln(cmd.Stdout(), msg) - - return nil - }), - ) -} diff --git a/examples/completion/main.go b/examples/completion/main.go deleted file mode 100644 index b7ff4c2..0000000 --- a/examples/completion/main.go +++ /dev/null @@ -1,29 +0,0 @@ -// Package completion demonstrates how to add shell completion support to a CLI -// using [cli.CompletionSubCommand]. -package main - -import ( - "context" - "fmt" - "os" -) - -func main() { - if err := run(); err != nil { - fmt.Fprintf(os.Stderr, "Error: %s\n", err) - os.Exit(1) - } -} - -func run() error { - cmd, err := BuildCLI() - if err != nil { - return fmt.Errorf("could not build root command: %w", err) - } - - if err := cmd.Execute(context.Background()); err != nil { - return fmt.Errorf("could not execute root command: %w", err) - } - - return nil -} diff --git a/go.mod b/go.mod index 6de4b91..044d7b6 100644 --- a/go.mod +++ b/go.mod @@ -11,11 +11,11 @@ require ( go.followtheprocess.codes/hue v1.1.0 go.followtheprocess.codes/snapshot v0.10.1 go.followtheprocess.codes/test v1.4.0 - go.yaml.in/yaml/v4 v4.0.0-rc.4 ) require ( go.followtheprocess.codes/diff v0.2.0 // indirect + go.yaml.in/yaml/v4 v4.0.0-rc.4 // indirect golang.org/x/sys v0.43.0 // indirect golang.org/x/term v0.42.0 // indirect ) diff --git a/testdata/snapshots/TestCompletionSpec/bool_flag.snap b/testdata/snapshots/TestCompletionSpec/bool_flag.snap deleted file mode 100644 index 7795712..0000000 --- a/testdata/snapshots/TestCompletionSpec/bool_flag.snap +++ /dev/null @@ -1,14 +0,0 @@ -source: completion_test.go -expression: stdout.String() ---- -| - name: mytool - description: My tool - flags: - -f, --force: Force deletion - persistentflags: - -V, --version: Show version info for mytool - -h, --help: Show help for mytool - commands: - - name: completion - description: Output a carapace-spec YAML document to stdout diff --git a/testdata/snapshots/TestCompletionSpec/count_flag.snap b/testdata/snapshots/TestCompletionSpec/count_flag.snap deleted file mode 100644 index 50c6771..0000000 --- a/testdata/snapshots/TestCompletionSpec/count_flag.snap +++ /dev/null @@ -1,14 +0,0 @@ -source: completion_test.go -expression: stdout.String() ---- -| - name: mytool - description: My tool - flags: - -v, --verbose*: Verbosity level - persistentflags: - -V, --version: Show version info for mytool - -h, --help: Show help for mytool - commands: - - name: completion - description: Output a carapace-spec YAML document to stdout diff --git a/testdata/snapshots/TestCompletionSpec/duration_flag.snap b/testdata/snapshots/TestCompletionSpec/duration_flag.snap deleted file mode 100644 index c4408ee..0000000 --- a/testdata/snapshots/TestCompletionSpec/duration_flag.snap +++ /dev/null @@ -1,14 +0,0 @@ -source: completion_test.go -expression: stdout.String() ---- -| - name: mytool - description: My tool - flags: - -t, --timeout=: Request timeout - persistentflags: - -V, --version: Show version info for mytool - -h, --help: Show help for mytool - commands: - - name: completion - description: Output a carapace-spec YAML document to stdout diff --git a/testdata/snapshots/TestCompletionSpec/float_flag.snap b/testdata/snapshots/TestCompletionSpec/float_flag.snap deleted file mode 100644 index c21cd1e..0000000 --- a/testdata/snapshots/TestCompletionSpec/float_flag.snap +++ /dev/null @@ -1,14 +0,0 @@ -source: completion_test.go -expression: stdout.String() ---- -| - name: mytool - description: My tool - flags: - --threshold=: Minimum threshold - persistentflags: - -V, --version: Show version info for mytool - -h, --help: Show help for mytool - commands: - - name: completion - description: Output a carapace-spec YAML document to stdout diff --git a/testdata/snapshots/TestCompletionSpec/ip_flag.snap b/testdata/snapshots/TestCompletionSpec/ip_flag.snap deleted file mode 100644 index ebf6ddf..0000000 --- a/testdata/snapshots/TestCompletionSpec/ip_flag.snap +++ /dev/null @@ -1,14 +0,0 @@ -source: completion_test.go -expression: stdout.String() ---- -| - name: mytool - description: My tool - flags: - -b, --bind=: Address to bind - persistentflags: - -V, --version: Show version info for mytool - -h, --help: Show help for mytool - commands: - - name: completion - description: Output a carapace-spec YAML document to stdout diff --git a/testdata/snapshots/TestCompletionSpec/long-only_flag.snap b/testdata/snapshots/TestCompletionSpec/long-only_flag.snap deleted file mode 100644 index 6d81cac..0000000 --- a/testdata/snapshots/TestCompletionSpec/long-only_flag.snap +++ /dev/null @@ -1,14 +0,0 @@ -source: completion_test.go -expression: stdout.String() ---- -| - name: mytool - description: My tool - flags: - --dry-run: Dry run mode - persistentflags: - -V, --version: Show version info for mytool - -h, --help: Show help for mytool - commands: - - name: completion - description: Output a carapace-spec YAML document to stdout diff --git a/testdata/snapshots/TestCompletionSpec/mid-level_command_with_flags_and_subcommands.snap b/testdata/snapshots/TestCompletionSpec/mid-level_command_with_flags_and_subcommands.snap deleted file mode 100644 index a82ae42..0000000 --- a/testdata/snapshots/TestCompletionSpec/mid-level_command_with_flags_and_subcommands.snap +++ /dev/null @@ -1,21 +0,0 @@ -source: completion_test.go -expression: stdout.String() ---- -| - name: mytool - description: My tool - persistentflags: - -V, --version: Show version info for mytool - -h, --help: Show help for mytool - commands: - - name: completion - description: Output a carapace-spec YAML document to stdout - - name: repo - description: Repository commands - flags: - --format=: Output format - commands: - - name: clone - description: Clone a repository - flags: - -b, --branch=: Branch to clone diff --git a/testdata/snapshots/TestCompletionSpec/mixed_flag_types.snap b/testdata/snapshots/TestCompletionSpec/mixed_flag_types.snap deleted file mode 100644 index 1d0b590..0000000 --- a/testdata/snapshots/TestCompletionSpec/mixed_flag_types.snap +++ /dev/null @@ -1,19 +0,0 @@ -source: completion_test.go -expression: stdout.String() ---- -| - name: mytool - description: My tool - flags: - --dry-run: Dry run, make no changes - --tags=: Tags to apply - --timeout=: Timeout in seconds - -f, --force: Force the operation - -o, --output=: Output file - -v, --verbose*: Verbosity level - persistentflags: - -V, --version: Show version info for mytool - -h, --help: Show help for mytool - commands: - - name: completion - description: Output a carapace-spec YAML document to stdout diff --git a/testdata/snapshots/TestCompletionSpec/nested_subcommands.snap b/testdata/snapshots/TestCompletionSpec/nested_subcommands.snap deleted file mode 100644 index a235438..0000000 --- a/testdata/snapshots/TestCompletionSpec/nested_subcommands.snap +++ /dev/null @@ -1,19 +0,0 @@ -source: completion_test.go -expression: stdout.String() ---- -| - name: mytool - description: My tool - persistentflags: - -V, --version: Show version info for mytool - -h, --help: Show help for mytool - commands: - - name: completion - description: Output a carapace-spec YAML document to stdout - - name: repo - description: Repository commands - commands: - - name: clone - description: Clone a repository - flags: - -b, --branch=: Branch to clone diff --git a/testdata/snapshots/TestCompletionSpec/no_user_flags.snap b/testdata/snapshots/TestCompletionSpec/no_user_flags.snap deleted file mode 100644 index 7f2ff05..0000000 --- a/testdata/snapshots/TestCompletionSpec/no_user_flags.snap +++ /dev/null @@ -1,12 +0,0 @@ -source: completion_test.go -expression: stdout.String() ---- -| - name: mytool - description: My tool - persistentflags: - -V, --version: Show version info for mytool - -h, --help: Show help for mytool - commands: - - name: completion - description: Output a carapace-spec YAML document to stdout diff --git a/testdata/snapshots/TestCompletionSpec/root_flags_with_nested_subcommand_flags.snap b/testdata/snapshots/TestCompletionSpec/root_flags_with_nested_subcommand_flags.snap deleted file mode 100644 index 61d6808..0000000 --- a/testdata/snapshots/TestCompletionSpec/root_flags_with_nested_subcommand_flags.snap +++ /dev/null @@ -1,21 +0,0 @@ -source: completion_test.go -expression: stdout.String() ---- -| - name: mytool - description: My tool - flags: - -f, --force: Force the operation - persistentflags: - -V, --version: Show version info for mytool - -h, --help: Show help for mytool - commands: - - name: completion - description: Output a carapace-spec YAML document to stdout - - name: deploy - description: Deploy commands - commands: - - name: prod - description: Deploy to production - flags: - --dry-run: Dry run mode diff --git a/testdata/snapshots/TestCompletionSpec/slice_flag.snap b/testdata/snapshots/TestCompletionSpec/slice_flag.snap deleted file mode 100644 index 10cd24e..0000000 --- a/testdata/snapshots/TestCompletionSpec/slice_flag.snap +++ /dev/null @@ -1,14 +0,0 @@ -source: completion_test.go -expression: stdout.String() ---- -| - name: mytool - description: My tool - flags: - -t, --tags=: Tags to apply - persistentflags: - -V, --version: Show version info for mytool - -h, --help: Show help for mytool - commands: - - name: completion - description: Output a carapace-spec YAML document to stdout diff --git a/testdata/snapshots/TestCompletionSpec/string_flag.snap b/testdata/snapshots/TestCompletionSpec/string_flag.snap deleted file mode 100644 index c9f99a5..0000000 --- a/testdata/snapshots/TestCompletionSpec/string_flag.snap +++ /dev/null @@ -1,14 +0,0 @@ -source: completion_test.go -expression: stdout.String() ---- -| - name: mytool - description: My tool - flags: - -o, --output=: Output file - persistentflags: - -V, --version: Show version info for mytool - -h, --help: Show help for mytool - commands: - - name: completion - description: Output a carapace-spec YAML document to stdout diff --git a/testdata/snapshots/TestCompletionSpec/subcommand_with_default_description.snap b/testdata/snapshots/TestCompletionSpec/subcommand_with_default_description.snap deleted file mode 100644 index cbc8094..0000000 --- a/testdata/snapshots/TestCompletionSpec/subcommand_with_default_description.snap +++ /dev/null @@ -1,14 +0,0 @@ -source: completion_test.go -expression: stdout.String() ---- -| - name: mytool - description: My tool - persistentflags: - -V, --version: Show version info for mytool - -h, --help: Show help for mytool - commands: - - name: completion - description: Output a carapace-spec YAML document to stdout - - name: frobnicate - description: A placeholder for something cool diff --git a/testdata/snapshots/TestCompletionSpec/subcommands_sorted_alphabetically.snap b/testdata/snapshots/TestCompletionSpec/subcommands_sorted_alphabetically.snap deleted file mode 100644 index a4166af..0000000 --- a/testdata/snapshots/TestCompletionSpec/subcommands_sorted_alphabetically.snap +++ /dev/null @@ -1,16 +0,0 @@ -source: completion_test.go -expression: stdout.String() ---- -| - name: mytool - description: My tool - persistentflags: - -V, --version: Show version info for mytool - -h, --help: Show help for mytool - commands: - - name: completion - description: Output a carapace-spec YAML document to stdout - - name: deploy - description: Deploy commands - - name: repo - description: Repository commands diff --git a/testdata/snapshots/TestCompletionSpec/three_level_nesting.snap b/testdata/snapshots/TestCompletionSpec/three_level_nesting.snap deleted file mode 100644 index e7ef3ff..0000000 --- a/testdata/snapshots/TestCompletionSpec/three_level_nesting.snap +++ /dev/null @@ -1,22 +0,0 @@ -source: completion_test.go -expression: stdout.String() ---- -| - name: mytool - description: My tool - persistentflags: - -V, --version: Show version info for mytool - -h, --help: Show help for mytool - commands: - - name: completion - description: Output a carapace-spec YAML document to stdout - - name: repo - description: Repository commands - commands: - - name: pr - description: Pull request commands - commands: - - name: create - description: Create a pull request - flags: - -t, --title=: PR title diff --git a/testdata/snapshots/TestCompletionSpec/with_subcommands.snap b/testdata/snapshots/TestCompletionSpec/with_subcommands.snap deleted file mode 100644 index 1d85a8f..0000000 --- a/testdata/snapshots/TestCompletionSpec/with_subcommands.snap +++ /dev/null @@ -1,16 +0,0 @@ -source: completion_test.go -expression: stdout.String() ---- -| - name: mytool - description: My tool - persistentflags: - -V, --version: Show version info for mytool - -h, --help: Show help for mytool - commands: - - name: completion - description: Output a carapace-spec YAML document to stdout - - name: delete - description: Delete a resource - - name: get - description: Get a resource diff --git a/testdata/snapshots/TestCompletionSpec/yaml_special_chars_in_usage.snap b/testdata/snapshots/TestCompletionSpec/yaml_special_chars_in_usage.snap deleted file mode 100644 index b0b42b4..0000000 --- a/testdata/snapshots/TestCompletionSpec/yaml_special_chars_in_usage.snap +++ /dev/null @@ -1,15 +0,0 @@ -source: completion_test.go -expression: stdout.String() ---- -| - name: mytool - description: My tool - flags: - -c, --config=: 'Config file (default: "~/.config.yaml")' - -v, --verbose: 'Verbose: show all output' - persistentflags: - -V, --version: Show version info for mytool - -h, --help: Show help for mytool - commands: - - name: completion - description: Output a carapace-spec YAML document to stdout