@@ -371,11 +371,11 @@ _comp_split()
371
371
done
372
372
shift " $(( OPTIND - 1 )) "
373
373
if (( $# != 2 )) ; then
374
- printf ' %s\n' " bash_completion: $FUNCNAME : unexpected number of arguments. " >&2
374
+ printf ' %s\n' " bash_completion: $FUNCNAME : unexpected number of arguments" >&2
375
375
printf ' %s\n' " usage: $FUNCNAME [-a] [-F SEP] ARRAY_NAME TEXT" >&2
376
376
return 2
377
377
elif [[ $1 == @ (* [^_a-zA-Z0-9]* | [0-9]* | ' ' | _* | IFS| OPTIND| OPTARG| OPTERR) ]]; then
378
- printf ' %s\n' " bash_completion: $FUNCNAME : invalid array name '$1 '. " >&2
378
+ printf ' %s\n' " bash_completion: $FUNCNAME : invalid array name '$1 '" >&2
379
379
return 2
380
380
fi
381
381
@@ -422,26 +422,27 @@ _comp_compgen__error_fallback()
422
422
# The array name should not start with an underscores "_", which is
423
423
# internally used. The array name should not be either "IFS" or
424
424
# "OPT{IND,ARG,ERR}".
425
- # -F sep Set a set of separator characters (used as IFS in evaluating
426
- # `compgen'). The default separator is $' \t\n'. Note that this is
427
- # not the set of separators to delimit output of `compgen', but the
428
- # separators in evaluating the expansions of `-W '...'`, etc. The
429
- # delimiter of the output of `compgen` is always a newline.
430
- # -l The same as -F $'\n'. Use lines as words in evaluating compgen.
431
425
# -c cur Set a word used as a prefix to filter the completions. The default
432
426
# is ${cur-}.
433
427
# -R The same as -c ''. Use raw outputs without filtering.
434
428
# -C dir Evaluate compgen/generator in the specified directory.
435
429
# @var[in,opt] cur Used as the default value of a prefix to filter the
436
430
# completions.
437
431
#
438
- # Usage #1: _comp_compgen [-alR|-F sep|-v arr|-c cur] -- options...
432
+ # Usage #1: _comp_compgen [-alR|-F sep|-v arr|-c cur|-C dir ] -- options...
439
433
# Call `compgen` with the specified arguments and store the results in the
440
434
# specified array. This function essentially performs arr=($(compgen args...))
441
435
# but properly handles shell options, IFS, etc. using _comp_split. This
442
436
# function is equivalent to `_comp_split [-a] -l arr "$(IFS=sep; compgen
443
437
# args... -- cur)"`, but this pattern is frequent in the codebase and is good
444
438
# to separate out as a function for the possible future implementation change.
439
+ # OPTIONS
440
+ # -F sep Set a set of separator characters (used as IFS in evaluating
441
+ # `compgen'). The default separator is $' \t\n'. Note that this is
442
+ # not the set of separators to delimit output of `compgen', but the
443
+ # separators in evaluating the expansions of `-W '...'`, etc. The
444
+ # delimiter of the output of `compgen` is always a newline.
445
+ # -l The same as -F $'\n'. Use lines as words in evaluating compgen.
445
446
# @param $1... options Arguments that are passed to compgen (if $1 starts with
446
447
# a hyphen `-`).
447
448
#
@@ -453,12 +454,17 @@ _comp_compgen__error_fallback()
453
454
#
454
455
# Note: The array option `-V arr` in bash >= 5.3 should be instead specified
455
456
# as `-v arr` as a part of the `_comp_compgen` options.
457
+ # @return True (0) if at least one completion is generated, False (1) if no
458
+ # completion is generated, or 2 with an incorrect usage.
456
459
#
457
- # Usage #2: _comp_compgen [-alR |-v arr|-c cur] name args...
460
+ # Usage #2: _comp_compgen [-aR |-v arr|-c cur|-C dir|-i cmd|-x cmd ] name args...
458
461
# Call the generator `_comp_compgen_NAME ARGS...` with the specified options.
459
462
# This provides a common interface to call the functions `_comp_compgen_NAME`,
460
463
# which produce completion candidates, with custom options [-alR|-v arr|-c
461
464
# cur]. The option `-F sep` is not used with this usage.
465
+ # OPTIONS
466
+ # -x cmd Call exported generator `_comp_xfunc_CMD_compgen_NAME`
467
+ # -i cmd Call internal generator `_comp_cmd_CMD__compgen_NAME`
462
468
# @param $1... name args Calls the function _comp_compgen_NAME with the
463
469
# specified ARGS (if $1 does not start with a hyphen `-`). The options
464
470
# [-alR|-v arr|-c cur] are inherited by the child calls of `_comp_compgen`
@@ -470,6 +476,7 @@ _comp_compgen__error_fallback()
470
476
# These variables are internally used to pass the effect of the options
471
477
# [-alR|-v arr|-c cur] to the child calls of `_comp_compgen` in
472
478
# `_comp_compgen_NAME`.
479
+ # @return Exit status of the generator.
473
480
#
474
481
# @remarks When no options are supplied to _comp_compgen, `_comp_compgen NAME
475
482
# args` is equivalent to the direct call `_comp_compgen_NAME args`. As the
@@ -502,35 +509,51 @@ _comp_compgen()
502
509
local _append=${_comp_compgen__append-}
503
510
local _var=${_comp_compgen__var-COMPREPLY}
504
511
local _cur=${_comp_compgen__cur-${cur-} }
505
- local _ifs=$' \t\n ' _dir=" "
512
+ local _dir=" "
513
+ local _ifs=$' \t\n ' _has_ifs=" "
514
+ local _icmd=" " _xcmd=" "
506
515
507
516
local _old_nocasematch=" "
508
517
if shopt -q nocasematch; then
509
518
_old_nocasematch=set
510
519
shopt -u nocasematch
511
520
fi
512
521
local OPTIND=1 OPTARG=" " OPTERR=0 _opt
513
- while getopts ' :alF:v: Rc:C:' _opt " $@ " ; do
522
+ while getopts ' :av: Rc:C:lF:i:x :' _opt " $@ " ; do
514
523
case $_opt in
515
524
a) _append=set ;;
516
525
v)
517
526
if [[ $OPTARG == @ (* [^_a-zA-Z0-9]* | [0-9]* | ' ' | _* | IFS| OPTIND| OPTARG| OPTERR) ]]; then
518
- printf ' bash_completion: %s: -v: invalid array name `%s' \' ' . \n' " $FUNCNAME " " $OPTARG " >&2
527
+ printf ' bash_completion: %s: -v: invalid array name `%s' \' ' \n' " $FUNCNAME " " $OPTARG " >&2
519
528
return 2
520
529
fi
521
530
_var=$OPTARG
522
531
;;
523
- l) _ifs=$' \n ' ;;
524
- F) _ifs=$OPTARG ;;
525
532
c) _cur=$OPTARG ;;
526
533
R) _cur=" " ;;
527
534
C)
528
535
if [[ ! $OPTARG ]]; then
529
- printf ' bash_completion: %s: -C: invalid directory name `%s' \' ' . \n' " $FUNCNAME " " $OPTARG " >&2
536
+ printf ' bash_completion: %s: -C: invalid directory name `%s' \' ' \n' " $FUNCNAME " " $OPTARG " >&2
530
537
return 2
531
538
fi
532
539
_dir=$OPTARG
533
540
;;
541
+ l) _has_ifs=set _ifs=$' \n ' ;;
542
+ F) _has_ifs=set _ifs=$OPTARG ;;
543
+ [ix])
544
+ if [[ ! $OPTARG ]]; then
545
+ printf ' bash_completion: %s: -%s: invalid command name `%s' \' ' \n' " $FUNCNAME " " $_opt " " $OPTARG " >&2
546
+ return 2
547
+ elif [[ $_icmd ]]; then
548
+ printf ' bash_completion: %s: -%s: `-i %s' \' ' is already specified\n' " $FUNCNAME " " $_opt " " $_icmd " >&2
549
+ return 2
550
+ elif [[ $_xcmd ]]; then
551
+ printf ' bash_completion: %s: -%s: `-x %s' \' ' is already specified\n' " $FUNCNAME " " $_opt " " $_xcmd " >&2
552
+ return 2
553
+ fi
554
+ ;;&
555
+ i) _icmd=$OPTARG ;;
556
+ x) _xcmd=$OPTARG ;;
534
557
* )
535
558
printf ' bash_completion: %s: usage error\n' " $FUNCNAME " >&2
536
559
return 2
@@ -540,15 +563,28 @@ _comp_compgen()
540
563
[[ $_old_nocasematch ]] && shopt -s nocasematch
541
564
shift " $(( OPTIND - 1 )) "
542
565
if (( $# == 0 )) ; then
543
- printf ' bash_completion: %s: unexpected number of arguments. \n' " $FUNCNAME " >&2
566
+ printf ' bash_completion: %s: unexpected number of arguments\n' " $FUNCNAME " >&2
544
567
printf ' usage: %s [-alR|-F SEP|-v ARR|-c CUR] -- ARGS...' " $FUNCNAME " >&2
545
568
return 2
546
569
fi
547
570
548
571
if [[ $1 != -* ]]; then
549
572
# usage: _comp_compgen [options] NAME args
550
- if ! declare -F " _comp_compgen_$1 " & > /dev/null; then
551
- printf ' bash_completion: %s: unrecognized category `%s' \' ' (function _comp_compgen_%s not found).\n' " $FUNCNAME " " $1 " " $1 " >&2
573
+ if [[ $_has_ifs ]]; then
574
+ printf ' bash_completion: %s: `-l' \' ' and `-F sep' \' ' are not supported for generators\n' " $FUNCNAME " >&2
575
+ return 2
576
+ fi
577
+
578
+ local -a _generator
579
+ if [[ $_icmd ]]; then
580
+ _generator=(" _comp_cmd_${_icmd// [^a-zA-Z0-9_]/ _} __compgen_$1 " )
581
+ elif [[ $_xcmd ]]; then
582
+ _generator=(_comp_xfunc " $_xcmd " " compgen_$1 " )
583
+ else
584
+ _generator=(" _comp_compgen_$1 " )
585
+ fi
586
+ if ! declare -F " ${_generator[0]} " & > /dev/null; then
587
+ printf ' bash_completion: %s: unrecognized generator `%s' \' ' (function %s not found)\n' " $FUNCNAME " " $1 " " ${_generator[0]} " >&2
552
588
return 2
553
589
fi
554
590
@@ -570,7 +606,7 @@ _comp_compgen()
570
606
# Note: we use $1 as a part of a function name, and we use $2... as
571
607
# arguments to the function if any.
572
608
# shellcheck disable=SC2145
573
- _comp_compgen_ " $@ "
609
+ " ${_generator[@]} " " ${ @: 2} "
574
610
local _status=$?
575
611
576
612
# Go back to the original directory.
@@ -584,6 +620,10 @@ _comp_compgen()
584
620
fi
585
621
586
622
# usage: _comp_compgen [options] -- [compgen_options]
623
+ if [[ $_icmd || $_xcmd ]]; then
624
+ printf ' bash_completion: %s: generator name is unspecified for `%s' \' ' \n' " $FUNCNAME " " ${_icmd: +-i $_icmd }${_xcmd: +x $_xcmd } " >&2
625
+ return 2
626
+ fi
587
627
588
628
# Note: $* in the below checks would be affected by uncontrolled IFS in
589
629
# bash >= 5.0, so we need to set IFS to the normal value. The behavior in
@@ -596,7 +636,7 @@ _comp_compgen()
596
636
# "${*:2:_nopt}" becomes longer, so we test \$[0-9] and \$\{[0-9]
597
637
# separately.
598
638
if [[ $* == * \$ [0-9]* || $* == * \$\{ [0-9]* ]]; then
599
- printf ' bash_completion: %s: positional parameter $1, $2, ... do not work inside this function. \n' " $FUNCNAME " >&2
639
+ printf ' bash_completion: %s: positional parameter $1, $2, ... do not work inside this function\n' " $FUNCNAME " >&2
600
640
return 2
601
641
fi
602
642
0 commit comments