Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: [PATCH] Support the mksh's ${|func;} substitution
On Sat, 7 Sep 2019 at 22:19, Stephane Chazelas
<stephane.chazelas@xxxxxxxxx> wrote:
>
> 2019-09-07 20:09:57 +0200, Sebastian Gniazdowski:
> > The parsing would have to be changed to prevent the "=" in function names?
> [...]
>
> No, I meant that you'd need the parser to handle that case of a
> pseudo-command group (a {any shell code here} but with {|
> instead of {)).
>
> So you can do:
>
> echo ${|
> whatever $(...)
> for i do
> ...
> done}
>
> Whether it would actually be difficult or not I can't comment,
> I've not looked at the parser code.
I think that it's already supported with the single exception that }
would have to be quoted:
% print ${|
whatever $(...)
for i do
...
done;}
zsh: no such function: \n whatever $(...)\n for i do\n ...\n done
> Having an operator that *only* invokes a function to do an
> expansion is less useful IMO. That just sound like a very
> limited form of command substitution where you could have done a
> more complete form by allowing any code instead of just one
> function invocation without argument.
Ok, I agree, the lambda-function reminiscent version is better. It
also isn't much harder to implement – instead of the doshfunc() just
bin_eval() would have to be called. I attach such patch. However, it
has some problems:
arr=( val1 val2 abc1 abc3 )
print ${arr[@]//(#b)(*)/${|REPLY\=test;}}
Output:test test test test
So the = has to be quoted. Also, not much more works. REPLY\=$MATCH
nor REPLY\=\$MATCH are working. I wonder why, as it doesn't look that
bad in general:
whatever() { echo func ran; }
echo ${|
whatever $(...)
for i in a b c; do
REPLY\=1
done;}
Output:
func ran
1
--
Sebastian Gniazdowski
News: https://twitter.com/ZdharmaI
IRC: https://kiwiirc.com/client/chat.freenode.net:+6697/#zplugin
Blog: http://zdharma.org
From 6c4a2b778ca4c625bf15cf700d6ec3ce1aea1bcf Mon Sep 17 00:00:00 2001
From: Sebastian Gniazdowski <sgniazdowski@xxxxxxxxx>
Date: Fri, 6 Sep 2019 02:35:14 +0200
Subject: [PATCH] Support the mksh's substitution ${|func;}
---
Src/subst.c | 46 +++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 45 insertions(+), 1 deletion(-)
diff --git a/Src/subst.c b/Src/subst.c
index b132f251b..dc2b58cc7 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -29,6 +29,7 @@
#include "zsh.mdh"
#include "subst.pro"
+#include "builtin.pro"
#define LF_ARRAY 1
@@ -1847,8 +1848,17 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,
* nested (P) flags.
*/
int fetch_needed;
+ /* Indicates ${|func;} */
+ int rplyfunc = 0;
+ /* The name of the function to be ran by ${|...;} */
+ char *rplycode[2] = {NULL, NULL};
+ /* The length of the input string */
+ int slen = 0;
+ /* The closing brace pointer */
+ char *outbracep;
*s++ = '\0';
+ slen = strlen(s);
/*
* Nothing to do unless the character following the $ is
* something we recognise.
@@ -1876,6 +1886,36 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,
if (c == Inbrace) {
inbrace = 1;
s++;
+
+ /* Short-path for the function-running substitution ${|func;}
+ * The function name is extracted and called, and the
+ * substitution assigned. There's no (...)-flags processing,
+ * i.e. no ${|(U)func;}, because it looks quite awful and
+ * also requires a change to the manual, part about the
+ * substitution order. Use ${(U)${|func;}} instead, it looks
+ * cleaner. */
+ if ( ((outbracep=strchr(s,Outbrace)) ||
+ (outbracep=strchr(s,'}'))) &&
+ (s[0] == Bar || s[0] == '|') &&
+ outbracep[-1] == ';' )
+ {
+ rplyfunc = 1;
+ rplycode[0] = dupstrpfx(s+1, outbracep-s-2);
+ s=outbracep;
+
+ /* Execute the shell function */
+ bin_eval(NULL, rplycode, NULL, 0);
+
+ val = getsparam("REPLY");
+ if (val)
+ vunset = 0;
+ else {
+ vunset = 1;
+ val = dupstring("");
+ }
+ fetch_needed = 0;
+ }
+
/*
* In ksh emulation a leading `!' is a special flag working
* sort of like our (k).
@@ -2519,7 +2559,11 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,
scanflags)) ||
(v->pm && (v->pm->node.flags & PM_UNSET)) ||
(v->flags & VALFLAG_EMPTY))
- vunset = 1;
+ {
+ if (!rplyfunc) {
+ vunset = 1;
+ }
+ }
if (wantt) {
/*
--
2.21.0
Messages sorted by:
Reverse Date,
Date,
Thread,
Author