@@ -1335,13 +1335,51 @@ _comp_variable_assignments()
13351335 return 0
13361336}
13371337
1338- _comp_return_hook ()
1339- {
1340- (( ${# FUNCNAME[*]} != 2 )) && return # this _will_ need some refinement and thought
1341- echo " Hello from return hook for ${FUNCNAME[1]} "
1342- echo " words: ${words[@]} "
1343- echo " COMPREPLY: ${COMPREPLY[@]} "
1338+ _comp_finalize__depth= ()
1339+ _comp_finalize__target= ()
1340+ _comp_finalize__original_return_trap=
1341+
1342+ # This associative array contains the finalizer commands with the key
1343+ # being the name of the completed command.
1344+ declare -g A BASH_COMPLETION_FINALIZE_CMD_HOOKS
1345+
1346+ # This array contains the general finalizer commands that will be
1347+ # executed for all the commands.
1348+ declare -g a BASH_COMPLETION_FINALIZE_HOOKS
1349+
1350+ _comp_finalize ()
1351+ {
1352+ (( ${# _comp_finalize__depth[@]} )) || return 0
1353+ while (( ${# FUNCNAME[@]} <= ${_comp_finalize__depth[-1]} )) ; do
1354+ if [[ ${# FUNCNAME[@]} -eq ${_comp_finalize__depth[-1]} && ${FUNCNAME[1]-} == " ${_comp_finalize__target[-1]} " ]]; then
1355+ # Call finalizer for each command
1356+ local cmd=${words[0]-} _comp_local_hook
1357+ if [[ $cmd ]]; then
1358+ _comp_local_hook=${BASH_COMPLETION_FINALIZE_CMD_HOOKS[$cmd]-}
1359+ eval -- " $_comp_local_hook "
1360+ fi
1361+
1362+ # Call general finalizers
1363+ if [[ ${BASH_COMPLETION_FINALIZE_HOOKS[*]+set} ]]; then
1364+ for _comp_local_hook in " ${BASH_COMPLETION_FINALIZE_HOOKS[@]} " ; do
1365+ eval -- " $_comp_local_hook "
1366+ done
1367+ fi
1368+ fi
1369+
1370+ unset -v ' _comp_finalize__depth[-1]'
1371+ unset -v ' _comp_finalize__target[-1]'
1372+ if (( ${# _comp_finalize__depth[@]} == 0 )) ; then
1373+ eval -- " ${_comp_finalize__original_return_trap:- trap - RETURN} "
1374+ _comp_finalize__original_return_trap=
1375+ break
1376+ fi
1377+ done
13441378}
1379+ # Note: We need to set "trace" function attribute of _comp_finalize to
1380+ # make the trap restoration by "trap - RETURN" take effect in the
1381+ # upper level.
1382+ declare -f t _comp_finalize
13451383
13461384# Initialize completion and deal with various general things: do file
13471385# and variable completion where appropriate, and adjust prev, words,
@@ -1380,7 +1418,28 @@ _comp_initialize()
13801418{
13811419 local exclude=" " opt_split=" " outx=" " errx=" " inx=" "
13821420
1383- trap _comp_return_hook RETURN
1421+ if (( ${# FUNCNAME[@]} >= 2 )) ; then
1422+ # Install "_comp_finalize" to the RETURN trap when "_init_completion" is
1423+ # called for the top-level completion. [ Note: the completion function may
1424+ # be called recursively using "_command_offset", etc. ]
1425+ if (( ${# _comp_finalize__depth[@]} == 0 )) ; then
1426+ if shopt -q extdebug || shopt -qo functrace; then
1427+ # If extdebug / functrace is set, we need to explicitly save and
1428+ # restore the original trap handler because the outer trap handlers
1429+ # will be affected by "trap - RETURN" inside functions with these
1430+ # settings.
1431+ _comp_finalize__original_return_trap=$( trap -p RETURN)
1432+ else
1433+ # Otherwise, the outer RETURN trap will be restored when the RETURN
1434+ # trap is removed inside the functions using "trap - RETURN". So, we
1435+ # do not need to explicitly save the outer trap handler.
1436+ _comp_finalize__original_return_trap=
1437+ fi
1438+ trap _comp_finalize RETURN
1439+ fi
1440+ _comp_finalize__depth+=(" ${# FUNCNAME[@]} " )
1441+ _comp_finalize__target+=(" ${FUNCNAME[1]-} " )
1442+ fi
13841443
13851444 local flag OPTIND=1 OPTARG=" " OPTERR=0
13861445 while getopts " n:e:o:i:s" flag " $@ " ; do
0 commit comments