From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 4585 invoked by alias); 9 Apr 2010 20:27:22 -0000 Mailing-List: contact zsh-users-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Users List List-Post: List-Help: X-Seq: 14998 Received: (qmail 20167 invoked from network); 9 Apr 2010 20:27:08 -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=-1.9 required=5.0 tests=BAYES_00 autolearn=ham version=3.3.1 Received-SPF: pass (ns1.primenet.com.au: SPF record at ntlworld.com designates 81.103.221.58 as permitted sender) Date: Fri, 9 Apr 2010 20:50:23 +0100 From: Peter Stephenson To: zsh-users@zsh.org Subject: Re: Count only visible characters? Message-ID: <20100409205023.21295434@pws-pc> In-Reply-To: References: X-Mailer: Claws Mail 3.7.5 (GTK+ 2.18.7; x86_64-redhat-linux-gnu) Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit X-Cloudmark-Analysis: v=1.1 cv=ZtHxNT4mZm3rCuM0SmWmgWxeBwJsziC8EqOrwwVkrhA= c=1 sm=0 a=2JLGgpPhQ5wA:10 a=DogomfpGjd0A:10 a=kj9zAlcOel0A:10 a=aJkWhImKAAAA:8 a=NLZqzBF-AAAA:8 a=cq6Uq8D8EFc3bdW_I2AA:9 a=Kec9qNA9tpkKdb5OA2MA:7 a=AyifH4WAGmA_K2taWyd84l4gIucA:4 a=CjuIK1q_8ugA:10 a=QuUPX6yVhgoA:10 a=_dQi-Dcv4p4A:10 a=IHIAf_xzWhaaSNTe:21 a=haY_kwQkjUQ6luf7:21 a=HpAAvcLHHh0Zw7uRqdWCyQ==:117 On Thu, 8 Apr 2010 22:38:05 +0000 (UTC) Seth House wrote: > Is there any way to count only visible characters? > > testing="%F{green}hello" > echo ${(%)#testing} > > The number I'm interested in is 5 not 14. > > After an awful lot of Googling, I'm under the impression this isn't a trivial > problem. That's correct, it isn't trivial using shell code. (It's not *so* hard to strip the various highlighting codes and %{ ... %} sections if you want an exercise in shell programming.) However, the code to do this is already built into the shell itself, so making this available is a straightforward change. Note you need the `#' inside the parentheses---the normal `#' is too long established for me to be keen on changing its meaning even in combination with `(%)'. print ${(%#):-%F{red}hello%f there} 11 I'm guessing there's no call for what this syntax previously meant, doing prompt expansion on a string and then treating the result as a numeric expression to give you a character. I've spent too much of my life finding new codes for substitution flags. However, I'm open to more imaginative suggestions. Index: Doc/Zsh/expn.yo =================================================================== RCS file: /cvsroot/zsh/zsh/Doc/Zsh/expn.yo,v retrieving revision 1.112 diff -p -u -r1.112 expn.yo --- Doc/Zsh/expn.yo 27 Mar 2010 19:04:35 -0000 1.112 +++ Doc/Zsh/expn.yo 9 Apr 2010 19:38:28 -0000 @@ -729,6 +729,14 @@ entirely distinct from use of the tt(#) If the tt(MULTIBYTE) option is set and the number is greater than 127 (i.e. not an ASCII character) it is treated as a Unicode character. + +In combination with the tt(%) flag, described immediately below, +this has a different meaning: the expanded prompt is replaced by +the width of the string as it would appear on the screen in the same +way as it would be calculated by the prompt code. In other words, +this takes account of tt(%{), tt(%}) and highlighting sequences in +the string, but is not otherwise sensitive to embedded control +sequences. ) item(tt(%))( Expand all tt(%) escapes in the resulting words in the same way as in Index: Src/subst.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/subst.c,v retrieving revision 1.103 diff -p -u -r1.103 subst.c --- Src/subst.c 9 Apr 2010 15:40:14 -0000 1.103 +++ Src/subst.c 9 Apr 2010 19:38:28 -0000 @@ -2660,7 +2660,7 @@ paramsubst(LinkList l, LinkNode n, char } if (errflag) return NULL; - if (evalchar) { + if (evalchar && !presc) { int one = noerrs, oef = errflag, haserr = 0; if (!quoteerr) @@ -2801,6 +2801,7 @@ paramsubst(LinkList l, LinkNode n, char if (presc) { int ops = opts[PROMPTSUBST], opb = opts[PROMPTBANG]; int opp = opts[PROMPTPERCENT]; + int width; if (presc < 2) { opts[PROMPTPERCENT] = 1; @@ -2823,17 +2824,33 @@ paramsubst(LinkList l, LinkNode n, char for (; *ap; ap++) { char *tmps; untokenize(*ap); - tmps = promptexpand(*ap, 0, NULL, NULL, NULL); - *ap = dupstring(tmps); + tmps = promptexpand(*ap, evalchar, NULL, NULL, NULL); + if (evalchar) { + char digbuf[DIGBUFSIZE]; + countprompt(tmps, &width, NULL, -1); + sprintf(digbuf, "%d", width); + *ap = dupstring(digbuf); + } else { + *ap = dupstring(tmps); + } free(tmps); } } else { char *tmps; - if (!copied) - val = dupstring(val), copied = 1; + if (!copied) { + val = dupstring(val); + copied = 1; + } untokenize(val); - tmps = promptexpand(val, 0, NULL, NULL, NULL); - val = dupstring(tmps); + tmps = promptexpand(val, evalchar, NULL, NULL, NULL); + if (evalchar) { + char digbuf[DIGBUFSIZE]; + countprompt(tmps, &width, NULL, -1); + sprintf(digbuf, "%d", width); + val = dupstring(digbuf); + } else { + val = dupstring(tmps); + } free(tmps); } opts[PROMPTSUBST] = ops; -- Peter Stephenson Web page now at http://homepage.ntlworld.com/p.w.stephenson/