Use native zsh completion

Signed-off-by: Marc Khouzam <marc.khouzam@montreal.ca>
This commit is contained in:
Marc Khouzam 2021-06-05 22:09:03 -04:00
parent 46aa6045e4
commit 77bb053102

View File

@ -17,7 +17,6 @@ limitations under the License.
package completion
import (
"bytes"
"io"
"github.com/spf13/cobra"
@ -150,8 +149,7 @@ func runCompletionBash(out io.Writer, boilerPlate string, kubectl *cobra.Command
}
func runCompletionZsh(out io.Writer, boilerPlate string, kubectl *cobra.Command) error {
zshHead := "#compdef kubectl\n"
zshHead := "#compdef kubectl\ncompdef _kubectl kubectl\n"
out.Write([]byte(zshHead))
if len(boilerPlate) == 0 {
@ -161,118 +159,5 @@ func runCompletionZsh(out io.Writer, boilerPlate string, kubectl *cobra.Command)
return err
}
zshInitialization := `
__kubectl_bash_source() {
alias shopt=':'
emulate -L sh
setopt kshglob noshglob braceexpand
source "$@"
}
__kubectl_type() {
# -t is not supported by zsh
if [ "$1" == "-t" ]; then
shift
# fake Bash 4 to disable "complete -o nospace". Instead
# "compopt +-o nospace" is used in the code to toggle trailing
# spaces. We don't support that, but leave trailing spaces on
# all the time
if [ "$1" = "__kubectl_compopt" ]; then
echo builtin
return 0
fi
fi
type "$@"
}
__kubectl_compgen() {
local completions w
completions=( $(compgen "$@") ) || return $?
# filter by given word as prefix
while [[ "$1" = -* && "$1" != -- ]]; do
shift
shift
done
if [[ "$1" == -- ]]; then
shift
fi
for w in "${completions[@]}"; do
if [[ "${w}" = "$1"* ]]; then
echo "${w}"
fi
done
}
__kubectl_compopt() {
true # don't do anything. Not supported by bashcompinit in zsh
}
__kubectl_ltrim_colon_completions()
{
if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then
# Remove colon-word prefix from COMPREPLY items
local colon_word=${1%${1##*:}}
local i=${#COMPREPLY[*]}
while [[ $((--i)) -ge 0 ]]; do
COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"}
done
fi
}
__kubectl_get_comp_words_by_ref() {
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[${COMP_CWORD}-1]}"
words=("${COMP_WORDS[@]}")
cword=("${COMP_CWORD[@]}")
}
__kubectl_filedir() {
# Don't need to do anything here.
# Otherwise we will get trailing space without "compopt -o nospace"
true
}
autoload -U +X bashcompinit && bashcompinit
# use word boundary patterns for BSD or GNU sed
LWORD='[[:<:]]'
RWORD='[[:>:]]'
if sed --version 2>&1 | grep -q GNU; then
LWORD='\<'
RWORD='\>'
fi
__kubectl_convert_bash_to_zsh() {
sed \
-e 's/declare -F/whence -w/' \
-e 's/_get_comp_words_by_ref "\$@"/_get_comp_words_by_ref "\$*"/' \
-e 's/local \([a-zA-Z0-9_]*\)=/local \1; \1=/' \
-e 's/flags+=("\(--.*\)=")/flags+=("\1"); two_word_flags+=("\1")/' \
-e 's/must_have_one_flag+=("\(--.*\)=")/must_have_one_flag+=("\1")/' \
-e "s/${LWORD}_filedir${RWORD}/__kubectl_filedir/g" \
-e "s/${LWORD}_get_comp_words_by_ref${RWORD}/__kubectl_get_comp_words_by_ref/g" \
-e "s/${LWORD}__ltrim_colon_completions${RWORD}/__kubectl_ltrim_colon_completions/g" \
-e "s/${LWORD}compgen${RWORD}/__kubectl_compgen/g" \
-e "s/${LWORD}compopt${RWORD}/__kubectl_compopt/g" \
-e "s/${LWORD}declare${RWORD}/builtin declare/g" \
-e "s/\\\$(type${RWORD}/\$(__kubectl_type/g" \
<<'BASH_COMPLETION_EOF'
`
out.Write([]byte(zshInitialization))
buf := new(bytes.Buffer)
kubectl.GenBashCompletion(buf)
out.Write(buf.Bytes())
zshTail := `
BASH_COMPLETION_EOF
}
__kubectl_bash_source <(__kubectl_convert_bash_to_zsh)
`
out.Write([]byte(zshTail))
return nil
return kubectl.GenZshCompletion(out)
}