Skip to content

Commit a127550

Browse files
committed
refactor: rename _realcommand => _comp_realcommand
As a bonus, this implementation eliminates a superfluous `type -P` call.
1 parent 9e82abf commit a127550

File tree

5 files changed

+85
-58
lines changed

5 files changed

+85
-58
lines changed

bash_completion

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1660,23 +1660,25 @@ _fstypes()
16601660
}
16611661

16621662
# Get real command.
1663-
# - arg: $1 Command
1664-
# - stdout: Filename of command in PATH with possible symbolic links resolved.
1665-
# Empty string if command not found.
1666-
# - return: True (0) if command found, False (> 0) if not.
1667-
_realcommand()
1668-
{
1669-
type -P "$1" >/dev/null && {
1670-
if type -p realpath >/dev/null; then
1671-
realpath "$(type -P "$1")"
1672-
elif type -p greadlink >/dev/null; then
1673-
greadlink -f "$(type -P "$1")"
1674-
elif type -p readlink >/dev/null; then
1675-
readlink -f "$(type -P "$1")"
1676-
else
1677-
type -P "$1"
1678-
fi
1679-
}
1663+
# Command is the filename of command in PATH with possible symlinks resolved
1664+
# (if resolve tooling available), empty string if command not found.
1665+
# @param $1 Command
1666+
# @var[out] ret Resulting string
1667+
# @return True (0) if command found, False (> 0) if not.
1668+
_comp_realcommand()
1669+
{
1670+
ret=""
1671+
local file
1672+
file=$(type -P "$1") || return $?
1673+
if type -p realpath >/dev/null; then
1674+
ret=$(realpath "$file")
1675+
elif type -p greadlink >/dev/null; then
1676+
ret=$(greadlink -f "$file")
1677+
elif type -p readlink >/dev/null; then
1678+
ret=$(readlink -f "$file")
1679+
else
1680+
ret=$file
1681+
fi
16801682
}
16811683

16821684
# This function returns the first argument, excluding options
@@ -2513,8 +2515,9 @@ __load_completion()
25132515
fi
25142516
25152517
# 3) From bin directories extracted from $(realpath "$cmd") and PATH
2516-
dir=$(_realcommand "$1")
2517-
paths=("${dir%/*}")
2518+
local ret
2519+
_comp_realcommand "$1"
2520+
paths=("${ret%/*}")
25182521
_comp_split -aF : paths "$PATH"
25192522
for dir in "${paths[@]%/}"; do
25202523
if [[ -d $dir && $dir == ?*/@(bin|sbin) ]]; then

bash_completion.d/000_bash_completion_compat.bash

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,19 @@ _get_pword()
165165
fi
166166
}
167167

168+
# Get real command.
169+
# @deprecated Use `_comp_realcommand` instead.
170+
# Note that `_comp_realcommand` stores the result in the variable `ret`
171+
# instead of writing it to stdout.
172+
_realcommand()
173+
{
174+
local ret
175+
_comp_realcommand "$1"
176+
local rc=$?
177+
printf "%s\n" "$ret"
178+
return $rc
179+
}
180+
168181
# @deprecated Use the variable `_comp_backup_glob` instead. This is the
169182
# backward-compatibility name.
170183
# shellcheck disable=SC2154 # defined in the main "bash_completion"

completions/gcc

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -58,31 +58,21 @@ _comp_cmd_gcc()
5858
} &&
5959
complete -F _comp_cmd_gcc gcc{,-5,-6,-7,-8} g++{,-5,-6,-7,-8} g77 g95 \
6060
gccgo{,-5,-6,-7,-8} gcj gfortran{,-5,-6,-7,-8} gpc &&
61+
_comp_cmd_gcc__setup_cmd()
6162
{
62-
if cc --version 2>/dev/null | command grep -q GCC ||
63-
[[ $(_realcommand cc) == *gcc* ]]; then
64-
complete -F _comp_cmd_gcc cc
63+
local ret
64+
_comp_realcommand "$1"
65+
if [[ $ret == *$2* ]] ||
66+
"$1" --version 2>/dev/null | command grep -q GCC; then
67+
complete -F _comp_cmd_gcc "$1"
6568
else
66-
complete -F _minimal cc
69+
complete -F _minimal "$1"
6770
fi
68-
if c++ --version 2>/dev/null | command grep -q GCC ||
69-
[[ $(_realcommand c++) == *g++* ]]; then
70-
complete -F _comp_cmd_gcc c++
71-
else
72-
complete -F _minimal c++
73-
fi
74-
if f77 --version 2>/dev/null | command grep -q GCC ||
75-
[[ $(_realcommand f77) == *gfortran* ]]; then
76-
complete -F _comp_cmd_gcc f77
77-
else
78-
complete -F _minimal f77
79-
fi
80-
if f95 --version 2>/dev/null | command grep -q GCC ||
81-
[[ $(_realcommand f95) == *gfortran* ]]; then
82-
complete -F _comp_cmd_gcc f95
83-
else
84-
complete -F _minimal f95
85-
fi
86-
}
71+
} &&
72+
_comp_cmd_gcc__setup_cmd cc gcc &&
73+
_comp_cmd_gcc__setup_cmd c++ g++ &&
74+
_comp_cmd_gcc__setup_cmd f77 gfortran &&
75+
_comp_cmd_gcc__setup_cmd f95 gfortran &&
76+
unset -f _comp_cmd_gcc__setup_cmd
8777

8878
# ex: filetype=sh

completions/vncviewer

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22

33
_vncviewer_bootstrap()
44
{
5-
local fname
6-
case $(_realcommand vncviewer) in
5+
local fname ret
6+
_comp_realcommand vncviewer
7+
case $ret in
78
*xvnc4viewer) fname=_xvnc4viewer ;;
89
*tightvncviewer) fname=_tightvncviewer ;;
910
*) fname=_known_hosts ;;

test/t/unit/test_unit_realcommand.py

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,45 @@
33
from conftest import assert_bash_exec, bash_env_saved
44

55

6-
@pytest.mark.bashcomp(cmd=None, cwd="shared", ignore_env=r"^\+COMPREPLY=")
6+
@pytest.mark.bashcomp(
7+
cmd=None, cwd="shared", ignore_env=r"^\+declare -f __tester$"
8+
)
79
class TestUnitRealCommand:
10+
@pytest.fixture
11+
def functions(self, bash):
12+
assert_bash_exec(
13+
bash,
14+
(
15+
"__tester() { "
16+
"local ret rc; "
17+
'_comp_realcommand "$1"; '
18+
"rc=$?; "
19+
'printf %s "$ret"; '
20+
"return $rc; "
21+
"}"
22+
),
23+
)
24+
825
def test_non_pollution(self, bash):
926
"""Test environment non-pollution, detected at teardown."""
1027
assert_bash_exec(
1128
bash,
12-
"foo() { local cur=; _realcommand bar; }; foo; unset -f foo",
29+
"foo() { local ret=; _comp_realcommand bar; }; foo; unset -f foo",
1330
want_output=None,
1431
)
1532

16-
def test_basename(self, bash):
33+
def test_basename(self, bash, functions):
1734
with bash_env_saved(bash) as bash_env:
1835
bash_env.write_variable("PATH", "$PWD/bin:$PATH", quote=False)
1936
output = assert_bash_exec(
2037
bash,
21-
"_realcommand arp",
38+
"__tester arp",
2239
want_output=True,
40+
want_newline=False,
2341
)
2442
assert output.strip().endswith("/shared/bin/arp")
2543

26-
def test_basename_nonexistent(self, bash):
44+
def test_basename_nonexistent(self, bash, functions):
2745
filename = "non-existent-file-for-bash-completion-tests"
2846
skipif = "! type -P %s" % filename
2947
try:
@@ -32,39 +50,41 @@ def test_basename_nonexistent(self, bash):
3250
pytest.skipif(skipif)
3351
output = assert_bash_exec(
3452
bash,
35-
"! _realcommand %s" % filename,
53+
"! __tester %s" % filename,
3654
want_output=False,
3755
)
3856
assert output.strip() == ""
3957

40-
def test_relative(self, bash):
58+
def test_relative(self, bash, functions):
4159
output = assert_bash_exec(
4260
bash,
43-
"_realcommand bin/arp",
61+
"__tester bin/arp",
4462
want_output=True,
63+
want_newline=False,
4564
)
4665
assert output.strip().endswith("/shared/bin/arp")
4766

48-
def test_relative_nonexistent(self, bash):
67+
def test_relative_nonexistent(self, bash, functions):
4968
output = assert_bash_exec(
5069
bash,
51-
"! _realcommand bin/non-existent",
70+
"! __tester bin/non-existent",
5271
want_output=False,
5372
)
5473
assert output.strip() == ""
5574

56-
def test_absolute(self, bash):
75+
def test_absolute(self, bash, functions):
5776
output = assert_bash_exec(
5877
bash,
59-
'_realcommand "$PWD/bin/arp"',
78+
'__tester "$PWD/bin/arp"',
6079
want_output=True,
80+
want_newline=False,
6181
)
6282
assert output.strip().endswith("/shared/bin/arp")
6383

64-
def test_absolute_nonexistent(self, bash):
84+
def test_absolute_nonexistent(self, bash, functions):
6585
output = assert_bash_exec(
6686
bash,
67-
'! _realcommand "$PWD/bin/non-existent"',
87+
'! __tester "$PWD/bin/non-existent"',
6888
want_output=False,
6989
)
7090
assert output.strip() == ""

0 commit comments

Comments
 (0)