Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

[PATCH] Better ERR_EXIT and ERR_RETURN documentation



Here is a patch that updates the documentation of the ERR_EXIT and ERR_RETURN options. The main improvement is to better explain when these options are ignored.

As it may be a bit difficult to read it directly in the patch, I reproduced below the updated documentation:

ERR_EXIT
 
If a command has a non-zero exit status, execute the tt(ZERR)
trap, if set, and exit.

The option is ignored when executing the commands following tt(while),
tt(until), tt(if), or tt(elif), a pipeline beginning with tt(!), or
any command other than the last in command list containing tt(&&) or
tt(||).  Hence neither `tt(if foo; then true; fi)', nor `tt(foo &&
true)' trigger exit when tt(foo) returns with a non-zero exit status.
Note that if tt(foo) is a function, the option is also ignored during
its whole execution.

The option is also ignored when executing a complex command (tt(if),
tt(for), tt(while), tt(until), tt(repeat), tt(case), tt(select),
tt(always), or a list in braces) if its exit status comes from a
command executed while the option is ignored. Hence, the tt(if)
command in `tt(if true; then false && true; fi)' does not trigger
exit.

Finally, the option is also ignored while running initialization
scripts and inside tt(DEBUG) traps.  In the latter case, the option is
handled specially: it is unset on entry to the trap.  If the option
tt(DEBUG_BEFORE_CMD) is set, as it is by default, and the option
tt(ERR_EXIT) is found to have been set on exit, then the command for
which the tt(DEBUG) trap is being executed is skipped.  The option is
restored after the trap exits.

Exiting due to tt(ERR_EXIT) has certain interactions with asynchronous
jobs noted in
ifzman(the section JOBS in zmanref(zshmisc))\
ifnzman(noderef(Jobs & Signals)).

Note this behaviour is not disabled in interactive shells ---
a non-zero status on the command line causes the shell to exit.

ERR_RETURN

If a command has a non-zero exit status, return immediately from the
enclosing function.  Except for the exceptions described below, the
logic is the same as that for tt(ERR_EXIT), except that an implicit
tt(return) statement is executed instead of an tt(exit).  This will
trigger an exit at the outermost level of a non-interactive script.
At the top level of an interactive shell, it will trigger a return to
the command prompt; in other words, the sequence of commands typed by
the user may be thought of as a function for this purpose.

Unlike for tt(ERR_EXIT), when a function is called while the option is
being ignored, the option is NOT ignored during the execution of the
function.  Hence, if tt(foo) in `tt(foo && true)' is a function, code
inside it is considered separately: it may force a return from tt(foo)
(assuming the option remains set within tt(foo)).

Like for tt(ERR_EXIT), the option is ignored inside tt(DEBUG) traps
but it's not unset on entry to the trap and setting or unsetting it
inside the trap has no special effect.

If tt(ERR_RETURN) and tt(ERR_EXIT) are both set, the latter takes
precedence. Hence, exit rather than return is triggered when a command
has a non-zero exit status.

Philippe

diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo
index e92969531..698943fa7 100644
--- a/Doc/Zsh/options.yo
+++ b/Doc/Zsh/options.yo
@@ -1723,22 +1723,30 @@ pindex(NOERREXIT)
 cindex(exit status, trapping)
 item(tt(ERR_EXIT) (tt(-e), ksh: tt(-e)))(
 If a command has a non-zero exit status, execute the tt(ZERR)
-trap, if set, and exit.  This is disabled while running initialization
-scripts.
-
-The behaviour is also disabled inside tt(DEBUG) traps.  In this
-case the option is handled specially: it is unset on entry to
-the trap.  If the option tt(DEBUG_BEFORE_CMD) is set,
-as it is by default, and the option tt(ERR_EXIT) is found to have been set
-on exit, then the command for which the tt(DEBUG) trap is being executed is
-skipped.  The option is restored after the trap exits.
-
-Non-zero status in a command list containing tt(&&) or tt(||) is ignored
-for commands not at the end of the list.  Hence
-
-example(false && true)
-
-does not trigger exit.
+trap, if set, and exit.
+
+The option is ignored when executing the commands following tt(while),
+tt(until), tt(if), or tt(elif), a pipeline beginning with tt(!), or
+any command other than the last in command list containing tt(&&) or
+tt(||).  Hence neither `tt(if foo; then true; fi)', nor `tt(foo &&
+true)' trigger exit when tt(foo) returns with a non-zero exit status.
+Note that if tt(foo) is a function, the option is also ignored during
+its whole execution.
+
+The option is also ignored when executing a complex command (tt(if),
+tt(for), tt(while), tt(until), tt(repeat), tt(case), tt(select),
+tt(always), or a list in braces) if its exit status comes from a
+command executed while the option is ignored. Hence, the tt(if)
+command in `tt(if true; then false && true; fi)' does not trigger
+exit.
+
+Finally, the option is also ignored while running initialization
+scripts and inside tt(DEBUG) traps.  In the latter case, the option is
+handled specially: it is unset on entry to the trap.  If the option
+tt(DEBUG_BEFORE_CMD) is set, as it is by default, and the option
+tt(ERR_EXIT) is found to have been set on exit, then the command for
+which the tt(DEBUG) trap is being executed is skipped.  The option is
+restored after the trap exits.
 
 Exiting due to tt(ERR_EXIT) has certain interactions with asynchronous
 jobs noted in
@@ -1756,28 +1764,27 @@ cindex(function return, on error)
 cindex(return from function, on error)
 item(tt(ERR_RETURN))(
 If a command has a non-zero exit status, return immediately from the
-enclosing function.  The logic is similar to that for tt(ERR_EXIT),
-except that an implicit tt(return) statement is executed instead of an
-tt(exit).  This will trigger an exit at the outermost level of a
-non-interactive script.  At the top level of an interactive shell,
-it will trigger a return to the command prompt; in other
-words, the sequence of commands typed by the user may be
-thought of as a function for this purpose.
-
-Normally this option inherits the behaviour of tt(ERR_EXIT) that
-code followed by `tt(&&)' `tt(||)' does not trigger a return.  Hence
-in the following:
-
-example(summit || true)
-
-no return is forced as the combined effect always has a zero return
-status.
-
-Note. however, that if tt(summit) in the above example is itself a
-function, code inside it is considered separately: it may force a return
-from tt(summit) (assuming the option remains set within tt(summit)), but
-not from the enclosing context.  This behaviour is different from
-tt(ERR_EXIT) which is unaffected by function scope.
+enclosing function.  Except for the exceptions described below, the
+logic is the same as that for tt(ERR_EXIT), except that an implicit
+tt(return) statement is executed instead of an tt(exit).  This will
+trigger an exit at the outermost level of a non-interactive script.
+At the top level of an interactive shell, it will trigger a return to
+the command prompt; in other words, the sequence of commands typed by
+the user may be thought of as a function for this purpose.
+
+Unlike for tt(ERR_EXIT), when a function is called while the option is
+being ignored, the option is NOT ignored during the execution of the
+function.  Hence, if tt(foo) in `tt(foo && true)' is a function, code
+inside it is considered separately: it may force a return from tt(foo)
+(assuming the option remains set within tt(foo)).
+
+Like for tt(ERR_EXIT), the option is ignored inside tt(DEBUG) traps
+but it's not unset on entry to the trap and setting or unsetting it
+inside the trap has no special effect.
+
+If tt(ERR_RETURN) and tt(ERR_EXIT) are both set, the latter takes
+precedence. Hence, exit rather than return is triggered when a command
+has a non-zero exit status.
 )
 pindex(EVAL_LINENO)
 pindex(NO_EVAL_LINENO)


Messages sorted by: Reverse Date, Date, Thread, Author