Skip to content

Commit 0264a15

Browse files
authored
Merge pull request urfave#2103 from urfave/publish-build-completion-command
Enable to customize completion commands
2 parents c6c5804 + d82d555 commit 0264a15

File tree

7 files changed

+86
-3
lines changed

7 files changed

+86
-3
lines changed

command.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ type Command struct {
5656
ShellCompletionCommandName string `json:"-"`
5757
// The function to call when checking for shell command completions
5858
ShellComplete ShellCompleteFunc `json:"-"`
59+
// The function to configure a shell completion command
60+
ConfigureShellCompletionCommand ConfigureShellCompletionCommand `json:"-"`
5961
// An action to execute before any subcommands are run, but after the context is ready
6062
// If a non-nil error is returned, no subcommands are run
6163
Before BeforeFunc `json:"-"`

command_setup.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ func (cmd *Command) setupDefaults(osArgs []string) {
8888
cmd.SuggestCommandFunc = suggestCommand
8989
}
9090

91-
if isRoot && cmd.EnableShellCompletion {
91+
if isRoot && cmd.EnableShellCompletion || cmd.ConfigureShellCompletionCommand != nil {
9292
completionCommand := buildCompletionCommand(cmd.Name)
9393

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

103103
tracef("appending completionCommand (cmd=%[1]q)", cmd.Name)
104104
cmd.appendCommand(completionCommand)
105+
if cmd.ConfigureShellCompletionCommand != nil {
106+
cmd.ConfigureShellCompletionCommand(completionCommand)
107+
}
105108
}
106109

107110
tracef("setting command categories (cmd=%[1]q)", cmd.Name)

completion.go

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"embed"
66
"fmt"
77
"sort"
8+
"strings"
89
)
910

1011
const (
@@ -39,10 +40,28 @@ var (
3940
}
4041
)
4142

43+
const completionDescription = `Output shell completion script for bash, zsh, fish, or Powershell.
44+
Source the output to enable completion.
45+
46+
# .bashrc
47+
source <($COMMAND completion bash)
48+
49+
# .zshrc
50+
source <($COMMAND completion zsh)
51+
52+
# fish
53+
$COMMAND completion fish > ~/.config/fish/completions/$COMMAND.fish
54+
55+
# Powershell
56+
Output the script to path/to/autocomplete/$COMMAND.ps1 an run it.
57+
`
58+
4259
func buildCompletionCommand(appName string) *Command {
4360
return &Command{
44-
Name: completionCommandName,
45-
Hidden: true,
61+
Name: completionCommandName,
62+
Hidden: true,
63+
Usage: "Output shell completion script for bash, zsh, fish, or Powershell",
64+
Description: strings.ReplaceAll(completionDescription, "$COMMAND", appName),
4665
Action: func(ctx context.Context, cmd *Command) error {
4766
return printShellCompletion(ctx, cmd, appName)
4867
},

docs/v3/examples/completions/shell-completions.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,50 @@ func main() {
233233
```
234234
![](../../images/custom-bash-autocomplete.gif)
235235

236+
#### Customize a completion command
237+
238+
By default, a completion command is hidden, meaning the command isn't included in the help message.
239+
You can customize it by setting root Command's `ConfigureShellCompletionCommand`.
240+
241+
```go
242+
package main
243+
244+
import (
245+
"context"
246+
"fmt"
247+
"log"
248+
"os"
249+
250+
"github.com/urfave/cli/v3"
251+
)
252+
253+
func main() {
254+
cmd := &cli.Command{
255+
Name: "greet",
256+
// EnableShellCompletion is unnecessary
257+
ConfigureShellCompletionCommand: func(cmd *cli.Command) { // cmd is a completion command
258+
cmd.Hidden = false // Make a completion command public
259+
cmd.Usage = "..." // Customize Usage
260+
cmd.Description = "..." // Customize Description
261+
},
262+
Commands: []*cli.Command{
263+
{
264+
Name: "hello",
265+
Usage: "Say hello",
266+
Action: func(ctx context.Context, cmd *cli.Command) error {
267+
fmt.Println("Hello")
268+
return nil
269+
},
270+
},
271+
},
272+
}
273+
274+
if err := cmd.Run(context.Background(), os.Args); err != nil {
275+
log.Fatal(err)
276+
}
277+
}
278+
```
279+
236280
#### Customization
237281

238282
The default shell completion flag (`--generate-shell-completion`) is defined as

funcs.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ type ActionFunc func(context.Context, *Command) error
2020
// CommandNotFoundFunc is executed if the proper command cannot be found
2121
type CommandNotFoundFunc func(context.Context, *Command, string)
2222

23+
// ConfigureShellCompletionCommand is a function to configure a shell completion command
24+
type ConfigureShellCompletionCommand func(*Command)
25+
2326
// OnUsageErrorFunc is executed if a usage error occurs. This is useful for displaying
2427
// customized usage error messages. This function is able to replace the
2528
// original error messages. If this function is not set, the "Incorrect usage"

godoc-current.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,8 @@ type Command struct {
433433
ShellCompletionCommandName string `json:"-"`
434434
// The function to call when checking for shell command completions
435435
ShellComplete ShellCompleteFunc `json:"-"`
436+
// The function to configure a shell completion command
437+
ConfigureShellCompletionCommand ConfigureShellCompletionCommand `json:"-"`
436438
// An action to execute before any subcommands are run, but after the context is ready
437439
// If a non-nil error is returned, no subcommands are run
438440
Before BeforeFunc `json:"-"`
@@ -751,6 +753,10 @@ type CommandCategory interface {
751753
type CommandNotFoundFunc func(context.Context, *Command, string)
752754
CommandNotFoundFunc is executed if the proper command cannot be found
753755

756+
type ConfigureShellCompletionCommand func(*Command)
757+
ConfigureShellCompletionCommand is a function to configure a shell
758+
completion command
759+
754760
type Countable interface {
755761
Count() int
756762
}

testdata/godoc-v3.x.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,8 @@ type Command struct {
433433
ShellCompletionCommandName string `json:"-"`
434434
// The function to call when checking for shell command completions
435435
ShellComplete ShellCompleteFunc `json:"-"`
436+
// The function to configure a shell completion command
437+
ConfigureShellCompletionCommand ConfigureShellCompletionCommand `json:"-"`
436438
// An action to execute before any subcommands are run, but after the context is ready
437439
// If a non-nil error is returned, no subcommands are run
438440
Before BeforeFunc `json:"-"`
@@ -751,6 +753,10 @@ type CommandCategory interface {
751753
type CommandNotFoundFunc func(context.Context, *Command, string)
752754
CommandNotFoundFunc is executed if the proper command cannot be found
753755

756+
type ConfigureShellCompletionCommand func(*Command)
757+
ConfigureShellCompletionCommand is a function to configure a shell
758+
completion command
759+
754760
type Countable interface {
755761
Count() int
756762
}

0 commit comments

Comments
 (0)