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

Re: zmv exits from function





On Tue, Jan 2, 2024 at 12:09 PM Ray Andrews <rayandrews@xxxxxxxxxxx> wrote:
BTW, just to whine, 'always' is sure hard to find in the help. One
obviously can't just search for that word, and it doesn't show up in the
list of reserved words neither.

Shell Grammar, under Complex Commands. (A bit of jargon, really; a command line to execute a program once is a "simple" command; anything that combines simple commands together – a loop or conditional or whatever –is a "complex" command):

https://zsh.sourceforge.io/Doc/Release/Shell-Grammar.html#Complex-Commands

> That's what I meant.  Right tho -- it's handled in two passes but one is called  parsing, the second is called running.   But the parse sets a memo that zmv will not be permitted to crash the function at run time.

Well, no.  It runs the code on the left, and then when it finishes it runs the code on the right. That's the extent of the `always` functionality. What makes it special is that the code on the right runs even if the code on the left blows up somehow. 

It's similar to a feature called the "finally block" in other languages, where it's usually attached to the exception-handling mechanism; something like `try { start here } catch (ErrorType) { do this if the previous block failed this particular way } finally { run this no matter what }`.  Because of that similarity, the code on the left of the `always` is called the "try block" or "try list", even though zsh doesn't use the keyword "try". The code on the right is called the "always block" or "always list".

So, the point of `always` is to run the always block no matter what, even if the try block blows up. But now we have an information problem: the main point of the exercise was to run the code in the try block, and presumably the caller would like to know whether it blew up or not. But how does that information get back to them? You can't just go by exit code (`$?`/`$status`), because by the time control gets back to the caller, that will reflect the result of the always block, not the try block.

Zsh uses a variable called TRY_BLOCK_ERROR (which should be read as "an error that occurred in the 'try' block" rather than some version of "try to block the error" :)) to remember whether the try block errored out or not. If it did, that variable will be 1, and after the always block executes, zsh will go back to handling the error (i.e. potentially blowing up the world). If you want the world not to be blown up, you can set TRY_BLOCK_ERROR to 0, and then zsh will forget that anything went wrong and continue about its business.

--
Mark J. Reed <markjreed@xxxxxxxxx>


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