From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 8697 invoked by alias); 13 May 2011 12:39:36 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: X-Seq: 29261 Received: (qmail 4978 invoked from network); 13 May 2011 12:39:33 -0000 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-2.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,RCVD_IN_DNSWL_LOW, T_TO_NO_BRKTS_FREEMAIL autolearn=ham version=3.3.1 Received-SPF: pass (ns1.primenet.com.au: SPF record at _spf.google.com designates 209.85.214.43 as permitted sender) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:from:to:subject:date:message-id:x-mailer :in-reply-to:references; bh=Da7KVZpBoeYfzY/VdVuiaIuTcQta8pQppQdcs1sGGRY=; b=moEC1OEmf6uzFVhwhFQgn2t6SqiAI/KdKaOMshHkQ6Pk0Y4ovYXIkRrFGQqqE5uxHP gq4ZZnwNI4v/Hp2StXlQmDXGOBF5i74Pvf6XdANxm8ss4sL0ETZQgmOg0FsIw2EYzLGx 9wwN9LlhLpST8wF7SefDwRPH77m8s05CGeYQ4= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:subject:date:message-id:x-mailer:in-reply-to:references; b=h2XVq/qRLQQ4u/CT5zKAJDlZj+GSTnekAunHJ9H0YScyhjGDFeDBfI0/B0gC9IvCD4 Q7mjNVyVVRThzwD2N2BZr0UzeterNc4Xsb3q6IflU3bxaJTCNTbXPZC8n2/dCaMIlQ/H Jf063bkaIaXGWuAuDK69y2mU01/wTB0PpDYVw= From: Mikael Magnusson To: zsh-workers@zsh.org Subject: PATCH: Add g:: parameter expansion flag Date: Fri, 13 May 2011 14:38:43 +0200 Message-Id: <1305290323-25573-1-git-send-email-mikachu@gmail.com> X-Mailer: git-send-email 1.7.4-rc1 In-Reply-To: <20110513125408.314f6359@pwslap01u.europe.root.pri> References: <20110513125408.314f6359@pwslap01u.europe.root.pri> On 13 May 2011 13:54, Peter Stephenson wrote: > On Fri, 13 May 2011 11:51:13 +0200 > Mikael Magnusson wrote: >> >> So I am pretty sure I want to use META_HREALLOC, is that correct? >> > That would do, as it's what untok_and_escape() does, although >> > META_HEAPDUP would probably be OK at this point. Reallocating >> > what's on the heap is a slightly strange thing to do, since the >> > point of the heap is to provide quick storage without the need to >> > micromanage it; >> >> In that case, isn't USEHEAP better? It'll allocate on the heap if >> there's anything to escape and otherwise do it in-place. Which is what >> I thought HREALLOC would do, but I guess that one would do more stuff >> to try and just grow. Won't it always succeed though, since the to-be >> reallocated value was just allocated on the line before? (At least >> when the heap isn't full). > > USEHEAP is fine if you don't mind further modifications to the string > propagating back to the original. In some places the string might not > be modifiable, or might refer to a permanently stored string, so you > wouldn't want to do that. That may not be the case here; it needs > deciding case by case. Right, it isn't the case here, so I'll use this one. Actually, it turns out getkeystring() always performs a copy, so I can skip the dupstring and always set copied = 1, like for casemodify above it. I also added an array to the test case, since it turns out you can write code that works in one branch and code that doesn't work in the other branch ;). -- Mikael Magnusson --- Doc/Zsh/expn.yo | 17 ++++++++++++-- Src/subst.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ Test/D04parameter.ztst | 20 +++++++++++++++++ 3 files changed, 90 insertions(+), 3 deletions(-) diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index 1cad3d2..9d5c81b 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -863,6 +863,14 @@ item(tt(F))( Join the words of arrays together using newline as a separator. This is a shorthand for `tt(pj:\n:)'. ) +item(tt(g:opts:))( +Process escape sequences like the echo builtin when no options are given +(tt(g::)). With the tt(o) option, octal escapes don't take a leading +zero. With the tt(c) option, sequences like `tt(^X)' are also processed. +With the tt(e) option, processes `tt(\M-t)' and similar sequences like the +print builtin. With both of the tt(o) and tt(e) options, behaves like the +print builtin except that in none of these modes is `tt(\c)' interpreted. +) item(tt(i))( Sort case-insensitively. May be combined with `tt(n)' or `tt(O)'. ) @@ -1108,7 +1116,9 @@ Force field splitting at the separator var(string). Note that a var(string) of two or more characters means that all of them must match in sequence; this differs from the treatment of two or more characters in the tt(IFS) parameter. -See also the tt(=) flag and the tt(SH_WORD_SPLIT) option. +See also the tt(=) flag and the tt(SH_WORD_SPLIT) option. An empty +string may also be given in which case every character will be a separate +element. For historical reasons, the usual behaviour that empty array elements are retained inside double quotes is disabled for arrays generated @@ -1292,8 +1302,9 @@ item(tt(11.) em(Case modification))( Any case modification from one of the flags tt((L)), tt((U)) or tt((C)) is applied. ) -item(tt(12.) em(Prompt evaluation))( -Any prompt-style formatting from the tt((%)) family of flags is applied. +item(tt(12.) em(Escape sequence replacement))( +First any replacements from the tt((g)) flag are performed, then any +prompt-style formatting from the tt((%)) family of flags is applied. ) item(tt(13.) em(Quote application))( Any quoting or unquoting using tt((q)) and tt((Q)) and related flags diff --git a/Src/subst.c b/Src/subst.c index 5d7a8b4..6bc0a82 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -1607,6 +1607,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) */ int presc = 0; /* + * The (g) flag. Process escape sequences with various GETKEY_ flags. + */ + int getkeys = -1; + /* * The (@) flag; interacts obscurely with qt and isarr. * This is one of the things that decides whether multsub * will produce an array, but in an extremely indirect fashion. @@ -1932,6 +1936,36 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) presc++; break; + case 'g': + t = get_strarg(++s, &arglen); + if (getkeys < 0) + getkeys = 0; + if (*t) { + sav = *t; + *t = 0; + while (*++s) { + switch (*s) { + case 'e': + getkeys |= GETKEY_EMACS; + break; + case 'o': + getkeys |= GETKEY_OCTAL_ESC; + break; + case 'c': + getkeys |= GETKEY_CTRL; + break; + + default: + *t = sav; + goto flagerr; + } + } + *t = sav; + s = t + arglen - 1; + } else + goto flagerr; + break; + case 'z': shsplit = LEXFLAGS_ACTIVE; break; @@ -3100,6 +3134,28 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) } } /* + * Process echo- and print-style escape sequences. + */ + if (getkeys >= 0) { + int len; + + copied = 1; /* string is always copied */ + if (isarr) { + char **ap, **ap2; + + ap = aval; + aval = (char **) zhalloc(sizeof(char *) * (arrlen(aval)+1)); + for (ap2 = aval; *ap; ap++, ap2++) { + *ap2 = getkeystring(*ap, &len, getkeys, NULL); + *ap2 = metafy(*ap2, len, META_USEHEAP); + } + *ap2++ = NULL; + } else { + val = getkeystring(val, &len, getkeys, NULL); + val = metafy(val, len, META_USEHEAP); + } + } + /* * Perform prompt-style modifications. */ if (presc) { diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst index b91caaa..6379c8c 100644 --- a/Test/D04parameter.ztst +++ b/Test/D04parameter.ztst @@ -298,6 +298,26 @@ >Howzat >usay + foo='\u65\123' + print -r ${(g:o:)foo} + foo='\u65\0123' + print -r ${(g::)foo} + foo='\u65^X' + print -r ${(V)${(g:c:)foo}} + foo='\u65\C-x\M-a' + print -r ${(V)${(g:e:)foo}} + foo='\u65\123\C-x' + print -r ${(V)${(g:eo:)foo}} + foo=('\u65' '\0123' '^X\M-a') + print -r ${(V)${(g:e:)foo}} +0:${(g)...} +>eS +>eS +>e^X +>e^X\M-a +>eS^X +>e S ^X\M-a + foo='I'\''m nearly out of my mind with tedium' bar=foo print ${(P)bar} -- 1.7.4-rc1