@@ -1485,13 +1485,51 @@ _comp_variable_assignments()
14851485 return 0
14861486}
14871487
1488- _comp_return_hook ()
1489- {
1490- (( ${# FUNCNAME[*]} != 2 )) && return # this _will_ need some refinement and thought
1491- echo " Hello from return hook for ${FUNCNAME[1]} "
1492- echo " words: ${words[@]} "
1493- echo " COMPREPLY: ${COMPREPLY[@]} "
1488+ _comp_finalize__depth= ()
1489+ _comp_finalize__target= ()
1490+ _comp_finalize__original_return_trap=
1491+
1492+ # This associative array contains the finalizer commands with the key
1493+ # being the name of the completed command.
1494+ declare -g A BASH_COMPLETION_FINALIZE_CMD_HOOKS
1495+
1496+ # This array contains the general finalizer commands that will be
1497+ # executed for all the commands.
1498+ declare -g a BASH_COMPLETION_FINALIZE_HOOKS
1499+
1500+ _comp_finalize ()
1501+ {
1502+ (( ${# _comp_finalize__depth[@]} )) || return 0
1503+ while (( ${# FUNCNAME[@]} <= ${_comp_finalize__depth[-1]} )) ; do
1504+ if [[ ${# FUNCNAME[@]} -eq ${_comp_finalize__depth[-1]} && ${FUNCNAME[1]-} == " ${_comp_finalize__target[-1]} " ]]; then
1505+ # Call finalizer for each command
1506+ local cmd=${words[0]-} _comp_local_hook
1507+ if [[ $cmd ]]; then
1508+ _comp_local_hook=${BASH_COMPLETION_FINALIZE_CMD_HOOKS[$cmd]-}
1509+ eval -- " $_comp_local_hook "
1510+ fi
1511+
1512+ # Call general finalizers
1513+ if [[ ${BASH_COMPLETION_FINALIZE_HOOKS[*]+set} ]]; then
1514+ for _comp_local_hook in " ${BASH_COMPLETION_FINALIZE_HOOKS[@]} " ; do
1515+ eval -- " $_comp_local_hook "
1516+ done
1517+ fi
1518+ fi
1519+
1520+ unset -v ' _comp_finalize__depth[-1]'
1521+ unset -v ' _comp_finalize__target[-1]'
1522+ if (( ${# _comp_finalize__depth[@]} == 0 )) ; then
1523+ eval -- " ${_comp_finalize__original_return_trap:- trap - RETURN} "
1524+ _comp_finalize__original_return_trap=
1525+ break
1526+ fi
1527+ done
14941528}
1529+ # Note: We need to set "trace" function attribute of _comp_finalize to
1530+ # make the trap restoration by "trap - RETURN" take effect in the
1531+ # upper level.
1532+ declare -f t _comp_finalize
14951533
14961534# Initialize completion and deal with various general things: do file
14971535# and variable completion where appropriate, and adjust prev, words,
@@ -1530,7 +1568,28 @@ _comp_initialize()
15301568{
15311569 local exclude=" " opt_split=" " outx=" " errx=" " inx=" "
15321570
1533- trap _comp_return_hook RETURN
1571+ if (( ${# FUNCNAME[@]} >= 2 )) ; then
1572+ # Install "_comp_finalize" to the RETURN trap when "_init_completion" is
1573+ # called for the top-level completion. [ Note: the completion function may
1574+ # be called recursively using "_command_offset", etc. ]
1575+ if (( ${# _comp_finalize__depth[@]} == 0 )) ; then
1576+ if shopt -q extdebug || shopt -qo functrace; then
1577+ # If extdebug / functrace is set, we need to explicitly save and
1578+ # restore the original trap handler because the outer trap handlers
1579+ # will be affected by "trap - RETURN" inside functions with these
1580+ # settings.
1581+ _comp_finalize__original_return_trap=$( trap -p RETURN)
1582+ else
1583+ # Otherwise, the outer RETURN trap will be restored when the RETURN
1584+ # trap is removed inside the functions using "trap - RETURN". So, we
1585+ # do not need to explicitly save the outer trap handler.
1586+ _comp_finalize__original_return_trap=
1587+ fi
1588+ trap _comp_finalize RETURN
1589+ fi
1590+ _comp_finalize__depth+=(" ${# FUNCNAME[@]} " )
1591+ _comp_finalize__target+=(" ${FUNCNAME[1]-} " )
1592+ fi
15341593
15351594 local flag OPTIND=1 OPTARG=" " OPTERR=0
15361595 while getopts " n:e:o:i:s" flag " $@ " ; do
0 commit comments