zsh-workers
 help / color / mirror / code / Atom feed
From: Philippe Altherr <philippe.altherr@gmail.com>
To: Zsh hackers list <zsh-workers@zsh.org>
Subject: [PATCH] Better ERR_EXIT and ERR_RETURN documentation
Date: Mon, 12 Dec 2022 17:03:22 +0100	[thread overview]
Message-ID: <CAGdYchuFZb17c+_iwNc_uVp+_0sVibU9=JUMzGOPQ2ahUCPbew@mail.gmail.com> (raw)


[-- Attachment #1.1: Type: text/plain, Size: 3215 bytes --]

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

[-- Attachment #1.2: Type: text/html, Size: 5910 bytes --]

[-- Attachment #2: patch-errexit-documentation-update.txt --]
[-- Type: text/plain, Size: 4761 bytes --]

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)

             reply	other threads:[~2022-12-12 16:04 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-12-12 16:03 Philippe Altherr [this message]
2022-12-12 16:21 ` Bart Schaefer
2022-12-13  0:02   ` Philippe Altherr

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAGdYchuFZb17c+_iwNc_uVp+_0sVibU9=JUMzGOPQ2ahUCPbew@mail.gmail.com' \
    --to=philippe.altherr@gmail.com \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).