Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: Count only visible characters?
- X-seq: zsh-users 14998
- From: Peter Stephenson <p.w.stephenson@xxxxxxxxxxxx>
- To: zsh-users@xxxxxxx
- Subject: Re: Count only visible characters?
- Date: Fri, 9 Apr 2010 20:50:23 +0100
- In-reply-to: <loom.20100409T002951-342@xxxxxxxxxxxxxx>
- List-help: <mailto:zsh-users-help@zsh.org>
- List-id: Zsh Users List <zsh-users.zsh.org>
- List-post: <mailto:zsh-users@zsh.org>
- Mailing-list: contact zsh-users-help@xxxxxxx; run by ezmlm
- References: <loom.20100409T002951-342@xxxxxxxxxxxxxx>
On Thu, 8 Apr 2010 22:38:05 +0000 (UTC)
Seth House <seth@xxxxxxxxx> 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 <p.w.stephenson@xxxxxxxxxxxx>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/
Messages sorted by:
Reverse Date,
Date,
Thread,
Author