On Mon, Jul 3, 2023 at 6:55 PM Bart Schaefer wrote: > > Also in that thread Stephane points out that it would be ideal if > (paraphrasing his example) "${| echo { }" were parsed similarly to "{ > echo { }" and that to do so would require changes to the parser More specifically, it's going to require changes to the tokenizer. There would need to be an analog of skipcomm() that knows how to stop at the appropriately significant Outbrace instead of at Outpar, and similarly a skipparens() analog that does the same for a string. For the nonce it gets most of the way there to require that braces inside ${|...} are either balanced or quoted. One of the harder things to get right is the "%_" prompt replacement for this. I ended up with "braceparam cursh" because that's otherwise impossible, as opposed to "braceparam cmdsubst" or just "cmdsubst" or even "cmdsubst cursh" any of which could result from other valid syntaxes. As an aside ... compatibility-wise we're stuck with using braces for this, but why not parens like $(|...) instead, by analogy with $(<...)? Parsing would be so much ... saner ... and the whole fake-it-with $REPLY bit could be skipped, go straight to capturing stdout. On Tue, Jul 4, 2023 at 10:32 PM Bart Schaefer wrote: > > -- REPLY is treated as a local, i.e., it's value gets saved and > restored around the substitution I've implemented this, but after experimenting with it both ways, I've done so only for REPLY, that is, other cases of $VAR as in ${|VAR|...} remain non-localized. Again I wonder whether instead of being initialized as unset, REPLY should be initialized to the value from the calling scope, so that ${+REPLY} is usable. The drawback of course is that the called code must then explicitly clobber $REPLY if an empty result is desired. > -- "local" works inside the substitution as it would inside a function > body, but $@ refers to the calling environment. Implemented this. Combined with the foregoing, this means that ${|VAR|local VAR; ...} substitutes the value of $VAR from the caller, not from the command (so, don't do that unless you mean it). > -- "return" also behaves as if in a function body. Also implemented this. Following Chet's lead, though, "exit" does exit the shell. I could instead make "exit" work like ${notset?error} and thus exit only if the shell is not interactive. Thoughts? I have not yet implemented the anonymous tempfile for ${ capture_stdout }. However, this equivalent construction does work (extra newlines for clarity): ${| () { capture_stdout > $1 REPLY=$(<$1) } =(