-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Expand file tree
/
Copy pathcompletion.go
More file actions
98 lines (82 loc) · 2.9 KB
/
Copy pathcompletion.go
File metadata and controls
98 lines (82 loc) · 2.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package cli
import (
"context"
"embed"
"fmt"
"strings"
)
const (
completionCommandName = "completion"
// This flag is supposed to only be used by the completion script itself to generate completions on the fly.
completionFlag = "--generate-shell-completion"
)
type renderCompletion func(cmd *Command, appName string) (string, error)
var (
//go:embed autocomplete
autoCompleteFS embed.FS
// completionShells defines the order in which the shell completion
// subcommands appear in help output. Iterating shellCompletions directly
// would use Go's randomized map order, making the listing nondeterministic.
// Keep this in sync with shellCompletions.
completionShells = []string{"bash", "zsh", "fish", "pwsh"}
shellCompletions = map[string]renderCompletion{
"bash": func(c *Command, appName string) (string, error) {
b, err := autoCompleteFS.ReadFile("autocomplete/bash_autocomplete")
return fmt.Sprintf(string(b), appName), err
},
"zsh": func(c *Command, appName string) (string, error) {
b, err := autoCompleteFS.ReadFile("autocomplete/zsh_autocomplete")
return fmt.Sprintf(string(b), appName), err
},
"fish": func(c *Command, appName string) (string, error) {
b, err := autoCompleteFS.ReadFile("autocomplete/fish_autocomplete")
return fmt.Sprintf(string(b), appName), err
},
"pwsh": func(c *Command, appName string) (string, error) {
b, err := autoCompleteFS.ReadFile("autocomplete/powershell_autocomplete.ps1")
return string(b), err
},
}
)
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 {
cmd := &Command{
Name: completionCommandName,
Hidden: true,
Usage: "Output shell completion script for bash, zsh, fish, or Powershell",
Description: strings.ReplaceAll(completionDescription, "$COMMAND", appName),
isCompletionCommand: true,
}
for _, shell := range completionShells {
cmd.Commands = append(cmd.Commands, buildShellCompletionSubcommand(shell, shellCompletions[shell], appName))
}
return cmd
}
func buildShellCompletionSubcommand(shell string, render renderCompletion, appName string) *Command {
return &Command{
Name: shell,
Usage: fmt.Sprintf("Output %s completion script", shell),
isCompletionCommand: true,
Action: func(ctx context.Context, cmd *Command) error {
completionScript, err := render(cmd, appName)
if err != nil {
return Exit(err, 1)
}
_, err = cmd.Root().Writer.Write([]byte(completionScript))
if err != nil {
return Exit(err, 1)
}
return nil
},
}
}