@@ -968,13 +968,51 @@ _comp_variable_assignments()
968968 return 0
969969}
970970
971- _comp_return_hook ()
972- {
973- (( ${# FUNCNAME[*]} != 2 )) && return # this _will_ need some refinement and thought
974- echo " Hello from return hook for ${FUNCNAME[1]} "
975- echo " words: ${words[@]} "
976- echo " COMPREPLY: ${COMPREPLY[@]} "
971+ _comp_finalize__depth= ()
972+ _comp_finalize__target= ()
973+ _comp_finalize__original_return_trap=
974+
975+ # This associative array contains the finalizer commands with the key
976+ # being the name of the completed command.
977+ declare -g A BASH_COMPLETION_FINALIZE_CMD_HOOKS
978+
979+ # This array contains the general finalizer commands that will be
980+ # executed for all the commands.
981+ declare -g a BASH_COMPLETION_FINALIZE_HOOKS
982+
983+ _comp_finalize ()
984+ {
985+ (( ${# _comp_finalize__depth[@]} )) || return 0
986+ while (( ${# FUNCNAME[@]} <= ${_comp_finalize__depth[-1]} )) ; do
987+ if [[ ${# FUNCNAME[@]} -eq ${_comp_finalize__depth[-1]} && ${FUNCNAME[1]-} == " ${_comp_finalize__target[-1]} " ]]; then
988+ # Call finalizer for each command
989+ local cmd=${words[0]-} _comp_local_hook
990+ if [[ $cmd ]]; then
991+ _comp_local_hook=${BASH_COMPLETION_FINALIZE_CMD_HOOKS[$cmd]-}
992+ eval -- " $_comp_local_hook "
993+ fi
994+
995+ # Call general finalizers
996+ if [[ ${BASH_COMPLETION_FINALIZE_HOOKS[*]+set} ]]; then
997+ for _comp_local_hook in " ${BASH_COMPLETION_FINALIZE_HOOKS[@]} " ; do
998+ eval -- " $_comp_local_hook "
999+ done
1000+ fi
1001+ fi
1002+
1003+ unset -v ' _comp_finalize__depth[-1]'
1004+ unset -v ' _comp_finalize__target[-1]'
1005+ if (( ${# _comp_finalize__depth[@]} == 0 )) ; then
1006+ eval -- " ${_comp_finalize__original_return_trap:- trap - RETURN} "
1007+ _comp_finalize__original_return_trap=
1008+ break
1009+ fi
1010+ done
9771011}
1012+ # Note: We need to set "trace" function attribute of _comp_finalize to
1013+ # make the trap restoration by "trap - RETURN" take effect in the
1014+ # upper level.
1015+ declare -f t _comp_finalize
9781016
9791017# Initialize completion and deal with various general things: do file
9801018# and variable completion where appropriate, and adjust prev, words,
@@ -1009,7 +1047,28 @@ _comp_initialize()
10091047{
10101048 local exclude=" " opt_split=" " outx errx inx
10111049
1012- trap _comp_return_hook RETURN
1050+ if (( ${# FUNCNAME[@]} >= 2 )) ; then
1051+ # Install "_comp_finalize" to the RETURN trap when "_init_completion" is
1052+ # called for the top-level completion. [ Note: the completion function may
1053+ # be called recursively using "_command_offset", etc. ]
1054+ if (( ${# _comp_finalize__depth[@]} == 0 )) ; then
1055+ if shopt -q extdebug || shopt -qo functrace; then
1056+ # If extdebug / functrace is set, we need to explicitly save and
1057+ # restore the original trap handler because the outer trap handlers
1058+ # will be affected by "trap - RETURN" inside functions with these
1059+ # settings.
1060+ _comp_finalize__original_return_trap=$( trap -p RETURN)
1061+ else
1062+ # Otherwise, the outer RETURN trap will be restored when the RETURN
1063+ # trap is removed inside the functions using "trap - RETURN". So, we
1064+ # do not need to explicitly save the outer trap handler.
1065+ _comp_finalize__original_return_trap=
1066+ fi
1067+ trap _comp_finalize RETURN
1068+ fi
1069+ _comp_finalize__depth+=(" ${# FUNCNAME[@]} " )
1070+ _comp_finalize__target+=(" ${FUNCNAME[1]-} " )
1071+ fi
10131072
10141073 local flag OPTIND=1 OPTARG=" " OPTERR=0
10151074 while getopts " n:e:o:i:s" flag " $@ " ; do
0 commit comments