@@ -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=" " OPTERR=0 _opt
473- while getopts ' :alF:v:Rc:' _opt " $@ " ; do
496+ while getopts ' :alF:v:Rc:C: ' _opt " $@ " ; 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