Allow functions within BashCompletionFunction to run unconditionally, limit their scope to a particular command.

This commit is contained in:
cpfair 2016-01-12 16:17:19 +00:00
parent 97f831a4fd
commit beaa4630e5
2 changed files with 31 additions and 6 deletions

View file

@ -103,10 +103,18 @@ __handle_reply()
fi fi
COMPREPLY=( $(compgen -W "${completions[*]}" -- "$cur") ) COMPREPLY=( $(compgen -W "${completions[*]}" -- "$cur") )
declare -F __custom_unconditional_func >/dev/null && __custom_unconditional_func
declare -F __custom_unconditional_command_func >/dev/null && __custom_unconditional_command_func
if [[ ${#COMPREPLY[@]} -eq 0 ]]; then if [[ ${#COMPREPLY[@]} -eq 0 ]]; then
declare -F __custom_func >/dev/null && __custom_func declare -F __custom_func >/dev/null && __custom_func
declare -F __custom_command_func >/dev/null && __custom_command_func
fi fi
# These are declared as globals within the specific commands' handler functions
# We must undefine them here, otherwise they will persist outside of their intended lifetime
unset -f __custom_func __custom_unconditional_func
__ltrim_colon_completions "$cur" __ltrim_colon_completions "$cur"
} }
@ -177,6 +185,8 @@ __handle_noun()
__handle_command() __handle_command()
{ {
# Clear handlers meant to be command-specific
unset -f __custom_command_func __custom_unconditional_command_func
__debug "${FUNCNAME}: c is $c words[c] is ${words[c]}" __debug "${FUNCNAME}: c is $c words[c] is ${words[c]}"
local next_command local next_command
@ -446,6 +456,11 @@ func gen(cmd *Command, w io.Writer) error {
if _, err := fmt.Fprintf(w, "_%s()\n{\n", commandName); err != nil { if _, err := fmt.Fprintf(w, "_%s()\n{\n", commandName); err != nil {
return err return err
} }
if len(cmd.BashCompletionFunction) > 0 {
if _, err := fmt.Fprintf(w, "%s\n", cmd.BashCompletionFunction); err != nil {
return err
}
}
if _, err := fmt.Fprintf(w, " last_command=%q\n", commandName); err != nil { if _, err := fmt.Fprintf(w, " last_command=%q\n", commandName); err != nil {
return err return err
} }
@ -471,11 +486,6 @@ func (cmd *Command) GenBashCompletion(w io.Writer) error {
if err := preamble(w, cmd.Name()); err != nil { if err := preamble(w, cmd.Name()); err != nil {
return err return err
} }
if len(cmd.BashCompletionFunction) > 0 {
if _, err := fmt.Fprintf(w, "%s\n", cmd.BashCompletionFunction); err != nil {
return err
}
}
if err := gen(cmd, w); err != nil { if err := gen(cmd, w); err != nil {
return err return err
} }

View file

@ -22,6 +22,14 @@ That will get you completions of subcommands and flags. If you make additional a
## Creating your own custom functions ## Creating your own custom functions
The `BashCompletionFunction` member can be used to define bash functions which generate completion suggestions. Within `BashCompletionFunction` you can define some of the following four bash functions, which should modify `COMPREPLY` as appropriate.
| Function | Runs always | Runs when no earlier handler produced completion results |
| ------- | ----------- | -------------------------------------------------------- |
| **Runs for Command** | `__custom_unconditional_command_func` | `__custom_command_func` |
| **Runs for Command & children** | `__custom_func` | `__custom_unconditional_func` |
Some more actual code that works in kubernetes: Some more actual code that works in kubernetes:
```bash ```bash
@ -73,7 +81,14 @@ Find more information at https://github.com/GoogleCloudPlatform/kubernetes.`,
} }
``` ```
The `BashCompletionFunction` option is really only valid/useful on the root command. Doing the above will cause `__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 `__customc_func()` will run because the cobra.Command only understood "kubectl" and "get." `__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! 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 `__customc_func()` will run because the cobra.Command only understood "kubectl" and "get." `__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!
If you define more than one `__custom*_func`, they will execute in the following order (latest takes precedence):
* `__custom_unconditional_func`
* `__custom_unconditional_command_func`
* `__custom_func`
* `__custom_command_func`
## Have the completions code complete your 'nouns' ## Have the completions code complete your 'nouns'