diff options
-rw-r--r-- | cmd/podman/completion/completion.go | 2 | ||||
-rw-r--r-- | completions/bash/podman | 192 | ||||
-rw-r--r-- | completions/bash/podman-remote | 192 | ||||
-rw-r--r-- | completions/fish/podman-remote.fish | 114 | ||||
-rw-r--r-- | completions/fish/podman.fish | 114 | ||||
-rw-r--r-- | completions/powershell/podman-remote.ps1 | 30 | ||||
-rw-r--r-- | completions/powershell/podman.ps1 | 30 | ||||
-rw-r--r-- | completions/zsh/_podman | 2 | ||||
-rw-r--r-- | completions/zsh/_podman-remote | 2 | ||||
-rwxr-xr-x | contrib/cirrus/runner.sh | 2 |
10 files changed, 339 insertions, 341 deletions
diff --git a/cmd/podman/completion/completion.go b/cmd/podman/completion/completion.go index da74eefdd..12fba9a54 100644 --- a/cmd/podman/completion/completion.go +++ b/cmd/podman/completion/completion.go @@ -65,7 +65,7 @@ func completion(cmd *cobra.Command, args []string) error { var err error switch args[0] { case "bash": - err = cmd.Root().GenBashCompletion(w) + err = cmd.Root().GenBashCompletionV2(w, !noDesc) case "zsh": if noDesc { err = cmd.Root().GenZshCompletionNoDesc(w) diff --git a/completions/bash/podman b/completions/bash/podman index 17d1e86b7..dcac09db5 100644 --- a/completions/bash/podman +++ b/completions/bash/podman @@ -1,38 +1,29 @@ -# bash completion for podman -*- shell-script -*- +# bash completion V2 for podman -*- shell-script -*- __podman_debug() { - if [[ -n ${BASH_COMP_DEBUG_FILE} ]]; then + if [[ -n ${BASH_COMP_DEBUG_FILE:-} ]]; then echo "$*" >> "${BASH_COMP_DEBUG_FILE}" fi } -__podman_perform_completion() +# Macs have bash3 for which the bash-completion package doesn't include +# _init_completion. This is a minimal version of that function. +__podman_init_completion() { - __podman_debug - __podman_debug "========= starting completion logic ==========" - __podman_debug "cur is ${cur}, words[*] is ${words[*]}, #words[@] is ${#words[@]}, cword is $cword" - - # The user could have moved the cursor backwards on the command-line. - # We need to trigger completion from the $cword location, so we need - # to truncate the command-line ($words) up to the $cword location. - words=("${words[@]:0:$cword+1}") - __podman_debug "Truncated words[*]: ${words[*]}," - - local shellCompDirectiveError=1 - local shellCompDirectiveNoSpace=2 - local shellCompDirectiveNoFileComp=4 - local shellCompDirectiveFilterFileExt=8 - local shellCompDirectiveFilterDirs=16 - local shellCompDirectiveLegacyCustomComp=32 - local shellCompDirectiveLegacyCustomArgsComp=64 + COMPREPLY=() + _get_comp_words_by_ref "$@" cur prev words cword +} - local out requestComp lastParam lastChar comp directive args flagPrefix +# This function calls the podman program to obtain the completion +# results and the directive. It fills the 'out' and 'directive' vars. +__podman_get_completion_results() { + local requestComp lastParam lastChar args # Prepare the command to request completions for the program. # Calling ${words[0]} instead of directly podman allows to handle aliases args=("${words[@]:1}") - requestComp="${words[0]} __completeNoDesc ${args[*]}" + requestComp="${words[0]} __complete ${args[*]}" lastParam=${words[$((${#words[@]}-1))]} lastChar=${lastParam:$((${#lastParam}-1)):1} @@ -42,14 +33,13 @@ __podman_perform_completion() # If the last parameter is complete (there is a space following it) # We add an extra empty parameter so we can indicate this to the go method. __podman_debug "Adding extra empty parameter" - requestComp="${requestComp} \"\"" + requestComp="${requestComp} ''" fi # When completing a flag with an = (e.g., podman -n=<TAB>) # bash focuses on the part after the =, so we need to remove # the flag part from $cur if [[ "${cur}" == -*=* ]]; then - flagPrefix="${cur%%=*}=" cur="${cur#*=}" fi @@ -67,6 +57,14 @@ __podman_perform_completion() fi __podman_debug "The completion directive is: ${directive}" __podman_debug "The completions are: ${out[*]}" +} + +__podman_process_completion_results() { + local shellCompDirectiveError=1 + local shellCompDirectiveNoSpace=2 + local shellCompDirectiveNoFileComp=4 + local shellCompDirectiveFilterFileExt=8 + local shellCompDirectiveFilterDirs=16 if [ $((directive & shellCompDirectiveError)) -ne 0 ]; then # Error code. No completion. @@ -77,12 +75,16 @@ __podman_perform_completion() if [[ $(type -t compopt) = "builtin" ]]; then __podman_debug "Activating no space" compopt -o nospace + else + __podman_debug "No space directive not supported in this version of bash" fi fi if [ $((directive & shellCompDirectiveNoFileComp)) -ne 0 ]; then if [[ $(type -t compopt) = "builtin" ]]; then __podman_debug "Activating no file completion" compopt +o default + else + __podman_debug "No file completion directive not supported in this version of bash" fi fi fi @@ -113,87 +115,56 @@ __podman_perform_completion() __podman_debug "Listing directories in ." _filedir -d fi - elif [ $((directive & shellCompDirectiveLegacyCustomComp)) -ne 0 ]; then - local cmd - __podman_debug "Legacy custom completion. Directive: $directive, cmds: ${out[*]}" - - # The following variables should get their value through the commands - # we have received as completions and are parsing below. - local last_command - local nouns - - # Execute every command received - while IFS='' read -r cmd; do - __podman_debug "About to execute: $cmd" - eval "$cmd" - done < <(printf "%s\n" "${out[@]}") - - __podman_debug "last_command: $last_command" - __podman_debug "nouns[0]: ${nouns[0]}, nouns[1]: ${nouns[1]}" - - if [ $((directive & shellCompDirectiveLegacyCustomArgsComp)) -ne 0 ]; then - # We should call the global legacy custom completion function, if it is defined - if declare -F __podman_custom_func >/dev/null; then - # Use command name qualified legacy custom func - __podman_debug "About to call: __podman_custom_func" - __podman_custom_func - elif declare -F __custom_func >/dev/null; then - # Otherwise fall back to unqualified legacy custom func for compatibility - __podman_debug "About to call: __custom_func" - __custom_func - fi - fi else - local tab - tab=$(printf '\t') - local longest=0 - # Look for the longest completion so that we can format things nicely - while IFS='' read -r comp; do - comp=${comp%%$tab*} - if ((${#comp}>longest)); then - longest=${#comp} - fi - done < <(printf "%s\n" "${out[@]}") - - local completions=() - while IFS='' read -r comp; do - if [ -z "$comp" ]; then - continue - fi - - __podman_debug "Original comp: $comp" - comp="$(__podman_format_comp_descriptions "$comp" "$longest")" - __podman_debug "Final comp: $comp" - completions+=("$comp") - done < <(printf "%s\n" "${out[@]}") - - while IFS='' read -r comp; do - # Although this script should only be used for bash - # there may be programs that still convert the bash - # script into a zsh one. To continue supporting those - # programs, we do this single adaptation for zsh - if [ -n "${ZSH_VERSION}" ]; then - # zsh completion needs --flag= prefix - COMPREPLY+=("$flagPrefix$comp") - else - COMPREPLY+=("$comp") - fi - done < <(compgen -W "${completions[*]}" -- "$cur") - - # If there is a single completion left, remove the description text - if [ ${#COMPREPLY[*]} -eq 1 ]; then - __podman_debug "COMPREPLY[0]: ${COMPREPLY[0]}" - comp="${COMPREPLY[0]%% *}" - __podman_debug "Removed description from single completion, which is now: ${comp}" - COMPREPLY=() - COMPREPLY+=("$comp") - fi + __podman_handle_standard_completion_case fi __podman_handle_special_char "$cur" : __podman_handle_special_char "$cur" = } +__podman_handle_standard_completion_case() { + local tab comp + tab=$(printf '\t') + + local longest=0 + # Look for the longest completion so that we can format things nicely + while IFS='' read -r comp; do + # Strip any description before checking the length + comp=${comp%%$tab*} + # Only consider the completions that match + comp=$(compgen -W "$comp" -- "$cur") + if ((${#comp}>longest)); then + longest=${#comp} + fi + done < <(printf "%s\n" "${out[@]}") + + local completions=() + while IFS='' read -r comp; do + if [ -z "$comp" ]; then + continue + fi + + __podman_debug "Original comp: $comp" + comp="$(__podman_format_comp_descriptions "$comp" "$longest")" + __podman_debug "Final comp: $comp" + completions+=("$comp") + done < <(printf "%s\n" "${out[@]}") + + while IFS='' read -r comp; do + COMPREPLY+=("$comp") + done < <(compgen -W "${completions[*]}" -- "$cur") + + # If there is a single completion left, remove the description text + if [ ${#COMPREPLY[*]} -eq 1 ]; then + __podman_debug "COMPREPLY[0]: ${COMPREPLY[0]}" + comp="${COMPREPLY[0]%% *}" + __podman_debug "Removed description from single completion, which is now: ${comp}" + COMPREPLY=() + COMPREPLY+=("$comp") + fi +} + __podman_handle_special_char() { local comp="$1" @@ -252,12 +223,31 @@ __podman_format_comp_descriptions() __start_podman() { - local cur prev words cword + local cur prev words cword split COMPREPLY=() - _get_comp_words_by_ref -n "=:" cur prev words cword - __podman_perform_completion + # Call _init_completion from the bash-completion package + # to prepare the arguments properly + if declare -F _init_completion >/dev/null 2>&1; then + _init_completion -n "=:" || return + else + __podman_init_completion -n "=:" || return + fi + + __podman_debug + __podman_debug "========= starting completion logic ==========" + __podman_debug "cur is ${cur}, words[*] is ${words[*]}, #words[@] is ${#words[@]}, cword is $cword" + + # The user could have moved the cursor backwards on the command-line. + # We need to trigger completion from the $cword location, so we need + # to truncate the command-line ($words) up to the $cword location. + words=("${words[@]:0:$cword+1}") + __podman_debug "Truncated words[*]: ${words[*]}," + + local out directive + __podman_get_completion_results + __podman_process_completion_results } if [[ $(type -t compopt) = "builtin" ]]; then diff --git a/completions/bash/podman-remote b/completions/bash/podman-remote index 43a5ce959..7bd10abb2 100644 --- a/completions/bash/podman-remote +++ b/completions/bash/podman-remote @@ -1,38 +1,29 @@ -# bash completion for podman-remote -*- shell-script -*- +# bash completion V2 for podman-remote -*- shell-script -*- __podman-remote_debug() { - if [[ -n ${BASH_COMP_DEBUG_FILE} ]]; then + if [[ -n ${BASH_COMP_DEBUG_FILE:-} ]]; then echo "$*" >> "${BASH_COMP_DEBUG_FILE}" fi } -__podman-remote_perform_completion() +# Macs have bash3 for which the bash-completion package doesn't include +# _init_completion. This is a minimal version of that function. +__podman-remote_init_completion() { - __podman-remote_debug - __podman-remote_debug "========= starting completion logic ==========" - __podman-remote_debug "cur is ${cur}, words[*] is ${words[*]}, #words[@] is ${#words[@]}, cword is $cword" - - # The user could have moved the cursor backwards on the command-line. - # We need to trigger completion from the $cword location, so we need - # to truncate the command-line ($words) up to the $cword location. - words=("${words[@]:0:$cword+1}") - __podman-remote_debug "Truncated words[*]: ${words[*]}," - - local shellCompDirectiveError=1 - local shellCompDirectiveNoSpace=2 - local shellCompDirectiveNoFileComp=4 - local shellCompDirectiveFilterFileExt=8 - local shellCompDirectiveFilterDirs=16 - local shellCompDirectiveLegacyCustomComp=32 - local shellCompDirectiveLegacyCustomArgsComp=64 + COMPREPLY=() + _get_comp_words_by_ref "$@" cur prev words cword +} - local out requestComp lastParam lastChar comp directive args flagPrefix +# This function calls the podman-remote program to obtain the completion +# results and the directive. It fills the 'out' and 'directive' vars. +__podman-remote_get_completion_results() { + local requestComp lastParam lastChar args # Prepare the command to request completions for the program. # Calling ${words[0]} instead of directly podman-remote allows to handle aliases args=("${words[@]:1}") - requestComp="${words[0]} __completeNoDesc ${args[*]}" + requestComp="${words[0]} __complete ${args[*]}" lastParam=${words[$((${#words[@]}-1))]} lastChar=${lastParam:$((${#lastParam}-1)):1} @@ -42,14 +33,13 @@ __podman-remote_perform_completion() # If the last parameter is complete (there is a space following it) # We add an extra empty parameter so we can indicate this to the go method. __podman-remote_debug "Adding extra empty parameter" - requestComp="${requestComp} \"\"" + requestComp="${requestComp} ''" fi # When completing a flag with an = (e.g., podman-remote -n=<TAB>) # bash focuses on the part after the =, so we need to remove # the flag part from $cur if [[ "${cur}" == -*=* ]]; then - flagPrefix="${cur%%=*}=" cur="${cur#*=}" fi @@ -67,6 +57,14 @@ __podman-remote_perform_completion() fi __podman-remote_debug "The completion directive is: ${directive}" __podman-remote_debug "The completions are: ${out[*]}" +} + +__podman-remote_process_completion_results() { + local shellCompDirectiveError=1 + local shellCompDirectiveNoSpace=2 + local shellCompDirectiveNoFileComp=4 + local shellCompDirectiveFilterFileExt=8 + local shellCompDirectiveFilterDirs=16 if [ $((directive & shellCompDirectiveError)) -ne 0 ]; then # Error code. No completion. @@ -77,12 +75,16 @@ __podman-remote_perform_completion() if [[ $(type -t compopt) = "builtin" ]]; then __podman-remote_debug "Activating no space" compopt -o nospace + else + __podman-remote_debug "No space directive not supported in this version of bash" fi fi if [ $((directive & shellCompDirectiveNoFileComp)) -ne 0 ]; then if [[ $(type -t compopt) = "builtin" ]]; then __podman-remote_debug "Activating no file completion" compopt +o default + else + __podman-remote_debug "No file completion directive not supported in this version of bash" fi fi fi @@ -113,87 +115,56 @@ __podman-remote_perform_completion() __podman-remote_debug "Listing directories in ." _filedir -d fi - elif [ $((directive & shellCompDirectiveLegacyCustomComp)) -ne 0 ]; then - local cmd - __podman-remote_debug "Legacy custom completion. Directive: $directive, cmds: ${out[*]}" - - # The following variables should get their value through the commands - # we have received as completions and are parsing below. - local last_command - local nouns - - # Execute every command received - while IFS='' read -r cmd; do - __podman-remote_debug "About to execute: $cmd" - eval "$cmd" - done < <(printf "%s\n" "${out[@]}") - - __podman-remote_debug "last_command: $last_command" - __podman-remote_debug "nouns[0]: ${nouns[0]}, nouns[1]: ${nouns[1]}" - - if [ $((directive & shellCompDirectiveLegacyCustomArgsComp)) -ne 0 ]; then - # We should call the global legacy custom completion function, if it is defined - if declare -F __podman-remote_custom_func >/dev/null; then - # Use command name qualified legacy custom func - __podman-remote_debug "About to call: __podman-remote_custom_func" - __podman-remote_custom_func - elif declare -F __custom_func >/dev/null; then - # Otherwise fall back to unqualified legacy custom func for compatibility - __podman-remote_debug "About to call: __custom_func" - __custom_func - fi - fi else - local tab - tab=$(printf '\t') - local longest=0 - # Look for the longest completion so that we can format things nicely - while IFS='' read -r comp; do - comp=${comp%%$tab*} - if ((${#comp}>longest)); then - longest=${#comp} - fi - done < <(printf "%s\n" "${out[@]}") - - local completions=() - while IFS='' read -r comp; do - if [ -z "$comp" ]; then - continue - fi - - __podman-remote_debug "Original comp: $comp" - comp="$(__podman-remote_format_comp_descriptions "$comp" "$longest")" - __podman-remote_debug "Final comp: $comp" - completions+=("$comp") - done < <(printf "%s\n" "${out[@]}") - - while IFS='' read -r comp; do - # Although this script should only be used for bash - # there may be programs that still convert the bash - # script into a zsh one. To continue supporting those - # programs, we do this single adaptation for zsh - if [ -n "${ZSH_VERSION}" ]; then - # zsh completion needs --flag= prefix - COMPREPLY+=("$flagPrefix$comp") - else - COMPREPLY+=("$comp") - fi - done < <(compgen -W "${completions[*]}" -- "$cur") - - # If there is a single completion left, remove the description text - if [ ${#COMPREPLY[*]} -eq 1 ]; then - __podman-remote_debug "COMPREPLY[0]: ${COMPREPLY[0]}" - comp="${COMPREPLY[0]%% *}" - __podman-remote_debug "Removed description from single completion, which is now: ${comp}" - COMPREPLY=() - COMPREPLY+=("$comp") - fi + __podman-remote_handle_standard_completion_case fi __podman-remote_handle_special_char "$cur" : __podman-remote_handle_special_char "$cur" = } +__podman-remote_handle_standard_completion_case() { + local tab comp + tab=$(printf '\t') + + local longest=0 + # Look for the longest completion so that we can format things nicely + while IFS='' read -r comp; do + # Strip any description before checking the length + comp=${comp%%$tab*} + # Only consider the completions that match + comp=$(compgen -W "$comp" -- "$cur") + if ((${#comp}>longest)); then + longest=${#comp} + fi + done < <(printf "%s\n" "${out[@]}") + + local completions=() + while IFS='' read -r comp; do + if [ -z "$comp" ]; then + continue + fi + + __podman-remote_debug "Original comp: $comp" + comp="$(__podman-remote_format_comp_descriptions "$comp" "$longest")" + __podman-remote_debug "Final comp: $comp" + completions+=("$comp") + done < <(printf "%s\n" "${out[@]}") + + while IFS='' read -r comp; do + COMPREPLY+=("$comp") + done < <(compgen -W "${completions[*]}" -- "$cur") + + # If there is a single completion left, remove the description text + if [ ${#COMPREPLY[*]} -eq 1 ]; then + __podman-remote_debug "COMPREPLY[0]: ${COMPREPLY[0]}" + comp="${COMPREPLY[0]%% *}" + __podman-remote_debug "Removed description from single completion, which is now: ${comp}" + COMPREPLY=() + COMPREPLY+=("$comp") + fi +} + __podman-remote_handle_special_char() { local comp="$1" @@ -252,12 +223,31 @@ __podman-remote_format_comp_descriptions() __start_podman-remote() { - local cur prev words cword + local cur prev words cword split COMPREPLY=() - _get_comp_words_by_ref -n "=:" cur prev words cword - __podman-remote_perform_completion + # Call _init_completion from the bash-completion package + # to prepare the arguments properly + if declare -F _init_completion >/dev/null 2>&1; then + _init_completion -n "=:" || return + else + __podman-remote_init_completion -n "=:" || return + fi + + __podman-remote_debug + __podman-remote_debug "========= starting completion logic ==========" + __podman-remote_debug "cur is ${cur}, words[*] is ${words[*]}, #words[@] is ${#words[@]}, cword is $cword" + + # The user could have moved the cursor backwards on the command-line. + # We need to trigger completion from the $cword location, so we need + # to truncate the command-line ($words) up to the $cword location. + words=("${words[@]:0:$cword+1}") + __podman-remote_debug "Truncated words[*]: ${words[*]}," + + local out directive + __podman-remote_get_completion_results + __podman-remote_process_completion_results } if [[ $(type -t compopt) = "builtin" ]]; then diff --git a/completions/fish/podman-remote.fish b/completions/fish/podman-remote.fish index b3a4a173a..bcfacbb00 100644 --- a/completions/fish/podman-remote.fish +++ b/completions/fish/podman-remote.fish @@ -1,7 +1,7 @@ # fish completion for podman-remote -*- shell-script -*- function __podman_remote_debug - set file "$BASH_COMP_DEBUG_FILE" + set -l file "$BASH_COMP_DEBUG_FILE" if test -n "$file" echo "$argv" >> $file end @@ -10,32 +10,38 @@ end function __podman_remote_perform_completion __podman_remote_debug "Starting __podman_remote_perform_completion" - set args (string split -- " " (string trim -l (commandline -c))) - set lastArg "$args[-1]" + # Extract all args except the last one + set -l args (commandline -opc) + # Extract the last arg and escape it in case it is a space + set -l lastArg (string escape -- (commandline -ct)) __podman_remote_debug "args: $args" __podman_remote_debug "last arg: $lastArg" - set emptyArg "" - if test -z "$lastArg" - __podman_remote_debug "Setting emptyArg" - set emptyArg \"\" - end - __podman_remote_debug "emptyArg: $emptyArg" + set -l requestComp "$args[1] __complete $args[2..-1] $lastArg" - set requestComp "$args[1] __complete $args[2..-1] $emptyArg" __podman_remote_debug "Calling $requestComp" + set -l results (eval $requestComp 2> /dev/null) + + # Some programs may output extra empty lines after the directive. + # Let's ignore them or else it will break completion. + # Ref: https://github.com/spf13/cobra/issues/1279 + for line in $results[-1..1] + if test (string trim -- $line) = "" + # Found an empty line, remove it + set results $results[1..-2] + else + # Found non-empty line, we have our proper output + break + end + end - # Call the command as a sub-shell so that we can redirect any errors - # For example, if $requestComp has an unmatched quote - # https://github.com/spf13/cobra/issues/1214 - set results (fish -c "$requestComp" 2> /dev/null) - set comps $results[1..-2] - set directiveLine $results[-1] + set -l comps $results[1..-2] + set -l directiveLine $results[-1] # For Fish, when completing a flag with an = (e.g., <program> -n=<TAB>) # completions must be prefixed with the flag - set flagPrefix (string match -r -- '-.*=' "$lastArg") + set -l flagPrefix (string match -r -- '-.*=' "$lastArg") __podman_remote_debug "Comps: $comps" __podman_remote_debug "DirectiveLine: $directiveLine" @@ -58,7 +64,7 @@ function __podman_remote_prepare_completions # Start fresh set --erase __podman_remote_comp_results - set results (__podman_remote_perform_completion) + set -l results (__podman_remote_perform_completion) __podman_remote_debug "Completion results: $results" if test -z "$results" @@ -67,39 +73,39 @@ function __podman_remote_prepare_completions return 1 end - set directive (string sub --start 2 $results[-1]) + set -l directive (string sub --start 2 $results[-1]) set --global __podman_remote_comp_results $results[1..-2] __podman_remote_debug "Completions are: $__podman_remote_comp_results" __podman_remote_debug "Directive is: $directive" - set shellCompDirectiveError 1 - set shellCompDirectiveNoSpace 2 - set shellCompDirectiveNoFileComp 4 - set shellCompDirectiveFilterFileExt 8 - set shellCompDirectiveFilterDirs 16 + set -l shellCompDirectiveError 1 + set -l shellCompDirectiveNoSpace 2 + set -l shellCompDirectiveNoFileComp 4 + set -l shellCompDirectiveFilterFileExt 8 + set -l shellCompDirectiveFilterDirs 16 if test -z "$directive" set directive 0 end - set compErr (math (math --scale 0 $directive / $shellCompDirectiveError) % 2) + set -l compErr (math (math --scale 0 $directive / $shellCompDirectiveError) % 2) if test $compErr -eq 1 __podman_remote_debug "Received error directive: aborting." # Might as well do file completion, in case it helps return 1 end - set filefilter (math (math --scale 0 $directive / $shellCompDirectiveFilterFileExt) % 2) - set dirfilter (math (math --scale 0 $directive / $shellCompDirectiveFilterDirs) % 2) + set -l filefilter (math (math --scale 0 $directive / $shellCompDirectiveFilterFileExt) % 2) + set -l dirfilter (math (math --scale 0 $directive / $shellCompDirectiveFilterDirs) % 2) if test $filefilter -eq 1; or test $dirfilter -eq 1 __podman_remote_debug "File extension filtering or directory filtering not supported" # Do full file completion instead return 1 end - set nospace (math (math --scale 0 $directive / $shellCompDirectiveNoSpace) % 2) - set nofiles (math (math --scale 0 $directive / $shellCompDirectiveNoFileComp) % 2) + set -l nospace (math (math --scale 0 $directive / $shellCompDirectiveNoSpace) % 2) + set -l nofiles (math (math --scale 0 $directive / $shellCompDirectiveNoFileComp) % 2) __podman_remote_debug "nospace: $nospace, nofiles: $nofiles" @@ -109,34 +115,34 @@ function __podman_remote_prepare_completions # may not already be filtered so as to allow fish to match on different # criteria than the prefix. if test $nospace -ne 0; or test $nofiles -eq 0 - set prefix (commandline -t) + set -l prefix (commandline -t | string escape --style=regex) __podman_remote_debug "prefix: $prefix" - set completions - for comp in $__podman_remote_comp_results - if test (string match -e -r -- "^$prefix" "$comp") - set -a completions $comp - end - end + set -l completions (string match -r -- "^$prefix.*" $__podman_remote_comp_results) set --global __podman_remote_comp_results $completions __podman_remote_debug "Filtered completions are: $__podman_remote_comp_results" # Important not to quote the variable for count to work - set numComps (count $__podman_remote_comp_results) + set -l numComps (count $__podman_remote_comp_results) __podman_remote_debug "numComps: $numComps" if test $numComps -eq 1; and test $nospace -ne 0 - # To support the "nospace" directive we trick the shell - # by outputting an extra, longer completion. - # We must first split on \t to get rid of the descriptions because - # the extra character we add to the fake second completion must be - # before the description. We don't need descriptions anyway since - # there is only a single real completion which the shell will expand - # immediately. - __podman_remote_debug "Adding second completion to perform nospace directive" - set split (string split --max 1 \t $__podman_remote_comp_results[1]) - set --global __podman_remote_comp_results $split[1] $split[1]. - __podman_remote_debug "Completions are now: $__podman_remote_comp_results" + # We must first split on \t to get rid of the descriptions to be + # able to check what the actual completion will be. + # We don't need descriptions anyway since there is only a single + # real completion which the shell will expand immediately. + set -l split (string split --max 1 \t $__podman_remote_comp_results[1]) + + # Fish won't add a space if the completion ends with any + # of the following characters: @=/:., + set -l lastChar (string sub -s -1 -- $split) + if not string match -r -q "[@=/:.,]" -- "$lastChar" + # In other cases, to support the "nospace" directive we trick the shell + # by outputting an extra, longer completion. + __podman_remote_debug "Adding second completion to perform nospace directive" + set --global __podman_remote_comp_results $split[1] $split[1]. + __podman_remote_debug "Completions are now: $__podman_remote_comp_results" + end end if test $numComps -eq 0; and test $nofiles -eq 0 @@ -152,10 +158,14 @@ end # Since Fish completions are only loaded once the user triggers them, we trigger them ourselves # so we can properly delete any completions provided by another script. -# The space after the program name is essential to trigger completion for the program -# and not completion of the program name itself. -complete --do-complete "podman-remote " > /dev/null 2>&1 -# Using '> /dev/null 2>&1' since '&>' is not supported in older versions of fish. +# Only do this if the program can be found, or else fish may print some errors; besides, +# the existing completions will only be loaded if the program can be found. +if type -q "podman-remote" + # The space after the program name is essential to trigger completion for the program + # and not completion of the program name itself. + # Also, we use '> /dev/null 2>&1' since '&>' is not supported in older versions of fish. + complete --do-complete "podman-remote " > /dev/null 2>&1 +end # Remove any pre-existing completions for the program since we will be handling all of them. complete -c podman-remote -e diff --git a/completions/fish/podman.fish b/completions/fish/podman.fish index 05dd2d72b..6394535a9 100644 --- a/completions/fish/podman.fish +++ b/completions/fish/podman.fish @@ -1,7 +1,7 @@ # fish completion for podman -*- shell-script -*- function __podman_debug - set file "$BASH_COMP_DEBUG_FILE" + set -l file "$BASH_COMP_DEBUG_FILE" if test -n "$file" echo "$argv" >> $file end @@ -10,32 +10,38 @@ end function __podman_perform_completion __podman_debug "Starting __podman_perform_completion" - set args (string split -- " " (string trim -l (commandline -c))) - set lastArg "$args[-1]" + # Extract all args except the last one + set -l args (commandline -opc) + # Extract the last arg and escape it in case it is a space + set -l lastArg (string escape -- (commandline -ct)) __podman_debug "args: $args" __podman_debug "last arg: $lastArg" - set emptyArg "" - if test -z "$lastArg" - __podman_debug "Setting emptyArg" - set emptyArg \"\" - end - __podman_debug "emptyArg: $emptyArg" + set -l requestComp "$args[1] __complete $args[2..-1] $lastArg" - set requestComp "$args[1] __complete $args[2..-1] $emptyArg" __podman_debug "Calling $requestComp" + set -l results (eval $requestComp 2> /dev/null) + + # Some programs may output extra empty lines after the directive. + # Let's ignore them or else it will break completion. + # Ref: https://github.com/spf13/cobra/issues/1279 + for line in $results[-1..1] + if test (string trim -- $line) = "" + # Found an empty line, remove it + set results $results[1..-2] + else + # Found non-empty line, we have our proper output + break + end + end - # Call the command as a sub-shell so that we can redirect any errors - # For example, if $requestComp has an unmatched quote - # https://github.com/spf13/cobra/issues/1214 - set results (fish -c "$requestComp" 2> /dev/null) - set comps $results[1..-2] - set directiveLine $results[-1] + set -l comps $results[1..-2] + set -l directiveLine $results[-1] # For Fish, when completing a flag with an = (e.g., <program> -n=<TAB>) # completions must be prefixed with the flag - set flagPrefix (string match -r -- '-.*=' "$lastArg") + set -l flagPrefix (string match -r -- '-.*=' "$lastArg") __podman_debug "Comps: $comps" __podman_debug "DirectiveLine: $directiveLine" @@ -58,7 +64,7 @@ function __podman_prepare_completions # Start fresh set --erase __podman_comp_results - set results (__podman_perform_completion) + set -l results (__podman_perform_completion) __podman_debug "Completion results: $results" if test -z "$results" @@ -67,39 +73,39 @@ function __podman_prepare_completions return 1 end - set directive (string sub --start 2 $results[-1]) + set -l directive (string sub --start 2 $results[-1]) set --global __podman_comp_results $results[1..-2] __podman_debug "Completions are: $__podman_comp_results" __podman_debug "Directive is: $directive" - set shellCompDirectiveError 1 - set shellCompDirectiveNoSpace 2 - set shellCompDirectiveNoFileComp 4 - set shellCompDirectiveFilterFileExt 8 - set shellCompDirectiveFilterDirs 16 + set -l shellCompDirectiveError 1 + set -l shellCompDirectiveNoSpace 2 + set -l shellCompDirectiveNoFileComp 4 + set -l shellCompDirectiveFilterFileExt 8 + set -l shellCompDirectiveFilterDirs 16 if test -z "$directive" set directive 0 end - set compErr (math (math --scale 0 $directive / $shellCompDirectiveError) % 2) + set -l compErr (math (math --scale 0 $directive / $shellCompDirectiveError) % 2) if test $compErr -eq 1 __podman_debug "Received error directive: aborting." # Might as well do file completion, in case it helps return 1 end - set filefilter (math (math --scale 0 $directive / $shellCompDirectiveFilterFileExt) % 2) - set dirfilter (math (math --scale 0 $directive / $shellCompDirectiveFilterDirs) % 2) + set -l filefilter (math (math --scale 0 $directive / $shellCompDirectiveFilterFileExt) % 2) + set -l dirfilter (math (math --scale 0 $directive / $shellCompDirectiveFilterDirs) % 2) if test $filefilter -eq 1; or test $dirfilter -eq 1 __podman_debug "File extension filtering or directory filtering not supported" # Do full file completion instead return 1 end - set nospace (math (math --scale 0 $directive / $shellCompDirectiveNoSpace) % 2) - set nofiles (math (math --scale 0 $directive / $shellCompDirectiveNoFileComp) % 2) + set -l nospace (math (math --scale 0 $directive / $shellCompDirectiveNoSpace) % 2) + set -l nofiles (math (math --scale 0 $directive / $shellCompDirectiveNoFileComp) % 2) __podman_debug "nospace: $nospace, nofiles: $nofiles" @@ -109,34 +115,34 @@ function __podman_prepare_completions # may not already be filtered so as to allow fish to match on different # criteria than the prefix. if test $nospace -ne 0; or test $nofiles -eq 0 - set prefix (commandline -t) + set -l prefix (commandline -t | string escape --style=regex) __podman_debug "prefix: $prefix" - set completions - for comp in $__podman_comp_results - if test (string match -e -r -- "^$prefix" "$comp") - set -a completions $comp - end - end + set -l completions (string match -r -- "^$prefix.*" $__podman_comp_results) set --global __podman_comp_results $completions __podman_debug "Filtered completions are: $__podman_comp_results" # Important not to quote the variable for count to work - set numComps (count $__podman_comp_results) + set -l numComps (count $__podman_comp_results) __podman_debug "numComps: $numComps" if test $numComps -eq 1; and test $nospace -ne 0 - # To support the "nospace" directive we trick the shell - # by outputting an extra, longer completion. - # We must first split on \t to get rid of the descriptions because - # the extra character we add to the fake second completion must be - # before the description. We don't need descriptions anyway since - # there is only a single real completion which the shell will expand - # immediately. - __podman_debug "Adding second completion to perform nospace directive" - set split (string split --max 1 \t $__podman_comp_results[1]) - set --global __podman_comp_results $split[1] $split[1]. - __podman_debug "Completions are now: $__podman_comp_results" + # We must first split on \t to get rid of the descriptions to be + # able to check what the actual completion will be. + # We don't need descriptions anyway since there is only a single + # real completion which the shell will expand immediately. + set -l split (string split --max 1 \t $__podman_comp_results[1]) + + # Fish won't add a space if the completion ends with any + # of the following characters: @=/:., + set -l lastChar (string sub -s -1 -- $split) + if not string match -r -q "[@=/:.,]" -- "$lastChar" + # In other cases, to support the "nospace" directive we trick the shell + # by outputting an extra, longer completion. + __podman_debug "Adding second completion to perform nospace directive" + set --global __podman_comp_results $split[1] $split[1]. + __podman_debug "Completions are now: $__podman_comp_results" + end end if test $numComps -eq 0; and test $nofiles -eq 0 @@ -152,10 +158,14 @@ end # Since Fish completions are only loaded once the user triggers them, we trigger them ourselves # so we can properly delete any completions provided by another script. -# The space after the program name is essential to trigger completion for the program -# and not completion of the program name itself. -complete --do-complete "podman " > /dev/null 2>&1 -# Using '> /dev/null 2>&1' since '&>' is not supported in older versions of fish. +# Only do this if the program can be found, or else fish may print some errors; besides, +# the existing completions will only be loaded if the program can be found. +if type -q "podman" + # The space after the program name is essential to trigger completion for the program + # and not completion of the program name itself. + # Also, we use '> /dev/null 2>&1' since '&>' is not supported in older versions of fish. + complete --do-complete "podman " > /dev/null 2>&1 +end # Remove any pre-existing completions for the program since we will be handling all of them. complete -c podman -e diff --git a/completions/powershell/podman-remote.ps1 b/completions/powershell/podman-remote.ps1 index 875684b34..e065d0426 100644 --- a/completions/powershell/podman-remote.ps1 +++ b/completions/powershell/podman-remote.ps1 @@ -123,19 +123,6 @@ Register-ArgumentCompleter -CommandName 'podman-remote' -ScriptBlock { $Space = "" } - if (($Directive -band $ShellCompDirectiveNoFileComp) -ne 0 ) { - __podman-remote_debug "ShellCompDirectiveNoFileComp is called" - - if ($Values.Length -eq 0) { - # Just print an empty string here so the - # shell does not start to complete paths. - # We cannot use CompletionResult here because - # it does not accept an empty string as argument. - "" - return - } - } - if ((($Directive -band $ShellCompDirectiveFilterFileExt) -ne 0 ) -or (($Directive -band $ShellCompDirectiveFilterDirs) -ne 0 )) { __podman-remote_debug "ShellCompDirectiveFilterFileExt ShellCompDirectiveFilterDirs are not supported" @@ -148,13 +135,26 @@ Register-ArgumentCompleter -CommandName 'podman-remote' -ScriptBlock { # filter the result $_.Name -like "$WordToComplete*" - # Join the flag back if we have a equal sign flag + # Join the flag back if we have an equal sign flag if ( $IsEqualFlag ) { __podman-remote_debug "Join the equal sign flag back to the completion value" $_.Name = $Flag + "=" + $_.Name } } + if (($Directive -band $ShellCompDirectiveNoFileComp) -ne 0 ) { + __podman-remote_debug "ShellCompDirectiveNoFileComp is called" + + if ($Values.Length -eq 0) { + # Just print an empty string here so the + # shell does not start to complete paths. + # We cannot use CompletionResult here because + # it does not accept an empty string as argument. + "" + return + } + } + # Get the current mode $Mode = (Get-PSReadLineKeyHandler | Where-Object {$_.Key -eq "Tab" }).Function __podman-remote_debug "Mode: $Mode" @@ -216,7 +216,7 @@ Register-ArgumentCompleter -CommandName 'podman-remote' -ScriptBlock { Default { # Like MenuComplete but we don't want to add a space here because # the user need to press space anyway to get the completion. - # Description will not be shown because that's not possible with TabCompleteNext + # Description will not be shown because thats not possible with TabCompleteNext [System.Management.Automation.CompletionResult]::new($($comp.Name | __podman-remote_escapeStringWithSpecialChars), "$($comp.Name)", 'ParameterValue', "$($comp.Description)") } } diff --git a/completions/powershell/podman.ps1 b/completions/powershell/podman.ps1 index 619c5beea..fa856eee4 100644 --- a/completions/powershell/podman.ps1 +++ b/completions/powershell/podman.ps1 @@ -123,19 +123,6 @@ Register-ArgumentCompleter -CommandName 'podman' -ScriptBlock { $Space = "" } - if (($Directive -band $ShellCompDirectiveNoFileComp) -ne 0 ) { - __podman_debug "ShellCompDirectiveNoFileComp is called" - - if ($Values.Length -eq 0) { - # Just print an empty string here so the - # shell does not start to complete paths. - # We cannot use CompletionResult here because - # it does not accept an empty string as argument. - "" - return - } - } - if ((($Directive -band $ShellCompDirectiveFilterFileExt) -ne 0 ) -or (($Directive -band $ShellCompDirectiveFilterDirs) -ne 0 )) { __podman_debug "ShellCompDirectiveFilterFileExt ShellCompDirectiveFilterDirs are not supported" @@ -148,13 +135,26 @@ Register-ArgumentCompleter -CommandName 'podman' -ScriptBlock { # filter the result $_.Name -like "$WordToComplete*" - # Join the flag back if we have a equal sign flag + # Join the flag back if we have an equal sign flag if ( $IsEqualFlag ) { __podman_debug "Join the equal sign flag back to the completion value" $_.Name = $Flag + "=" + $_.Name } } + if (($Directive -band $ShellCompDirectiveNoFileComp) -ne 0 ) { + __podman_debug "ShellCompDirectiveNoFileComp is called" + + if ($Values.Length -eq 0) { + # Just print an empty string here so the + # shell does not start to complete paths. + # We cannot use CompletionResult here because + # it does not accept an empty string as argument. + "" + return + } + } + # Get the current mode $Mode = (Get-PSReadLineKeyHandler | Where-Object {$_.Key -eq "Tab" }).Function __podman_debug "Mode: $Mode" @@ -216,7 +216,7 @@ Register-ArgumentCompleter -CommandName 'podman' -ScriptBlock { Default { # Like MenuComplete but we don't want to add a space here because # the user need to press space anyway to get the completion. - # Description will not be shown because that's not possible with TabCompleteNext + # Description will not be shown because thats not possible with TabCompleteNext [System.Management.Automation.CompletionResult]::new($($comp.Name | __podman_escapeStringWithSpecialChars), "$($comp.Name)", 'ParameterValue', "$($comp.Description)") } } diff --git a/completions/zsh/_podman b/completions/zsh/_podman index b25e9cb08..9bad56d9a 100644 --- a/completions/zsh/_podman +++ b/completions/zsh/_podman @@ -17,8 +17,6 @@ _podman() local shellCompDirectiveNoFileComp=4 local shellCompDirectiveFilterFileExt=8 local shellCompDirectiveFilterDirs=16 - local shellCompDirectiveLegacyCustomComp=32 - local shellCompDirectiveLegacyCustomArgsComp=64 local lastParam lastChar flagPrefix requestComp out directive comp lastComp noSpace local -a completions diff --git a/completions/zsh/_podman-remote b/completions/zsh/_podman-remote index fc2984cfd..5132d0e53 100644 --- a/completions/zsh/_podman-remote +++ b/completions/zsh/_podman-remote @@ -17,8 +17,6 @@ _podman-remote() local shellCompDirectiveNoFileComp=4 local shellCompDirectiveFilterFileExt=8 local shellCompDirectiveFilterDirs=16 - local shellCompDirectiveLegacyCustomComp=32 - local shellCompDirectiveLegacyCustomArgsComp=64 local lastParam lastChar flagPrefix requestComp out directive comp lastComp noSpace local -a completions diff --git a/contrib/cirrus/runner.sh b/contrib/cirrus/runner.sh index c46258cd6..cac679466 100755 --- a/contrib/cirrus/runner.sh +++ b/contrib/cirrus/runner.sh @@ -196,6 +196,8 @@ function _run_consistency() { SUGGESTION="run 'make vendor' and commit all changes" ./hack/tree_status.sh make generate-bindings SUGGESTION="run 'make generate-bindings' and commit all changes" ./hack/tree_status.sh + make completions + SUGGESTION="run 'make completions' and commit all changes" ./hack/tree_status.sh } function _run_build() { |