1# Generating shell completions
2
3Cobra can generate shell completions for multiple shells.
4The currently supported shells are:
5- Bash
6- Zsh
7- Fish
8- PowerShell
9
10If you are using the generator you can create a completion command by running
11
12```bash
13cobra add completion
14```
15and then modifying the generated `cmd/completion.go` file to look something like this
16(writing the shell script to stdout allows the most flexible use):
17
18```go
19var completionCmd = &cobra.Command{
20	Use:                   "completion [bash|zsh|fish|powershell]",
21	Short:                 "Generate completion script",
22	Long: `To load completions:
23
24Bash:
25
26$ source <(yourprogram completion bash)
27
28# To load completions for each session, execute once:
29Linux:
30  $ yourprogram completion bash > /etc/bash_completion.d/yourprogram
31MacOS:
32  $ yourprogram completion bash > /usr/local/etc/bash_completion.d/yourprogram
33
34Zsh:
35
36# If shell completion is not already enabled in your environment you will need
37# to enable it.  You can execute the following once:
38
39$ echo "autoload -U compinit; compinit" >> ~/.zshrc
40
41# To load completions for each session, execute once:
42$ yourprogram completion zsh > "${fpath[1]}/_yourprogram"
43
44# You will need to start a new shell for this setup to take effect.
45
46Fish:
47
48$ yourprogram completion fish | source
49
50# To load completions for each session, execute once:
51$ yourprogram completion fish > ~/.config/fish/completions/yourprogram.fish
52`,
53	DisableFlagsInUseLine: true,
54	ValidArgs:             []string{"bash", "zsh", "fish", "powershell"},
55	Args:                  cobra.ExactValidArgs(1),
56	Run: func(cmd *cobra.Command, args []string) {
57		switch args[0] {
58		case "bash":
59			cmd.Root().GenBashCompletion(os.Stdout)
60		case "zsh":
61			cmd.Root().GenZshCompletion(os.Stdout)
62		case "fish":
63			cmd.Root().GenFishCompletion(os.Stdout, true)
64		case "powershell":
65			cmd.Root().GenPowerShellCompletion(os.Stdout)
66		}
67	},
68}
69```
70
71**Note:** The cobra generator may include messages printed to stdout for example if the config file is loaded, this will break the auto complete script so must be removed.
72
73# Customizing completions
74
75The generated completion scripts will automatically handle completing commands and flags.  However, you can make your completions much more powerful by providing information to complete your program's nouns and flag values.
76
77## Completion of nouns
78
79### Static completion of nouns
80
81Cobra allows you to provide a pre-defined list of completion choices for your nouns using the `ValidArgs` field.
82For example, if you want `kubectl get [tab][tab]` to show a list of valid "nouns" you have to set them.
83Some simplified code from `kubectl get` looks like:
84
85```go
86validArgs []string = { "pod", "node", "service", "replicationcontroller" }
87
88cmd := &cobra.Command{
89	Use:     "get [(-o|--output=)json|yaml|template|...] (RESOURCE [NAME] | RESOURCE/NAME ...)",
90	Short:   "Display one or many resources",
91	Long:    get_long,
92	Example: get_example,
93	Run: func(cmd *cobra.Command, args []string) {
94		err := RunGet(f, out, cmd, args)
95		util.CheckErr(err)
96	},
97	ValidArgs: validArgs,
98}
99```
100
101Notice we put the `ValidArgs` field on the `get` sub-command. Doing so will give results like:
102
103```bash
104$ kubectl get [tab][tab]
105node   pod   replicationcontroller   service
106```
107
108#### Aliases for nouns
109
110If your nouns have aliases, you can define them alongside `ValidArgs` using `ArgAliases`:
111
112```go
113argAliases []string = { "pods", "nodes", "services", "svc", "replicationcontrollers", "rc" }
114
115cmd := &cobra.Command{
116    ...
117	ValidArgs:  validArgs,
118	ArgAliases: argAliases
119}
120```
121
122The aliases are not shown to the user on tab completion, but they are accepted as valid nouns by
123the completion algorithm if entered manually, e.g. in:
124
125```bash
126$ kubectl get rc [tab][tab]
127backend        frontend       database
128```
129
130Note that without declaring `rc` as an alias, the completion algorithm would not know to show the list of
131replication controllers following `rc`.
132
133### Dynamic completion of nouns
134
135In some cases it is not possible to provide a list of completions in advance.  Instead, the list of completions must be determined at execution-time. In a similar fashion as for static completions, you can use the `ValidArgsFunction` field to provide a Go function that Cobra will execute when it needs the list of completion choices for the nouns of a command.  Note that either `ValidArgs` or `ValidArgsFunction` can be used for a single cobra command, but not both.
136Simplified code from `helm status` looks like:
137
138```go
139cmd := &cobra.Command{
140	Use:   "status RELEASE_NAME",
141	Short: "Display the status of the named release",
142	Long:  status_long,
143	RunE: func(cmd *cobra.Command, args []string) {
144		RunGet(args[0])
145	},
146	ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
147		if len(args) != 0 {
148			return nil, cobra.ShellCompDirectiveNoFileComp
149		}
150		return getReleasesFromCluster(toComplete), cobra.ShellCompDirectiveNoFileComp
151	},
152}
153```
154Where `getReleasesFromCluster()` is a Go function that obtains the list of current Helm releases running on the Kubernetes cluster.
155Notice we put the `ValidArgsFunction` on the `status` sub-command. Let's assume the Helm releases on the cluster are: `harbor`, `notary`, `rook` and `thanos` then this dynamic completion will give results like:
156
157```bash
158$ helm status [tab][tab]
159harbor notary rook thanos
160```
161You may have noticed the use of `cobra.ShellCompDirective`.  These directives are bit fields allowing to control some shell completion behaviors for your particular completion.  You can combine them with the bit-or operator such as `cobra.ShellCompDirectiveNoSpace | cobra.ShellCompDirectiveNoFileComp`
162```go
163// Indicates that the shell will perform its default behavior after completions
164// have been provided (this implies none of the other directives).
165ShellCompDirectiveDefault
166
167// Indicates an error occurred and completions should be ignored.
168ShellCompDirectiveError
169
170// Indicates that the shell should not add a space after the completion,
171// even if there is a single completion provided.
172ShellCompDirectiveNoSpace
173
174// Indicates that the shell should not provide file completion even when
175// no completion is provided.
176ShellCompDirectiveNoFileComp
177
178// Indicates that the returned completions should be used as file extension filters.
179// For example, to complete only files of the form *.json or *.yaml:
180//    return []string{"yaml", "json"}, ShellCompDirectiveFilterFileExt
181// For flags, using MarkFlagFilename() and MarkPersistentFlagFilename()
182// is a shortcut to using this directive explicitly.
183//
184ShellCompDirectiveFilterFileExt
185
186// Indicates that only directory names should be provided in file completion.
187// For example:
188//    return nil, ShellCompDirectiveFilterDirs
189// For flags, using MarkFlagDirname() is a shortcut to using this directive explicitly.
190//
191// To request directory names within another directory, the returned completions
192// should specify a single directory name within which to search. For example,
193// to complete directories within "themes/":
194//    return []string{"themes"}, ShellCompDirectiveFilterDirs
195//
196ShellCompDirectiveFilterDirs
197```
198
199***Note***: When using the `ValidArgsFunction`, Cobra will call your registered function after having parsed all flags and arguments provided in the command-line.  You therefore don't need to do this parsing yourself.  For example, when a user calls `helm status --namespace my-rook-ns [tab][tab]`, Cobra will call your registered `ValidArgsFunction` after having parsed the `--namespace` flag, as it would have done when calling the `RunE` function.
200
201#### Debugging
202
203Cobra achieves dynamic completion through the use of a hidden command called by the completion script.  To debug your Go completion code, you can call this hidden command directly:
204```bash
205$ helm __complete status har<ENTER>
206harbor
207:4
208Completion ended with directive: ShellCompDirectiveNoFileComp # This is on stderr
209```
210***Important:*** If the noun to complete is empty (when the user has not yet typed any letters of that noun), you must pass an empty parameter to the `__complete` command:
211```bash
212$ helm __complete status ""<ENTER>
213harbor
214notary
215rook
216thanos
217:4
218Completion ended with directive: ShellCompDirectiveNoFileComp # This is on stderr
219```
220Calling the `__complete` command directly allows you to run the Go debugger to troubleshoot your code.  You can also add printouts to your code; Cobra provides the following functions to use for printouts in Go completion code:
221```go
222// Prints to the completion script debug file (if BASH_COMP_DEBUG_FILE
223// is set to a file path) and optionally prints to stderr.
224cobra.CompDebug(msg string, printToStdErr bool) {
225cobra.CompDebugln(msg string, printToStdErr bool)
226
227// Prints to the completion script debug file (if BASH_COMP_DEBUG_FILE
228// is set to a file path) and to stderr.
229cobra.CompError(msg string)
230cobra.CompErrorln(msg string)
231```
232***Important:*** You should **not** leave traces that print directly to stdout in your completion code as they will be interpreted as completion choices by the completion script.  Instead, use the cobra-provided debugging traces functions mentioned above.
233
234## Completions for flags
235
236### Mark flags as required
237
238Most of the time completions will only show sub-commands. But if a flag is required to make a sub-command work, you probably want it to show up when the user types [tab][tab].  You can mark a flag as 'Required' like so:
239
240```go
241cmd.MarkFlagRequired("pod")
242cmd.MarkFlagRequired("container")
243```
244
245and you'll get something like
246
247```bash
248$ kubectl exec [tab][tab]
249-c            --container=  -p            --pod=
250```
251
252### Specify dynamic flag completion
253
254As for nouns, Cobra provides a way of defining dynamic completion of flags.  To provide a Go function that Cobra will execute when it needs the list of completion choices for a flag, you must register the function using the `command.RegisterFlagCompletionFunc()` function.
255
256```go
257flagName := "output"
258cmd.RegisterFlagCompletionFunc(flagName, func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
259	return []string{"json", "table", "yaml"}, cobra.ShellCompDirectiveDefault
260})
261```
262Notice that calling `RegisterFlagCompletionFunc()` is done through the `command` with which the flag is associated.  In our example this dynamic completion will give results like so:
263
264```bash
265$ helm status --output [tab][tab]
266json table yaml
267```
268
269#### Debugging
270
271You can also easily debug your Go completion code for flags:
272```bash
273$ helm __complete status --output ""
274json
275table
276yaml
277:4
278Completion ended with directive: ShellCompDirectiveNoFileComp # This is on stderr
279```
280***Important:*** You should **not** leave traces that print to stdout in your completion code as they will be interpreted as completion choices by the completion script.  Instead, use the cobra-provided debugging traces functions mentioned further above.
281
282### Specify valid filename extensions for flags that take a filename
283
284To limit completions of flag values to file names with certain extensions you can either use the different `MarkFlagFilename()` functions or a combination of `RegisterFlagCompletionFunc()` and `ShellCompDirectiveFilterFileExt`, like so:
285```go
286flagName := "output"
287cmd.MarkFlagFilename(flagName, "yaml", "json")
288```
289or
290```go
291flagName := "output"
292cmd.RegisterFlagCompletionFunc(flagName, func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
293	return []string{"yaml", "json"}, ShellCompDirectiveFilterFileExt})
294```
295
296### Limit flag completions to directory names
297
298To limit completions of flag values to directory names you can either use the `MarkFlagDirname()` functions or a combination of `RegisterFlagCompletionFunc()` and `ShellCompDirectiveFilterDirs`, like so:
299```go
300flagName := "output"
301cmd.MarkFlagDirname(flagName)
302```
303or
304```go
305flagName := "output"
306cmd.RegisterFlagCompletionFunc(flagName, func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
307	return nil, cobra.ShellCompDirectiveFilterDirs
308})
309```
310To limit completions of flag values to directory names *within another directory* you can use a combination of `RegisterFlagCompletionFunc()` and `ShellCompDirectiveFilterDirs` like so:
311```go
312flagName := "output"
313cmd.RegisterFlagCompletionFunc(flagName, func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
314	return []string{"themes"}, cobra.ShellCompDirectiveFilterDirs
315})
316```
317### Descriptions for completions
318
319Both `zsh` and `fish` allow for descriptions to annotate completion choices.  For commands and flags, Cobra will provide the descriptions automatically, based on usage information.  For example, using zsh:
320```
321$ helm s[tab]
322search  -- search for a keyword in charts
323show    -- show information of a chart
324status  -- displays the status of the named release
325```
326while using fish:
327```
328$ helm s[tab]
329search  (search for a keyword in charts)  show  (show information of a chart)  status  (displays the status of the named release)
330```
331
332Cobra allows you to add annotations to your own completions.  Simply add the annotation text after each completion, following a `\t` separator.  This technique applies to completions returned by `ValidArgs`, `ValidArgsFunction` and `RegisterFlagCompletionFunc()`.  For example:
333```go
334ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
335	return []string{"harbor\tAn image registry", "thanos\tLong-term metrics"}, cobra.ShellCompDirectiveNoFileComp
336}}
337```
338or
339```go
340ValidArgs: []string{"bash\tCompletions for bash", "zsh\tCompletions for zsh"}
341```
342## Bash completions
343
344### Dependencies
345
346The bash completion script generated by Cobra requires the `bash_completion` package. You should update the help text of your completion command to show how to install the `bash_completion` package ([Kubectl docs](https://kubernetes.io/docs/tasks/tools/install-kubectl/#enabling-shell-autocompletion))
347
348### Aliases
349
350You can also configure `bash` aliases for your program and they will also support completions.
351
352```bash
353alias aliasname=origcommand
354complete -o default -F __start_origcommand aliasname
355
356# and now when you run `aliasname` completion will make
357# suggestions as it did for `origcommand`.
358
359$ aliasname <tab><tab>
360completion     firstcommand   secondcommand
361```
362### Bash legacy dynamic completions
363
364For backwards-compatibility, Cobra still supports its bash legacy dynamic completion solution.
365Please refer to [Bash Completions](bash_completions.md) for details.
366
367## Zsh completions
368
369Cobra supports native Zsh completion generated from the root `cobra.Command`.
370The generated completion script should be put somewhere in your `$fpath` and be named
371`_<yourProgram>`.  You will need to start a new shell for the completions to become available.
372
373Zsh supports descriptions for completions. Cobra will provide the description automatically,
374based on usage information. Cobra provides a way to completely disable such descriptions by
375using `GenZshCompletionNoDesc()` or `GenZshCompletionFileNoDesc()`. You can choose to make
376this a configurable option to your users.
377```
378# With descriptions
379$ helm s[tab]
380search  -- search for a keyword in charts
381show    -- show information of a chart
382status  -- displays the status of the named release
383
384# Without descriptions
385$ helm s[tab]
386search  show  status
387```
388*Note*: Because of backwards-compatibility requirements, we were forced to have a different API to disable completion descriptions between `Zsh` and `Fish`.
389
390### Limitations
391
392* Custom completions implemented in Bash scripting (legacy) are not supported and will be ignored for `zsh` (including the use of the `BashCompCustom` flag annotation).
393  * You should instead use `ValidArgsFunction` and `RegisterFlagCompletionFunc()` which are portable to the different shells (`bash`, `zsh`, `fish`).
394* The function `MarkFlagCustom()` is not supported and will be ignored for `zsh`.
395  * You should instead use `RegisterFlagCompletionFunc()`.
396
397### Zsh completions standardization
398
399Cobra 1.1 standardized its zsh completion support to align it with its other shell completions.  Although the API was kept backwards-compatible, some small changes in behavior were introduced.
400Please refer to [Zsh Completions](zsh_completions.md) for details.
401
402## Fish completions
403
404Cobra supports native Fish completions generated from the root `cobra.Command`.  You can use the `command.GenFishCompletion()` or `command.GenFishCompletionFile()` functions. You must provide these functions with a parameter indicating if the completions should be annotated with a description; Cobra will provide the description automatically based on usage information.  You can choose to make this option configurable by your users.
405```
406# With descriptions
407$ helm s[tab]
408search  (search for a keyword in charts)  show  (show information of a chart)  status  (displays the status of the named release)
409
410# Without descriptions
411$ helm s[tab]
412search  show  status
413```
414*Note*: Because of backwards-compatibility requirements, we were forced to have a different API to disable completion descriptions between `Zsh` and `Fish`.
415
416### Limitations
417
418* Custom completions implemented in Bash scripting (legacy) are not supported and will be ignored for `fish` (including the use of the `BashCompCustom` flag annotation).
419  * You should instead use `ValidArgsFunction` and `RegisterFlagCompletionFunc()` which are portable to the different shells (`bash`, `zsh`, `fish`).
420* The function `MarkFlagCustom()` is not supported and will be ignored for `fish`.
421  * You should instead use `RegisterFlagCompletionFunc()`.
422* The following flag completion annotations are not supported and will be ignored for `fish`:
423  * `BashCompFilenameExt` (filtering by file extension)
424  * `BashCompSubdirsInDir` (filtering by directory)
425* The functions corresponding to the above annotations are consequently not supported and will be ignored for `fish`:
426  * `MarkFlagFilename()` and `MarkPersistentFlagFilename()` (filtering by file extension)
427  * `MarkFlagDirname()` and `MarkPersistentFlagDirname()` (filtering by directory)
428* Similarly, the following completion directives are not supported and will be ignored for `fish`:
429  * `ShellCompDirectiveFilterFileExt` (filtering by file extension)
430  * `ShellCompDirectiveFilterDirs` (filtering by directory)
431
432## PowerShell completions
433
434Please refer to [PowerShell Completions](powershell_completions.md) for details.
435