* Count only visible characters?
@ 2010-04-08 22:38 Seth House
2010-04-09 9:02 ` Joke de Buhr
2010-04-09 19:50 ` Peter Stephenson
0 siblings, 2 replies; 11+ messages in thread
From: Seth House @ 2010-04-08 22:38 UTC (permalink / raw)
To: zsh-users
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. If that is true, I would certainly enjoy a little exposition if someone
has time.
Thanks.
- Seth
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Count only visible characters?
2010-04-08 22:38 Count only visible characters? Seth House
@ 2010-04-09 9:02 ` Joke de Buhr
2010-04-09 9:13 ` Frank Terbeck
2010-04-09 19:50 ` Peter Stephenson
1 sibling, 1 reply; 11+ messages in thread
From: Joke de Buhr @ 2010-04-09 9:02 UTC (permalink / raw)
To: zsh-users
Since you are using prompt expansion you should always escape the color codes
with "%{...%}". That's the only way zsh can calculate the length of the prompt
line correctly. Otherwise the cursor will not be positioned at the end of the
visual end.
testing="%{%F{green}%}hello"
If you need to do manual counting you can use this
${(S%%)#testing//\%\{*\%\}}
The command replaces every escape %{...%} sequence prior to calculating the
length.
$ testing="%{%F{green}%}hello"
$ echo ${(S%%)#testing//\%\{*\%\}}
5
On Friday, 9. April 2010 00:38:05 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. If that is true, I would certainly enjoy a little
> exposition if someone has time.
>
> Thanks.
> - Seth
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Count only visible characters?
2010-04-09 9:02 ` Joke de Buhr
@ 2010-04-09 9:13 ` Frank Terbeck
2010-04-09 9:49 ` Joke de Buhr
2010-04-09 10:44 ` Sebastian Stark
0 siblings, 2 replies; 11+ messages in thread
From: Frank Terbeck @ 2010-04-09 9:13 UTC (permalink / raw)
To: zsh-users
Joke de Buhr wrote:
> Since you are using prompt expansion you should always escape the color codes
> with "%{...%}". That's the only way zsh can calculate the length of the prompt
> line correctly. Otherwise the cursor will not be positioned at the end of the
> visual end.
>
> testing="%{%F{green}%}hello"
No, with %F{...}...%f he does *not* need to wrap things in %{...%}.
Regards, Frank
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Count only visible characters?
2010-04-09 9:13 ` Frank Terbeck
@ 2010-04-09 9:49 ` Joke de Buhr
2010-04-09 19:22 ` Seth House
2010-04-09 10:44 ` Sebastian Stark
1 sibling, 1 reply; 11+ messages in thread
From: Joke de Buhr @ 2010-04-09 9:49 UTC (permalink / raw)
To: zsh-users
Sorry. I used the color array ${fg_*[green]} for my prompt. They need to be
escaped.
If you want to do character counting as suggested earlier you need to escape
the %F{...} sequences or it won't work unless you change the replacing pattern
to recognize %F, %f, %K, %k sequences.
On Friday, 9. April 2010 11:13:44 Frank Terbeck wrote:
> Joke de Buhr wrote:
> > Since you are using prompt expansion you should always escape the color
> > codes with "%{...%}". That's the only way zsh can calculate the length of
> > the prompt line correctly. Otherwise the cursor will not be positioned at
> > the end of the visual end.
> >
> > testing="%{%F{green}%}hello"
>
> No, with %F{...}...%f he does *not* need to wrap things in %{...%}.
>
> Regards, Frank
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Count only visible characters?
2010-04-09 9:13 ` Frank Terbeck
2010-04-09 9:49 ` Joke de Buhr
@ 2010-04-09 10:44 ` Sebastian Stark
2010-04-09 10:56 ` Sebastian Stark
1 sibling, 1 reply; 11+ messages in thread
From: Sebastian Stark @ 2010-04-09 10:44 UTC (permalink / raw)
To: zsh-users
Hi,
I was playing around with colors because of this post and noticed something strange along the way:
% echo $ZSH_VERSION
4.3.10
% print "${(%)a::=3D%F{green}hello}"
hello}
% print "${(%)a::=3D%F{green}hello"
hello
Why does the first print statement print the closing brace? How can the second print statement not produce an error?
Sebastian
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Count only visible characters?
2010-04-09 10:44 ` Sebastian Stark
@ 2010-04-09 10:56 ` Sebastian Stark
2010-04-09 12:08 ` Peter Stephenson
0 siblings, 1 reply; 11+ messages in thread
From: Sebastian Stark @ 2010-04-09 10:56 UTC (permalink / raw)
To: zsh-users
Am 09.04.2010 um 12:44 schrieb Sebastian Stark:
>
> Hi,
>
> I was playing around with colors because of this post and noticed something strange along the way:
>
> % echo $ZSH_VERSION
> 4.3.10
> % print "${(%)a::=3D%F{green}hello}"
> hello}
> % print "${(%)a::=3D%F{green}hello"
> hello
Sorry, I made a pasto. The two commands should be:
print "${(%)a::=%F{green}hello}"
and
print "${(%)a::=%F{green}hello"
respectively.
Sebastian
>
> Why does the first print statement print the closing brace? How can the second print statement not produce an error?
>
>
> Sebastian
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Count only visible characters?
2010-04-09 10:56 ` Sebastian Stark
@ 2010-04-09 12:08 ` Peter Stephenson
2010-04-09 12:27 ` Sebastian Stark
0 siblings, 1 reply; 11+ messages in thread
From: Peter Stephenson @ 2010-04-09 12:08 UTC (permalink / raw)
To: zsh-users
On Fri, 9 Apr 2010 12:56:02 +0200
Sebastian Stark <seb-zsh@biskalar.de> wrote:
> print "${(%)a::=%F{green}hello}"
> hello}
> % print "${(%)a::=%F{green}hello"
> hello
>
> Why does the first print statement print the closing brace? How can the
> second print statement not produce an error?
${...} doesn't attempt to balance braces internally, so the first } brings
it to an end. The final quoted "}" is then just an ordinary character.
You're being a bit too clever for your own good here by trying to too much
at once. If you separate out the assignment from the use it'll work.
If you absolutely have to do it this way, however, quoting the text you
want to be treated as a string by the parameter expansion works.
print "${(%)a::="%F{green}hello"}"
The outer double quotes are now overloaded too many times to be able to
tell this is what you mean: see a recent post by Bart for a reference to a
discussion on the standards mailing list about trouble with double quotes.
I'm not sure you actually want the outer double quotes at all, but I'm not
sure what you're trying to do (and it probably doesn't matter for this
particular issue).
--
Peter Stephenson <pws@csr.com> Software Engineer
Tel: +44 (0)1223 692070 Cambridge Silicon Radio Limited
Churchill House, Cambridge Business Park, Cowley Road, Cambridge, CB4 0WZ, UK
Member of the CSR plc group of companies. CSR plc registered in England and Wales, registered number 4187346, registered office Churchill House, Cambridge Business Park, Cowley Road, Cambridge, CB4 0WZ, United Kingdom
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Count only visible characters?
2010-04-09 12:08 ` Peter Stephenson
@ 2010-04-09 12:27 ` Sebastian Stark
0 siblings, 0 replies; 11+ messages in thread
From: Sebastian Stark @ 2010-04-09 12:27 UTC (permalink / raw)
To: Peter Stephenson; +Cc: zsh-users
Am 09.04.2010 um 14:08 schrieb Peter Stephenson:
> On Fri, 9 Apr 2010 12:56:02 +0200
> Sebastian Stark <seb-zsh@biskalar.de> wrote:
>> print "${(%)a::=%F{green}hello}"
>> hello}
>> % print "${(%)a::=%F{green}hello"
>> hello
>>
>> Why does the first print statement print the closing brace? How can the
>> second print statement not produce an error?
>
> ${...} doesn't attempt to balance braces internally, so the first } brings
> it to an end. The final quoted "}" is then just an ordinary character.
ok, good to know.
> You're being a bit too clever for your own good here by trying to too much
> at once. If you separate out the assignment from the use it'll work.
> If you absolutely have to do it this way, however, quoting the text you
> want to be treated as a string by the parameter expansion works.
>
> print "${(%)a::="%F{green}hello"}"
>
> The outer double quotes are now overloaded too many times to be able to
> tell this is what you mean: see a recent post by Bart for a reference to a
> discussion on the standards mailing list about trouble with double quotes.
The expression works as I expect when I leave out all the double quotes. I didn't think those were the problem.
> I'm not sure you actually want the outer double quotes at all, but I'm not
> sure what you're trying to do (and it probably doesn't matter for this
> particular issue).
Sometimes I want to use expansions that are only available as prompt expansions. It's a bit cumbersome having to assign them to a variable first and then evaluate it with the %-modifier. One example would be a condition that checks wether a background job is running:
if ((${(%):-%j}))
then
print "no reexec because background job is running"
return $E_JOB
fi
In this example the above is not an issue. But it could appear in other contexts, when using "inline prompt expansion" in print statements. I admit this is a bit esoteric, but still worth mentioning.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Count only visible characters?
2010-04-09 9:49 ` Joke de Buhr
@ 2010-04-09 19:22 ` Seth House
0 siblings, 0 replies; 11+ messages in thread
From: Seth House @ 2010-04-09 19:22 UTC (permalink / raw)
To: zsh-users
Joke de Buhr <joke <at> seiken.de> writes:
> If you want to do character counting as suggested earlier you need to escape
> the %F{...} sequences
I used to use %{%} before I found the %F short-form and now I've switched back.
:) Doing a search-and-replace for those delimiters seems so obvious in
retrospect. Works like a charm, thanks a lot! That made my day (and made my
prompt code about half as long).
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Count only visible characters?
2010-04-08 22:38 Count only visible characters? Seth House
2010-04-09 9:02 ` Joke de Buhr
@ 2010-04-09 19:50 ` Peter Stephenson
2010-04-10 4:02 ` Bart Schaefer
1 sibling, 1 reply; 11+ messages in thread
From: Peter Stephenson @ 2010-04-09 19:50 UTC (permalink / raw)
To: zsh-users
On Thu, 8 Apr 2010 22:38:05 +0000 (UTC)
Seth House <seth@eseth.com> 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@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Count only visible characters?
2010-04-09 19:50 ` Peter Stephenson
@ 2010-04-10 4:02 ` Bart Schaefer
0 siblings, 0 replies; 11+ messages in thread
From: Bart Schaefer @ 2010-04-10 4:02 UTC (permalink / raw)
To: zsh-users
On Apr 9, 8:50pm, Peter Stephenson wrote:
} On Thu, 8 Apr 2010 22:38:05 +0000 (UTC)
} Seth House <seth@eseth.com> 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.
Incidentally, ${(%)#testing} doesn't do what you think it does. # is
applied BEFORE (%), making (%) rather useless.
What you meant was ${#${(%)testing}}.
} 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.)
There's code to do part of this in Functions/Prompts/prompt_bart_setup,
in the prompt_bart_precmd function. Search for "zero". It doesn't
handle %{ %} pairs, though, just the other zero-width strings.
} 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 `(%)'.
Hmm. Might I suggest that this is of somewhat limited utility? A
better approach might be to add an option that produces the string
with the zero-width characters removed, and then simply apply the old
normal '#' operator to that result. Perhaps tripling the (%) flag
means this, e.g.
print ${(%%%):-%F{red}hello%f there}
hello there
print ${#${(%%%):-%F{red}hello%f there}}
11
My one qualm about (%%%) is that (%%) does more expansion than (%)
and one might want e.g. to count the result of (%) without doing the
PROMPT_SUBST etc. expansion ...
I realize this isn't as straightforward as what you just patched.
A related suggestion that doesn't actually solve the problem of
terminal escapes: Doubling the (V) flag could remove all special
characters from the result, rather than making them visible. (That
should also have the effect of removing any fragmentary multibyte
characters, I think.)
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2010-04-10 4:02 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-04-08 22:38 Count only visible characters? Seth House
2010-04-09 9:02 ` Joke de Buhr
2010-04-09 9:13 ` Frank Terbeck
2010-04-09 9:49 ` Joke de Buhr
2010-04-09 19:22 ` Seth House
2010-04-09 10:44 ` Sebastian Stark
2010-04-09 10:56 ` Sebastian Stark
2010-04-09 12:08 ` Peter Stephenson
2010-04-09 12:27 ` Sebastian Stark
2010-04-09 19:50 ` Peter Stephenson
2010-04-10 4:02 ` Bart Schaefer
Code repositories for project(s) associated with this public inbox
https://git.vuxu.org/mirror/zsh/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).