Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: missing Parameter Expansion Flag?



On Fri, Oct 19, 2007 at 12:53:21PM +1300, Atom Smasher wrote:
> *but* i don't see how to count the string so that it just counts the 
> printing characters (xxxyyy). i want to count it so the count returns 6, 
> which is how many printable characters are in the string. intuitively, i 
> would think there should be a parameter expansion flag to do that, but i 
> can't find it. is there another (good*) way? should there be a flag for 
> that?

There can't be a flag for that because zsh doesn't know what
characters are and are not printing, it just outputs them to the
terminal.  The actual codes supported are terminal-dependent.  For
a list of control sequences supported by xterm, see the list at
http://www.xfree86.org/current/ctlseqs.html .  A list of control
sequences recognized by screen can be found in `man screen', in the
'The Virtual Terminal' section.  Quick googling should find you
a similar list for rxvt.  While all of those lists have some
similarities ("\e[{3,4}{0..7}m" being one of them), they also all have
their differences, and a comprehensive list would be a larger project
than terminfo or termcap.  The fact that many of those commands can
take a variable number of arguments make it even harder.  If zsh could
do that, though, we wouldn't need %{...%} in our prompt strings.

That being said...

> let's say i set a string to print "xxxyyy" with the "xxx" in the default 
> color and the "yyy" in red:
> 	foo="xxx${fg[red]}yyy"
>
> which results in:
> 	print ${foo}
> 	xxxyyy
>
> 	print ${(V)foo}
> 	xxx^[[31myyy

Why not wrap your stuff in the prompt expansion stuff?

mastermind% autoload -U colors; colors
mastermind% foo="xx%{${fg[red]}%}yy%{${fg[blue]}%}zz%{$reset_color%}"
mastermind% echo ${(V)foo}
xx%{^[[31m%}yy%{^[[34m%}zz%{^[[00m%}
mastermind% echo ${(VS)foo//\%\{*\%\}}
xxyyzz
mastermind% echo $#foo
33
mastermind% echo ${#${(S)foo//\%\{*\%\}}}
6
mastermind% echo ${(%)foo}
xxyyzz   <- *colored*
mastermind% echo ${(S)foo//\%\{*\%\}}
xxyyzz   <- *not colored*

That is, if you wrap unprintable sequences in %{..%}, you can still
print out the string without the delimiters using ${(%)var} ( (%)
causes %-escapes in the resulting string to be expanded, and %{ and %}
expand to nothing. )  Then, you can also get the size of the string by
expanding it to remove ( ${var//foo}, replace foo with nothing) the %{
up til %} (non-greedy matching with (S).  So, the short answer is that
zsh has no way of keeping track of what was printable, and the long
answer is that it's not impossible to keep track of yourself, as long
as you are only using escape sequences that you know will not be
shown and mark them up accordingly ahead of time.

~Matt



Messages sorted by: Reverse Date, Date, Thread, Author