Skip to content

Commit 0f14cc0

Browse files
committed
feat(_comp_get_fist_arg): support "-o GLOB" to skip optargs
1 parent 1e4315a commit 0f14cc0

File tree

2 files changed

+75
-2
lines changed

2 files changed

+75
-2
lines changed

bash_completion

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2157,17 +2157,36 @@ _comp_realcommand()
21572157
}
21582158

21592159
# This function returns the first argument, excluding options
2160+
#
2161+
# Options:
2162+
# -a GLOB Pattern of options that take an option argument
2163+
#
21602164
# @var[out] ret First argument before current being completed if any, or
21612165
# otherwise an empty string
21622166
# @return True (0) if any argument is found, False (> 0) otherwise.
21632167
# @since 2.12
21642168
_comp_get_first_arg()
21652169
{
2166-
local i
2170+
local has_optarg=""
2171+
local OPTIND=1 OPTARG="" OPTERR=0 _opt
2172+
while getopts ':a:' _opt "$@"; do
2173+
case $_opt in
2174+
a) has_optarg=$OPTARG ;;
2175+
*)
2176+
echo "bash_completion: $FUNCNAME: usage error" >&2
2177+
return 2
2178+
;;
2179+
esac
2180+
done
2181+
shift "$((OPTIND - 1))"
21672182

2183+
local i
21682184
ret=
21692185
for ((i = 1; i < cword; i++)); do
2170-
if [[ ${words[i]} != -?* ]]; then
2186+
# shellcheck disable=SC2053
2187+
if [[ $has_optarg && ${words[i]} == $has_optarg ]]; then
2188+
((i++))
2189+
elif [[ ${words[i]} != -?* ]]; then
21712190
ret=${words[i]}
21722191
return 0
21732192
elif [[ ${words[i]} == -- ]]; then

test/t/unit/test_unit_get_first_arg.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,57 @@ def test_8_double_hyphen_2(self, bash, functions):
6969
bash, '_comp__test_unit "(a b -- -c -d e)" 5', want_output=None
7070
).strip()
7171
assert output == "b"
72+
73+
def test_9_skip_optarg_1(self, bash, functions):
74+
output = assert_bash_exec(
75+
bash,
76+
'_comp__test_unit "(a -b -c d e f)" 5 -a "@(-c|--foo)"',
77+
want_output=None,
78+
).strip()
79+
assert output == "e"
80+
81+
def test_9_skip_optarg_2(self, bash, functions):
82+
output = assert_bash_exec(
83+
bash,
84+
'_comp__test_unit "(a -b --foo d e f)" 5 -a "@(-c|--foo)"',
85+
want_output=None,
86+
).strip()
87+
assert output == "e"
88+
89+
def test_9_skip_optarg_3(self, bash):
90+
output = assert_bash_exec(
91+
bash,
92+
'_comp__test_unit "(a -b - c d e)" 5 -a "-b"',
93+
want_output=None,
94+
).strip()
95+
assert output == "c"
96+
97+
def test_9_skip_optarg_4(self, bash):
98+
output = assert_bash_exec(
99+
bash,
100+
'_comp__test_unit "(a -b -c d e f)" 5 -a "-[bc]"',
101+
want_output=None,
102+
).strip()
103+
assert output == "d"
104+
105+
def test_9_skip_optarg_5(self, bash):
106+
output = assert_bash_exec(
107+
bash, '_comp__test_unit "(a +o b c d)" 4 -a "+o"', want_output=None
108+
).strip()
109+
assert output == "c"
110+
111+
def test_9_skip_optarg_6(self, bash):
112+
output = assert_bash_exec(
113+
bash,
114+
'_comp__test_unit "(a -o -o -o -o b c)" 6 -a "-o"',
115+
want_output=None,
116+
).strip()
117+
assert output == "b"
118+
119+
def test_9_skip_optarg_7(self, bash):
120+
output = assert_bash_exec(
121+
bash,
122+
'_comp__test_unit "(a -o -- -b -c d e)" 6 -a "-o"',
123+
want_output=None,
124+
).strip()
125+
assert output == "d"

0 commit comments

Comments
 (0)