@@ -819,13 +819,46 @@ _comp_variable_assignments()
819819 return 0
820820}
821821
822- _comp_return_hook ()
823- {
824- (( ${# FUNCNAME[*]} != 2 )) && return # this _will_ need some refinement and thought
825- echo " Hello from return hook for ${FUNCNAME[1]} "
826- echo " words: ${words[@]} "
827- echo " COMPREPLY: ${COMPREPLY[@]} "
822+ _comp_finalize__depth= ()
823+ _comp_finalize__original_return_trap=
824+
825+ # This associative array contains the finalizer commands with the key
826+ # being the name of the completed command.
827+ declare -g A BASH_COMPLETION_FINALIZE_CMD_HOOKS= ()
828+
829+ # This array contains the general finalizer commands that will be
830+ # executed for all the commands.
831+ BASH_COMPLETION_FINALIZE_HOOKS= ()
832+
833+ _comp_finalize ()
834+ {
835+ (( ${# _comp_finalize__depth[@]} )) || return 0
836+ while (( ${# FUNCNAME[@]} <= ${_comp_finalize__depth[-1]} )) ; do
837+ if (( ${# FUNCNAME[@]} == ${_comp_finalize__depth[-1]} )) ; then
838+ # Call finalizer for each command
839+ local __comp_hook=${BASH_COMPLETION_FINALIZE_CMD_HOOKS[${words[0]-} ]-}
840+ eval -- " $__comp_hook "
841+
842+ # Call general finalizers
843+ if (( ${# BASH_COMPLETION_FINALIZE_HOOKS[@]} )) ; then
844+ for __comp_hook in " ${BASH_COMPLETION_FINALIZE_HOOKS[@]} " ; do
845+ eval -- " $__comp_hook "
846+ done
847+ fi
848+ fi
849+
850+ unset -v ' _comp_finalize__depth[-1]'
851+ if (( ${# _comp_finalize__depth[@]} == 0 )) ; then
852+ eval -- " ${_comp_finalize__original_return_trap:- trap - RETURN} "
853+ _comp_finalize__original_return_trap=
854+ break
855+ fi
856+ done
828857}
858+ # Note: We need to set "trace" function attribute of _comp_finalize to
859+ # make the trap restoration by "trap - RETURN" take effect in the
860+ # upper level.
861+ declare -f t _comp_finalize
829862
830863# Initialize completion and deal with various general things: do file
831864# and variable completion where appropriate, and adjust prev, words,
@@ -846,7 +879,25 @@ _init_completion()
846879{
847880 local exclude=" " flag outx errx inx OPTIND=1
848881
849- trap _comp_return_hook RETURN
882+ # Install "_comp_finalize" to the RETURN trap when "_init_completion" is
883+ # called for the top-level completion. [ Note: the completion function may
884+ # be called recursively using "_command_offset", etc. ]
885+ if (( ${# _comp_finalize__depth[@]} == 0 )) ; then
886+ if shopt -q extdebug || shopt -qo functrace; then
887+ # If extdebug / functrace is set, we need to explicitly save and
888+ # restore the original trap handler because the outer trap handlers
889+ # will be affected by "trap - RETURN" inside functions with these
890+ # settings.
891+ _comp_finalize__original_return_trap=$( trap -p RETURN)
892+ else
893+ # Otherwise, the outer RETURN trap will be restored when the RETURN
894+ # trap is removed inside the functions using "trap - RETURN". So, we
895+ # do not need to explicitly save the outer trap handler.
896+ _comp_finalize__original_return_trap=
897+ fi
898+ trap _comp_finalize RETURN
899+ fi
900+ _comp_finalize__depth+=(${# FUNCNAME[@]} )
850901
851902 while getopts " n:e:o:i:s" flag " $@ " ; do
852903 case $flag in
0 commit comments