From 74f70eeb65ee9a10b2b398c9c40d61a7a1324f78 Mon Sep 17 00:00:00 2001 From: Bittrance Date: Sun, 27 Apr 2025 12:15:22 +0200 Subject: [PATCH 1/2] Avoid suggesting files in fish command completions. --- fish.go | 2 +- testdata/expected-fish-full.fish | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/fish.go b/fish.go index 6c6cf0c7eb..b1086ebc9e 100644 --- a/fish.go +++ b/fish.go @@ -69,7 +69,7 @@ func (cmd *Command) prepareFishCommands(commands []*Command, allCommands *[]stri for _, command := range commands { var completion strings.Builder fmt.Fprintf(&completion, - "complete -r -c %s -n '%s' -a '%s'", + "complete -x -c %s -n '%s' -a '%s'", cmd.Name, cmd.fishSubcommandHelper(previousCommands, commands), strings.Join(command.Names(), " "), diff --git a/testdata/expected-fish-full.fish b/testdata/expected-fish-full.fish index db4b2b5e04..f586c66fda 100644 --- a/testdata/expected-fish-full.fish +++ b/testdata/expected-fish-full.fish @@ -17,21 +17,21 @@ complete -c greet -n '__fish_greet_no_subcommand' -l foofile -r complete -c greet -n '__fish_greet_no_subcommand' -f -l help -s h -d 'show help' complete -c greet -n '__fish_greet_no_subcommand' -f -l version -s v -d 'print the version' complete -c greet -n '__fish_seen_subcommand_from config c' -f -l help -s h -d 'show help' -complete -r -c greet -n '__fish_greet_no_subcommand' -a 'config c' -d 'another usage test' +complete -x -c greet -n '__fish_greet_no_subcommand' -a 'config c' -d 'another usage test' complete -c greet -n '__fish_seen_subcommand_from config c' -l flag -s fl -s f -r complete -c greet -n '__fish_seen_subcommand_from config c' -f -l another-flag -s b -d 'another usage text' complete -c greet -n '__fish_seen_subcommand_from sub-config s ss' -f -l help -s h -d 'show help' -complete -r -c greet -n '__fish_seen_subcommand_from config c; and not __fish_seen_subcommand_from sub-config s ss' -a 'sub-config s ss' -d 'another usage test' +complete -x -c greet -n '__fish_seen_subcommand_from config c; and not __fish_seen_subcommand_from sub-config s ss' -a 'sub-config s ss' -d 'another usage test' complete -c greet -n '__fish_seen_subcommand_from sub-config s ss' -f -l sub-flag -s sub-fl -s s -r complete -c greet -n '__fish_seen_subcommand_from sub-config s ss' -f -l sub-command-flag -s s -d 'some usage text' complete -c greet -n '__fish_seen_subcommand_from info i in' -f -l help -s h -d 'show help' -complete -r -c greet -n '__fish_greet_no_subcommand' -a 'info i in' -d 'retrieve generic information' +complete -x -c greet -n '__fish_greet_no_subcommand' -a 'info i in' -d 'retrieve generic information' complete -c greet -n '__fish_seen_subcommand_from some-command' -f -l help -s h -d 'show help' -complete -r -c greet -n '__fish_greet_no_subcommand' -a 'some-command' +complete -x -c greet -n '__fish_greet_no_subcommand' -a 'some-command' complete -c greet -n '__fish_seen_subcommand_from usage u' -f -l help -s h -d 'show help' -complete -r -c greet -n '__fish_greet_no_subcommand' -a 'usage u' -d 'standard usage text' +complete -x -c greet -n '__fish_greet_no_subcommand' -a 'usage u' -d 'standard usage text' complete -c greet -n '__fish_seen_subcommand_from usage u' -l flag -s fl -s f -r complete -c greet -n '__fish_seen_subcommand_from usage u' -f -l another-flag -s b -d 'another usage text' complete -c greet -n '__fish_seen_subcommand_from sub-usage su' -f -l help -s h -d 'show help' -complete -r -c greet -n '__fish_seen_subcommand_from usage u; and not __fish_seen_subcommand_from sub-usage su' -a 'sub-usage su' -d 'standard usage text' +complete -x -c greet -n '__fish_seen_subcommand_from usage u; and not __fish_seen_subcommand_from sub-usage su' -a 'sub-usage su' -d 'standard usage text' complete -c greet -n '__fish_seen_subcommand_from sub-usage su' -f -l sub-command-flag -s s -d 'some usage text' From 9a8c558267f495db76351df5de3a84087a29593a Mon Sep 17 00:00:00 2001 From: Naveen Gogineni Date: Sun, 27 Apr 2025 15:41:40 -0400 Subject: [PATCH 2/2] Cleanup docs --- .../v3/examples/completions/customizations.md | 142 ++++++++++++++++++ .../examples/completions/shell-completions.md | 137 +---------------- docs/v3/examples/flags/basics.md | 1 + mkdocs.yml | 1 + 4 files changed, 148 insertions(+), 133 deletions(-) create mode 100644 docs/v3/examples/completions/customizations.md diff --git a/docs/v3/examples/completions/customizations.md b/docs/v3/examples/completions/customizations.md new file mode 100644 index 0000000000..06cbd67b84 --- /dev/null +++ b/docs/v3/examples/completions/customizations.md @@ -0,0 +1,142 @@ +--- +tags: + - v3 +search: + boost: 2 +--- + +If default completion isnt sufficient additional customizations are available + +- custom auto-completion +- customizing completion command + +#### Custom auto-completion + +```go +package main + +import ( + "fmt" + "log" + "os" + "context" + + "github.com/urfave/cli/v3" +) + +func main() { + tasks := []string{"cook", "clean", "laundry", "eat", "sleep", "code"} + + cmd := &cli.Command{ + EnableShellCompletion: true, + Commands: []*cli.Command{ + { + Name: "complete", + Aliases: []string{"c"}, + Usage: "complete a task on the list", + Action: func(ctx context.Context, cmd *cli.Command) error { + fmt.Println("completed task: ", cmd.Args().First()) + return nil + }, + ShellComplete: func(ctx context.Context, cmd *cli.Command) { + // This will complete if no args are passed + if cmd.NArg() > 0 { + return + } + for _, t := range tasks { + fmt.Println(t) + } + }, + }, + }, + } + + if err := cmd.Run(context.Background(), os.Args); err != nil { + log.Fatal(err) + } +} +``` +![](../../images/custom-bash-autocomplete.gif) + +#### Customize a completion command + +By default, a completion command is hidden, meaning the command isn't included in the help message. +You can customize it by setting root Command's `ConfigureShellCompletionCommand`. + +```go +package main + +import ( + "context" + "fmt" + "log" + "os" + + "github.com/urfave/cli/v3" +) + +func main() { + cmd := &cli.Command{ + Name: "greet", + // EnableShellCompletion is unnecessary + ConfigureShellCompletionCommand: func(cmd *cli.Command) { // cmd is a completion command + cmd.Hidden = false // Make a completion command public + cmd.Usage = "..." // Customize Usage + cmd.Description = "..." // Customize Description + }, + Commands: []*cli.Command{ + { + Name: "hello", + Usage: "Say hello", + Action: func(ctx context.Context, cmd *cli.Command) error { + fmt.Println("Hello") + return nil + }, + }, + }, + } + + if err := cmd.Run(context.Background(), os.Args); err != nil { + log.Fatal(err) + } +} +``` + +#### Customization + +The default shell completion flag (`--generate-shell-completion`) is defined as +`cli.EnableShellCompletion`, and may be redefined if desired, e.g.: + + +```go +package main + +import ( + "log" + "os" + "context" + + "github.com/urfave/cli/v3" +) + +func main() { + cmd := &cli.Command{ + EnableShellCompletion: true, + Commands: []*cli.Command{ + { + Name: "wat", + }, + }, + } + + if err := cmd.Run(context.Background(), os.Args); err != nil { + log.Fatal(err) + } +} +``` diff --git a/docs/v3/examples/completions/shell-completions.md b/docs/v3/examples/completions/shell-completions.md index 29b55daab3..b355a6320f 100644 --- a/docs/v3/examples/completions/shell-completions.md +++ b/docs/v3/examples/completions/shell-completions.md @@ -9,17 +9,19 @@ The urfave/cli v3 library supports programmable completion for apps utilizing it that the completion is generated dynamically at runtime by invokiong the app itself with a special hidden flag. The urfave/cli searches for this flag and activates a different flow for command paths than regular flow The following shells are supported + - bash - zsh - fish - powershell Enabling auto complete requires 2 things + - Setting the `EnableShellCompletion` field on root `Command` object to `true`. - Sourcing the completion script for that particular shell. - The completion script for a particular shell can be retrieved by running the "completion" subcommand - on the app after the `EnableShellCompletion` field on root `Command` object has been set to `true`. +The completion script for a particular shell can be retrieved by running the "completion" subcommand +on the app after the `EnableShellCompletion` field on root `Command` object has been set to `true`. Consider the following program @@ -182,137 +184,6 @@ func main() { ``` ![](../../images/default-bash-autocomplete.gif) -#### Custom auto-completion - -```go -package main - -import ( - "fmt" - "log" - "os" - "context" - - "github.com/urfave/cli/v3" -) - -func main() { - tasks := []string{"cook", "clean", "laundry", "eat", "sleep", "code"} - - cmd := &cli.Command{ - EnableShellCompletion: true, - Commands: []*cli.Command{ - { - Name: "complete", - Aliases: []string{"c"}, - Usage: "complete a task on the list", - Action: func(ctx context.Context, cmd *cli.Command) error { - fmt.Println("completed task: ", cmd.Args().First()) - return nil - }, - ShellComplete: func(ctx context.Context, cmd *cli.Command) { - // This will complete if no args are passed - if cmd.NArg() > 0 { - return - } - for _, t := range tasks { - fmt.Println(t) - } - }, - }, - }, - } - - if err := cmd.Run(context.Background(), os.Args); err != nil { - log.Fatal(err) - } -} -``` -![](../../images/custom-bash-autocomplete.gif) - -#### Customize a completion command - -By default, a completion command is hidden, meaning the command isn't included in the help message. -You can customize it by setting root Command's `ConfigureShellCompletionCommand`. - -```go -package main - -import ( - "context" - "fmt" - "log" - "os" - - "github.com/urfave/cli/v3" -) - -func main() { - cmd := &cli.Command{ - Name: "greet", - // EnableShellCompletion is unnecessary - ConfigureShellCompletionCommand: func(cmd *cli.Command) { // cmd is a completion command - cmd.Hidden = false // Make a completion command public - cmd.Usage = "..." // Customize Usage - cmd.Description = "..." // Customize Description - }, - Commands: []*cli.Command{ - { - Name: "hello", - Usage: "Say hello", - Action: func(ctx context.Context, cmd *cli.Command) error { - fmt.Println("Hello") - return nil - }, - }, - }, - } - - if err := cmd.Run(context.Background(), os.Args); err != nil { - log.Fatal(err) - } -} -``` - -#### Customization - -The default shell completion flag (`--generate-shell-completion`) is defined as -`cli.EnableShellCompletion`, and may be redefined if desired, e.g.: - - -```go -package main - -import ( - "log" - "os" - "context" - - "github.com/urfave/cli/v3" -) - -func main() { - cmd := &cli.Command{ - EnableShellCompletion: true, - Commands: []*cli.Command{ - { - Name: "wat", - }, - }, - } - - if err := cmd.Run(context.Background(), os.Args); err != nil { - log.Fatal(err) - } -} -``` - #### ZSH Support Adding the following lines to diff --git a/docs/v3/examples/flags/basics.md b/docs/v3/examples/flags/basics.md index b587ed6835..172687c568 100644 --- a/docs/v3/examples/flags/basics.md +++ b/docs/v3/examples/flags/basics.md @@ -134,6 +134,7 @@ Note that most flag can be invoked multiple times but only the last value entere will be provided to the user(with some exceptions. See flags-advanced.md) The following basic flags are supported + - `IntFlag` - `Int8Flag` - `Int16Flag` diff --git a/mkdocs.yml b/mkdocs.yml index 34b4e68471..97bc4ad589 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -35,6 +35,7 @@ nav: - Categories: v3/examples/subcommands/categories.md - Completions: - Shell Completions: v3/examples/completions/shell-completions.md + - Customizations: v3/examples/completions/customizations.md - Help Text: - Generated Help Text: v3/examples/help/generated-help-text.md - Suggestions: v3/examples/help/suggestions.md