Skip to content

Commit 5d5ccb3

Browse files
authored
Merge pull request #1212 from akinomyoga/globsort
fix(_comp_expand_glob): set LC_COLLATE for the sorting order
2 parents 47af482 + 07d0eb4 commit 5d5ccb3

File tree

1 file changed

+64
-39
lines changed

1 file changed

+64
-39
lines changed

bash_completion

Lines changed: 64 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ _comp_upvars()
320320
# interference from user's shell options/settings or environment variables.
321321
# @param $1 array_name Array name
322322
# The array name should not start with an underscore "_", which is internally
323-
# used. The array name should not be "GLOBIGNORE".
323+
# used. The array name should not be "GLOBIGNORE" or "GLOBSORT".
324324
# @param $2 pattern Pattern string to be evaluated.
325325
# This pattern string will be evaluated using "eval", so brace expansions,
326326
# parameter expansions, command substitutions, and other expansions will be
@@ -335,7 +335,7 @@ _comp_expand_glob()
335335
printf 'bash-completion: %s: unexpected number of arguments\n' "$FUNCNAME" >&2
336336
printf 'usage: %s ARRAY_NAME PATTERN\n' "$FUNCNAME" >&2
337337
return 2
338-
elif [[ $1 == @(GLOBIGNORE|_*|*[^_a-zA-Z0-9]*|[0-9]*|'') ]]; then
338+
elif [[ $1 == @(GLOBIGNORE|GLOBSORT|_*|*[^_a-zA-Z0-9]*|[0-9]*|'') ]]; then
339339
printf 'bash-completion: %s: invalid array name "%s"\n' "$FUNCNAME" "$1" >&2
340340
return 2
341341
fi
@@ -346,8 +346,13 @@ _comp_expand_glob()
346346
shopt -s nullglob
347347
shopt -u failglob dotglob
348348

349-
# Also the user's GLOBIGNORE may affect the result of pathname expansions.
350-
local GLOBIGNORE=
349+
# Also the user's GLOBIGNORE and GLOBSORT (bash >= 5.3) may affect the
350+
# result of pathname expansions.
351+
local GLOBIGNORE="" GLOBSORT=name
352+
353+
# To canonicalize the sorting order of the generated paths, we set
354+
# LC_COLLATE=C and unset LC_ALL while preserving LC_CTYPE.
355+
local LC_COLLATE=C LC_CTYPE=${LC_ALL:-${LC_CTYPE:-${LANG-}}} LC_ALL=
351356

352357
eval -- "$1=()" # a fallback in case that the next line fails.
353358
eval -- "$1=($2)"
@@ -3298,45 +3303,65 @@ else
32983303
}
32993304
fi
33003305
3301-
# source compat completion directory definitions
3302-
_comp__init_compat_dirs=()
3303-
if [[ ${BASH_COMPLETION_COMPAT_DIR-} ]]; then
3304-
_comp__init_compat_dirs+=("$BASH_COMPLETION_COMPAT_DIR")
3305-
else
3306-
_comp__init_compat_dirs+=(/etc/bash_completion.d)
3307-
# Similarly as for the "completions" dir, look up from relative to
3308-
# bash_completion, primarily for installed-with-prefix and
3309-
# run-in-place-from-git-clone setups. Notably we do it after the system
3310-
# location here, in order to prefer in-tree variables and functions.
3311-
if [[ ${BASH_SOURCE%/*} == */share/bash-completion ]]; then
3312-
_comp__init_compat_dir=${BASH_SOURCE%/share/bash-completion/*}/etc/bash_completion.d
3313-
elif [[ $BASH_SOURCE == */* ]]; then
3314-
_comp__init_compat_dir="${BASH_SOURCE%/*}/bash_completion.d"
3306+
# List custom/extra completion files to source on the startup
3307+
## @param $1 path Path to "bash_completion"
3308+
## @var[out] _comp__init_startup_configs
3309+
_comp__init_collect_startup_configs()
3310+
{
3311+
local base_path=${1:-${BASH_SOURCE[1]}}
3312+
_comp__init_startup_configs=()
3313+
3314+
# source compat completion directory definitions
3315+
local -a compat_dirs=()
3316+
local compat_dir
3317+
if [[ ${BASH_COMPLETION_COMPAT_DIR-} ]]; then
3318+
compat_dirs+=("$BASH_COMPLETION_COMPAT_DIR")
33153319
else
3316-
_comp__init_compat_dir=./bash_completion.d
3317-
fi
3318-
[[ ${_comp__init_compat_dirs[0]} == "$_comp__init_compat_dir" ]] ||
3319-
_comp__init_compat_dirs+=("$_comp__init_compat_dir")
3320-
fi
3321-
for _comp__init_compat_dir in "${_comp__init_compat_dirs[@]}"; do
3322-
[[ -d $_comp__init_compat_dir && -r $_comp__init_compat_dir && -x $_comp__init_compat_dir ]] || continue
3323-
for _comp__init_file in "$_comp__init_compat_dir"/*; do
3324-
[[ ${_comp__init_file##*/} != @($_comp_backup_glob|Makefile*|${BASH_COMPLETION_COMPAT_IGNORE-}) &&
3325-
-f $_comp__init_file && -r $_comp__init_file ]] && . "$_comp__init_file"
3320+
compat_dirs+=(/etc/bash_completion.d)
3321+
# Similarly as for the "completions" dir, look up from relative to
3322+
# bash_completion, primarily for installed-with-prefix and
3323+
# run-in-place-from-git-clone setups. Notably we do it after the
3324+
# system location here, in order to prefer in-tree variables and
3325+
# functions.
3326+
if [[ ${base_path%/*} == */share/bash-completion ]]; then
3327+
compat_dir=${base_path%/share/bash-completion/*}/etc/bash_completion.d
3328+
elif [[ $base_path == */* ]]; then
3329+
compat_dir="${base_path%/*}/bash_completion.d"
3330+
else
3331+
compat_dir=./bash_completion.d
3332+
fi
3333+
[[ ${compat_dirs[0]} == "$compat_dir" ]] ||
3334+
compat_dirs+=("$compat_dir")
3335+
fi
3336+
for compat_dir in "${compat_dirs[@]}"; do
3337+
[[ -d $compat_dir && -r $compat_dir && -x $compat_dir ]] || continue
3338+
local compat_files
3339+
_comp_expand_glob compat_files '"$compat_dir"/*'
3340+
local compat_file
3341+
for compat_file in "${compat_files[@]}"; do
3342+
[[ ${compat_file##*/} != @($_comp_backup_glob|Makefile*|${BASH_COMPLETION_COMPAT_IGNORE-}) &&
3343+
-f $compat_file && -r $compat_file ]] &&
3344+
_comp__init_startup_configs+=("$compat_file")
3345+
done
33263346
done
3327-
done
3328-
unset -v _comp__init_compat_dirs _comp__init_compat_dir _comp__init_file
33293347
3330-
# source user completion file
3331-
#
3332-
# Remark: We explicitly check that $user_completion is not '/dev/null' since
3333-
# /dev/null may be a regular file in broken systems and can contain arbitrary
3334-
# garbages of suppressed command outputs.
3335-
_comp__init_user_file=${BASH_COMPLETION_USER_FILE:-~/.bash_completion}
3336-
[[ $_comp__init_user_file != "${BASH_SOURCE[0]}" && $_comp__init_user_file != /dev/null && -r $_comp__init_user_file && -f $_comp__init_user_file ]] &&
3337-
. "$_comp__init_user_file"
3338-
unset -v _comp__init_user_file
3348+
# source user completion file
3349+
#
3350+
# Remark: We explicitly check that $user_completion is not '/dev/null'
3351+
# since /dev/null may be a regular file in broken systems and can contain
3352+
# arbitrary garbages of suppressed command outputs.
3353+
local user_file=${BASH_COMPLETION_USER_FILE:-~/.bash_completion}
3354+
[[ $user_file != "$base_path" && $user_file != /dev/null && -r $user_file && -f $user_file ]] &&
3355+
_comp__init_startup_configs+=("$user_file")
33393356
3357+
unset -f "$FUNCNAME"
3358+
}
3359+
_comp__init_collect_startup_configs "$BASH_SOURCE"
3360+
# shellcheck disable=SC2154
3361+
for _comp_init_startup_config in "${_comp__init_startup_configs[@]}"; do
3362+
. "$_comp_init_startup_config"
3363+
done
3364+
unset -v _comp__init_startup_configs _comp_init_startup_config
33403365
unset -f have
33413366
unset -v have
33423367

0 commit comments

Comments
 (0)