@@ -381,6 +381,23 @@ _comp_split()
381381    (( _new_size >  _old_size)) 
382382}
383383
384+ #  Helper function for _comp_compgen
385+ #  @var[in] $?
386+ #  @var[in] _var
387+ #  @var[in] _append
388+ #  @return original $?
389+ _comp_compgen__error_fallback ()
390+ {
391+     local  _status=$? 
392+     if  [[ $_append  ]];  then 
393+         #  make sure existence of variable
394+         eval  -- " $_var +=()" 
395+     else 
396+         eval  -- " $_var =()" 
397+     fi 
398+     return  " $_status " 
399+ }
400+ 
384401#  Provide a common interface to generate completion candidates in COMPREPLY or
385402#  in a specified array.
386403#  OPTIONS
@@ -398,6 +415,7 @@ _comp_split()
398415#    -c cur  Set a word used as a prefix to filter the completions.  The default
399416#            is ${cur-}.
400417#    -R      The same as -c ''.  Use raw outputs without filtering.
418+ #    -C dir  Evaluate compgen/generator in the specified directory.
401419#  @var[in,opt] cur  Used as the default value of a prefix to filter the
402420#    completions.
403421# 
@@ -421,10 +439,10 @@ _comp_split()
421439#    as `-v arr` as a part of the `_comp_compgen` options.
422440# 
423441#  Usage #2: _comp_compgen [-alR|-v arr|-c cur] name args...
424- #  Call `_comp_compgen_NAME ARGS...` with the specified options.  This provides 
425- #  a common interface to call the functions `_comp_compgen_NAME`, which produce 
426- #  completion candidates, with custom options [-alR|-v arr|-c cur].  The option 
427- #  `-F sep` is not used with this usage.
442+ #  Call the generator  `_comp_compgen_NAME ARGS...` with the specified options.
443+ #  This provides  a common interface to call the functions `_comp_compgen_NAME`,
444+ #  which produce  completion candidates, with custom options [-alR|-v arr|-c
445+ #  cur].  The option  `-F sep` is not used with this usage.
428446#  @param $1... name args  Calls the function _comp_compgen_NAME with the
429447#    specified ARGS (if $1 does not start with a hyphen `-`).  The options
430448#    [-alR|-v arr|-c cur] are inherited by the child calls of `_comp_compgen`
@@ -467,10 +485,15 @@ _comp_compgen()
467485    local  _append=${_comp_compgen__append-} 
468486    local  _var=${_comp_compgen__var-COMPREPLY} 
469487    local  _cur=${_comp_compgen__cur-${cur-} } 
470-     local  _ifs=$'  \t\n ' 
488+     local  _ifs=$'  \t\n '  _dir= " " 
471489
490+     local  _old_nocasematch=" " 
491+     if  shopt  -q nocasematch;  then 
492+         _old_nocasematch=set
493+         shopt  -u nocasematch
494+     fi 
472495    local  OPTIND=1 OPTARG=" " 
473-     while  getopts  ' :alF:v:Rc:' " $@ " ;  do 
496+     while  getopts  ' :alF:v:Rc:C: ' " $@ " ;  do 
474497        case  $_opt  in 
475498            a) _append=set ;;
476499            v)
@@ -484,6 +507,13 @@ _comp_compgen()
484507            F) _ifs=$OPTARG  ;;
485508            c) _cur=$OPTARG  ;;
486509            R) _cur=" " 
510+             C)
511+                 if  [[ !  $OPTARG  ||  !  -d  $OPTARG  ]];  then 
512+                     printf  ' bash_completion: %s: -C: invalid directory name `%s' \' ' .\n' " $FUNCNAME " " $OPTARG " >&2 
513+                     return  2
514+                 fi 
515+                 _dir=$OPTARG 
516+                 ;;
487517            * )
488518                printf  ' bash_completion: %s: usage error\n' " $FUNCNAME " >&2 
489519                return  2
@@ -494,8 +524,10 @@ _comp_compgen()
494524    if  (( $#  ==  0 )) ;  then 
495525        printf  ' bash_completion: %s: unexpected number of arguments.\n' " $FUNCNAME " >&2 
496526        printf  ' usage: %s [-alR|-F SEP|-v ARR|-c CUR] -- ARGS...' " $FUNCNAME " >&2 
527+         [[ $_old_nocasematch  ]] &&  shopt  -s nocasematch
497528        return  2
498529    fi 
530+     [[ $_old_nocasematch  ]] &&  shopt  -s nocasematch
499531
500532    if  [[ $1  !=  -*  ]];  then 
501533        #  usage: _comp_compgen [options] NAME args
@@ -504,14 +536,29 @@ _comp_compgen()
504536            return  2
505537        fi 
506538
539+         if  [[ $_dir  ]];  then 
540+             local  _original_pwd=$PWD 
541+             local  PWD=$PWD  OLDPWD=$OLDPWD 
542+             command  cd  -- " $_dir " & > /dev/null || 
543+                 {
544+                     _comp_compgen__error_fallback
545+                     return 
546+                 }
547+         fi 
548+ 
507549        local  _comp_compgen__append=$_append 
508550        local  _comp_compgen__var=$_var 
509551        local  _comp_compgen__cur=$_cur  cur=$_cur 
510552        #  Note: we use $1 as a part of a function name, and we use $2... as
511553        #  arguments to the function if any.
512554        #  shellcheck disable=SC2145
513555        _comp_compgen_" $@ " 
514-         return 
556+         local  _status=$? 
557+ 
558+         #  shellcheck disable=SC2164
559+         [[ $_dir  ]] &&  command  cd  -- " $_original_pwd " 
560+ 
561+         return  " $_status " 
515562    fi 
516563
517564    #  usage: _comp_compgen [options] -- [compgen_options]
@@ -533,16 +580,15 @@ _comp_compgen()
533580
534581    local  _result
535582    _result=$( 
583+         if  [[ $_dir  ]];  then  
584+             #  Note: We also redirect stdout because `cd` may output the target 
585+             #  directory to stdout when CDPATH is set. 
586+             command  cd  -- " $_dir " & > /dev/null ||  return  
587+         fi  
536588        IFS=$_ifs  compgen  " $@ " ${_cur: +-- " $_cur "   
537589    )   ||  {
538-         local  _status=$? 
539-         if  [[ $_append  ]];  then 
540-             #  make sure existence of variable
541-             eval  -- " $_var +=()" 
542-         else 
543-             eval  -- " $_var =()" 
544-         fi 
545-         return  " $_status " 
590+         _comp_compgen__error_fallback
591+         return 
546592    }
547593
548594    _comp_split -l ${_append: +-a}  " $_var " " $_result " 
0 commit comments