@@ -441,6 +441,7 @@ _comp_split()
441
441
# @var[in] $?
442
442
# @var[in] _var
443
443
# @var[in] _append
444
+ # @var[in] _upvars
444
445
# @return original $?
445
446
_comp_compgen__error_fallback ()
446
447
{
@@ -451,35 +452,46 @@ _comp_compgen__error_fallback()
451
452
else
452
453
eval -- " $_var =()"
453
454
fi
455
+ if (( ${# _upvars[@]} )) ; then
456
+ _comp_unlocal " ${_upvars[@]} "
457
+ _upvars=()
458
+ fi
454
459
return " $_status "
455
460
}
456
461
457
462
# Provide a common interface to generate completion candidates in COMPREPLY or
458
463
# in a specified array.
459
464
# OPTIONS
460
- # -a Append to the array
461
- # -v arr Store the results to the array ARR. The default is `COMPREPLY`.
462
- # The array name should not start with an underscores "_", which is
463
- # internally used. The array name should not be any of "cur", "IFS"
464
- # or "OPT{IND,ARG,ERR}".
465
- # -U var Unlocalize VAR before performing the assignments. This option can
466
- # be specified multiple times to register multiple variables. This
467
- # option is supposed to be used in implementing a generator (G1) when
468
- # G1 defines a local variable name that does not start with `_`. In
469
- # such a case, when the target variable specified to G1 by `-v VAR1`
470
- # conflicts with the local variable, the assignment to the target
471
- # variable fails to propagate outside G1. To avoid such a situation,
472
- # G1 can call `_comp_compgen` with `-U VAR` to unlocalize `VAR`
473
- # before accessing the target variable. For a builtin compgen call
474
- # (i.e., _comp_compgen [options] -- options), VAR is unlocalized
475
- # after calling the builtin `compgen` but before assigning results to
476
- # the target array. For a generator call (i.e., _comp_compgen
477
- # [options] G2 ...), VAR is unlocalized before calling the child
478
- # generator function `_comp_compgen_G2`.
479
- # -c cur Set a word used as a prefix to filter the completions. The default
480
- # is ${cur-}.
481
- # -R The same as -c ''. Use raw outputs without filtering.
482
- # -C dir Evaluate compgen/generator in the specified directory.
465
+ # -a Append to the array
466
+ # -v arr Store the results to the array ARR. The default is `COMPREPLY`.
467
+ # The array name should not start with an underscores "_", which is
468
+ # internally used. The array name should not be any of "cur",
469
+ # "IFS" or "OPT{IND,ARG,ERR}".
470
+ # -U var Unlocalize VAR before performing the assignments. This option
471
+ # can be specified multiple times to register multiple variables.
472
+ # This option is supposed to be used in implementing a generator
473
+ # (G1) when G1 defines a local variable name that does not start
474
+ # with `_`. In such a case, when the target variable specified to
475
+ # G1 by `-v VAR1` conflicts with the local variable, the assignment
476
+ # to the target variable fails to propagate outside G1. To avoid
477
+ # such a situation, G1 can call `_comp_compgen` with `-U VAR` to
478
+ # unlocalize `VAR` before accessing the target variable. For a
479
+ # builtin compgen call (i.e., _comp_compgen [options] -- options),
480
+ # VAR is unlocalized after calling the builtin `compgen` but before
481
+ # assigning results to the target array. For a generator call
482
+ # (i.e., _comp_compgen [options] G2 ...), VAR is unlocalized before
483
+ # calling the child generator function `_comp_compgen_G2`.
484
+ # -c cur Set a word used as a prefix to filter the completions. The
485
+ # default is ${cur-}.
486
+ # -R The same as -c ''. Use raw outputs without filtering.
487
+ # -C dir Evaluate compgen/generator in the specified directory.
488
+ # -P prefix Prepend the prefix to the generated completions. Unlike `compgen
489
+ # -P prefix`, this prefix is subject to filtering by `cur`. When a
490
+ # non-empty prefix is specified, first `cur` is tested whether it
491
+ # is consistent with the prefix. Then, `cur` is reduced for the
492
+ # part excluding the prefix, and the normal completion generation
493
+ # is performed. Finally, the prefix is prepended to generated
494
+ # completions.
483
495
# @var[in,opt] cur Used as the default value of a prefix to filter the
484
496
# completions.
485
497
#
@@ -564,6 +576,7 @@ _comp_compgen()
564
576
local _var=
565
577
local _cur=${_comp_compgen__cur-${cur-} }
566
578
local _dir=" "
579
+ local _prefix=" "
567
580
local _ifs=$' \t\n ' _has_ifs=" "
568
581
local _icmd=" " _xcmd=" "
569
582
local -a _upvars=()
@@ -574,7 +587,7 @@ _comp_compgen()
574
587
shopt -u nocasematch
575
588
fi
576
589
local OPTIND=1 OPTARG=" " OPTERR=0 _opt
577
- while getopts ' :av:U:Rc:C:lF:i:x:' _opt " $@ " ; do
590
+ while getopts ' :av:U:Rc:C:P: lF:i:x:' _opt " $@ " ; do
578
591
case $_opt in
579
592
a) _append=set ;;
580
593
v)
@@ -603,6 +616,7 @@ _comp_compgen()
603
616
fi
604
617
_dir=$OPTARG
605
618
;;
619
+ P) _prefix=$OPTARG ;;
606
620
l) _has_ifs=set _ifs=$' \n ' ;;
607
621
F) _has_ifs=set _ifs=$OPTARG ;;
608
622
[ix])
@@ -638,6 +652,19 @@ _comp_compgen()
638
652
[[ $_append ]] || _append=${_comp_compgen__append-}
639
653
fi
640
654
655
+ local _prefix_fail=" "
656
+ if [[ $_prefix ]]; then
657
+ if [[ $_cur == " $_prefix " * ]]; then
658
+ _cur=${_cur# " $_prefix " }
659
+ elif [[ $_prefix == " $_cur " * ]]; then
660
+ _cur=" "
661
+ else
662
+ # No completions are generated because the current word does not match
663
+ # the prefix.
664
+ _prefix_fail=set
665
+ fi
666
+ fi
667
+
641
668
if [[ $1 != -* ]]; then
642
669
# usage: _comp_compgen [options] NAME args
643
670
if [[ $_has_ifs ]]; then
@@ -659,6 +686,11 @@ _comp_compgen()
659
686
fi
660
687
shift
661
688
689
+ if [[ $_prefix_fail ]]; then
690
+ _comp_compgen__error_fallback
691
+ return 1
692
+ fi
693
+
662
694
_comp_compgen__call_generator " $@ "
663
695
else
664
696
# usage: _comp_compgen [options] -- [compgen_options]
@@ -682,6 +714,11 @@ _comp_compgen()
682
714
return 2
683
715
fi
684
716
717
+ if [[ $_prefix_fail ]]; then
718
+ _comp_compgen__error_fallback
719
+ return 1
720
+ fi
721
+
685
722
_comp_compgen__call_builtin " $@ "
686
723
fi
687
724
}
@@ -696,8 +733,6 @@ _comp_compgen()
696
733
# @var[in] _var
697
734
_comp_compgen__call_generator ()
698
735
{
699
- (( ${# _upvars[@]} )) && _comp_unlocal " ${_upvars[@]} "
700
-
701
736
if [[ $_dir ]]; then
702
737
local _original_pwd=$PWD
703
738
local PWD=${PWD-} OLDPWD=${OLDPWD-}
@@ -710,14 +745,28 @@ _comp_compgen__call_generator()
710
745
}
711
746
fi
712
747
748
+ (( ${# _upvars[@]} )) && _comp_unlocal " ${_upvars[@]} "
749
+
713
750
local _comp_compgen__append=$_append
714
751
local _comp_compgen__var=$_var
715
752
local _comp_compgen__cur=$_cur cur=$_cur
753
+ if [[ $_prefix ]]; then
754
+ local -a tmp=()
755
+ local _comp_compgen__var=tmp
756
+ local _comp_compgen__append=" "
757
+ fi
716
758
# Note: we use $1 as a part of a function name, and we use $2... as
717
759
# arguments to the function if any.
718
760
# shellcheck disable=SC2145
719
761
" ${_generator[@]} " " $@ "
720
762
local _status=$?
763
+ if [[ $_prefix ]]; then
764
+ local _i
765
+ for _i in " ${! tmp[@]} " ; do
766
+ tmp[_i]=$_prefix ${tmp[_i]}
767
+ done
768
+ _comp_compgen -RU tmp ${_append: +-a} -v " $_var " -- -W ' "${tmp[@]}"'
769
+ fi
721
770
722
771
# Go back to the original directory.
723
772
# Note: Failure of this line results in the change of the current
@@ -772,6 +821,13 @@ if ((BASH_VERSINFO[0] > 5 || BASH_VERSINFO[0] == 5 && BASH_VERSINFO[1] >= 3)); t
772
821
773
822
(( ${# _upvars[@]} )) && _comp_unlocal " ${_upvars[@]} "
774
823
(( ${# _result[@]} )) || return
824
+
825
+ if [[ $_prefix ]]; then
826
+ local _i
827
+ for _i in " ${! _result[@]} " ; do
828
+ _result[_i]=$_prefix ${_result[_i]}
829
+ done
830
+ fi
775
831
if [[ $_append ]]; then
776
832
eval -- " $_var +=(\"\$ {_result[@]}\" )"
777
833
else
@@ -796,7 +852,13 @@ else
796
852
}
797
853
798
854
(( ${# _upvars[@]} )) && _comp_unlocal " ${_upvars[@]} "
799
- _comp_split -l ${_append: +-a} " $_var " " $_result "
855
+
856
+ if [[ $_prefix ]]; then
857
+ _comp_split -l ${_append: +-a} " $_var " \
858
+ " $( IFS=$' \n ' compgen -W ' $_result' -P " $_prefix " ) "
859
+ else
860
+ _comp_split -l ${_append: +-a} " $_var " " $_result "
861
+ fi
800
862
}
801
863
fi
802
864
@@ -1854,7 +1916,7 @@ _comp_compgen_tilde()
1854
1916
{
1855
1917
if [[ ${cur-} == \~ * && $cur != * /* ]]; then
1856
1918
# Try generate ~username completions
1857
- if _comp_compgen -c " ${cur # \~ } " -- - P ' ~' -u; then
1919
+ if _comp_compgen -P ' ~' -- -u; then
1858
1920
# 2>/dev/null for direct invocation, e.g. in the
1859
1921
# _comp_compgen_tilde unit test
1860
1922
compopt -o filenames 2> /dev/null
0 commit comments