Bash completion script doesn't work for `flyctl` cmd anymore since v0.2.42
Describe the bug
I regularly update flyctl directly from GitHub releases via gh install superfly/flyctl and use the binary's default name flyctl (not fly).
Afterwards, I update the bash completion script via:
flyctl completion bash > ~/.local/share/bash-completion/completions/flyctl
I recently noticed that the bash completion stopped working and traced it back to flyctl v0.2.42, i.e. it stopped working from this version onwards. With flyctl v0.2.41, the completion works fine.
A quick diff reveals why – all the occurences of flyctl are now replaced with fly:
diff
--- /home/salim/Downloads/flyctl_completion_v0.2.41.bash 2024-05-03 13:25:56.738393399 +0200
+++ /home/salim/Downloads/flyctl_completion_v0.2.42.bash 2024-05-03 13:25:23.850232625 +0200
@@ -1,6 +1,6 @@
-# bash completion V2 for flyctl -*- shell-script -*-
+# bash completion V2 for fly -*- shell-script -*-
-__flyctl_debug()
+__fly_debug()
{
if [[ -n ${BASH_COMP_DEBUG_FILE-} ]]; then
echo "$*" >> "${BASH_COMP_DEBUG_FILE}"
@@ -9,41 +9,41 @@
# Macs have bash3 for which the bash-completion package doesn't include
# _init_completion. This is a minimal version of that function.
-__flyctl_init_completion()
+__fly_init_completion()
{
COMPREPLY=()
_get_comp_words_by_ref "$@" cur prev words cword
}
-# This function calls the flyctl program to obtain the completion
+# This function calls the fly program to obtain the completion
# results and the directive. It fills the 'out' and 'directive' vars.
-__flyctl_get_completion_results() {
+__fly_get_completion_results() {
local requestComp lastParam lastChar args
# Prepare the command to request completions for the program.
- # Calling ${words[0]} instead of directly flyctl allows handling aliases
+ # Calling ${words[0]} instead of directly fly allows handling aliases
args=("${words[@]:1}")
requestComp="${words[0]} __complete ${args[*]}"
lastParam=${words[$((${#words[@]}-1))]}
lastChar=${lastParam:$((${#lastParam}-1)):1}
- __flyctl_debug "lastParam ${lastParam}, lastChar ${lastChar}"
+ __fly_debug "lastParam ${lastParam}, lastChar ${lastChar}"
if [[ -z ${cur} && ${lastChar} != = ]]; then
# 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.
- __flyctl_debug "Adding extra empty parameter"
+ __fly_debug "Adding extra empty parameter"
requestComp="${requestComp} ''"
fi
- # When completing a flag with an = (e.g., flyctl -n=<TAB>)
+ # When completing a flag with an = (e.g., fly -n=<TAB>)
# bash focuses on the part after the =, so we need to remove
# the flag part from $cur
if [[ ${cur} == -*=* ]]; then
cur="${cur#*=}"
fi
- __flyctl_debug "Calling ${requestComp}"
+ __fly_debug "Calling ${requestComp}"
# Use eval to handle any environment variables and such
out=$(eval "${requestComp}" 2>/dev/null)
@@ -55,11 +55,11 @@
# There is not directive specified
directive=0
fi
- __flyctl_debug "The completion directive is: ${directive}"
- __flyctl_debug "The completions are: ${out}"
+ __fly_debug "The completion directive is: ${directive}"
+ __fly_debug "The completions are: ${out}"
}
-__flyctl_process_completion_results() {
+__fly_process_completion_results() {
local shellCompDirectiveError=1
local shellCompDirectiveNoSpace=2
local shellCompDirectiveNoFileComp=4
@@ -69,36 +69,36 @@
if (((directive & shellCompDirectiveError) != 0)); then
# Error code. No completion.
- __flyctl_debug "Received error from custom completion go code"
+ __fly_debug "Received error from custom completion go code"
return
else
if (((directive & shellCompDirectiveNoSpace) != 0)); then
if [[ $(type -t compopt) == builtin ]]; then
- __flyctl_debug "Activating no space"
+ __fly_debug "Activating no space"
compopt -o nospace
else
- __flyctl_debug "No space directive not supported in this version of bash"
+ __fly_debug "No space directive not supported in this version of bash"
fi
fi
if (((directive & shellCompDirectiveKeepOrder) != 0)); then
if [[ $(type -t compopt) == builtin ]]; then
# no sort isn't supported for bash less than < 4.4
if [[ ${BASH_VERSINFO[0]} -lt 4 || ( ${BASH_VERSINFO[0]} -eq 4 && ${BASH_VERSINFO[1]} -lt 4 ) ]]; then
- __flyctl_debug "No sort directive not supported in this version of bash"
+ __fly_debug "No sort directive not supported in this version of bash"
else
- __flyctl_debug "Activating keep order"
+ __fly_debug "Activating keep order"
compopt -o nosort
fi
else
- __flyctl_debug "No sort directive not supported in this version of bash"
+ __fly_debug "No sort directive not supported in this version of bash"
fi
fi
if (((directive & shellCompDirectiveNoFileComp) != 0)); then
if [[ $(type -t compopt) == builtin ]]; then
- __flyctl_debug "Activating no file completion"
+ __fly_debug "Activating no file completion"
compopt +o default
else
- __flyctl_debug "No file completion directive not supported in this version of bash"
+ __fly_debug "No file completion directive not supported in this version of bash"
fi
fi
fi
@@ -106,7 +106,7 @@
# Separate activeHelp from normal completions
local completions=()
local activeHelp=()
- __flyctl_extract_activeHelp
+ __fly_extract_activeHelp
if (((directive & shellCompDirectiveFilterFileExt) != 0)); then
# File extension filtering
@@ -119,7 +119,7 @@
done
filteringCmd="_filedir $fullFilter"
- __flyctl_debug "File filtering command: $filteringCmd"
+ __fly_debug "File filtering command: $filteringCmd"
$filteringCmd
elif (((directive & shellCompDirectiveFilterDirs) != 0)); then
# File completion for directories only
@@ -127,18 +127,18 @@
local subdir
subdir=${completions[0]}
if [[ -n $subdir ]]; then
- __flyctl_debug "Listing directories in $subdir"
+ __fly_debug "Listing directories in $subdir"
pushd "$subdir" >/dev/null 2>&1 && _filedir -d && popd >/dev/null 2>&1 || return
else
- __flyctl_debug "Listing directories in ."
+ __fly_debug "Listing directories in ."
_filedir -d
fi
else
- __flyctl_handle_completion_types
+ __fly_handle_completion_types
fi
- __flyctl_handle_special_char "$cur" :
- __flyctl_handle_special_char "$cur" =
+ __fly_handle_special_char "$cur" :
+ __fly_handle_special_char "$cur" =
# Print the activeHelp statements before we finish
if ((${#activeHelp[*]} != 0)); then
@@ -160,14 +160,14 @@
# Separate activeHelp lines from real completions.
# Fills the $activeHelp and $completions arrays.
-__flyctl_extract_activeHelp() {
+__fly_extract_activeHelp() {
local activeHelpMarker="_activeHelp_ "
local endIndex=${#activeHelpMarker}
while IFS='' read -r comp; do
if [[ ${comp:0:endIndex} == $activeHelpMarker ]]; then
comp=${comp:endIndex}
- __flyctl_debug "ActiveHelp found: $comp"
+ __fly_debug "ActiveHelp found: $comp"
if [[ -n $comp ]]; then
activeHelp+=("$comp")
fi
@@ -178,8 +178,8 @@
done <<<"${out}"
}
-__flyctl_handle_completion_types() {
- __flyctl_debug "__flyctl_handle_completion_types: COMP_TYPE is $COMP_TYPE"
+__fly_handle_completion_types() {
+ __fly_debug "__fly_handle_completion_types: COMP_TYPE is $COMP_TYPE"
case $COMP_TYPE in
37|42)
@@ -201,12 +201,12 @@
*)
# Type: complete (normal completion)
- __flyctl_handle_standard_completion_case
+ __fly_handle_standard_completion_case
;;
esac
}
-__flyctl_handle_standard_completion_case() {
+__fly_handle_standard_completion_case() {
local tab=$'\t' comp
# Short circuit to optimize if we don't have descriptions
@@ -232,16 +232,16 @@
# If there is a single completion left, remove the description text
if ((${#COMPREPLY[*]} == 1)); then
- __flyctl_debug "COMPREPLY[0]: ${COMPREPLY[0]}"
+ __fly_debug "COMPREPLY[0]: ${COMPREPLY[0]}"
comp="${COMPREPLY[0]%%$tab*}"
- __flyctl_debug "Removed description from single completion, which is now: ${comp}"
+ __fly_debug "Removed description from single completion, which is now: ${comp}"
COMPREPLY[0]=$comp
else # Format the descriptions
- __flyctl_format_comp_descriptions $longest
+ __fly_format_comp_descriptions $longest
fi
}
-__flyctl_handle_special_char()
+__fly_handle_special_char()
{
local comp="$1"
local char=$2
@@ -254,7 +254,7 @@
fi
}
-__flyctl_format_comp_descriptions()
+__fly_format_comp_descriptions()
{
local tab=$'\t'
local comp desc maxdesclength
@@ -265,7 +265,7 @@
comp=${COMPREPLY[ci]}
# Properly format the description string which follows a tab character if there is one
if [[ "$comp" == *$tab* ]]; then
- __flyctl_debug "Original comp: $comp"
+ __fly_debug "Original comp: $comp"
desc=${comp#*$tab}
comp=${comp%%$tab*}
@@ -295,12 +295,12 @@
comp+=" ($desc)"
fi
COMPREPLY[ci]=$comp
- __flyctl_debug "Final comp: $comp"
+ __fly_debug "Final comp: $comp"
fi
done
}
-__start_flyctl()
+__start_fly()
{
local cur prev words cword split
@@ -311,28 +311,28 @@
if declare -F _init_completion >/dev/null 2>&1; then
_init_completion -n =: || return
else
- __flyctl_init_completion -n =: || return
+ __fly_init_completion -n =: || return
fi
- __flyctl_debug
- __flyctl_debug "========= starting completion logic =========="
- __flyctl_debug "cur is ${cur}, words[*] is ${words[*]}, #words[@] is ${#words[@]}, cword is $cword"
+ __fly_debug
+ __fly_debug "========= starting completion logic =========="
+ __fly_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}")
- __flyctl_debug "Truncated words[*]: ${words[*]},"
+ __fly_debug "Truncated words[*]: ${words[*]},"
local out directive
- __flyctl_get_completion_results
- __flyctl_process_completion_results
+ __fly_get_completion_results
+ __fly_process_completion_results
}
if [[ $(type -t compopt) = "builtin" ]]; then
- complete -o default -F __start_flyctl flyctl
+ complete -o default -F __start_fly fly
else
- complete -o default -o nospace -F __start_flyctl flyctl
+ complete -o default -o nospace -F __start_fly fly
fi
# ex: ts=4 sw=4 et filetype=sh
System details
- OS: Ubuntu 22.04
fly version: v0.2.42+
Related
- https://github.com/superfly/flyctl/issues/1845 (maybe)
@salim-b It looks like the flag parsing library we use, cobra, is what generates out the completions automatically. Does the autocompletion work if you use fly instead of flyctl?
@benbjohnson Yes, it works if I name the binary fly (and do fly completion bash > ~/.local/share/bash-completion/completions/fly) since the completion bash subcommand now (i.e. since v0.2.42) always generates a completion script for fly, regardless of the actual binary name, see the diff above.
Before v0.2.42, the completion bash subcommand always generated a completion script for flyctl (again, regardless of the actual binary name).
Would be nice if the completion subcommands could take the exec's actual name into account.