diff --git a/contrib/completions/zsh/kubectl b/contrib/completions/zsh/kubectl new file mode 100755 index 00000000000..3285a5036b7 --- /dev/null +++ b/contrib/completions/zsh/kubectl @@ -0,0 +1,155 @@ +#!/bin/zsh + +# Copyright 2016 The Kubernetes Authors All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +__kubectl_bash_source() { + alias shopt=':' + alias _expand=_bash_expand + alias _complete=_bash_comp + 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_declare() { + if [ "$1" == "-F" ]; then + whence -w "$@" + else + builtin declare "$@" + fi +} + +__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() { + local RET OLD_IFS w qw + + __debug "_filedir $@ cur=$cur" + if [[ "$1" = \~* ]]; then + # somehow does not work. Maybe, zsh does not call this at all + eval echo "$1" + return 0 + fi + + OLD_IFS="$IFS" + IFS=$'\n' + if [ "$1" = "-d" ]; then + shift + RET=( $(compgen -d) ) + else + RET=( $(compgen -f) ) + fi + IFS="$OLD_IFS" + + IFS="," __debug "RET=${RET[@]} len=${#RET[@]}" + + for w in ${RET[@]}; do + if [[ ! "${w}" = "${cur}"* ]]; then + continue + fi + if eval "[[ \"\${w}\" = *.$1 || -d \"\${w}\" ]]"; then + qw="$(__kubectl_quote "${w}")" + if [ -d "${w}" ]; then + COMPREPLY+=("${qw}/") + else + COMPREPLY+=("${qw}") + fi + fi + done +} + +__kubectl_quote() { + if [[ $1 == \'* || $1 == \"* ]]; then + # Leave out first character + printf %q "${1:1}" + else + printf %q "$1" + fi +} + +autoload -U +X compinit && compinit +autoload -U +X bashcompinit && bashcompinit +__kubectl_bash_source <(sed \ + -e 's/declare -F/whence -w/' \ + -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/[[:<:]]_filedir[[:>:]]/__kubectl_filedir/g' \ + -e 's/[[:<:]]_get_comp_words_by_ref[[:>:]]/__kubectl_get_comp_words_by_ref/g' \ + -e 's/[[:<:]]__ltrim_colon_completions[[:>:]]/__kubectl_ltrim_colon_completions/g' \ + -e 's/[[:<:]]compgen[[:>:]]/__kubectl_compgen/g' \ + -e 's/[[:<:]]compopt[[:>:]]/__kubectl_compopt/g' \ + -e 's/[[:<:]]declare[[:>:]]/__kubectl_declare/g' \ + -e 's/\$(type[[:>:]]/$(__kubectl_type/g' \ + $(dirname $0)/../bash/kubectl +)