github.com/nallagondu/helm@v3.0.0-beta.3+incompatible/cmd/helm/completion.go (about) 1 /* 2 Copyright The Helm Authors. 3 Licensed under the Apache License, Version 2.0 (the "License"); 4 you may not use this file except in compliance with the License. 5 You may obtain a copy of the License at 6 7 http://www.apache.org/licenses/LICENSE-2.0 8 9 Unless required by applicable law or agreed to in writing, software 10 distributed under the License is distributed on an "AS IS" BASIS, 11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 See the License for the specific language governing permissions and 13 limitations under the License. 14 */ 15 16 package main 17 18 import ( 19 "bytes" 20 "io" 21 22 "github.com/pkg/errors" 23 "github.com/spf13/cobra" 24 ) 25 26 const completionDesc = ` 27 Generate autocompletions script for Helm for the specified shell (bash or zsh). 28 29 This command can generate shell autocompletions. e.g. 30 31 $ helm completion bash 32 33 Can be sourced as such 34 35 $ source <(helm completion bash) 36 ` 37 38 var ( 39 completionShells = map[string]func(out io.Writer, cmd *cobra.Command) error{ 40 "bash": runCompletionBash, 41 "zsh": runCompletionZsh, 42 } 43 ) 44 45 func newCompletionCmd(out io.Writer) *cobra.Command { 46 shells := []string{} 47 for s := range completionShells { 48 shells = append(shells, s) 49 } 50 51 cmd := &cobra.Command{ 52 Use: "completion SHELL", 53 Short: "Generate autocompletions script for the specified shell (bash or zsh)", 54 Long: completionDesc, 55 RunE: func(cmd *cobra.Command, args []string) error { 56 return runCompletion(out, cmd, args) 57 }, 58 ValidArgs: shells, 59 } 60 61 return cmd 62 } 63 64 func runCompletion(out io.Writer, cmd *cobra.Command, args []string) error { 65 if len(args) == 0 { 66 return errors.New("shell not specified") 67 } 68 if len(args) > 1 { 69 return errors.New("too many arguments, expected only the shell type") 70 } 71 run, found := completionShells[args[0]] 72 if !found { 73 return errors.Errorf("unsupported shell type %q", args[0]) 74 } 75 76 return run(out, cmd) 77 } 78 79 func runCompletionBash(out io.Writer, cmd *cobra.Command) error { 80 return cmd.Root().GenBashCompletion(out) 81 } 82 83 func runCompletionZsh(out io.Writer, cmd *cobra.Command) error { 84 zshInitialization := `#compdef helm 85 86 __helm_bash_source() { 87 alias shopt=':' 88 alias _expand=_bash_expand 89 alias _complete=_bash_comp 90 emulate -L sh 91 setopt kshglob noshglob braceexpand 92 source "$@" 93 } 94 __helm_type() { 95 # -t is not supported by zsh 96 if [ "$1" == "-t" ]; then 97 shift 98 # fake Bash 4 to disable "complete -o nospace". Instead 99 # "compopt +-o nospace" is used in the code to toggle trailing 100 # spaces. We don't support that, but leave trailing spaces on 101 # all the time 102 if [ "$1" = "__helm_compopt" ]; then 103 echo builtin 104 return 0 105 fi 106 fi 107 type "$@" 108 } 109 __helm_compgen() { 110 local completions w 111 completions=( $(compgen "$@") ) || return $? 112 # filter by given word as prefix 113 while [[ "$1" = -* && "$1" != -- ]]; do 114 shift 115 shift 116 done 117 if [[ "$1" == -- ]]; then 118 shift 119 fi 120 for w in "${completions[@]}"; do 121 if [[ "${w}" = "$1"* ]]; then 122 echo "${w}" 123 fi 124 done 125 } 126 __helm_compopt() { 127 true # don't do anything. Not supported by bashcompinit in zsh 128 } 129 __helm_declare() { 130 if [ "$1" == "-F" ]; then 131 whence -w "$@" 132 else 133 builtin declare "$@" 134 fi 135 } 136 __helm_ltrim_colon_completions() 137 { 138 if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then 139 # Remove colon-word prefix from COMPREPLY items 140 local colon_word=${1%${1##*:}} 141 local i=${#COMPREPLY[*]} 142 while [[ $((--i)) -ge 0 ]]; do 143 COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"} 144 done 145 fi 146 } 147 __helm_get_comp_words_by_ref() { 148 cur="${COMP_WORDS[COMP_CWORD]}" 149 prev="${COMP_WORDS[${COMP_CWORD}-1]}" 150 words=("${COMP_WORDS[@]}") 151 cword=("${COMP_CWORD[@]}") 152 } 153 __helm_filedir() { 154 local RET OLD_IFS w qw 155 __debug "_filedir $@ cur=$cur" 156 if [[ "$1" = \~* ]]; then 157 # somehow does not work. Maybe, zsh does not call this at all 158 eval echo "$1" 159 return 0 160 fi 161 OLD_IFS="$IFS" 162 IFS=$'\n' 163 if [ "$1" = "-d" ]; then 164 shift 165 RET=( $(compgen -d) ) 166 else 167 RET=( $(compgen -f) ) 168 fi 169 IFS="$OLD_IFS" 170 IFS="," __debug "RET=${RET[@]} len=${#RET[@]}" 171 for w in ${RET[@]}; do 172 if [[ ! "${w}" = "${cur}"* ]]; then 173 continue 174 fi 175 if eval "[[ \"\${w}\" = *.$1 || -d \"\${w}\" ]]"; then 176 qw="$(__helm_quote "${w}")" 177 if [ -d "${w}" ]; then 178 COMPREPLY+=("${qw}/") 179 else 180 COMPREPLY+=("${qw}") 181 fi 182 fi 183 done 184 } 185 __helm_quote() { 186 if [[ $1 == \'* || $1 == \"* ]]; then 187 # Leave out first character 188 printf %q "${1:1}" 189 else 190 printf %q "$1" 191 fi 192 } 193 autoload -U +X bashcompinit && bashcompinit 194 # use word boundary patterns for BSD or GNU sed 195 LWORD='[[:<:]]' 196 RWORD='[[:>:]]' 197 if sed --help 2>&1 | grep -q 'GNU\|BusyBox'; then 198 LWORD='\<' 199 RWORD='\>' 200 fi 201 __helm_convert_bash_to_zsh() { 202 sed \ 203 -e 's/declare -F/whence -w/' \ 204 -e 's/_get_comp_words_by_ref "\$@"/_get_comp_words_by_ref "\$*"/' \ 205 -e 's/local \([a-zA-Z0-9_]*\)=/local \1; \1=/' \ 206 -e 's/flags+=("\(--.*\)=")/flags+=("\1"); two_word_flags+=("\1")/' \ 207 -e 's/must_have_one_flag+=("\(--.*\)=")/must_have_one_flag+=("\1")/' \ 208 -e "s/${LWORD}_filedir${RWORD}/__helm_filedir/g" \ 209 -e "s/${LWORD}_get_comp_words_by_ref${RWORD}/__helm_get_comp_words_by_ref/g" \ 210 -e "s/${LWORD}__ltrim_colon_completions${RWORD}/__helm_ltrim_colon_completions/g" \ 211 -e "s/${LWORD}compgen${RWORD}/__helm_compgen/g" \ 212 -e "s/${LWORD}compopt${RWORD}/__helm_compopt/g" \ 213 -e "s/${LWORD}declare${RWORD}/__helm_declare/g" \ 214 -e "s/\\\$(type${RWORD}/\$(__helm_type/g" \ 215 -e 's/aliashash\["\(.\{1,\}\)"\]/aliashash[\1]/g' \ 216 <<'BASH_COMPLETION_EOF' 217 ` 218 out.Write([]byte(zshInitialization)) 219 220 buf := new(bytes.Buffer) 221 cmd.Root().GenBashCompletion(buf) 222 out.Write(buf.Bytes()) 223 224 zshTail := ` 225 BASH_COMPLETION_EOF 226 } 227 __helm_bash_source <(__helm_convert_bash_to_zsh) 228 ` 229 out.Write([]byte(zshTail)) 230 return nil 231 }