Skip to content

fix: use _comp_compgen with API changes #973

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 76 additions & 19 deletions bash_completion
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,23 @@ _comp_split()
((_new_size > _old_size))
}

# Helper function for _comp_compgen
# @var[in] $?
# @var[in] _var
# @var[in] _append
# @return original $?
_comp_compgen__error_fallback()
{
local _status=$?
if [[ $_append ]]; then
# make sure existence of variable
eval -- "$_var+=()"
else
eval -- "$_var=()"
fi
return "$_status"
}

# Provide a common interface to generate completion candidates in COMPREPLY or
# in a specified array.
# OPTIONS
Expand All @@ -414,6 +431,7 @@ _comp_split()
# -c cur Set a word used as a prefix to filter the completions. The default
# is ${cur-}.
# -R The same as -c ''. Use raw outputs without filtering.
# -C dir Evaluate compgen/generator in the specified directory.
# @var[in,opt] cur Used as the default value of a prefix to filter the
# completions.
#
Expand All @@ -437,10 +455,10 @@ _comp_split()
# as `-v arr` as a part of the `_comp_compgen` options.
#
# Usage #2: _comp_compgen [-alR|-v arr|-c cur] name args...
# Call `_comp_compgen_NAME ARGS...` with the specified options. This provides
# a common interface to call the functions `_comp_compgen_NAME`, which produce
# completion candidates, with custom options [-alR|-v arr|-c cur]. The option
# `-F sep` is not used with this usage.
# Call the generator `_comp_compgen_NAME ARGS...` with the specified options.
# This provides a common interface to call the functions `_comp_compgen_NAME`,
# which produce completion candidates, with custom options [-alR|-v arr|-c
# cur]. The option `-F sep` is not used with this usage.
# @param $1... name args Calls the function _comp_compgen_NAME with the
# specified ARGS (if $1 does not start with a hyphen `-`). The options
# [-alR|-v arr|-c cur] are inherited by the child calls of `_comp_compgen`
Expand Down Expand Up @@ -484,10 +502,15 @@ _comp_compgen()
local _append=${_comp_compgen__append-}
local _var=${_comp_compgen__var-COMPREPLY}
local _cur=${_comp_compgen__cur-${cur-}}
local _ifs=$' \t\n'
local _ifs=$' \t\n' _dir=""

local _old_nocasematch=""
if shopt -q nocasematch; then
_old_nocasematch=set
shopt -u nocasematch
fi
local OPTIND=1 OPTARG="" OPTERR=0 _opt
while getopts ':alF:v:Rc:' _opt "$@"; do
while getopts ':alF:v:Rc:C:' _opt "$@"; do
case $_opt in
a) _append=set ;;
v)
Expand All @@ -501,12 +524,20 @@ _comp_compgen()
F) _ifs=$OPTARG ;;
c) _cur=$OPTARG ;;
R) _cur="" ;;
C)
if [[ ! $OPTARG ]]; then
printf 'bash_completion: %s: -C: invalid directory name `%s'\''.\n' "$FUNCNAME" "$OPTARG" >&2
return 2
fi
_dir=$OPTARG
;;
*)
printf 'bash_completion: %s: usage error\n' "$FUNCNAME" >&2
return 2
;;
esac
done
[[ $_old_nocasematch ]] && shopt -s nocasematch
shift "$((OPTIND - 1))"
if (($# == 0)); then
printf 'bash_completion: %s: unexpected number of arguments.\n' "$FUNCNAME" >&2
Expand All @@ -521,14 +552,35 @@ _comp_compgen()
return 2
fi

if [[ $_dir ]]; then
local _original_pwd=$PWD
local PWD=${PWD-} OLDPWD=${OLDPWD-}
# Note: We also redirect stdout because `cd` may output the target
# directory to stdout when CDPATH is set.
command cd -- "$_dir" &>/dev/null ||
{
_comp_compgen__error_fallback
return
}
fi

local _comp_compgen__append=$_append
local _comp_compgen__var=$_var
local _comp_compgen__cur=$_cur cur=$_cur
# Note: we use $1 as a part of a function name, and we use $2... as
# arguments to the function if any.
# shellcheck disable=SC2145
_comp_compgen_"$@"
return
local _status=$?

# Go back to the original directory.
# Note: Failure of this line results in the change of the current
# directory visible to the user. We intentionally do not redirect
# stderr so that the error message appear in the terminal.
# shellcheck disable=SC2164
[[ $_dir ]] && command cd -- "$_original_pwd"

return "$_status"
fi

# usage: _comp_compgen [options] -- [compgen_options]
Expand All @@ -550,16 +602,15 @@ _comp_compgen()

local _result
_result=$(
if [[ $_dir ]]; then
# Note: We also redirect stdout because `cd` may output the target
# directory to stdout when CDPATH is set.
command cd -- "$_dir" &>/dev/null || return
fi
IFS=$_ifs compgen "$@" ${_cur:+-- "$_cur"}
) || {
local _status=$?
if [[ $_append ]]; then
# make sure existence of variable
eval -- "$_var+=()"
else
eval -- "$_var=()"
fi
return "$_status"
_comp_compgen__error_fallback
return
}

_comp_split -l ${_append:+-a} "$_var" "$_result"
Expand Down Expand Up @@ -1508,13 +1559,19 @@ _available_interfaces()
}

# Echo number of CPUs, falling back to 1 on failure.
# TODO:API: rename per conventions, rework to use vars rather than outputting
_ncpus()
# @var[out] ret
# @return 0 if it successfully obtained the number of CPUs, or otherwise 1
# @since 2.12
_comp_get_ncpus()
{
local var=NPROCESSORS_ONLN
[[ $OSTYPE == *@(linux|msys|cygwin)* ]] && var=_$var
local n=$(getconf $var 2>/dev/null)
printf %s "${n:-1}"
if ret=$(getconf $var 2>/dev/null) && ((ret >= 1)); then
return 0
else
ret=1
return 1
fi
}

# Perform tilde (~) completion
Expand Down
8 changes: 8 additions & 0 deletions bash_completion.d/000_bash_completion_compat.bash
Original file line number Diff line number Diff line change
Expand Up @@ -335,4 +335,12 @@ _parse_usage()
return 0
}

# @deprecated 2.12 Use `_comp_get_ncpus`.
_ncpus()
{
local ret
_comp_get_ncpus
printf %s "$ret"
}

# ex: filetype=sh
4 changes: 3 additions & 1 deletion completions/2to3
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ _comp_cmd_2to3()
return
;;
-j | --processes)
COMPREPLY=($(compgen -W "{1..$(_ncpus)}" -- "$cur"))
local ret
_comp_get_ncpus
_comp_compgen -- -W "{1..$ret}"
return
;;
-o | --output-dir)
Expand Down
28 changes: 14 additions & 14 deletions completions/_modules
Original file line number Diff line number Diff line change
Expand Up @@ -21,30 +21,26 @@
# being sourced before it and thus before the `module' alias has been defined.
[[ -f /etc/profile.d/modules.sh ]] || return 1

# TODO:API: rename per conventions, rework to use vars rather than outputting
_module_list()
_comp_cmd_module__compgen_list()
{
local modules="$(command sed 's/:/ /g' <<<"$LOADEDMODULES" | sort)"
compgen -W "$modules" -- "$1"
_comp_compgen -- -W "$modules"
}

# TODO:API: rename per conventions, rework to use vars rather than outputting
_module_path()
_comp_cmd_module__compgen_path()
{
local modules="$(command sed 's/:/ /g' <<<"$MODULEPATH" | sort)"
compgen -W "$modules" -- "$1"
_comp_compgen -- -W "$modules"
}

# TODO:API: rename per conventions, rework to use vars rather than outputting
_module_avail()
_comp_cmd_module__compgen_avail()
{
local modules="$(
module avail 2>&1 |
command grep -E -v '^(-|$)' |
xargs printf '%s\n' | command sed -e 's/(default)//g' | sort
)"

compgen -W "$modules" -- "$1"
_comp_compgen -- -W "$modules"
}

# A completion function for the module alias
Expand All @@ -65,19 +61,23 @@ _comp_cmd_module()
elif ((cword == 2)); then
case $prev in
add | display | help | load | show | whatis)
COMPREPLY=($(_module_avail "$cur"))
# TODO:API: use generator call?
_comp_cmd_module__compgen_avail
;;
rm | switch | swap | unload | update)
COMPREPLY=($(_module_list "$cur"))
# TODO:API: use generator call?
_comp_cmd_module__compgen_list
;;
unuse)
COMPREPLY=($(_module_path "$cur"))
# TODO:API: use generator call?
_comp_cmd_module__compgen_path
;;
esac
elif ((cword == 3)); then
case ${words[1]} in
swap | switch)
COMPREPLY=($(_module_avail "$cur"))
# TODO:API: use generator call?
_comp_cmd_module__compgen_avail
;;
esac
fi
Expand Down
10 changes: 2 additions & 8 deletions completions/_mount.linux
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,11 @@ _comp_cmd_mount()
return
;;
-L)
COMPREPLY=($(
command cd "/dev/disk/by-label/" 2>/dev/null || return
compgen -f -- "$cur"
))
_comp_compgen -C "/dev/disk/by-label/" -- -f
return
;;
-U)
COMPREPLY=($(
command cd "/dev/disk/by-uuid/" 2>/dev/null || return
compgen -f -- "$cur"
))
_comp_compgen -C "/dev/disk/by-uuid/" -- -f
return
;;
-O | --test-opts)
Expand Down
12 changes: 3 additions & 9 deletions completions/_slackpkg
Original file line number Diff line number Diff line change
Expand Up @@ -65,22 +65,16 @@ _comp_cmd_slackpkg()
;;
install-template | remove-template)
if [[ -e $confdir/templates ]]; then
COMPREPLY=($(
command cd -- "$confdir/templates"
compgen -f -X "!*.template" -- "$cur"
))
COMPREPLY=(${COMPREPLY[@]%.template})
_comp_compgen -C "$confdir/templates" -- -f -X \
"!?*.template" && COMPREPLY=("${COMPREPLY[@]%.template}")
fi
return
;;
remove)
_comp_compgen_filedir
_comp_compgen -a -- -W 'a ap d e f k kde kdei l n t tcl x xap xfce
y'
COMPREPLY+=($(
command cd /var/log/packages
compgen -f -- "$cur"
))
_comp_compgen -aC /var/log/packages -- -f
return
;;
install | reinstall | upgrade | blacklist | download)
Expand Down
5 changes: 2 additions & 3 deletions completions/_umount.linux
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,8 @@ _comp_cmd_umount__linux_fstab()
local i
for i in ${!COMPREPLY[*]}; do
[[ ${COMPREPLY[i]} == "$realcur"* ]] &&
COMPREPLY+=($(command cd -- "$dircur" 2>/dev/null &&
compgen -f -d -P "$dircur" \
-X "!${COMPREPLY[i]##"$dirrealcur"}" -- "$basecur"))
_comp_compgen -aC "$dircur" -c "$basecur" -- \
-f -d -P "$dircur" -X "!${COMPREPLY[i]##"$dirrealcur"}"
done
fi
fi
Expand Down
Loading