Skip to content

refactor: refactor _comp_{get_first_word,count_args} #1036

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Sep 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 71 additions & 16 deletions bash_completion
Original file line number Diff line number Diff line change
Expand Up @@ -2156,46 +2156,101 @@ _comp_realcommand()
fi
}

# This function returns the first argument, excluding options
# @var[out] ret First argument before current being completed if any, or
# otherwise an empty string
# This function returns the position of the first argument, excluding options
#
# Options:
# -a GLOB Pattern of options that take an option argument
#
# @var[out] ret Position of the first argument before the current one being
# completed if any, or otherwise an empty string
# @return True (0) if any argument is found, False (> 0) otherwise.
# @since 2.12
_comp_get_first_arg()
_comp_locate_first_arg()
{
local i
local has_optarg=""
local OPTIND=1 OPTARG="" OPTERR=0 _opt
while getopts ':a:' _opt "$@"; do
case $_opt in
a) has_optarg=$OPTARG ;;
*)
echo "bash_completion: $FUNCNAME: usage error" >&2
return 2
;;
esac
done
shift "$((OPTIND - 1))"

local i
ret=
for ((i = 1; i < cword; i++)); do
if [[ ${words[i]} != -?* ]]; then
ret=${words[i]}
# shellcheck disable=SC2053
if [[ $has_optarg && ${words[i]} == $has_optarg ]]; then
((i++))
elif [[ ${words[i]} != -?* ]]; then
ret=$i
return 0
elif [[ ${words[i]} == -- ]]; then
((i + 1 < cword)) && ret=${words[i + 1]} && return 0
((i + 1 < cword)) && ret=$((i + 1)) && return 0
break
fi
done
return 1
}

# This function returns the first argument, excluding options
#
# Options:
# -a GLOB Pattern of options that take an option argument
#
# @var[out] ret First argument before the current one being completed if any,
# or otherwise an empty string
# @return True (0) if any argument is found, False (> 0) otherwise.
# @since 2.12
_comp_get_first_arg()
{
_comp_locate_first_arg "$@" && ret=${words[ret]}
}

# This function counts the number of args, excluding options
# @param $1 chars Characters out of $COMP_WORDBREAKS which should
# NOT be considered word breaks. See _comp__reassemble_words.
# @param $2 glob Options whose following argument should not be counted
# @param $3 glob Options that should be counted as args
#
# Options:
# -n CHARS Characters out of $COMP_WORDBREAKS which should
# NOT be considered word breaks. See
# _comp__reassemble_words.
# -a GLOB Options whose following argument should not be counted
# -i GLOB Options that should be counted as args
#
# @var[out] ret Return the number of arguments
# @since 2.12
_comp_count_args()
{
local i cword words
_comp__reassemble_words "${1-}" words cword
local has_optarg="" has_exclude="" exclude="" glob_include=""
local OPTIND=1 OPTARG="" OPTERR=0 _opt
while getopts ':a:n:i:' _opt "$@"; do
case $_opt in
a) has_optarg=$OPTARG ;;
n) has_exclude=set exclude+=$OPTARG ;;
i) glob_include=$OPTARG ;;
*)
echo "bash_completion: $FUNCNAME: usage error" >&2
return 2
;;
esac
done
shift "$((OPTIND - 1))"

if [[ $has_exclude ]]; then
local cword words
_comp__reassemble_words "$exclude<>&" words cword
fi

local i
ret=1
for ((i = 1; i < cword; i++)); do
# shellcheck disable=SC2053
if [[ ${2-} && ${words[i]} == ${2-} ]]; then
if [[ $has_optarg && ${words[i]} == $has_optarg ]]; then
((i++))
elif [[ ${words[i]} != -?* || ${3-} && ${words[i]} == ${3-} ]]; then
elif [[ ${words[i]} != -?* || $glob_include && ${words[i]} == $glob_include ]]; then
((ret++))
elif [[ ${words[i]} == -- ]]; then
((ret += cword - i - 1))
Expand Down
2 changes: 1 addition & 1 deletion completions/7z
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ _comp_cmd_7z()
fi

local ret
_comp_count_args "="
_comp_count_args
if ((ret == 2)); then
_filedir_xspec unzip "${@:2}"
# TODO: parsing 7z i output?
Expand Down
2 changes: 1 addition & 1 deletion completions/arp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ _comp_cmd_arp()
fi

local ret
_comp_count_args "" "@(--device|--protocol|--file|--hw-type|-${noargopts}[iApfHt])"
_comp_count_args -a "@(--device|--protocol|--file|--hw-type|-${noargopts}[iApfHt])"
case $ret in
1)
local ips=$("$1" -an | command sed -ne \
Expand Down
2 changes: 1 addition & 1 deletion completions/chmod
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ _comp_cmd_chmod()
fi

local ret
_comp_count_args "" "" "$modearg"
_comp_count_args -i "$modearg"

case $ret in
1) ;; # mode
Expand Down
2 changes: 1 addition & 1 deletion completions/chown
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ _comp_cmd_chown()
local ret

# The first argument is a usergroup; the rest are filedir.
_comp_count_args :
_comp_count_args

if ((ret == 1)); then
_comp_compgen_usergroup -u
Expand Down
2 changes: 1 addition & 1 deletion completions/cryptsetup
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ _comp_cmd_cryptsetup()
local ret
if _comp_get_first_arg; then
local arg=$ret
_comp_count_args "" "-${noargopts}[chslSbopitTdM]"
_comp_count_args -a "-${noargopts}[chslSbopitTdM]"
local args=$ret
case $arg in
open | create | luksOpen | loopaesOpen | tcryptOpen)
Expand Down
2 changes: 1 addition & 1 deletion completions/gpgv
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ _comp_cmd_gpgv()
esac

local ret
_comp_count_args "" "--@(weak-digest|*-fd|keyring|homedir)"
_comp_count_args -a "--@(weak-digest|*-fd|keyring|homedir)"
local args=$ret

if [[ $cur == -* && $args -eq 1 ]]; then
Expand Down
2 changes: 1 addition & 1 deletion completions/ifup
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ _comp_cmd_ifupdown()
fi

local ret
_comp_count_args "" "@(--allow|-i|--interfaces|--state-dir|-X|--exclude|-o)"
_comp_count_args -a "@(--allow|-i|--interfaces|--state-dir|-X|--exclude|-o)"

if ((ret == 1)); then
_comp_compgen_configured_interfaces
Expand Down
2 changes: 1 addition & 1 deletion completions/jq
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ _comp_cmd_jq()
local ret
# TODO: DTRT with args taking 2 options
# -f|--from-file are not counted here because they supply the filter
_comp_count_args "" "@(--arg|--arg?(json|file)|--slurpfile|--indent|--run-tests|-${noargopts}L)"
_comp_count_args -a "@(--arg|--arg?(json|file)|--slurpfile|--indent|--run-tests|-${noargopts}L)"

# 1st arg is filter
((ret == 1)) && return
Expand Down
2 changes: 1 addition & 1 deletion completions/jsonschema
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ _comp_cmd_jsonschema()
fi

local ret
_comp_count_args "" "-*"
_comp_count_args -a "-*"
((ret == 1)) || return
_comp_compgen_filedir '@(json|schema)'
} &&
Expand Down
2 changes: 1 addition & 1 deletion completions/nc
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ _comp_cmd_nc()

# Complete 1st non-option arg only
local ret
_comp_count_args "" "-*[IiMmOPpqsTVWwXx]"
_comp_count_args -n "" -a "-*[IiMmOPpqsTVWwXx]"
((ret == 1)) || return

_known_hosts_real -- "$cur"
Expand Down
4 changes: 2 additions & 2 deletions completions/nslookup
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ _comp_cmd_nslookup()
fi

local ret
_comp_count_args "="
_comp_count_args
if ((ret <= 2)); then
_known_hosts_real -- "$cur"
[[ $ret -eq 1 && $cur == @(|-) ]] && COMPREPLY+=(-)
Expand Down Expand Up @@ -90,7 +90,7 @@ _comp_cmd_host()
fi

local ret
_comp_count_args "" "-*[ctmNRW]"
_comp_count_args -a "-*[ctmNRW]"
if ((ret == 1)); then
_known_hosts_real -- "$cur"
elif ((ret == 2)); then
Expand Down
2 changes: 1 addition & 1 deletion completions/sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ _comp_cmd_sh()
fi

local ret ext=
_comp_count_args "" "@(-c|[-+]o)"
_comp_count_args -a "@(-c|[-+]o)"
((ret == 1)) && ext="sh"
_comp_compgen_filedir $ext
} &&
Expand Down
2 changes: 1 addition & 1 deletion completions/ssh
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ _comp_cmd_ssh()
else
local ret
# Keep glob sort in sync with cases above
_comp_count_args "=" "-*[BbcDeLpRWEFSIiJlmOoQw]"
_comp_count_args -n "=" -a "-*[BbcDeLpRWEFSIiJlmOoQw]"
if ((ret > 1)); then
compopt -o filenames
_comp_compgen_commands
Expand Down
Loading