github.com/migueleliasweb/helm@v2.6.1+incompatible/cmd/helm/completion.go (about) 1 /* 2 Copyright 2016 The Kubernetes Authors All rights reserved. 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 "fmt" 21 "io" 22 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 fmt.Errorf("shell not specified") 67 } 68 if len(args) > 1 { 69 return fmt.Errorf("too many arguments, expected only the shell type") 70 } 71 run, found := completionShells[args[0]] 72 if !found { 73 return fmt.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 := ` 85 __helm_bash_source() { 86 alias shopt=':' 87 alias _expand=_bash_expand 88 alias _complete=_bash_comp 89 emulate -L sh 90 setopt kshglob noshglob braceexpand 91 source "$@" 92 } 93 __helm_type() { 94 # -t is not supported by zsh 95 if [ "$1" == "-t" ]; then 96 shift 97 # fake Bash 4 to disable "complete -o nospace". Instead 98 # "compopt +-o nospace" is used in the code to toggle trailing 99 # spaces. We don't support that, but leave trailing spaces on 100 # all the time 101 if [ "$1" = "__helm_compopt" ]; then 102 echo builtin 103 return 0 104 fi 105 fi 106 type "$@" 107 } 108 __helm_compgen() { 109 local completions w 110 completions=( $(compgen "$@") ) || return $? 111 # filter by given word as prefix 112 while [[ "$1" = -* && "$1" != -- ]]; do 113 shift 114 shift 115 done 116 if [[ "$1" == -- ]]; then 117 shift 118 fi 119 for w in "${completions[@]}"; do 120 if [[ "${w}" = "$1"* ]]; then 121 echo "${w}" 122 fi 123 done 124 } 125 __helm_compopt() { 126 true # don't do anything. Not supported by bashcompinit in zsh 127 } 128 __helm_declare() { 129 if [ "$1" == "-F" ]; then 130 whence -w "$@" 131 else 132 builtin declare "$@" 133 fi 134 } 135 __helm_ltrim_colon_completions() 136 { 137 if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then 138 # Remove colon-word prefix from COMPREPLY items 139 local colon_word=${1%${1##*:}} 140 local i=${#COMPREPLY[*]} 141 while [[ $((--i)) -ge 0 ]]; do 142 COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"} 143 done 144 fi 145 } 146 __helm_get_comp_words_by_ref() { 147 cur="${COMP_WORDS[COMP_CWORD]}" 148 prev="${COMP_WORDS[${COMP_CWORD}-1]}" 149 words=("${COMP_WORDS[@]}") 150 cword=("${COMP_CWORD[@]}") 151 } 152 __helm_filedir() { 153 local RET OLD_IFS w qw 154 __debug "_filedir $@ cur=$cur" 155 if [[ "$1" = \~* ]]; then 156 # somehow does not work. Maybe, zsh does not call this at all 157 eval echo "$1" 158 return 0 159 fi 160 OLD_IFS="$IFS" 161 IFS=$'\n' 162 if [ "$1" = "-d" ]; then 163 shift 164 RET=( $(compgen -d) ) 165 else 166 RET=( $(compgen -f) ) 167 fi 168 IFS="$OLD_IFS" 169 IFS="," __debug "RET=${RET[@]} len=${#RET[@]}" 170 for w in ${RET[@]}; do 171 if [[ ! "${w}" = "${cur}"* ]]; then 172 continue 173 fi 174 if eval "[[ \"\${w}\" = *.$1 || -d \"\${w}\" ]]"; then 175 qw="$(__helm_quote "${w}")" 176 if [ -d "${w}" ]; then 177 COMPREPLY+=("${qw}/") 178 else 179 COMPREPLY+=("${qw}") 180 fi 181 fi 182 done 183 } 184 __helm_quote() { 185 if [[ $1 == \'* || $1 == \"* ]]; then 186 # Leave out first character 187 printf %q "${1:1}" 188 else 189 printf %q "$1" 190 fi 191 } 192 autoload -U +X bashcompinit && bashcompinit 193 # use word boundary patterns for BSD or GNU sed 194 LWORD='[[:<:]]' 195 RWORD='[[:>:]]' 196 if sed --help 2>&1 | grep -q GNU; then 197 LWORD='\<' 198 RWORD='\>' 199 fi 200 __helm_convert_bash_to_zsh() { 201 sed \ 202 -e 's/declare -F/whence -w/' \ 203 -e 's/_get_comp_words_by_ref "\$@"/_get_comp_words_by_ref "\$*"/' \ 204 -e 's/local \([a-zA-Z0-9_]*\)=/local \1; \1=/' \ 205 -e 's/flags+=("\(--.*\)=")/flags+=("\1"); two_word_flags+=("\1")/' \ 206 -e 's/must_have_one_flag+=("\(--.*\)=")/must_have_one_flag+=("\1")/' \ 207 -e "s/${LWORD}_filedir${RWORD}/__helm_filedir/g" \ 208 -e "s/${LWORD}_get_comp_words_by_ref${RWORD}/__helm_get_comp_words_by_ref/g" \ 209 -e "s/${LWORD}__ltrim_colon_completions${RWORD}/__helm_ltrim_colon_completions/g" \ 210 -e "s/${LWORD}compgen${RWORD}/__helm_compgen/g" \ 211 -e "s/${LWORD}compopt${RWORD}/__helm_compopt/g" \ 212 -e "s/${LWORD}declare${RWORD}/__helm_declare/g" \ 213 -e "s/\\\$(type${RWORD}/\$(__helm_type/g" \ 214 <<'BASH_COMPLETION_EOF' 215 ` 216 out.Write([]byte(zshInitialization)) 217 218 buf := new(bytes.Buffer) 219 cmd.Root().GenBashCompletion(buf) 220 out.Write(buf.Bytes()) 221 222 zshTail := ` 223 BASH_COMPLETION_EOF 224 } 225 __helm_bash_source <(__helm_convert_bash_to_zsh) 226 ` 227 out.Write([]byte(zshTail)) 228 return nil 229 }