@@ -987,13 +987,51 @@ _comp_variable_assignments()
987987 return 0
988988}
989989
990- _comp_return_hook ()
991- {
992- (( ${# FUNCNAME[*]} != 2 )) && return # this _will_ need some refinement and thought
993- echo " Hello from return hook for ${FUNCNAME[1]} "
994- echo " words: ${words[@]} "
995- echo " COMPREPLY: ${COMPREPLY[@]} "
990+ _comp_finalize__depth= ()
991+ _comp_finalize__target= ()
992+ _comp_finalize__original_return_trap=
993+
994+ # This associative array contains the finalizer commands with the key
995+ # being the name of the completed command.
996+ declare -g A BASH_COMPLETION_FINALIZE_CMD_HOOKS
997+
998+ # This array contains the general finalizer commands that will be
999+ # executed for all the commands.
1000+ declare -g a BASH_COMPLETION_FINALIZE_HOOKS
1001+
1002+ _comp_finalize ()
1003+ {
1004+ (( ${# _comp_finalize__depth[@]} )) || return 0
1005+ while (( ${# FUNCNAME[@]} <= ${_comp_finalize__depth[-1]} )) ; do
1006+ if [[ ${# FUNCNAME[@]} -eq ${_comp_finalize__depth[-1]} && ${FUNCNAME[1]-} == " ${_comp_finalize__target[-1]} " ]]; then
1007+ # Call finalizer for each command
1008+ local cmd=${words[0]-} _comp_local_hook
1009+ if [[ $cmd ]]; then
1010+ _comp_local_hook=${BASH_COMPLETION_FINALIZE_CMD_HOOKS[$cmd]-}
1011+ eval -- " $_comp_local_hook "
1012+ fi
1013+
1014+ # Call general finalizers
1015+ if [[ ${BASH_COMPLETION_FINALIZE_HOOKS[*]+set} ]]; then
1016+ for _comp_local_hook in " ${BASH_COMPLETION_FINALIZE_HOOKS[@]} " ; do
1017+ eval -- " $_comp_local_hook "
1018+ done
1019+ fi
1020+ fi
1021+
1022+ unset -v ' _comp_finalize__depth[-1]'
1023+ unset -v ' _comp_finalize__target[-1]'
1024+ if (( ${# _comp_finalize__depth[@]} == 0 )) ; then
1025+ eval -- " ${_comp_finalize__original_return_trap:- trap - RETURN} "
1026+ _comp_finalize__original_return_trap=
1027+ break
1028+ fi
1029+ done
9961030}
1031+ # Note: We need to set "trace" function attribute of _comp_finalize to
1032+ # make the trap restoration by "trap - RETURN" take effect in the
1033+ # upper level.
1034+ declare -f t _comp_finalize
9971035
9981036# Initialize completion and deal with various general things: do file
9991037# and variable completion where appropriate, and adjust prev, words,
@@ -1028,7 +1066,28 @@ _comp_initialize()
10281066{
10291067 local exclude=" " opt_split=" " outx errx inx
10301068
1031- trap _comp_return_hook RETURN
1069+ if (( ${# FUNCNAME[@]} >= 2 )) ; then
1070+ # Install "_comp_finalize" to the RETURN trap when "_init_completion" is
1071+ # called for the top-level completion. [ Note: the completion function may
1072+ # be called recursively using "_command_offset", etc. ]
1073+ if (( ${# _comp_finalize__depth[@]} == 0 )) ; then
1074+ if shopt -q extdebug || shopt -qo functrace; then
1075+ # If extdebug / functrace is set, we need to explicitly save and
1076+ # restore the original trap handler because the outer trap handlers
1077+ # will be affected by "trap - RETURN" inside functions with these
1078+ # settings.
1079+ _comp_finalize__original_return_trap=$( trap -p RETURN)
1080+ else
1081+ # Otherwise, the outer RETURN trap will be restored when the RETURN
1082+ # trap is removed inside the functions using "trap - RETURN". So, we
1083+ # do not need to explicitly save the outer trap handler.
1084+ _comp_finalize__original_return_trap=
1085+ fi
1086+ trap _comp_finalize RETURN
1087+ fi
1088+ _comp_finalize__depth+=(" ${# FUNCNAME[@]} " )
1089+ _comp_finalize__target+=(" ${FUNCNAME[1]-} " )
1090+ fi
10321091
10331092 local flag OPTIND=1 OPTARG=" " OPTERR=0
10341093 while getopts " n:e:o:i:s" flag " $@ " ; do
0 commit comments