Skip to content

Commit f9d23a3

Browse files
committed
feat(_comp_compgen): support -U var to unlocal var
1 parent 4a7f5b4 commit f9d23a3

File tree

1 file changed

+49
-40
lines changed

1 file changed

+49
-40
lines changed

bash_completion

Lines changed: 49 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,21 @@ _comp_compgen__error_fallback()
422422
# The array name should not start with an underscores "_", which is
423423
# internally used. The array name should not be either "IFS" or
424424
# "OPT{IND,ARG,ERR}".
425+
# -U var Unlocal VAR before performing the assignments. This option can be
426+
# specified multiple times to register multiple variables. This
427+
# option is supposed to be used by a parent generator (G1) when G1
428+
# defines a local variable name that does not start with `_`. In
429+
# such a case, when a conflicting `-v VAR` is specified to the
430+
# generator call, the assignments to VAR fail to propagate outside
431+
# G1. To avoid such a situation, `-U VAR` provides a mechanism to
432+
# unlocal VAR before accessing variables specified to G1 by `-v`. If
433+
# this is a builtin compgen call (i.e., _comp_compgen [options] --
434+
# options), the specified variables are unlocalized after calling the
435+
# builtin `compgen` and before assigning results to the array
436+
# specified by `-v`. If this is a child generator call (i.e.,
437+
# _comp_compgen [options] G2 ...), the specified variables are
438+
# unlocalized before calling the generator function
439+
# `_comp_compgen_G2`.
425440
# -c cur Set a word used as a prefix to filter the completions. The default
426441
# is ${cur-}.
427442
# -R The same as -c ''. Use raw outputs without filtering.
@@ -512,14 +527,15 @@ _comp_compgen()
512527
local _dir=""
513528
local _ifs=$' \t\n' _has_ifs=""
514529
local _icmd="" _xcmd=""
530+
local -a _upvars=()
515531

516532
local _old_nocasematch=""
517533
if shopt -q nocasematch; then
518534
_old_nocasematch=set
519535
shopt -u nocasematch
520536
fi
521537
local OPTIND=1 OPTARG="" OPTERR=0 _opt
522-
while getopts ':av:Rc:C:lF:i:x:' _opt "$@"; do
538+
while getopts ':av:U:Rc:C:lF:i:x:' _opt "$@"; do
523539
case $_opt in
524540
a) _append=set ;;
525541
v)
@@ -529,6 +545,16 @@ _comp_compgen()
529545
fi
530546
_var=$OPTARG
531547
;;
548+
U)
549+
if [[ $OPTARG == @(*[^_a-zA-Z0-9]*|[0-9]*|'') ]]; then
550+
printf 'bash_completion: %s: -U: invalid variable name `%s'\''\n' "$FUNCNAME" "$OPTARG" >&2
551+
return 2
552+
elif [[ $OPTARG == @(_*|IFS|OPTIND|OPTARG|OPTERR) ]]; then
553+
printf 'bash_completion: %s: -U: unnecessary to mark `%s'\'' as upvar\n' "$FUNCNAME" "$OPTARG" >&2
554+
return 2
555+
fi
556+
_upvars+=("$OPTARG")
557+
;;
532558
c) _cur=$OPTARG ;;
533559
R) _cur="" ;;
534560
C)
@@ -588,6 +614,8 @@ _comp_compgen()
588614
return 2
589615
fi
590616

617+
((${#_upvars[@]})) && _comp_unlocal "${_upvars[@]}"
618+
591619
if [[ $_dir ]]; then
592620
local _original_pwd=$PWD
593621
local PWD=${PWD-} OLDPWD=${OLDPWD-}
@@ -653,6 +681,7 @@ _comp_compgen()
653681
return
654682
}
655683

684+
((${#_upvars[@]})) && _comp_unlocal "${_upvars[@]}"
656685
_comp_split -l ${_append:+-a} "$_var" "$_result"
657686
}
658687

@@ -1078,9 +1107,7 @@ _comp_compgen_filedir()
10781107
# Note: bash < 4.4 has a bug that all the elements are connected with
10791108
# ${v+"${a[@]}"} when IFS does not contain whitespace.
10801109
local IFS=$' \t\n'
1081-
local -a _tmp=(${toks[@]+"${toks[@]}"})
1082-
_comp_unlocal toks
1083-
_comp_compgen_set ${_tmp[@]+"${_tmp[@]}"}
1110+
_comp_compgen -U toks set ${toks[@]+"${toks[@]}"}
10841111
} # _comp_compgen_filedir()
10851112

10861113
# This function splits $cur=--foo=bar into $prev=--foo, $cur=bar, making it
@@ -1535,11 +1562,8 @@ _comp_compgen_usage()
15351562
_comp_compgen_signals()
15361563
{
15371564
local -a sigs
1538-
if _comp_compgen -v sigs -c "SIG${cur#"${1-}"}" -- -P "${1-}" -A signal; then
1539-
local -a _sigs=("${sigs[@]/#${1-}SIG/${1-}}")
1540-
_comp_unlocal sigs
1541-
_comp_compgen_set "${_sigs[@]}"
1542-
fi
1565+
_comp_compgen -v sigs -c "SIG${cur#"${1-}"}" -- -P "${1-}" -A signal &&
1566+
_comp_compgen -U sigs set "${sigs[@]/#${1-}SIG/${1-}}"
15431567
}
15441568

15451569
# This function completes on known mac addresses
@@ -1578,9 +1602,7 @@ _comp_compgen_mac_addresses()
15781602
_comp_compgen -av addresses split -- "$(command sed -ne \
15791603
"s/^[[:space:]]*\($_re\)[[:space:]].*/\1/p" /etc/ethers 2>/dev/null)"
15801604

1581-
local -a _addresses=("${addresses[@]}")
1582-
_comp_unlocal addresses
1583-
_comp_compgen_ltrim_colon "${_addresses[@]}"
1605+
_comp_compgen -U ltrim_colon "${addresses[@]}"
15841606
}
15851607

15861608
# This function completes on configured network interfaces
@@ -1589,32 +1611,29 @@ _comp_compgen_mac_addresses()
15891611
_comp_compgen_configured_interfaces()
15901612
{
15911613
local -a files
1592-
local _list
15931614
if [[ -f /etc/debian_version ]]; then
15941615
# Debian system
15951616
_comp_expand_glob files '/etc/network/interfaces /etc/network/interfaces.d/*'
15961617
((${#files[@]})) || return 0
1597-
_list=$(command sed -ne \
1598-
's|^iface \([^ ]\{1,\}\).*$|\1|p' "${files[@]}" 2>/dev/null)
1618+
_comp_compgen -U files split -- "$(command sed -ne \
1619+
's|^iface \([^ ]\{1,\}\).*$|\1|p' "${files[@]}" 2>/dev/null)"
15991620
elif [[ -f /etc/SuSE-release ]]; then
16001621
# SuSE system
16011622
_comp_expand_glob files '/etc/sysconfig/network/ifcfg-*'
16021623
((${#files[@]})) || return 0
1603-
_list=$(printf '%s\n' "${files[@]}" |
1604-
command sed -ne 's|.*ifcfg-\([^*].*\)$|\1|p')
1624+
_comp_compgen -U files split -- "$(printf '%s\n' "${files[@]}" |
1625+
command sed -ne 's|.*ifcfg-\([^*].*\)$|\1|p')"
16051626
elif [[ -f /etc/pld-release ]]; then
16061627
# PLD Linux
1607-
_list=$(command ls -B /etc/sysconfig/interfaces |
1608-
command sed -ne 's|.*ifcfg-\([^*].*\)$|\1|p')
1628+
_comp_compgen -U files split -- "$(command ls -B /etc/sysconfig/interfaces |
1629+
command sed -ne 's|.*ifcfg-\([^*].*\)$|\1|p')"
16091630
else
16101631
# Assume Red Hat
16111632
_comp_expand_glob files '/etc/sysconfig/network-scripts/ifcfg-*'
16121633
((${#files[@]})) || return 0
1613-
_list=$(printf '%s\n' "${files[@]}" |
1614-
command sed -ne 's|.*ifcfg-\([^*].*\)$|\1|p')
1634+
_comp_compgen -U files split -- "$(printf '%s\n' "${files[@]}" |
1635+
command sed -ne 's|.*ifcfg-\([^*].*\)$|\1|p')"
16151636
fi
1616-
_comp_unlocal files
1617-
_comp_compgen_split -- "$_list"
16181637
}
16191638

16201639
# Local IP addresses.
@@ -1642,12 +1661,10 @@ _comp_compgen_ip_addresses()
16421661
"s|.*inet${_n}[[:space:]]\{1,\}\([^[:space:]/]*\).*|\1|p")" ||
16431662
return
16441663

1645-
local -a _addrs=("${addrs[@]}")
1646-
_comp_unlocal addrs
16471664
if [[ ! $_n ]]; then
1648-
_comp_compgen_set "${_addrs[@]}"
1665+
_comp_compgen -U addrs set "${addrs[@]}"
16491666
else
1650-
_comp_compgen_ltrim_colon "${_addrs[@]}"
1667+
_comp_compgen -U addrs ltrim_colon "${addrs[@]}"
16511668
fi
16521669
}
16531670

@@ -1677,11 +1694,8 @@ _comp_compgen_available_interfaces()
16771694
ifconfig -a || ip -c=never link show || ip link show
16781695
fi
16791696
} 2>/dev/null | awk \
1680-
'/^[^ \t]/ { if ($1 ~ /^[0-9]+:/) { print $2 } else { print $1 } }')" ||
1681-
return
1682-
local -a _generated=("${generated[@]/%[[:punct:]]/}")
1683-
_comp_unlocal generated
1684-
_comp_compgen_set "${_generated[@]}"
1697+
'/^[^ \t]/ { if ($1 ~ /^[0-9]+:/) { print $2 } else { print $1 } }')" &&
1698+
_comp_compgen -U set "${generated[@]}"
16851699
}
16861700

16871701
# Echo number of CPUs, falling back to 1 on failure.
@@ -1845,11 +1859,8 @@ else
18451859
done
18461860
fi
18471861
fi
1848-
if ((${#procs[@]})); then
1849-
local -a _procs=("${procs[@]}")
1850-
_comp_unlocal procs
1851-
_comp_compgen -- -X "<defunct>" -W '"${_procs[@]}"'
1852-
fi
1862+
((${#procs[@]})) &&
1863+
_comp_compgen -U procs -- -X "<defunct>" -W '"${procs[@]}"'
18531864
}
18541865
fi
18551866

@@ -1897,9 +1908,7 @@ _comp_compgen_xinetd_services()
18971908
local -a svcs
18981909
_comp_expand_glob svcs '$_xinetddir/!($_comp_backup_glob)'
18991910
if ((${#svcs[@]})); then
1900-
local _svcs=("${svcs[@]}")
1901-
_comp_unlocal svcs
1902-
_comp_compgen -- -W '"${_svcs[@]#$_xinetddir/}"'
1911+
_comp_compgen -U svcs -- -W '"${svcs[@]#$_xinetddir/}"'
19031912
fi
19041913
fi
19051914
}

0 commit comments

Comments
 (0)