Qualify custom bash func name

- fixes issue where multiple cobra apps using custom bash completion
 would have their __custom_func collide
 - support fallback to plain __custom_func to maintain compatibility

#694
This commit is contained in:
pgwhalen 2018-08-19 21:55:45 -05:00
parent 7c4570c3eb
commit dff8b28b10
3 changed files with 14 additions and 5 deletions

View file

@ -129,7 +129,13 @@ __%[1]s_handle_reply()
fi fi
if [[ ${#COMPREPLY[@]} -eq 0 ]]; then if [[ ${#COMPREPLY[@]} -eq 0 ]]; then
declare -F __custom_func >/dev/null && __custom_func if declare -F __%[1]s_custom_func >/dev/null; then
# try command name qualified custom func
__%[1]s_custom_func
else
# otherwise fall back to unqualified for compatibility
declare -F ___custom_func >/dev/null && __custom_func
fi
fi fi
# available in bash-completion >= 2, not always present on macOS # available in bash-completion >= 2, not always present on macOS

View file

@ -82,7 +82,7 @@ __kubectl_get_resource()
fi fi
} }
__custom_func() { __kubectl_custom_func() {
case ${last_command} in case ${last_command} in
kubectl_get | kubectl_describe | kubectl_delete | kubectl_stop) kubectl_get | kubectl_describe | kubectl_delete | kubectl_stop)
__kubectl_get_resource __kubectl_get_resource
@ -109,7 +109,7 @@ 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! 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!
## Have the completions code complete your 'nouns' ## Have the completions code complete your 'nouns'

View file

@ -53,7 +53,7 @@ func runShellCheck(s string) error {
} }
// World worst custom function, just keep telling you to enter hello! // World worst custom function, just keep telling you to enter hello!
const bashCompletionFunc = `__custom_func() { const bashCompletionFunc = `__root_custom_func() {
COMPREPLY=( "hello" ) COMPREPLY=( "hello" )
} }
` `
@ -150,7 +150,10 @@ func TestBashCompletions(t *testing.T) {
// check for required flags // check for required flags
check(t, output, `must_have_one_flag+=("--introot=")`) check(t, output, `must_have_one_flag+=("--introot=")`)
check(t, output, `must_have_one_flag+=("--persistent-filename=")`) check(t, output, `must_have_one_flag+=("--persistent-filename=")`)
// check for custom completion function // check for custom completion function with both qualified and unqualified name
check(t, output, `__root_custom_func`)
check(t, output, `__custom_func`)
// check for custom completion function body
check(t, output, `COMPREPLY=( "hello" )`) check(t, output, `COMPREPLY=( "hello" )`)
// check for required nouns // check for required nouns
check(t, output, `must_have_one_noun+=("pod")`) check(t, output, `must_have_one_noun+=("pod")`)