Skip to content

Commit a124b3d

Browse files
authored
Merge pull request #888 from akinomyoga/failglob-3
fix(java): fix for failglob and refactor
2 parents adbf8ee + aebd676 commit a124b3d

File tree

2 files changed

+80
-31
lines changed

2 files changed

+80
-31
lines changed

completions/java

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,62 +8,65 @@ _comp_cmd_java__classpath()
88
}
99

1010
# exact classpath determination
11-
_java_find_classpath()
11+
# @var[out] ret Array to store classpaths
12+
# @return 0 if at least one element is generated, or otherwise 1
13+
_comp_cmd_java__find_classpath()
1214
{
1315
local i
1416

15-
classpath=
17+
ret=
1618

1719
# search first in current options
1820
for ((i = 1; i < cword; i++)); do
1921
if [[ ${words[i]} == -@(cp|classpath) ]]; then
20-
classpath=${words[i + 1]}
22+
ret=${words[i + 1]}
2123
break
2224
fi
2325
done
2426

25-
# default to environment
26-
[[ ! $classpath ]] && classpath=${CLASSPATH-}
27-
28-
# default to current directory
29-
[[ ! $classpath ]] && classpath=.
27+
# fall back to environment, followed by current directory
28+
_comp_split -F : ret "${ret:-${CLASSPATH:-.}}"
3029
}
3130

3231
# exact sourcepath determination
33-
_java_find_sourcepath()
32+
# @var[out] ret Array to store sourcepaths
33+
# @return 0 if at least one element is generated, or otherwise 1
34+
_comp_cmd_java__find_sourcepath()
3435
{
3536
local i
3637

37-
sourcepath=
38+
ret=
3839

3940
# search first in current options
4041
for ((i = 1; i < cword; i++)); do
4142
if [[ ${words[i]} == -sourcepath ]]; then
42-
sourcepath=${words[i + 1]}
43+
ret=${words[i + 1]}
4344
break
4445
fi
4546
done
4647

47-
# default to classpath
48-
if [[ ! -v sourcepath ]]; then
49-
local classpath
50-
_java_find_classpath
51-
sourcepath=$classpath
48+
# fall back to classpath
49+
if [[ ! $ret ]]; then
50+
_comp_cmd_java__find_classpath
51+
return
5252
fi
53+
54+
_comp_split -F : ret "$ret"
5355
}
5456

5557
# available classes completion
5658
_comp_cmd_java__classes()
5759
{
58-
local classpath i
60+
local ret i
5961

6062
# find which classpath to use
61-
_java_find_classpath
63+
_comp_cmd_java__find_classpath
64+
local -a classpaths=("${ret[@]}")
6265

6366
# convert package syntax to path syntax
6467
cur=${cur//.//}
6568
# parse each classpath element for classes
66-
for i in ${classpath//:/ }; do
69+
for i in "${classpaths[@]}"; do
6770
if [[ $i == *.@(jar|zip) && -r $i ]]; then
6871
if type zipinfo &>/dev/null; then
6972
COMPREPLY+=($(zipinfo -1 "$i" "$cur*" 2>/dev/null |
@@ -103,27 +106,30 @@ _comp_cmd_java__classes()
103106
# available packages completion
104107
_comp_cmd_java__packages()
105108
{
106-
local sourcepath i
109+
local ret i files
107110

108111
# find which sourcepath to use
109-
_java_find_sourcepath
112+
_comp_cmd_java__find_sourcepath || return 0
113+
local -a sourcepaths=("${ret[@]}")
110114

111115
# convert package syntax to path syntax
112-
cur=${cur//.//}
116+
local cur=${cur//.//}
113117
# parse each sourcepath element for packages
114-
for i in ${sourcepath//:/ }; do
118+
for i in "${sourcepaths[@]}"; do
115119
if [[ -d $i ]]; then
116-
COMPREPLY+=($(command ls -F -d "$i/$cur"* 2>/dev/null |
117-
command sed -e 's|^'"$i"'/||'))
120+
_comp_expand_glob files '"$i/$cur"*'
121+
((${#files[@]})) || continue
122+
_comp_split -la COMPREPLY "$(
123+
command ls -F -d "${files[@]}" 2>/dev/null |
124+
command sed -e 's|^'"$i"'/||'
125+
)"
118126
fi
119127
done
120128
if ((${#COMPREPLY[@]} != 0)); then
121-
# keep only packages
122-
COMPREPLY=($(tr " " "\n" <<<"${COMPREPLY[@]}" | command grep "/$"))
123-
# remove packages extension
124-
COMPREPLY=(${COMPREPLY[@]%/})
129+
# keep only packages with the package suffix `/` being removed
130+
_comp_split -l COMPREPLY "$(printf '%s\n' "${COMPREPLY[@]}" | command sed -n 's,/$,,p')"
125131
# convert path syntax to package syntax
126-
cur="${COMPREPLY[*]//\//.}"
132+
((${#COMPREPLY[@]})) && COMPREPLY=("${COMPREPLY[@]//\//.}")
127133
fi
128134
}
129135

test/t/test_java.py

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import pytest
22

3-
from conftest import is_bash_type
3+
from conftest import is_bash_type, assert_bash_exec, bash_env_saved
44

55

66
@pytest.mark.bashcomp(
@@ -47,3 +47,46 @@ def test_5(self, completion):
4747
@pytest.mark.complete("java -jar java/")
4848
def test_6(self, completion):
4949
assert completion == "a/ bashcomp.jar bashcomp.war".split()
50+
51+
@pytest.mark.complete("javadoc -sourcepath java/a:java/a/c ")
52+
def test_sourcepath_1(self, completion):
53+
"""sourcepath should be split by `:`"""
54+
assert completion == "c"
55+
56+
@pytest.mark.complete("javadoc -sourcepath java/?:java/x ")
57+
def test_sourcepath_2(self, completion):
58+
"""pathname expansion should not happen after splitting the argument by
59+
`:`"""
60+
assert not completion
61+
62+
@pytest.mark.complete("javadoc -sourcepath java/a ")
63+
def test_packages_1(self, completion):
64+
assert completion == "c"
65+
66+
@pytest.mark.complete("javadoc -sourcepath java/a x")
67+
def test_packages_2(self, completion):
68+
assert not completion
69+
70+
@pytest.mark.complete(
71+
"javadoc -sourcepath java/a x", shopt=dict(failglob=True)
72+
)
73+
def test_packages_3(self, completion):
74+
assert not completion
75+
76+
@pytest.mark.complete("javadoc -sourcepath java/a ", env=dict(IFS="a"))
77+
def test_packages_4(self, completion):
78+
assert completion == "c"
79+
80+
def test_packages_5(self, bash):
81+
"""_comp_cmd_java__packages should not modify the outerscope `cur`"""
82+
with bash_env_saved(bash) as bash_env:
83+
bash_env.write_variable("cur", "a.b.c")
84+
assert_bash_exec(
85+
bash,
86+
"_comp_test_f() { local cword=3 words=(javadoc -sourcepath java/a a.b.c); COMPREPLY+=(); _comp_cmd_java__packages; }; _comp_test_f",
87+
)
88+
89+
@pytest.mark.complete("javadoc -sourcepath java a.")
90+
def test_packages_6(self, completion):
91+
"""A period in package names should not be converted to slash."""
92+
assert completion == "c"

0 commit comments

Comments
 (0)