Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: [PATCH] Better ERR_EXIT and ERR_RETURN documentation
- X-seq: zsh-workers 51198
- From: Philippe Altherr <philippe.altherr@xxxxxxxxx>
- To: Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx>
- Cc: Zsh hackers list <zsh-workers@xxxxxxx>
- Subject: Re: [PATCH] Better ERR_EXIT and ERR_RETURN documentation
- Date: Tue, 13 Dec 2022 01:02:10 +0100
- Archived-at: <https://zsh.org/workers/51198>
- In-reply-to: <CAH+w=7b8WPi8diBWqRpn6T0PqUxxX-ScbaRbEQw1s0zg9H2k9A@mail.gmail.com>
- List-id: <zsh-workers.zsh.org>
- References: <CAGdYchuFZb17c+_iwNc_uVp+_0sVibU9=JUMzGOPQ2ahUCPbew@mail.gmail.com> <CAH+w=7b8WPi8diBWqRpn6T0PqUxxX-ScbaRbEQw1s0zg9H2k9A@mail.gmail.com>
That sentence is ... exceptional?
Yep, yep. I already cringed at the double except and now I notice the "Except for the exceptions" 🙈
Except as explained below, an implicit tt(return) statement is
executed following the same logic described for tt(ERR_EXIT).
Awesome! So much better.
>> 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.
Does this need to explain the interaction of the cases where ERR_EXIT
is ignored but ERR_RETURN is not? As written it seems to imply that
exit would always occur in the cases where it would otherwise be a
return.
Good point. I rephrased as follows:
If tt(ERR_RETURN) and tt(ERR_EXIT) are both set, it may happen that
both exit and return should be triggered. In that case only exit is
triggered.
This implicitly covers the special case. I hope it's not necessary to explain it explicitly as it's a rather corner case and it would significantly increase the length of the explanation.
Philippe
diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo
index e92969531..cbd3d0f8e 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
@@ -1755,29 +1763,29 @@ pindex(NOERRRETURN)
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 as explained below, an implicit tt(return)
+statement is executed following the same logic described for
+tt(ERR_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, it may happen that
+both exit and return should be triggered. In that case only exit is
+triggered.
)
pindex(EVAL_LINENO)
pindex(NO_EVAL_LINENO)
Messages sorted by:
Reverse Date,
Date,
Thread,
Author