vendor/github.com/spf13/cobra/bash_completions.go
changeset 260 445e01aede7e
parent 256 6d9efbef00a9
child 265 05c40b36d3b2
equal deleted inserted replaced
259:db4911b0c721 260:445e01aede7e
    22 func writePreamble(buf io.StringWriter, name string) {
    22 func writePreamble(buf io.StringWriter, name string) {
    23 	WriteStringAndCheck(buf, fmt.Sprintf("# bash completion for %-36s -*- shell-script -*-\n", name))
    23 	WriteStringAndCheck(buf, fmt.Sprintf("# bash completion for %-36s -*- shell-script -*-\n", name))
    24 	WriteStringAndCheck(buf, fmt.Sprintf(`
    24 	WriteStringAndCheck(buf, fmt.Sprintf(`
    25 __%[1]s_debug()
    25 __%[1]s_debug()
    26 {
    26 {
    27     if [[ -n ${BASH_COMP_DEBUG_FILE} ]]; then
    27     if [[ -n ${BASH_COMP_DEBUG_FILE:-} ]]; then
    28         echo "$*" >> "${BASH_COMP_DEBUG_FILE}"
    28         echo "$*" >> "${BASH_COMP_DEBUG_FILE}"
    29     fi
    29     fi
    30 }
    30 }
    31 
    31 
    32 # Homebrew on Macs have version 1.3 of bash-completion which doesn't include
    32 # Homebrew on Macs have version 1.3 of bash-completion which doesn't include
    71     local out requestComp lastParam lastChar comp directive args
    71     local out requestComp lastParam lastChar comp directive args
    72 
    72 
    73     # Prepare the command to request completions for the program.
    73     # Prepare the command to request completions for the program.
    74     # Calling ${words[0]} instead of directly %[1]s allows to handle aliases
    74     # Calling ${words[0]} instead of directly %[1]s allows to handle aliases
    75     args=("${words[@]:1}")
    75     args=("${words[@]:1}")
    76     requestComp="${words[0]} %[2]s ${args[*]}"
    76     # Disable ActiveHelp which is not supported for bash completion v1
       
    77     requestComp="%[8]s=0 ${words[0]} %[2]s ${args[*]}"
    77 
    78 
    78     lastParam=${words[$((${#words[@]}-1))]}
    79     lastParam=${words[$((${#words[@]}-1))]}
    79     lastChar=${lastParam:$((${#lastParam}-1)):1}
    80     lastChar=${lastParam:$((${#lastParam}-1)):1}
    80     __%[1]s_debug "${FUNCNAME[0]}: lastParam ${lastParam}, lastChar ${lastChar}"
    81     __%[1]s_debug "${FUNCNAME[0]}: lastParam ${lastParam}, lastChar ${lastChar}"
    81 
    82 
    97     if [ "${directive}" = "${out}" ]; then
    98     if [ "${directive}" = "${out}" ]; then
    98         # There is not directive specified
    99         # There is not directive specified
    99         directive=0
   100         directive=0
   100     fi
   101     fi
   101     __%[1]s_debug "${FUNCNAME[0]}: the completion directive is: ${directive}"
   102     __%[1]s_debug "${FUNCNAME[0]}: the completion directive is: ${directive}"
   102     __%[1]s_debug "${FUNCNAME[0]}: the completions are: ${out[*]}"
   103     __%[1]s_debug "${FUNCNAME[0]}: the completions are: ${out}"
   103 
   104 
   104     if [ $((directive & shellCompDirectiveError)) -ne 0 ]; then
   105     if [ $((directive & shellCompDirectiveError)) -ne 0 ]; then
   105         # Error code.  No completion.
   106         # Error code.  No completion.
   106         __%[1]s_debug "${FUNCNAME[0]}: received error from custom completion go code"
   107         __%[1]s_debug "${FUNCNAME[0]}: received error from custom completion go code"
   107         return
   108         return
   123     if [ $((directive & shellCompDirectiveFilterFileExt)) -ne 0 ]; then
   124     if [ $((directive & shellCompDirectiveFilterFileExt)) -ne 0 ]; then
   124         # File extension filtering
   125         # File extension filtering
   125         local fullFilter filter filteringCmd
   126         local fullFilter filter filteringCmd
   126         # Do not use quotes around the $out variable or else newline
   127         # Do not use quotes around the $out variable or else newline
   127         # characters will be kept.
   128         # characters will be kept.
   128         for filter in ${out[*]}; do
   129         for filter in ${out}; do
   129             fullFilter+="$filter|"
   130             fullFilter+="$filter|"
   130         done
   131         done
   131 
   132 
   132         filteringCmd="_filedir $fullFilter"
   133         filteringCmd="_filedir $fullFilter"
   133         __%[1]s_debug "File filtering command: $filteringCmd"
   134         __%[1]s_debug "File filtering command: $filteringCmd"
   134         $filteringCmd
   135         $filteringCmd
   135     elif [ $((directive & shellCompDirectiveFilterDirs)) -ne 0 ]; then
   136     elif [ $((directive & shellCompDirectiveFilterDirs)) -ne 0 ]; then
   136         # File completion for directories only
   137         # File completion for directories only
   137         local subDir
   138         local subdir
   138         # Use printf to strip any trailing newline
   139         # Use printf to strip any trailing newline
   139         subdir=$(printf "%%s" "${out[0]}")
   140         subdir=$(printf "%%s" "${out}")
   140         if [ -n "$subdir" ]; then
   141         if [ -n "$subdir" ]; then
   141             __%[1]s_debug "Listing directories in $subdir"
   142             __%[1]s_debug "Listing directories in $subdir"
   142             __%[1]s_handle_subdirs_in_dir_flag "$subdir"
   143             __%[1]s_handle_subdirs_in_dir_flag "$subdir"
   143         else
   144         else
   144             __%[1]s_debug "Listing directories in ."
   145             __%[1]s_debug "Listing directories in ."
   145             _filedir -d
   146             _filedir -d
   146         fi
   147         fi
   147     else
   148     else
   148         while IFS='' read -r comp; do
   149         while IFS='' read -r comp; do
   149             COMPREPLY+=("$comp")
   150             COMPREPLY+=("$comp")
   150         done < <(compgen -W "${out[*]}" -- "$cur")
   151         done < <(compgen -W "${out}" -- "$cur")
   151     fi
   152     fi
   152 }
   153 }
   153 
   154 
   154 __%[1]s_handle_reply()
   155 __%[1]s_handle_reply()
   155 {
   156 {
   185                 COMPREPLY=()
   186                 COMPREPLY=()
   186                 if [[ ${index} -ge 0 ]]; then
   187                 if [[ ${index} -ge 0 ]]; then
   187                     PREFIX=""
   188                     PREFIX=""
   188                     cur="${cur#*=}"
   189                     cur="${cur#*=}"
   189                     ${flags_completion[${index}]}
   190                     ${flags_completion[${index}]}
   190                     if [ -n "${ZSH_VERSION}" ]; then
   191                     if [ -n "${ZSH_VERSION:-}" ]; then
   191                         # zsh completion needs --flag= prefix
   192                         # zsh completion needs --flag= prefix
   192                         eval "COMPREPLY=( \"\${COMPREPLY[@]/#/${flag}=}\" )"
   193                         eval "COMPREPLY=( \"\${COMPREPLY[@]/#/${flag}=}\" )"
   193                     fi
   194                     fi
   194                 fi
   195                 fi
   195             fi
   196             fi
   196             return 0;
   197 
       
   198             if [[ -z "${flag_parsing_disabled}" ]]; then
       
   199                 # If flag parsing is enabled, we have completed the flags and can return.
       
   200                 # If flag parsing is disabled, we may not know all (or any) of the flags, so we fallthrough
       
   201                 # to possibly call handle_go_custom_completion.
       
   202                 return 0;
       
   203             fi
   197             ;;
   204             ;;
   198     esac
   205     esac
   199 
   206 
   200     # check if we are handling a flag with special work handling
   207     # check if we are handling a flag with special work handling
   201     local index
   208     local index
   230             COMPREPLY+=("$comp")
   237             COMPREPLY+=("$comp")
   231         done < <(compgen -W "${noun_aliases[*]}" -- "$cur")
   238         done < <(compgen -W "${noun_aliases[*]}" -- "$cur")
   232     fi
   239     fi
   233 
   240 
   234     if [[ ${#COMPREPLY[@]} -eq 0 ]]; then
   241     if [[ ${#COMPREPLY[@]} -eq 0 ]]; then
   235 		if declare -F __%[1]s_custom_func >/dev/null; then
   242         if declare -F __%[1]s_custom_func >/dev/null; then
   236 			# try command name qualified custom func
   243             # try command name qualified custom func
   237 			__%[1]s_custom_func
   244             __%[1]s_custom_func
   238 		else
   245         else
   239 			# otherwise fall back to unqualified for compatibility
   246             # otherwise fall back to unqualified for compatibility
   240 			declare -F __custom_func >/dev/null && __custom_func
   247             declare -F __custom_func >/dev/null && __custom_func
   241 		fi
   248         fi
   242     fi
   249     fi
   243 
   250 
   244     # available in bash-completion >= 2, not always present on macOS
   251     # available in bash-completion >= 2, not always present on macOS
   245     if declare -F __ltrim_colon_completions >/dev/null; then
   252     if declare -F __ltrim_colon_completions >/dev/null; then
   246         __ltrim_colon_completions "$cur"
   253         __ltrim_colon_completions "$cur"
   270 {
   277 {
   271     __%[1]s_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}"
   278     __%[1]s_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}"
   272 
   279 
   273     # if a command required a flag, and we found it, unset must_have_one_flag()
   280     # if a command required a flag, and we found it, unset must_have_one_flag()
   274     local flagname=${words[c]}
   281     local flagname=${words[c]}
   275     local flagvalue
   282     local flagvalue=""
   276     # if the word contained an =
   283     # if the word contained an =
   277     if [[ ${words[c]} == *"="* ]]; then
   284     if [[ ${words[c]} == *"="* ]]; then
   278         flagvalue=${flagname#*=} # take in as flagvalue after the =
   285         flagvalue=${flagname#*=} # take in as flagvalue after the =
   279         flagname=${flagname%%=*} # strip everything after the =
   286         flagname=${flagname%%=*} # strip everything after the =
   280         flagname="${flagname}=" # but put the = back
   287         flagname="${flagname}=" # but put the = back
   289       commands=()
   296       commands=()
   290     fi
   297     fi
   291 
   298 
   292     # keep flag value with flagname as flaghash
   299     # keep flag value with flagname as flaghash
   293     # flaghash variable is an associative array which is only supported in bash > 3.
   300     # flaghash variable is an associative array which is only supported in bash > 3.
   294     if [[ -z "${BASH_VERSION}" || "${BASH_VERSINFO[0]}" -gt 3 ]]; then
   301     if [[ -z "${BASH_VERSION:-}" || "${BASH_VERSINFO[0]:-}" -gt 3 ]]; then
   295         if [ -n "${flagvalue}" ] ; then
   302         if [ -n "${flagvalue}" ] ; then
   296             flaghash[${flagname}]=${flagvalue}
   303             flaghash[${flagname}]=${flagvalue}
   297         elif [ -n "${words[ $((c+1)) ]}" ] ; then
   304         elif [ -n "${words[ $((c+1)) ]}" ] ; then
   298             flaghash[${flagname}]=${words[ $((c+1)) ]}
   305             flaghash[${flagname}]=${words[ $((c+1)) ]}
   299         else
   306         else
   301         fi
   308         fi
   302     fi
   309     fi
   303 
   310 
   304     # skip the argument to a two word flag
   311     # skip the argument to a two word flag
   305     if [[ ${words[c]} != *"="* ]] && __%[1]s_contains_word "${words[c]}" "${two_word_flags[@]}"; then
   312     if [[ ${words[c]} != *"="* ]] && __%[1]s_contains_word "${words[c]}" "${two_word_flags[@]}"; then
   306 			  __%[1]s_debug "${FUNCNAME[0]}: found a flag ${words[c]}, skip the next argument"
   313         __%[1]s_debug "${FUNCNAME[0]}: found a flag ${words[c]}, skip the next argument"
   307         c=$((c+1))
   314         c=$((c+1))
   308         # if we are looking for a flags value, don't show commands
   315         # if we are looking for a flags value, don't show commands
   309         if [[ $c -eq $cword ]]; then
   316         if [[ $c -eq $cword ]]; then
   310             commands=()
   317             commands=()
   311         fi
   318         fi
   361         __%[1]s_handle_command
   368         __%[1]s_handle_command
   362     elif [[ $c -eq 0 ]]; then
   369     elif [[ $c -eq 0 ]]; then
   363         __%[1]s_handle_command
   370         __%[1]s_handle_command
   364     elif __%[1]s_contains_word "${words[c]}" "${command_aliases[@]}"; then
   371     elif __%[1]s_contains_word "${words[c]}" "${command_aliases[@]}"; then
   365         # aliashash variable is an associative array which is only supported in bash > 3.
   372         # aliashash variable is an associative array which is only supported in bash > 3.
   366         if [[ -z "${BASH_VERSION}" || "${BASH_VERSINFO[0]}" -gt 3 ]]; then
   373         if [[ -z "${BASH_VERSION:-}" || "${BASH_VERSINFO[0]:-}" -gt 3 ]]; then
   367             words[c]=${aliashash[${words[c]}]}
   374             words[c]=${aliashash[${words[c]}]}
   368             __%[1]s_handle_command
   375             __%[1]s_handle_command
   369         else
   376         else
   370             __%[1]s_handle_noun
   377             __%[1]s_handle_noun
   371         fi
   378         fi
   375     __%[1]s_handle_word
   382     __%[1]s_handle_word
   376 }
   383 }
   377 
   384 
   378 `, name, ShellCompNoDescRequestCmd,
   385 `, name, ShellCompNoDescRequestCmd,
   379 		ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp,
   386 		ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp,
   380 		ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs))
   387 		ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, activeHelpEnvVar(name)))
   381 }
   388 }
   382 
   389 
   383 func writePostscript(buf io.StringWriter, name string) {
   390 func writePostscript(buf io.StringWriter, name string) {
   384 	name = strings.Replace(name, ":", "__", -1)
   391 	name = strings.ReplaceAll(name, ":", "__")
   385 	WriteStringAndCheck(buf, fmt.Sprintf("__start_%s()\n", name))
   392 	WriteStringAndCheck(buf, fmt.Sprintf("__start_%s()\n", name))
   386 	WriteStringAndCheck(buf, fmt.Sprintf(`{
   393 	WriteStringAndCheck(buf, fmt.Sprintf(`{
   387     local cur prev words cword split
   394     local cur prev words cword split
   388     declare -A flaghash 2>/dev/null || :
   395     declare -A flaghash 2>/dev/null || :
   389     declare -A aliashash 2>/dev/null || :
   396     declare -A aliashash 2>/dev/null || :
   392     else
   399     else
   393         __%[1]s_init_completion -n "=" || return
   400         __%[1]s_init_completion -n "=" || return
   394     fi
   401     fi
   395 
   402 
   396     local c=0
   403     local c=0
       
   404     local flag_parsing_disabled=
   397     local flags=()
   405     local flags=()
   398     local two_word_flags=()
   406     local two_word_flags=()
   399     local local_nonpersistent_flags=()
   407     local local_nonpersistent_flags=()
   400     local flags_with_completion=()
   408     local flags_with_completion=()
   401     local flags_completion=()
   409     local flags_completion=()
   402     local commands=("%[1]s")
   410     local commands=("%[1]s")
   403     local command_aliases=()
   411     local command_aliases=()
   404     local must_have_one_flag=()
   412     local must_have_one_flag=()
   405     local must_have_one_noun=()
   413     local must_have_one_noun=()
   406     local has_completion_function
   414     local has_completion_function=""
   407     local last_command
   415     local last_command=""
   408     local nouns=()
   416     local nouns=()
   409     local noun_aliases=()
   417     local noun_aliases=()
   410 
   418 
   411     __%[1]s_handle_word
   419     __%[1]s_handle_word
   412 }
   420 }
   533     local_nonpersistent_flags=()
   541     local_nonpersistent_flags=()
   534     flags_with_completion=()
   542     flags_with_completion=()
   535     flags_completion=()
   543     flags_completion=()
   536 
   544 
   537 `)
   545 `)
       
   546 
       
   547 	if cmd.DisableFlagParsing {
       
   548 		WriteStringAndCheck(buf, "    flag_parsing_disabled=1\n")
       
   549 	}
       
   550 
   538 	localNonPersistentFlags := cmd.LocalNonPersistentFlags()
   551 	localNonPersistentFlags := cmd.LocalNonPersistentFlags()
   539 	cmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) {
   552 	cmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) {
   540 		if nonCompletableFlag(flag) {
   553 		if nonCompletableFlag(flag) {
   541 			return
   554 			return
   542 		}
   555 		}
   607 		return
   620 		return
   608 	}
   621 	}
   609 
   622 
   610 	sort.Strings(cmd.Aliases)
   623 	sort.Strings(cmd.Aliases)
   611 
   624 
   612 	WriteStringAndCheck(buf, fmt.Sprint(`    if [[ -z "${BASH_VERSION}" || "${BASH_VERSINFO[0]}" -gt 3 ]]; then`, "\n"))
   625 	WriteStringAndCheck(buf, fmt.Sprint(`    if [[ -z "${BASH_VERSION:-}" || "${BASH_VERSINFO[0]:-}" -gt 3 ]]; then`, "\n"))
   613 	for _, value := range cmd.Aliases {
   626 	for _, value := range cmd.Aliases {
   614 		WriteStringAndCheck(buf, fmt.Sprintf("        command_aliases+=(%q)\n", value))
   627 		WriteStringAndCheck(buf, fmt.Sprintf("        command_aliases+=(%q)\n", value))
   615 		WriteStringAndCheck(buf, fmt.Sprintf("        aliashash[%q]=%q\n", value, cmd.Name()))
   628 		WriteStringAndCheck(buf, fmt.Sprintf("        aliashash[%q]=%q\n", value, cmd.Name()))
   616 	}
   629 	}
   617 	WriteStringAndCheck(buf, `    fi`)
   630 	WriteStringAndCheck(buf, `    fi`)
   631 			continue
   644 			continue
   632 		}
   645 		}
   633 		gen(buf, c)
   646 		gen(buf, c)
   634 	}
   647 	}
   635 	commandName := cmd.CommandPath()
   648 	commandName := cmd.CommandPath()
   636 	commandName = strings.Replace(commandName, " ", "_", -1)
   649 	commandName = strings.ReplaceAll(commandName, " ", "_")
   637 	commandName = strings.Replace(commandName, ":", "__", -1)
   650 	commandName = strings.ReplaceAll(commandName, ":", "__")
   638 
   651 
   639 	if cmd.Root() == cmd {
   652 	if cmd.Root() == cmd {
   640 		WriteStringAndCheck(buf, fmt.Sprintf("_%s_root_command()\n{\n", commandName))
   653 		WriteStringAndCheck(buf, fmt.Sprintf("_%s_root_command()\n{\n", commandName))
   641 	} else {
   654 	} else {
   642 		WriteStringAndCheck(buf, fmt.Sprintf("_%s()\n{\n", commandName))
   655 		WriteStringAndCheck(buf, fmt.Sprintf("_%s()\n{\n", commandName))