Skip to content
6 changes: 3 additions & 3 deletions completions/_adb
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@

_comp_cmd_adb__command_usage()
{
COMPREPLY=($(compgen -W \
'$("$1" help 2>&1 | command grep "^ *\(adb \)\? *$2 " \
| command sed -e "s/[]|[]/\n/g" | _parse_help -)' -- "$cur"))
COMPREPLY=($(compgen -W '$("$1" help 2>&1 | \
command sed -e "/^ *\(adb \)\{0,1\} *$2 /!d;s/[]|[]/\n/g" | \
_parse_help -)' -- "$cur"))
}

_comp_cmd_adb()
Expand Down
4 changes: 2 additions & 2 deletions completions/_udevadm
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ _comp_cmd_udevadm()
local cur prev words cword was_split comp_args
_comp_initialize -s -- "$@" || return

local i udevcmd has_udevcmd=""
local i udevcmd="" has_udevcmd=""
for ((i = 1; i < cword; i++)); do
if [[ ${words[i]} != -* ]]; then
udevcmd=${words[i]}
Expand Down Expand Up @@ -69,7 +69,7 @@ _comp_cmd_udevadm()

if [[ $cur == -* ]]; then
COMPREPLY=($(compgen -W \
'$("$1" ${udevcmd-} --help 2>/dev/null | _parse_help -)' -- "$cur"))
'$(_parse_help "$1" "${udevcmd-} --help")' -- "$cur"))
[[ ${COMPREPLY-} == *= ]] && compopt -o nospace
fi
} &&
Expand Down
2 changes: 1 addition & 1 deletion completions/badblocks
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ _comp_cmd_badblocks()

if [[ $cur == -* ]]; then
# Filter out -w (dangerous) and -X (internal use)
COMPREPLY=($(compgen -X -[wX] -W '$(_parse_usage "$1")' -- "$cur"))
COMPREPLY=($(compgen -X '-[wX]' -W '$(_parse_usage "$1")' -- "$cur"))
return
fi

Expand Down
2 changes: 1 addition & 1 deletion completions/complete
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ _comp_cmd_complete()
local -a opts=($(compgen -W '$(_parse_usage help "-s $1")' -- "$cur"))
# -F, -C do not work the expected way with compgen
[[ $1 != *compgen ]] || opts=("${opts[@]//-[FC]/}")
COMPREPLY=($(compgen -W '"${opts[@]}"' -- "$cur"))
COMPREPLY=($(compgen -W '"${opts[@]}"' -X '' -- "$cur"))
else
COMPREPLY=($(compgen -A command -- "$cur"))
fi
Expand Down
14 changes: 9 additions & 5 deletions completions/gnokii
Original file line number Diff line number Diff line change
Expand Up @@ -221,14 +221,18 @@ _comp_cmd_gnokii()
esac
fi

# safer to use LANG=C
local all_cmd="$(LANG=C _parse_help "$1" "--help all")"
# these 2 below are allowed in combination with others
local main_cmd=$(command grep -v -- '--config\|--phone' <<<"$all_cmd")
local all_cmd="$(_parse_help "$1" "--help all")"

# these 2 below are allowed in combination with others
local main_cmd
_comp_split -l main_cmd "$(command sed -e '/--config/d;/--phone/d' -e \
's/[][\(){}|^$*+?.]/\\&/g' <<<"$all_cmd")"
# don't provide main command completions if one is
# already on the command line
[[ $COMP_LINE =~ $(tr ' ' '\b|' <<<"$main_cmd") ]] && return
local IFS='|'
local regex_main_cmd="(${main_cmd[*]})($|[^_[:alnum:]])"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this could end up as an invalid regex if _parse_help lets any strings through to main_cmd that make it so. The previous implementation had the same issue though, so not a regression. Leaving up to you to decide whether to address or merge as is.

Some array utilities would be nice to help with cases like this. I have this ages old unfinished patch for the main bash_completion in my stash, probably broken in the first place and uses namerefs so requires bash >= 4.3, but to illustrate what I was thinking back $then

+_bashcomp_uniq()
+{
+    local -n _bashcomp_uniq_array_=$1
+    local -A tmp
+    local -i i
+    for i in ${!_bashcomp_uniq_array_[*]}; do
+        (( tmp["${_bashcomp_uniq_array_[i]}"]++ > 0 )) &&
+            unset '_bashcomp_uniq_array_[i]'
+    done
+}
+
+_bashcomp_last_index() {
+    local -n _bashcomp_last_index_array_=$1 _bashcomp_last_index_ret_=$2
+    local -i i
+    for i in ${!_bashcomp_last_index_array_[*]}; do :; done
+    _bashcomp_last_index_ret_=$i
+}
+
+_bashcomp_compact() {
+    local -n _bashcomp_compact_array_=$1
+    local i j=0
+
+    for i in ${!_bashcomp_compact_array_[*]}; do
+        if (( i > j )); then
+            _bashcomp_compact_array_[j]="${_bashcomp_compact_array_[i]}"
+            unset "_bashcomp_compact_array_[i]"
+        fi
+        (( j++ ))
+    done
+}
+
+_bashcomp_index_of() {
+    # TODO getopts -> -r gets rightmost (last) index
+    # TODO getopts: -R uses regex instead of glob
+    local -n _bashcomp_index_of_array_=$1
+    local pattern=$2
+    local -n _bashcomp_index_of_ret_=$3
+
+    local -i i
+    for i in ${!_bashcomp_index_of_array_[*]}; do
+        # shellcheck disable=SC2053
+        if [[ ${_bashcomp_index_of_array_[i]} == $pattern ]]; then
+            _bashcomp_index_of_ret_=$i
+            return 0
+        fi
+    done
+
+    _bashcomp_index_of_ret_=-1
+    return 1
+}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this could end up as an invalid regex if _parse_help lets any strings through to main_cmd that make it so. The previous implementation had the same issue though, so not a regression. Leaving up to you to decide whether to address or merge as is.

OK, I think I can try to escape special characters in sed in the previous line.

Some array utilities would be nice to help with cases like this. I have this ages old unfinished patch for the main bash_completion in my stash, probably broken in the first place and uses namerefs so requires bash >= 4.3, but to illustrate what I was thinking back $then

Thank you for the suggestion. In this case, I indeed wanted to have something like remove and join (like _comp_array_remove main_cmd '--config' '--phone' and _comp_join '|' "${main_cmd[@]}"). The suggested uniq, last_index, compact, and index_of do not seem to be specifically able to be used for the present case, but I guess your idea is to give names to array manipulations as independent functions.

This might also be related to the discussion of _comp_xfunc_ARRAY_filter in #739.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a2d756e that escapes the ERE special characters.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Array utilities are moved to #953

IFS=$' \t\n'
[[ $COMP_LINE =~ $regex_main_cmd ]] && return

COMPREPLY=($(compgen -W "$all_cmd" -- "$cur"))
} &&
Expand Down
7 changes: 2 additions & 5 deletions completions/postfix
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,8 @@ _comp_cmd_postfix()
esac

if [[ $cur == -* ]]; then
COMPREPLY=($(
compgen -W \
'$(_bashcomp_try_faketty "$1" --help 2>&1 | _parse_usage -)' \
-- "$cur"
))
COMPREPLY=($(compgen -W \
'$(_parse_usage _bashcomp_try_faketty "$1 --help")' -- "$cur"))
return
fi

Expand Down