Skip to content

Commit ad973af

Browse files
authored
Merge pull request #12740 from rouault/completion_not_last_term
Bash completion: fix completion of intermediate term
2 parents 43ae412 + 410bc28 commit ad973af

File tree

4 files changed

+94
-4
lines changed

4 files changed

+94
-4
lines changed

apps/gdal.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,35 @@ MAIN_START(argc, argv)
149149
EQUAL(argv[argc - 1], "last_word_is_complete=true");
150150
if (STARTS_WITH(argv[argc - 1], "last_word_is_complete="))
151151
--argc;
152+
else if (argc >= 2 && STARTS_WITH(argv[argc - 2], "prev=") &&
153+
STARTS_WITH(argv[argc - 1], "cur="))
154+
{
155+
const char *pszPrevVal = argv[argc - 2] + strlen("prev=");
156+
const char *pszCurVal = argv[argc - 1] + strlen("cur=");
157+
std::string osCurVal;
158+
const bool bIsPrevValEqual = (strcmp(pszPrevVal, "=") == 0);
159+
if (bIsPrevValEqual)
160+
{
161+
osCurVal = std::string("=").append(pszCurVal);
162+
pszCurVal = osCurVal.c_str();
163+
}
164+
int iMatch = 0;
165+
for (int i = 3; i < argc - 1; ++i)
166+
{
167+
if (bIsPrevValEqual ? (strstr(argv[i], pszCurVal) != nullptr)
168+
: (strcmp(argv[i], pszCurVal) == 0))
169+
{
170+
if (iMatch == 0)
171+
iMatch = i;
172+
else
173+
iMatch = -1;
174+
}
175+
}
176+
if (iMatch > 0)
177+
argc = iMatch + 1;
178+
else
179+
argc -= 2;
180+
}
152181

153182
// Process lines like "gdal completion gdal raster last_word_is_complete=true|false"
154183
EmitCompletion(std::move(alg),

autotest/utilities/test_gdal.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,16 @@ def test_gdal_completion_co(gdal_path):
297297
assert "1" in out
298298
assert "9" in out
299299

300+
out = gdaltest.runexternal(
301+
f"{gdal_path} completion gdal raster convert --of CO in.tif out.tif prev=of cur=CO"
302+
).split(" ")
303+
assert "COG" in out
304+
305+
out = gdaltest.runexternal(
306+
f"{gdal_path} completion gdal raster convert --of=CO in.tif out.tif prev== cur=CO"
307+
).split(" ")
308+
assert "COG" in out
309+
300310
out = gdaltest.runexternal(
301311
f"{gdal_path} completion gdal raster convert --of COG --co="
302312
).split(" ")

scripts/completionFinder.py

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,9 @@ def main(argv):
291291
outFile = argv[1]
292292
of = open(outFile, "w")
293293
of.write("# shellcheck shell=bash disable=SC2148\n")
294-
of.write("# File auto-generated by completionFinder.py, do not modify manually\n")
294+
of.write(
295+
"# WARNING: File auto-generated by completionFinder.py, do not modify manually\n"
296+
)
295297
of.write(
296298
"""
297299
@@ -307,12 +309,36 @@ def main(argv):
307309
bashcompinit
308310
fi
309311
312+
HAS_GET_COMP_WORDS_BY_REF=no
313+
if [ "$CURRENT_SHELL" = "bash" ]; then
314+
function_exists() {
315+
declare -f -F "$1" > /dev/null
316+
return $?
317+
}
318+
319+
# Checks that bash-completion is recent enough
320+
if function_exists _get_comp_words_by_ref; then
321+
HAS_GET_COMP_WORDS_BY_REF=yes;
322+
fi
323+
fi
324+
310325
_gdal()
311326
{
312327
COMPREPLY=()
313328
cur="${COMP_WORDS[$COMP_CWORD]}"
314329
315-
choices=$(gdal completion ${COMP_LINE})
330+
if test "$HAS_GET_COMP_WORDS_BY_REF" = "yes"; then
331+
local cur prev
332+
_get_comp_words_by_ref cur prev
333+
if test "$cur" = ""; then
334+
extra="last_word_is_complete=true"
335+
else
336+
extra="prev=${prev} cur=${cur}"
337+
fi
338+
choices=$(gdal completion ${COMP_LINE} ${extra})
339+
else
340+
choices=$(gdal completion ${COMP_LINE})
341+
fi
316342
if [ "$CURRENT_SHELL" = "bash" ]; then
317343
if [[ "$cur" == "=" ]]; then
318344
mapfile -t COMPREPLY < <(compgen -W "$choices" --)

scripts/gdal-bash-completion.sh

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# shellcheck shell=bash disable=SC2148
2-
# File auto-generated by completionFinder.py, do not modify manually
2+
# WARNING: File auto-generated by completionFinder.py, do not modify manually
3+
34

45
if ! ps -p $$ >/dev/null 2>/dev/null; then
56
# For busybox
@@ -13,12 +14,36 @@ if [ "$CURRENT_SHELL" = "zsh" ]; then
1314
bashcompinit
1415
fi
1516

17+
HAS_GET_COMP_WORDS_BY_REF=no
18+
if [ "$CURRENT_SHELL" = "bash" ]; then
19+
function_exists() {
20+
declare -f -F "$1" > /dev/null
21+
return $?
22+
}
23+
24+
# Checks that bash-completion is recent enough
25+
if function_exists _get_comp_words_by_ref; then
26+
HAS_GET_COMP_WORDS_BY_REF=yes;
27+
fi
28+
fi
29+
1630
_gdal()
1731
{
1832
COMPREPLY=()
1933
cur="${COMP_WORDS[$COMP_CWORD]}"
2034

21-
choices=$(gdal completion ${COMP_LINE})
35+
if test "$HAS_GET_COMP_WORDS_BY_REF" = "yes"; then
36+
local cur prev
37+
_get_comp_words_by_ref cur prev
38+
if test "$cur" = ""; then
39+
extra="last_word_is_complete=true"
40+
else
41+
extra="prev=${prev} cur=${cur}"
42+
fi
43+
choices=$(gdal completion ${COMP_LINE} ${extra})
44+
else
45+
choices=$(gdal completion ${COMP_LINE})
46+
fi
2247
if [ "$CURRENT_SHELL" = "bash" ]; then
2348
if [[ "$cur" == "=" ]]; then
2449
mapfile -t COMPREPLY < <(compgen -W "$choices" --)

0 commit comments

Comments
 (0)