vendor/github.com/spf13/cobra/bash_completions.md
changeset 256 6d9efbef00a9
parent 251 1c52a0eeb952
equal deleted inserted replaced
255:4f153a23adab 256:6d9efbef00a9
     1 # Generating Bash Completions For Your Own cobra.Command
     1 # Generating Bash Completions For Your cobra.Command
     2 
     2 
     3 If you are using the generator you can create a completion command by running
     3 Please refer to [Shell Completions](shell_completions.md) for details.
     4 
     4 
     5 ```bash
     5 ## Bash legacy dynamic completions
     6 cobra add completion
       
     7 ```
       
     8 
     6 
     9 Update the help text show how to install the bash_completion Linux show here [Kubectl docs show mac options](https://kubernetes.io/docs/tasks/tools/install-kubectl/#enabling-shell-autocompletion)
     7 For backward compatibility, Cobra still supports its legacy dynamic completion solution (described below).  Unlike the `ValidArgsFunction` solution, the legacy solution will only work for Bash shell-completion and not for other shells. This legacy solution can be used along-side `ValidArgsFunction` and `RegisterFlagCompletionFunc()`, as long as both solutions are not used for the same command.  This provides a path to gradually migrate from the legacy solution to the new solution.
    10 
     8 
    11 Writing the shell script to stdout allows the most flexible use.
     9 **Note**: Cobra's default `completion` command uses bash completion V2.  If you are currently using Cobra's legacy dynamic completion solution, you should not use the default `completion` command but continue using your own.
    12 
    10 
    13 ```go
    11 The legacy solution allows you to inject bash functions into the bash completion script.  Those bash functions are responsible for providing the completion choices for your own completions.
    14 // completionCmd represents the completion command
       
    15 var completionCmd = &cobra.Command{
       
    16 	Use:   "completion",
       
    17 	Short: "Generates bash completion scripts",
       
    18 	Long: `To load completion run
       
    19 
    12 
    20 . <(bitbucket completion)
    13 Some code that works in kubernetes:
    21 
       
    22 To configure your bash shell to load completions for each session add to your bashrc
       
    23 
       
    24 # ~/.bashrc or ~/.profile
       
    25 . <(bitbucket completion)
       
    26 `,
       
    27 	Run: func(cmd *cobra.Command, args []string) {
       
    28 		rootCmd.GenBashCompletion(os.Stdout);
       
    29 	},
       
    30 }
       
    31 ```
       
    32 
       
    33 **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
       
    34 
       
    35 
       
    36 ## Example from kubectl
       
    37 
       
    38 Generating bash completions from a cobra command is incredibly easy. An actual program which does so for the kubernetes kubectl binary is as follows:
       
    39 
       
    40 ```go
       
    41 package main
       
    42 
       
    43 import (
       
    44 	"io/ioutil"
       
    45 	"os"
       
    46 
       
    47 	"k8s.io/kubernetes/pkg/kubectl/cmd"
       
    48 	"k8s.io/kubernetes/pkg/kubectl/cmd/util"
       
    49 )
       
    50 
       
    51 func main() {
       
    52 	kubectl := cmd.NewKubectlCommand(util.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard)
       
    53 	kubectl.GenBashCompletionFile("out.sh")
       
    54 }
       
    55 ```
       
    56 
       
    57 `out.sh` will get you completions of subcommands and flags. Copy it to `/etc/bash_completion.d/` as described [here](https://debian-administration.org/article/316/An_introduction_to_bash_completion_part_1) and reset your terminal to use autocompletion. If you make additional annotations to your code, you can get even more intelligent and flexible behavior.
       
    58 
       
    59 ## Creating your own custom functions
       
    60 
       
    61 Some more actual code that works in kubernetes:
       
    62 
    14 
    63 ```bash
    15 ```bash
    64 const (
    16 const (
    65         bash_completion_func = `__kubectl_parse_get()
    17         bash_completion_func = `__kubectl_parse_get()
    66 {
    18 {
   109 }
    61 }
   110 ```
    62 ```
   111 
    63 
   112 The `BashCompletionFunction` option is really only valid/useful on the root command. Doing the above will cause `__kubectl_custom_func()` (`__<command-use>_custom_func()`) to be called when the built in processor was unable to find a solution. In the case of kubernetes a valid command might look something like `kubectl get pod [mypod]`. If you type `kubectl get pod [tab][tab]` the `__kubectl_customc_func()` will run because the cobra.Command only understood "kubectl" and "get." `__kubectl_custom_func()` will see that the cobra.Command is "kubectl_get" and will thus call another helper `__kubectl_get_resource()`.  `__kubectl_get_resource` will look at the 'nouns' collected. In our example the only noun will be `pod`.  So it will call `__kubectl_parse_get pod`.  `__kubectl_parse_get` will actually call out to kubernetes and get any pods.  It will then set `COMPREPLY` to valid pods!
    64 The `BashCompletionFunction` option is really only valid/useful on the root command. Doing the above will cause `__kubectl_custom_func()` (`__<command-use>_custom_func()`) to be called when the built in processor was unable to find a solution. In the case of kubernetes a valid command might look something like `kubectl get pod [mypod]`. If you type `kubectl get pod [tab][tab]` the `__kubectl_customc_func()` will run because the cobra.Command only understood "kubectl" and "get." `__kubectl_custom_func()` will see that the cobra.Command is "kubectl_get" and will thus call another helper `__kubectl_get_resource()`.  `__kubectl_get_resource` will look at the 'nouns' collected. In our example the only noun will be `pod`.  So it will call `__kubectl_parse_get pod`.  `__kubectl_parse_get` will actually call out to kubernetes and get any pods.  It will then set `COMPREPLY` to valid pods!
   113 
    65 
   114 ## Have the completions code complete your 'nouns'
    66 Similarly, for flags:
   115 
       
   116 In the above example "pod" was assumed to already be typed. But if you want `kubectl get [tab][tab]` to show a list of valid "nouns" you have to set them. Simplified code from `kubectl get` looks like:
       
   117 
       
   118 ```go
       
   119 validArgs []string = { "pod", "node", "service", "replicationcontroller" }
       
   120 
       
   121 cmd := &cobra.Command{
       
   122 	Use:     "get [(-o|--output=)json|yaml|template|...] (RESOURCE [NAME] | RESOURCE/NAME ...)",
       
   123 	Short:   "Display one or many resources",
       
   124 	Long:    get_long,
       
   125 	Example: get_example,
       
   126 	Run: func(cmd *cobra.Command, args []string) {
       
   127 		err := RunGet(f, out, cmd, args)
       
   128 		util.CheckErr(err)
       
   129 	},
       
   130 	ValidArgs: validArgs,
       
   131 }
       
   132 ```
       
   133 
       
   134 Notice we put the "ValidArgs" on the "get" subcommand. Doing so will give results like
       
   135 
       
   136 ```bash
       
   137 # kubectl get [tab][tab]
       
   138 node                 pod                    replicationcontroller  service
       
   139 ```
       
   140 
       
   141 ## Plural form and shortcuts for nouns
       
   142 
       
   143 If your nouns have a number of aliases, you can define them alongside `ValidArgs` using `ArgAliases`:
       
   144 
       
   145 ```go
       
   146 argAliases []string = { "pods", "nodes", "services", "svc", "replicationcontrollers", "rc" }
       
   147 
       
   148 cmd := &cobra.Command{
       
   149     ...
       
   150 	ValidArgs:  validArgs,
       
   151 	ArgAliases: argAliases
       
   152 }
       
   153 ```
       
   154 
       
   155 The aliases are not shown to the user on tab completion, but they are accepted as valid nouns by
       
   156 the completion algorithm if entered manually, e.g. in:
       
   157 
       
   158 ```bash
       
   159 # kubectl get rc [tab][tab]
       
   160 backend        frontend       database 
       
   161 ```
       
   162 
       
   163 Note that without declaring `rc` as an alias, the completion algorithm would show the list of nouns
       
   164 in this example again instead of the replication controllers.
       
   165 
       
   166 ## Mark flags as required
       
   167 
       
   168 Most of the time completions will only show subcommands. But if a flag is required to make a subcommand work, you probably want it to show up when the user types [tab][tab].  Marking a flag as 'Required' is incredibly easy.
       
   169 
       
   170 ```go
       
   171 cmd.MarkFlagRequired("pod")
       
   172 cmd.MarkFlagRequired("container")
       
   173 ```
       
   174 
       
   175 and you'll get something like
       
   176 
       
   177 ```bash
       
   178 # kubectl exec [tab][tab][tab]
       
   179 -c            --container=  -p            --pod=  
       
   180 ```
       
   181 
       
   182 # Specify valid filename extensions for flags that take a filename
       
   183 
       
   184 In this example we use --filename= and expect to get a json or yaml file as the argument. To make this easier we annotate the --filename flag with valid filename extensions.
       
   185 
       
   186 ```go
       
   187 	annotations := []string{"json", "yaml", "yml"}
       
   188 	annotation := make(map[string][]string)
       
   189 	annotation[cobra.BashCompFilenameExt] = annotations
       
   190 
       
   191 	flag := &pflag.Flag{
       
   192 		Name:        "filename",
       
   193 		Shorthand:   "f",
       
   194 		Usage:       usage,
       
   195 		Value:       value,
       
   196 		DefValue:    value.String(),
       
   197 		Annotations: annotation,
       
   198 	}
       
   199 	cmd.Flags().AddFlag(flag)
       
   200 ```
       
   201 
       
   202 Now when you run a command with this filename flag you'll get something like
       
   203 
       
   204 ```bash
       
   205 # kubectl create -f 
       
   206 test/                         example/                      rpmbuild/
       
   207 hello.yml                     test.json
       
   208 ```
       
   209 
       
   210 So while there are many other files in the CWD it only shows me subdirs and those with valid extensions.
       
   211 
       
   212 # Specify custom flag completion
       
   213 
       
   214 Similar to the filename completion and filtering using cobra.BashCompFilenameExt, you can specify
       
   215 a custom flag completion function with cobra.BashCompCustom:
       
   216 
    67 
   217 ```go
    68 ```go
   218 	annotation := make(map[string][]string)
    69 	annotation := make(map[string][]string)
   219 	annotation[cobra.BashCompCustom] = []string{"__kubectl_get_namespaces"}
    70 	annotation[cobra.BashCompCustom] = []string{"__kubectl_get_namespaces"}
   220 
    71 
   224 		Annotations: annotation,
    75 		Annotations: annotation,
   225 	}
    76 	}
   226 	cmd.Flags().AddFlag(flag)
    77 	cmd.Flags().AddFlag(flag)
   227 ```
    78 ```
   228 
    79 
   229 In addition add the `__handle_namespace_flag` implementation in the `BashCompletionFunction`
    80 In addition add the `__kubectl_get_namespaces` implementation in the `BashCompletionFunction`
   230 value, e.g.:
    81 value, e.g.:
   231 
    82 
   232 ```bash
    83 ```bash
   233 __kubectl_get_namespaces()
    84 __kubectl_get_namespaces()
   234 {
    85 {
   238     if kubectl_out=$(kubectl get -o template --template="${template}" namespace 2>/dev/null); then
    89     if kubectl_out=$(kubectl get -o template --template="${template}" namespace 2>/dev/null); then
   239         COMPREPLY=( $( compgen -W "${kubectl_out}[*]" -- "$cur" ) )
    90         COMPREPLY=( $( compgen -W "${kubectl_out}[*]" -- "$cur" ) )
   240     fi
    91     fi
   241 }
    92 }
   242 ```
    93 ```
   243 # Using bash aliases for commands
       
   244 
       
   245 You can also configure the `bash aliases` for the commands and they will also support completions.
       
   246 
       
   247 ```bash
       
   248 alias aliasname=origcommand
       
   249 complete -o default -F __start_origcommand aliasname
       
   250 
       
   251 # and now when you run `aliasname` completion will make
       
   252 # suggestions as it did for `origcommand`.
       
   253 
       
   254 $) aliasname <tab><tab>
       
   255 completion     firstcommand   secondcommand
       
   256 ```