Skip to content

Commit 0661fb5

Browse files
authored
Merge pull request #1036 from akinomyoga/refactor-api-5
refactor: refactor `_comp_{get_first_word,count_args}`
2 parents 349ac51 + 3127703 commit 0661fb5

File tree

16 files changed

+170
-77
lines changed

16 files changed

+170
-77
lines changed

bash_completion

Lines changed: 71 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2159,46 +2159,101 @@ _comp_realcommand()
21592159
fi
21602160
}
21612161

2162-
# This function returns the first argument, excluding options
2163-
# @var[out] ret First argument before current being completed if any, or
2164-
# otherwise an empty string
2162+
# This function returns the position of the first argument, excluding options
2163+
#
2164+
# Options:
2165+
# -a GLOB Pattern of options that take an option argument
2166+
#
2167+
# @var[out] ret Position of the first argument before the current one being
2168+
# completed if any, or otherwise an empty string
21652169
# @return True (0) if any argument is found, False (> 0) otherwise.
21662170
# @since 2.12
2167-
_comp_get_first_arg()
2171+
_comp_locate_first_arg()
21682172
{
2169-
local i
2173+
local has_optarg=""
2174+
local OPTIND=1 OPTARG="" OPTERR=0 _opt
2175+
while getopts ':a:' _opt "$@"; do
2176+
case $_opt in
2177+
a) has_optarg=$OPTARG ;;
2178+
*)
2179+
echo "bash_completion: $FUNCNAME: usage error" >&2
2180+
return 2
2181+
;;
2182+
esac
2183+
done
2184+
shift "$((OPTIND - 1))"
21702185

2186+
local i
21712187
ret=
21722188
for ((i = 1; i < cword; i++)); do
2173-
if [[ ${words[i]} != -?* ]]; then
2174-
ret=${words[i]}
2189+
# shellcheck disable=SC2053
2190+
if [[ $has_optarg && ${words[i]} == $has_optarg ]]; then
2191+
((i++))
2192+
elif [[ ${words[i]} != -?* ]]; then
2193+
ret=$i
21752194
return 0
21762195
elif [[ ${words[i]} == -- ]]; then
2177-
((i + 1 < cword)) && ret=${words[i + 1]} && return 0
2196+
((i + 1 < cword)) && ret=$((i + 1)) && return 0
21782197
break
21792198
fi
21802199
done
21812200
return 1
21822201
}
21832202

2203+
# This function returns the first argument, excluding options
2204+
#
2205+
# Options:
2206+
# -a GLOB Pattern of options that take an option argument
2207+
#
2208+
# @var[out] ret First argument before the current one being completed if any,
2209+
# or otherwise an empty string
2210+
# @return True (0) if any argument is found, False (> 0) otherwise.
2211+
# @since 2.12
2212+
_comp_get_first_arg()
2213+
{
2214+
_comp_locate_first_arg "$@" && ret=${words[ret]}
2215+
}
2216+
21842217
# This function counts the number of args, excluding options
2185-
# @param $1 chars Characters out of $COMP_WORDBREAKS which should
2186-
# NOT be considered word breaks. See _comp__reassemble_words.
2187-
# @param $2 glob Options whose following argument should not be counted
2188-
# @param $3 glob Options that should be counted as args
2218+
#
2219+
# Options:
2220+
# -n CHARS Characters out of $COMP_WORDBREAKS which should
2221+
# NOT be considered word breaks. See
2222+
# _comp__reassemble_words.
2223+
# -a GLOB Options whose following argument should not be counted
2224+
# -i GLOB Options that should be counted as args
2225+
#
21892226
# @var[out] ret Return the number of arguments
21902227
# @since 2.12
21912228
_comp_count_args()
21922229
{
2193-
local i cword words
2194-
_comp__reassemble_words "${1-}" words cword
2230+
local has_optarg="" has_exclude="" exclude="" glob_include=""
2231+
local OPTIND=1 OPTARG="" OPTERR=0 _opt
2232+
while getopts ':a:n:i:' _opt "$@"; do
2233+
case $_opt in
2234+
a) has_optarg=$OPTARG ;;
2235+
n) has_exclude=set exclude+=$OPTARG ;;
2236+
i) glob_include=$OPTARG ;;
2237+
*)
2238+
echo "bash_completion: $FUNCNAME: usage error" >&2
2239+
return 2
2240+
;;
2241+
esac
2242+
done
2243+
shift "$((OPTIND - 1))"
21952244

2245+
if [[ $has_exclude ]]; then
2246+
local cword words
2247+
_comp__reassemble_words "$exclude<>&" words cword
2248+
fi
2249+
2250+
local i
21962251
ret=1
21972252
for ((i = 1; i < cword; i++)); do
21982253
# shellcheck disable=SC2053
2199-
if [[ ${2-} && ${words[i]} == ${2-} ]]; then
2254+
if [[ $has_optarg && ${words[i]} == $has_optarg ]]; then
22002255
((i++))
2201-
elif [[ ${words[i]} != -?* || ${3-} && ${words[i]} == ${3-} ]]; then
2256+
elif [[ ${words[i]} != -?* || $glob_include && ${words[i]} == $glob_include ]]; then
22022257
((ret++))
22032258
elif [[ ${words[i]} == -- ]]; then
22042259
((ret += cword - i - 1))

completions/7z

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ _comp_cmd_7z()
8585
fi
8686

8787
local ret
88-
_comp_count_args "="
88+
_comp_count_args
8989
if ((ret == 2)); then
9090
_filedir_xspec unzip "${@:2}"
9191
# TODO: parsing 7z i output?

completions/arp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ _comp_cmd_arp()
3434
fi
3535

3636
local ret
37-
_comp_count_args "" "@(--device|--protocol|--file|--hw-type|-${noargopts}[iApfHt])"
37+
_comp_count_args -a "@(--device|--protocol|--file|--hw-type|-${noargopts}[iApfHt])"
3838
case $ret in
3939
1)
4040
local ips=$("$1" -an | command sed -ne \

completions/chmod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ _comp_cmd_chmod()
2828
fi
2929

3030
local ret
31-
_comp_count_args "" "" "$modearg"
31+
_comp_count_args -i "$modearg"
3232

3333
case $ret in
3434
1) ;; # mode

completions/chown

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ _comp_cmd_chown()
3232
local ret
3333

3434
# The first argument is a usergroup; the rest are filedir.
35-
_comp_count_args :
35+
_comp_count_args
3636

3737
if ((ret == 1)); then
3838
_comp_compgen_usergroups -u

completions/cryptsetup

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ _comp_cmd_cryptsetup()
3737
local ret
3838
if _comp_get_first_arg; then
3939
local arg=$ret
40-
_comp_count_args "" "-${noargopts}[chslSbopitTdM]"
40+
_comp_count_args -a "-${noargopts}[chslSbopitTdM]"
4141
local args=$ret
4242
case $arg in
4343
open | create | luksOpen | loopaesOpen | tcryptOpen)

completions/gpgv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ _comp_cmd_gpgv()
2020
esac
2121

2222
local ret
23-
_comp_count_args "" "--@(weak-digest|*-fd|keyring|homedir)"
23+
_comp_count_args -a "--@(weak-digest|*-fd|keyring|homedir)"
2424
local args=$ret
2525

2626
if [[ $cur == -* && $args -eq 1 ]]; then

completions/ifup

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ _comp_cmd_ifupdown()
2929
fi
3030

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

3434
if ((ret == 1)); then
3535
_comp_compgen_configured_interfaces

completions/jq

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ _comp_cmd_jq()
6666
local ret
6767
# TODO: DTRT with args taking 2 options
6868
# -f|--from-file are not counted here because they supply the filter
69-
_comp_count_args "" "@(--arg|--arg?(json|file)|--slurpfile|--indent|--run-tests|-${noargopts}L)"
69+
_comp_count_args -a "@(--arg|--arg?(json|file)|--slurpfile|--indent|--run-tests|-${noargopts}L)"
7070

7171
# 1st arg is filter
7272
((ret == 1)) && return

completions/jsonschema

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ _comp_cmd_jsonschema()
2121
fi
2222

2323
local ret
24-
_comp_count_args "" "-*"
24+
_comp_count_args -a "-*"
2525
((ret == 1)) || return
2626
_comp_compgen_filedir '@(json|schema)'
2727
} &&

0 commit comments

Comments
 (0)