@@ -655,29 +655,111 @@ _comp_compgen()
655
655
printf ' bash_completion: %s: unrecognized generator `%s' \' ' (function %s not found)\n' " $FUNCNAME " " $1 " " ${_generator[0]} " >&2
656
656
return 2
657
657
fi
658
+ shift
658
659
659
- (( ${# _upvars[@]} )) && _comp_unlocal " ${_upvars[@]} "
660
+ _comp_compgen__call_generator " $@ "
661
+ else
662
+ # usage: _comp_compgen [options] -- [compgen_options]
663
+ if [[ $_icmd || $_xcmd ]]; then
664
+ printf ' bash_completion: %s: generator name is unspecified for `%s' \' ' \n' " $FUNCNAME " " ${_icmd: +-i $_icmd }${_xcmd: +x $_xcmd } " >&2
665
+ return 2
666
+ fi
667
+
668
+ # Note: $* in the below checks would be affected by uncontrolled IFS in
669
+ # bash >= 5.0, so we need to set IFS to the normal value. The behavior
670
+ # in bash < 5.0, where unquoted $* in conditional command did not honor
671
+ # IFS, was a bug.
672
+ # Note: Also, ${_cur:+-- "$_cur"} and ${_append:+-a} would be affected
673
+ # by uncontrolled IFS.
674
+ local IFS=$' \t\n '
675
+ # Note: extglob *\$?(\{)[0-9]* can be extremely slow when the string
676
+ # "${*:2:_nopt}" becomes longer, so we test \$[0-9] and \$\{[0-9]
677
+ # separately.
678
+ if [[ $* == * \$ [0-9]* || $* == * \$\{ [0-9]* ]]; then
679
+ printf ' bash_completion: %s: positional parameter $1, $2, ... do not work inside this function\n' " $FUNCNAME " >&2
680
+ return 2
681
+ fi
660
682
683
+ _comp_compgen__call_builtin " $@ "
684
+ fi
685
+ }
686
+
687
+ # Helper function for _comp_compgen. This function calls a generator.
688
+ # @param $1... generator_args
689
+ # @var[in] _dir
690
+ # @var[in] _cur
691
+ # @arr[in] _generator
692
+ # @arr[in] _upvars
693
+ # @var[in] _append
694
+ # @var[in] _var
695
+ _comp_compgen__call_generator ()
696
+ {
697
+ (( ${# _upvars[@]} )) && _comp_unlocal " ${_upvars[@]} "
698
+
699
+ if [[ $_dir ]]; then
700
+ local _original_pwd=$PWD
701
+ local PWD=${PWD-} OLDPWD=${OLDPWD-}
702
+ # Note: We also redirect stdout because `cd` may output the target
703
+ # directory to stdout when CDPATH is set.
704
+ command cd -- " $_dir " & > /dev/null ||
705
+ {
706
+ _comp_compgen__error_fallback
707
+ return
708
+ }
709
+ fi
710
+
711
+ local _comp_compgen__append=$_append
712
+ local _comp_compgen__var=$_var
713
+ local _comp_compgen__cur=$_cur cur=$_cur
714
+ # Note: we use $1 as a part of a function name, and we use $2... as
715
+ # arguments to the function if any.
716
+ # shellcheck disable=SC2145
717
+ " ${_generator[@]} " " $@ "
718
+ local _status=$?
719
+
720
+ # Go back to the original directory.
721
+ # Note: Failure of this line results in the change of the current
722
+ # directory visible to the user. We intentionally do not redirect
723
+ # stderr so that the error message appear in the terminal.
724
+ # shellcheck disable=SC2164
725
+ [[ $_dir ]] && command cd -- " $_original_pwd "
726
+
727
+ return " $_status "
728
+ }
729
+
730
+ # Helper function for _comp_compgen. This function calls the builtin compgen.
731
+ # @param $1... compgen_args
732
+ # @var[in] _dir
733
+ # @var[in] _ifs
734
+ # @var[in] _cur
735
+ # @arr[in] _upvars
736
+ # @var[in] _append
737
+ # @var[in] _var
738
+ if (( BASH_VERSINFO[0 ] > 5 || BASH_VERSINFO[0 ] == 5 && BASH_VERSINFO[1 ] >= 3 )) ; then
739
+ # bash >= 5.3 has `compgen -V array_name`
740
+ _comp_compgen__call_builtin ()
741
+ {
661
742
if [[ $_dir ]]; then
662
743
local _original_pwd=$PWD
663
744
local PWD=${PWD-} OLDPWD=${OLDPWD-}
664
745
# Note: We also redirect stdout because `cd` may output the target
665
746
# directory to stdout when CDPATH is set.
666
- command cd -- " $_dir " & > /dev/null ||
667
- {
668
- _comp_compgen__error_fallback
669
- return
670
- }
747
+ command cd -- " $_dir " & > /dev/null || {
748
+ _comp_compgen__error_fallback
749
+ return
750
+ }
671
751
fi
672
752
673
- local _comp_compgen__append=$_append
674
- local _comp_compgen__var=$_var
675
- local _comp_compgen__cur=$_cur cur=$_cur
676
- # Note: we use $1 as a part of a function name, and we use $2... as
677
- # arguments to the function if any.
678
- # shellcheck disable=SC2145
679
- " ${_generator[@]} " " ${@: 2} "
680
- local _status=$?
753
+ local -a _result=()
754
+
755
+ # Note: We specify -X '' to exclude empty completions to make the
756
+ # behavior consistent with the implementation for Bash < 5.3 where
757
+ # `_comp_split -l` removes empty lines. If the caller specifies -X
758
+ # pat, the effect of -X '' is overwritten by the specified one.
759
+ IFS=$_ifs compgen -V _result -X ' ' " $@ " ${_cur: +-- " $_cur " } || {
760
+ _comp_compgen__error_fallback
761
+ return
762
+ }
681
763
682
764
# Go back to the original directory.
683
765
# Note: Failure of this line results in the change of the current
@@ -686,46 +768,35 @@ _comp_compgen()
686
768
# shellcheck disable=SC2164
687
769
[[ $_dir ]] && command cd -- " $_original_pwd "
688
770
689
- return " $_status "
690
- fi
691
-
692
- # usage: _comp_compgen [options] -- [compgen_options]
693
- if [[ $_icmd || $_xcmd ]]; then
694
- printf ' bash_completion: %s: generator name is unspecified for `%s' \' ' \n' " $FUNCNAME " " ${_icmd: +-i $_icmd }${_xcmd: +x $_xcmd } " >&2
695
- return 2
696
- fi
697
-
698
- # Note: $* in the below checks would be affected by uncontrolled IFS in
699
- # bash >= 5.0, so we need to set IFS to the normal value. The behavior in
700
- # bash < 5.0, where unquoted $* in conditional command did not honor IFS,
701
- # was a bug.
702
- # Note: Also, ${_cur:+-- "$_cur"} and ${_append:+-a} would be affected by
703
- # uncontrolled IFS.
704
- local IFS=$' \t\n '
705
- # Note: extglob *\$?(\{)[0-9]* can be extremely slow when the string
706
- # "${*:2:_nopt}" becomes longer, so we test \$[0-9] and \$\{[0-9]
707
- # separately.
708
- if [[ $* == * \$ [0-9]* || $* == * \$\{ [0-9]* ]]; then
709
- printf ' bash_completion: %s: positional parameter $1, $2, ... do not work inside this function\n' " $FUNCNAME " >&2
710
- return 2
711
- fi
712
-
713
- local _result
714
- _result=$(
715
- if [[ $_dir ]]; then
716
- # Note: We also redirect stdout because `cd` may output the target
717
- # directory to stdout when CDPATH is set.
718
- command cd -- " $_dir " & > /dev/null || return
771
+ (( ${# _upvars[@]} )) && _comp_unlocal " ${_upvars[@]} "
772
+ (( ${# _result[@]} )) || return
773
+ if [[ $_append ]]; then
774
+ eval -- " $_var +=(\"\$ {_result[@]}\" )"
775
+ else
776
+ eval -- " $_var =(\"\$ {_result[@]}\" )"
719
777
fi
720
- IFS=$_ifs compgen " $@ " ${_cur: +-- " $_cur " }
721
- ) || {
722
- _comp_compgen__error_fallback
723
778
return
724
779
}
780
+ else
781
+ _comp_compgen__call_builtin ()
782
+ {
783
+ local _result
784
+ _result=$(
785
+ if [[ $_dir ]]; then
786
+ # Note: We also redirect stdout because `cd` may output the target
787
+ # directory to stdout when CDPATH is set.
788
+ command cd -- " $_dir " & > /dev/null || return
789
+ fi
790
+ IFS=$_ifs compgen " $@ " ${_cur: +-- " $_cur " }
791
+ ) || {
792
+ _comp_compgen__error_fallback
793
+ return
794
+ }
725
795
726
- (( ${# _upvars[@]} )) && _comp_unlocal " ${_upvars[@]} "
727
- _comp_split -l ${_append: +-a} " $_var " " $_result "
728
- }
796
+ (( ${# _upvars[@]} )) && _comp_unlocal " ${_upvars[@]} "
797
+ _comp_split -l ${_append: +-a} " $_var " " $_result "
798
+ }
799
+ fi
729
800
730
801
# usage: _comp_compgen_set [words...]
731
802
# Reset COMPREPLY with the specified WORDS. If no arguments are specified, the
0 commit comments