Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions command.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ type Command struct {
ShellCompletionCommandName string `json:"-"`
// The function to call when checking for shell command completions
ShellComplete ShellCompleteFunc `json:"-"`
// The function to configure a shell completion command
ConfigureShellCompletionCommand ConfigureShellCompletionCommand `json:"-"`
// An action to execute before any subcommands are run, but after the context is ready
// If a non-nil error is returned, no subcommands are run
Before BeforeFunc `json:"-"`
Expand Down
5 changes: 4 additions & 1 deletion command_setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ func (cmd *Command) setupDefaults(osArgs []string) {
cmd.SuggestCommandFunc = suggestCommand
}

if isRoot && cmd.EnableShellCompletion {
if isRoot && cmd.EnableShellCompletion || cmd.ConfigureShellCompletionCommand != nil {
completionCommand := buildCompletionCommand(cmd.Name)

if cmd.ShellCompletionCommandName != "" {
Expand All @@ -102,6 +102,9 @@ func (cmd *Command) setupDefaults(osArgs []string) {

tracef("appending completionCommand (cmd=%[1]q)", cmd.Name)
cmd.appendCommand(completionCommand)
if cmd.ConfigureShellCompletionCommand != nil {
cmd.ConfigureShellCompletionCommand(completionCommand)
}
}

tracef("setting command categories (cmd=%[1]q)", cmd.Name)
Expand Down
23 changes: 21 additions & 2 deletions completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"embed"
"fmt"
"sort"
"strings"
)

const (
Expand Down Expand Up @@ -39,10 +40,28 @@ var (
}
)

const completionDescription = `Output shell completion script for bash, zsh, fish, or Powershell.
Source the output to enable completion.

# .bashrc
source <($COMMAND completion bash)

# .zshrc
source <($COMMAND completion zsh)

# fish
$COMMAND completion fish > ~/.config/fish/completions/$COMMAND.fish

# Powershell
Output the script to path/to/autocomplete/$COMMAND.ps1 an run it.
`

func buildCompletionCommand(appName string) *Command {
return &Command{
Name: completionCommandName,
Hidden: true,
Name: completionCommandName,
Hidden: true,
Usage: "Output shell completion script for bash, zsh, fish, or Powershell",
Description: strings.ReplaceAll(completionDescription, "$COMMAND", appName),
Action: func(ctx context.Context, cmd *Command) error {
return printShellCompletion(ctx, cmd, appName)
},
Expand Down
44 changes: 44 additions & 0 deletions docs/v3/examples/completions/shell-completions.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,50 @@ func main() {
```
![](../../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
Expand Down
3 changes: 3 additions & 0 deletions funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ type ActionFunc func(context.Context, *Command) error
// CommandNotFoundFunc is executed if the proper command cannot be found
type CommandNotFoundFunc func(context.Context, *Command, string)

// ConfigureShellCompletionCommand is a function to configure a shell completion command
type ConfigureShellCompletionCommand func(*Command)

// OnUsageErrorFunc is executed if a usage error occurs. This is useful for displaying
// customized usage error messages. This function is able to replace the
// original error messages. If this function is not set, the "Incorrect usage"
Expand Down
6 changes: 6 additions & 0 deletions godoc-current.txt
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,8 @@ type Command struct {
ShellCompletionCommandName string `json:"-"`
// The function to call when checking for shell command completions
ShellComplete ShellCompleteFunc `json:"-"`
// The function to configure a shell completion command
ConfigureShellCompletionCommand ConfigureShellCompletionCommand `json:"-"`
// An action to execute before any subcommands are run, but after the context is ready
// If a non-nil error is returned, no subcommands are run
Before BeforeFunc `json:"-"`
Expand Down Expand Up @@ -751,6 +753,10 @@ type CommandCategory interface {
type CommandNotFoundFunc func(context.Context, *Command, string)
CommandNotFoundFunc is executed if the proper command cannot be found

type ConfigureShellCompletionCommand func(*Command)
ConfigureShellCompletionCommand is a function to configure a shell
completion command

type Countable interface {
Count() int
}
Expand Down
6 changes: 6 additions & 0 deletions testdata/godoc-v3.x.txt
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,8 @@ type Command struct {
ShellCompletionCommandName string `json:"-"`
// The function to call when checking for shell command completions
ShellComplete ShellCompleteFunc `json:"-"`
// The function to configure a shell completion command
ConfigureShellCompletionCommand ConfigureShellCompletionCommand `json:"-"`
// An action to execute before any subcommands are run, but after the context is ready
// If a non-nil error is returned, no subcommands are run
Before BeforeFunc `json:"-"`
Expand Down Expand Up @@ -751,6 +753,10 @@ type CommandCategory interface {
type CommandNotFoundFunc func(context.Context, *Command, string)
CommandNotFoundFunc is executed if the proper command cannot be found

type ConfigureShellCompletionCommand func(*Command)
ConfigureShellCompletionCommand is a function to configure a shell
completion command

type Countable interface {
Count() int
}
Expand Down