Skip to content

Commit

Permalink
feat(__load_completion): check that a completion was actually set
Browse files Browse the repository at this point in the history
On successful return, at least the full path to the command in question
should have a completion set.

If the command invoked was given without a path, the pathless one should
have one set, too.
  • Loading branch information
scop committed Apr 10, 2023
1 parent 42b2c02 commit f16dd80
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 4 deletions.
28 changes: 24 additions & 4 deletions bash_completion
Original file line number Diff line number Diff line change
Expand Up @@ -2509,7 +2509,7 @@ __load_completion()
fi
# Try to resolve real path to $cmd, and make it absolute
local ret realcmd=
local ret realcmd="" origcmd=$cmd
if _comp_realcommand "$cmd"; then
realcmd=$ret
cmd=${realcmd%/*}/$cmdname # basename could be an alias
Expand Down Expand Up @@ -2551,7 +2551,8 @@ __load_completion()
_comp_split -F : paths "${XDG_DATA_DIRS:-/usr/local/share:/usr/share}"
dirs+=("${paths[@]/%//bash-completion/completions}")
# For loading 3rd party completions wrapped in shopt reset
# Set up default $IFS in case loaded completions depend on it,
# as well as for $compspec invocation below.
local IFS=$' \t\n'
# Look up and source
Expand All @@ -2573,8 +2574,27 @@ __load_completion()
[[ $compfile == */.?(.) ]] ||
echo "bash_completion: $compfile: is a directory" >&2
elif [[ -e $compfile ]] && . "$compfile" "$cmd" "$@"; then
[[ $backslash ]] && $(complete -p "$cmdname") "\\$cmdname"
return 0
# At least $cmd is expected to have a completion set when
# we return successfully; see if it already does
if compspec=$(complete -p "$cmd" 2>/dev/null); then
local -a extspecs=()
# $cmd is the case in which we do backslash processing
[[ $backslash ]] && extspecs+=("$backslash$cmd")
# If invoked without path, that one should be set, too
# ...but let's not overwrite an existing one, if any
[[ $origcmd != */* ]] &&
! complete -p "$origcmd" &>/dev/null &&
extspecs+=("$origcmd")
((${#extspecs[*]} != 0)) && $compspec "${extspecs[@]}"
return 0
fi
# If not, see if we got one for $cmdname
if compspec=$(complete -p "$cmdname" 2>/dev/null); then
# Use that for $cmd too, if we have a full path to it
[[ $cmd == /* ]] && $compspec "$cmd"
return 0
fi
# Nothing expected was set, continue lookup
fi
done
done
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
echo 'cmd1: sourced from prefix1'
complete -C true "$1"
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
echo 'cmd2: sourced from prefix1'
complete -C true "$1"
1 change: 1 addition & 0 deletions test/fixtures/__load_completion/userdir1/completions/cmd1
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
echo 'cmd1: sourced from userdir1'
complete -C true "$1"
1 change: 1 addition & 0 deletions test/fixtures/__load_completion/userdir2/completions/cmd2
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
echo 'cmd2: sourced from userdir2'
complete -C true "$1"
14 changes: 14 additions & 0 deletions test/t/unit/test_unit_load_completion.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,26 @@ def test_PATH_1(self, bash):
bash, "__load_completion cmd2", want_output=True
)
assert output.strip() == "cmd2: sourced from prefix1"
output = assert_bash_exec(
bash, "complete -p cmd2", want_output=True
)
assert " cmd2" in output
output = assert_bash_exec(
bash, 'complete -p "$PWD/prefix1/sbin/cmd2"', want_output=True
)
assert "/prefix1/sbin/cmd2" in output

def test_cmd_path_1(self, bash):
assert_bash_exec(bash, "complete -r cmd1 || :", want_output=None)
output = assert_bash_exec(
bash, "__load_completion prefix1/bin/cmd1", want_output=True
)
assert output.strip() == "cmd1: sourced from prefix1"
output = assert_bash_exec(
bash, 'complete -p "$PWD/prefix1/bin/cmd1"', want_output=True
)
assert "/prefix1/bin/cmd1" in output
assert_bash_exec(bash, "! complete -p cmd1", want_output=None)
output = assert_bash_exec(
bash, "__load_completion prefix1/sbin/cmd2", want_output=True
)
Expand Down

0 comments on commit f16dd80

Please sign in to comment.