zsh-workers
 help / color / mirror / code / Atom feed
* Fw: Phil's prompt is not working when LANG is set to UTF-8
@ 2008-02-15 23:52 Peter Stephenson
  2008-02-16  7:56 ` Andrey Borzenkov
  2008-02-16 19:13 ` Bart Schaefer
  0 siblings, 2 replies; 8+ messages in thread
From: Peter Stephenson @ 2008-02-15 23:52 UTC (permalink / raw)
  To: Zsh Hackers' List

On Fri, 15 Feb 2008 22:55:58 +0300
Andrey Borzenkov <arvidjaar@newmail.ru> wrote:
> On Friday 15 February 2008, Andrey Borzenkov wrote:  
> > The actual prompt lengths are (see screenshot)
> > 
> > lpromptw = 13
> > rptomptw = 16 (it has one space in it)
> > 
> > this perfectly correspnds to something (zsh?) ignoring invalid characters
> > with high bit set.  
> 
> For sure.
> 
> Src/prompt.c:countprompt()
> 
>             case MB_INVALID:
>                 memset(&mbs, 0, sizeof mbs);
>                 /* FALL THROUGH */
>             case 0:
>                 /* Invalid character or null: assume no output. */
>                 multi = 0;
>                 break;
> 
> Oops.
> 
> I do not actually see how can we fix it except introducing prompt
> expansion syntax for ACS (or may be for any terminfo sequence in general)
> and simply assuming characters in any of them are of width 1.  

Thanks for looking.  I think I've now roughly caught up; tell me if I'm
mistaken.

- Both terminal and shell start correctly in UTF-8 mode.
- However, Phil's prompt (http://aperiodic.net/phil/prompt/) uses
  the Alternative Character Set by appropriate terminfo trickery.
- The ACS is an old-fashioned grungy VT100 thing from the days
  when nobody had heard of multibyte character sets.
- Hence it falls foul of the multibyte tests.  In principle it
  might clash with a UTF-8 character anyway and have the wrong
  width, so assuming a width 1 for an unknown character is not
  necessarily better than assuming width 0.
- Anyway, assumptions are best avoided if possible.
- Nobody is worrying about editing the ACS, only using it in prompts,
  so a prompt-specific fix is fine.  (Editing with ACS would be
  stupid since the glyphs on the screen wouldn't actually reflect what
  the bytes meant to any programme to which they got fed, right?)

How about the following tweak to prompts to support this?  The upshot is
that you include any funny characters in %{...%G%} where the %G for
`glitch' (which may be repeated or take a numeric argument) indicates a
screen cell taken up by the sequence.  I like this because it uses
facilities that have been present in the shell for a long time and hence
was trivial to implement and might work.

I played with this in simple cases, but would anybody like to confirm
this works in the cases that matter (and maybe produce an updated Phil's
Prompt)?  To put it another way:  I am happy to support this fix but
have no interest in doing anything with it myself.

I think this is clean and useful enough that I will commit it anyway.

Index: Doc/Zsh/prompt.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/prompt.yo,v
retrieving revision 1.9
diff -u -r1.9 prompt.yo
--- Doc/Zsh/prompt.yo	29 Jan 2008 17:51:02 -0000	1.9
+++ Doc/Zsh/prompt.yo	15 Feb 2008 23:34:06 -0000
@@ -188,6 +188,18 @@
 The string within the braces should not change the cursor
 position.  Brace pairs can nest.
 )
+item(tt(%G))(
+Within a tt(%{)...tt(%}) sequence, include a `glitch': that is, assume
+that a single character width will be output.  This is useful when
+outputting characters that otherwise cannot be correctly handled by the
+shell, such as the alternate character set on some terminals.
+The characters in question can be included within a tt(%{)...tt(%})
+sequence together with the appropriate number of tt(%G) sequences to
+indicate the correct width.  An integer between the `tt(%)' and `tt(G)'
+indicates a character width other than one.  Hence tt(%{)var(seq)tt(%2G%})
+outputs var(seq) and assumes it takes up the width of two standard
+characters.
+)
 enditem()
 
 sect(Conditional Substrings in Prompts)
Index: Src/prompt.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/prompt.c,v
retrieving revision 1.44
diff -u -r1.44 prompt.c
--- Src/prompt.c	20 Nov 2007 09:55:10 -0000	1.44
+++ Src/prompt.c	15 Feb 2008 23:34:06 -0000
@@ -473,6 +473,16 @@
 		    *bp++ = Inpar;
 		}
 		break;
+	    case 'G':
+		if (arg > 0) {
+		    addbufspc(arg);
+		    while (arg--)
+			*bp++ = Nularg;
+		} else {
+		    addbufspc(1);
+		    *bp++ = Nularg;
+		}
+		break;
 	    case /*{*/ '}':
 		if (trunccount && trunccount >= dontcount)
 		    return *fm;


-- 
Peter Stephenson <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Fw: Phil's prompt is not working when LANG is set to UTF-8
  2008-02-15 23:52 Fw: Phil's prompt is not working when LANG is set to UTF-8 Peter Stephenson
@ 2008-02-16  7:56 ` Andrey Borzenkov
  2008-02-16  8:50   ` Wael Nasreddine
  2008-02-16  9:00   ` Bart Schaefer
  2008-02-16 19:13 ` Bart Schaefer
  1 sibling, 2 replies; 8+ messages in thread
From: Andrey Borzenkov @ 2008-02-16  7:56 UTC (permalink / raw)
  To: zsh-workers; +Cc: Wael Nasreddine


[-- Attachment #1.1: Type: text/plain, Size: 1152 bytes --]

On Saturday 16 February 2008, Peter Stephenson wrote:
> How about the following tweak to prompts to support this?  The upshot is
> that you include any funny characters in %{...%G%} where the %G for
> `glitch' (which may be repeated or take a numeric argument) indicates a
> screen cell taken up by the sequence. 

Yes, I was about to try the same today morning (you have to sleep on it);
but I likely would not end up with such elegant solution.

> I like this because it uses 
> facilities that have been present in the shell for a long time and hence
> was trivial to implement and might work.
> 
> I played with this in simple cases, but would anybody like to confirm
> this works in the cases that matter (and maybe produce an updated Phil's
> Prompt)? 

I confirm that this works and updated prompt is attached. Wael, does it work
for you with this patch applied?

Now downside of course is, it works only with patched shell ...

> To put it another way:  I am happy to support this fix but 
> have no interest in doing anything with it myself.
> 
> I think this is clean and useful enough that I will commit it anyway.

[-- Attachment #1.2: phils.new --]
[-- Type: text/plain, Size: 3939 bytes --]

# vim:ft=zsh:fenc=UTF-8:ts=4:sts=4:sw=4:expandtab:
# $Id$

function precmd {

    local TERMWIDTH
    (( TERMWIDTH = ${COLUMNS} - 1 ))


    ###
    # Truncate the path if it's too long.

    PR_FILLBAR=""
    PR_FILLBAR_PRE=""
    PR_FILLBAR_POST=""
    PR_PWDLEN=""

    local promptsize=${#${(%):---(%n@%m:%l)---()--}}
    local pwdsize=${#${(%):-%~}}

    if [[ "$promptsize + $pwdsize" -gt $TERMWIDTH ]]; then
	    ((PR_PWDLEN=$TERMWIDTH - $promptsize))
    else
	PR_FILLBAR="\${(l.(($TERMWIDTH - ($promptsize + $pwdsize)))..${PR_HBAR_PURE}.)}"
    PR_FILLBAR_PRE="%{"
    PR_FILLBAR_POST="%${#PR_FILLBAR}G%}"
    fi


    ###
    # Get APM info.

#    if which ibam &> /dev/null; then
#	PR_APM_RESULT=`ibam --percentbattery 2> /dev/null`
#    elif which apm &> /dev/null; then
#	PR_APM_RESULT=`apm 2> /dev/null`
#    fi
}


setopt extended_glob
preexec () {
    if [[ "$TERM" == "screen" ]]; then
	local CMD=${1[(wr)^(*=*|sudo|-*)]}
	echo -n "\ek$CMD\e\\"
    fi
}


setprompt () {
    ###
    # Need this so the prompt will work.

    setopt prompt_subst


    ###
    # See if we can use colors.

    autoload colors zsh/terminfo
    if [[ "$terminfo[colors]" -ge 8 ]]; then
	colors
    fi
    for color in RED GREEN YELLOW BLUE MAGENTA CYAN WHITE; do
	eval PR_$color='%{$terminfo[bold]$fg[${(L)color}]%}'
	eval PR_LIGHT_$color='%{$fg[${(L)color}]%}'
	(( count = $count + 1 ))
    done
    PR_NO_COLOUR="%{$terminfo[sgr0]%}"


    ###
    # See if we can use extended characters to look nicer.

    typeset -A altchar
    set -A altchar ${(s..)terminfo[acsc]}
    PR_SET_CHARSET="%{$terminfo[enacs]%}"
    PR_SHIFT_IN="%{$terminfo[smacs]%}"
    PR_SHIFT_OUT="%{$terminfo[rmacs]%}"
    PR_HBAR_PURE="${altchar[q]:--}"
    PR_HBAR="%{${altchar[q]:--}%G%}"
    PR_ULCORNER="%{${altchar[l]:--}%G%}"
    PR_LLCORNER="%{${altchar[m]:--}%G%}"
    PR_LRCORNER="%{${altchar[j]:--}%G%}"
    PR_URCORNER="%{${altchar[k]:--}%G%}"


    ###
    # Decide if we need to set titlebar text.

    case $TERM in
	xterm*)
	    PR_TITLEBAR=$'%{\e]0;%(!.-=*[ROOT]*=- | .)%n@%m:%~ | ${COLUMNS}x${LINES} | %y\a%}'
	    ;;
	screen*)
	    PR_TITLEBAR=$'%{\e_screen \005 (\005t) | %(!.-=[ROOT]=- | .)%n@%m:%~ | ${COLUMNS}x${LINES} | %y\e\\%}'
	    ;;
	*)
	    PR_TITLEBAR=''
	    ;;
    esac


    ###
    # Decide whether to set a screen title
    if echo "${TERM}" | grep -q "^screen"; then
	PR_STITLE=$'%{\ekzsh\e\\%}'
    else
	PR_STITLE=''
    fi


    ###
    # APM detection

#    if which ibam > /dev/null; then
#	PR_APM='$PR_RED${${PR_APM_RESULT[(f)1]}[(w)-2]}%%(${${PR_APM_RESULT[(f)3]}[(w)-1]})$PR_LIGHT_BLUE:'
#    elif which apm > /dev/null; then
#	PR_APM='$PR_RED${PR_APM_RESULT[(w)5,(w)6]/\% /%%}$PR_LIGHT_BLUE:'
#    else
#	PR_APM=''
#    fi


    ###
    # Finally, the prompt.

    PROMPT='$PR_SET_CHARSET$PR_STITLE${(e)PR_TITLEBAR}\
$PR_CYAN$PR_SHIFT_IN$PR_ULCORNER$PR_BLUE$PR_HBAR$PR_SHIFT_OUT(\
$PR_CYAN%(!.%SROOT%s.%n)$PR_YELLOW@$PR_GREEN%m$PR_YELLOW:$PR_BLUE%l\
$PR_BLUE)$PR_SHIFT_IN$PR_HBAR$PR_CYAN$PR_HBAR$PR_FILLBAR_PRE${(e)PR_FILLBAR}$PR_FILLBAR_POST$PR_BLUE$PR_HBAR$PR_SHIFT_OUT(\
$PR_MAGENTA%$PR_PWDLEN<...<%~%<<\
$PR_BLUE)$PR_SHIFT_IN$PR_HBAR$PR_CYAN$PR_URCORNER$PR_SHIFT_OUT\

$PR_CYAN$PR_SHIFT_IN$PR_LLCORNER$PR_BLUE$PR_HBAR$PR_SHIFT_OUT(\
%(?..$PR_LIGHT_RED%?$PR_BLUE:)\
${(e)PR_APM}$PR_YELLOW%D{%H:%M}\
$PR_LIGHT_BLUE:%(!.$PR_RED.$PR_WHITE)%#$PR_BLUE)$PR_SHIFT_IN$PR_HBAR$PR_SHIFT_OUT\
$PR_CYAN$PR_SHIFT_IN$PR_HBAR$PR_SHIFT_OUT\
$PR_NO_COLOUR '

    RPROMPT=' $PR_CYAN$PR_SHIFT_IN$PR_HBAR$PR_BLUE$PR_HBAR$PR_SHIFT_OUT\
($PR_YELLOW%D{%a,%b%d}$PR_BLUE)$PR_SHIFT_IN$PR_HBAR$PR_CYAN$PR_LRCORNER$PR_SHIFT_OUT$PR_NO_COLOUR'

    PS2='$PR_CYAN$PR_SHIFT_IN$PR_HBAR$PR_SHIFT_OUT\
$PR_BLUE$PR_SHIFT_IN$PR_HBAR$PR_SHIFT_OUT(\
$PR_LIGHT_GREEN%_$PR_BLUE)$PR_SHIFT_IN$PR_HBAR$PR_SHIFT_OUT\
$PR_CYAN$PR_SHIFT_IN$PR_HBAR$PR_SHIFT_OUT$PR_NO_COLOUR '
}

setprompt
print -rnP -- "$PROMPT" > /tmp/PROMPT
print -rnP -- "$RPROMPT" > /tmp/RPROMPT

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Fw: Phil's prompt is not working when LANG is set to UTF-8
  2008-02-16  7:56 ` Andrey Borzenkov
@ 2008-02-16  8:50   ` Wael Nasreddine
  2008-02-16  9:00   ` Bart Schaefer
  1 sibling, 0 replies; 8+ messages in thread
From: Wael Nasreddine @ 2008-02-16  8:50 UTC (permalink / raw)
  To: zsh-workers

[-- Attachment #1: Type: text/plain, Size: 1784 bytes --]

This One Time, at Band Camp, Andrey Borzenkov <arvidjaar@newmail.ru> said, On Sat, Feb 16, 2008 at 10:56:25AM +0300:
> On Saturday 16 February 2008, Peter Stephenson wrote:
> > How about the following tweak to prompts to support this?  The upshot is
> > that you include any funny characters in %{...%G%} where the %G for
> > `glitch' (which may be repeated or take a numeric argument) indicates a
> > screen cell taken up by the sequence. 

> Yes, I was about to try the same today morning (you have to sleep on it);
> but I likely would not end up with such elegant solution.

> > I like this because it uses 
> > facilities that have been present in the shell for a long time and hence
> > was trivial to implement and might work.

> > I played with this in simple cases, but would anybody like to confirm
> > this works in the cases that matter (and maybe produce an updated Phil's
> > Prompt)? 

> I confirm that this works and updated prompt is attached. Wael, does it work
> for you with this patch applied?

> Now downside of course is, it works only with patched shell ...

> > To put it another way:  I am happy to support this fix but 
> > have no interest in doing anything with it myself.

> > I think this is clean and useful enough that I will commit it anyway.


OMG it finally works... Thank you so much guys, thanks a lot Peter...

BTW don't Cc to me anymore, I've switched my subscription from
-users to -workers

Thanks again... I use it daily so if anything's wrong I'll notify
you...

-- 
Wael Nasreddine
http://wael.nasreddine.com
PGP: 1024D/C8DD18A2 06F6 1622 4BC8 4CEB D724  DE12 5565 3945 C8DD 18A2

.: An infinite number of monkeys typing into GNU emacs,
   would never make a good program. (L. Torvalds 1995) :.

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Fw: Phil's prompt is not working when LANG is set to UTF-8
  2008-02-16  7:56 ` Andrey Borzenkov
  2008-02-16  8:50   ` Wael Nasreddine
@ 2008-02-16  9:00   ` Bart Schaefer
  1 sibling, 0 replies; 8+ messages in thread
From: Bart Schaefer @ 2008-02-16  9:00 UTC (permalink / raw)
  To: Andrey Borzenkov, zsh-workers; +Cc: Wael Nasreddine

On Feb 16, 10:56am, Andrey Borzenkov wrote:
}
} Now downside of course is, it works only with patched shell ...

I'll describe a workaround but I don't have time now to actually
write code for it:

(1) Emit %{, the sequence for "save cursor position", %}

(2) Emit ${#PR_FILLBAR} spaces.

(3) Emit %{, "restore cursor position", then the actual line drawing
    characters (which will overwrite the spaces), then %}

This should work in any shell, and should work whether the shell is
correctly calculating the width of the ACS characters or not, and
should even work if the ACS characters are not being used.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Fw: Phil's prompt is not working when LANG is set to UTF-8
  2008-02-15 23:52 Fw: Phil's prompt is not working when LANG is set to UTF-8 Peter Stephenson
  2008-02-16  7:56 ` Andrey Borzenkov
@ 2008-02-16 19:13 ` Bart Schaefer
  2008-02-16 19:32   ` Bart Schaefer
  2008-02-17 16:43   ` Peter Stephenson
  1 sibling, 2 replies; 8+ messages in thread
From: Bart Schaefer @ 2008-02-16 19:13 UTC (permalink / raw)
  To: Zsh Hackers' List

On Feb 15, 11:52pm, Peter Stephenson wrote:
}
} - Hence it falls foul of the multibyte tests.  In principle it
}   might clash with a UTF-8 character anyway and have the wrong
}   width, so assuming a width 1 for an unknown character is not
}   necessarily better than assuming width 0.

I agree with "not necessarily," but I suspect it'll be right more
often than wrong to assume 1.  *Most* characters are not going to be
"non-printing," and if the mb library doesn't recognize them, then
they're also unlikely to be simultaneously multibyte and handled
correctly by the terminal.

I'll bet I argued this the other way when this came up the last time,
but now we have some empirical results.

} How about the following tweak to prompts to support this? The upshot
} is that you include any funny characters in %{...%G%} where the %G for
} `glitch' (which may be repeated or take a numeric argument) indicates
} a screen cell taken up by the sequence.

I like this, but I'm wondering if it might not be better to have %{
accept a count, e.g., instead of %{...%6G%} just write %6{...%}.  Does
it matter where %G appears?  %{...%7G...%} ?  What if you use it more
than once, as in %{...%7G...%3G%} ?  Using a count on %{ might make it
more obvious that you should write %7{...%}%3{...%} if %7G%3G != %10G.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Fw: Phil's prompt is not working when LANG is set to UTF-8
  2008-02-16 19:13 ` Bart Schaefer
@ 2008-02-16 19:32   ` Bart Schaefer
  2008-02-17 16:43   ` Peter Stephenson
  1 sibling, 0 replies; 8+ messages in thread
From: Bart Schaefer @ 2008-02-16 19:32 UTC (permalink / raw)
  To: Zsh Hackers' List

On Feb 16, 11:13am, Bart Schaefer wrote:
}
} Does it matter where %G appears?  %{...%7G...%} ?
} What if you use it more than once, as in %{...%7G...%3G%} ?

Ooh, and what about negative numbers?  Can one say %-4G to mean that
the sequence actually moved the cursor to the LEFT four positions?
*That* could be really useful.

Another idea:  How about sequences that actually move the cursor?
%H and %V for horizontal/vertical?

%4H -> move cursor four spaces to the right
%5V -> move cursor five lines down
%{%-6H%} -> move cursor six spaces to the left, but pretend you didn't

If %} also remembered the cursor position, then you could also have:

%P -> "pop" cursor back to where it was at the end of the last %{...%}

This may be getting a little bit too far out there.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Phil's prompt is not working when LANG is set to UTF-8
  2008-02-16 19:13 ` Bart Schaefer
  2008-02-16 19:32   ` Bart Schaefer
@ 2008-02-17 16:43   ` Peter Stephenson
  2008-02-17 17:40     ` Peter Stephenson
  1 sibling, 1 reply; 8+ messages in thread
From: Peter Stephenson @ 2008-02-17 16:43 UTC (permalink / raw)
  To: Zsh Hackers' List

On Sat, 16 Feb 2008 11:13:35 -0800
Bart Schaefer <schaefer@brasslantern.com> wrote:
> On Feb 15, 11:52pm, Peter Stephenson wrote:
> }
> } - Hence it falls foul of the multibyte tests.  In principle it
> }   might clash with a UTF-8 character anyway and have the wrong
> }   width, so assuming a width 1 for an unknown character is not
> }   necessarily better than assuming width 0.
> 
> I agree with "not necessarily," but I suspect it'll be right more
> often than wrong to assume 1.  *Most* characters are not going to be
> "non-printing," and if the mb library doesn't recognize them, then
> they're also unlikely to be simultaneously multibyte and handled
> correctly by the terminal.

OK, I'll change that (though needless to say the %G method is
still recommended as being less hit and miss).

> I like this, but I'm wondering if it might not be better to have %{
> accept a count, e.g., instead of %{...%6G%} just write %6{...%}.

That was my originally thought, but then I realisd that as far as the
code is concerned they're logically independent.  From the point of view
of the user it's a rather different matter, however.  It's trivial to
support both.

> Does it matter where %G appears?  %{...%7G...%} ?

Because they're indepdendent, it doesn't matter at all, and multiple
uses acumulate.  In fact, they don't actually need to appear within
the %{...%}, although there's no obvious reason to put them elsewhere.

> Ooh, and what about negative numbers?  Can one say %-4G to mean that
> the sequence actually moved the cursor to the LEFT four positions?
> *That* could be really useful.

Yes, but I picked the present change because it was already supported by
the backend code.  Additions like the above are another story.

Index: Doc/Zsh/prompt.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/prompt.yo,v
retrieving revision 1.10
diff -u -r1.10 prompt.yo
--- Doc/Zsh/prompt.yo	15 Feb 2008 23:59:09 -0000	1.10
+++ Doc/Zsh/prompt.yo	17 Feb 2008 16:42:43 -0000
@@ -187,6 +187,9 @@
 Include a string as a literal escape sequence.
 The string within the braces should not change the cursor
 position.  Brace pairs can nest.
+
+A positive numeric argument between the tt(%) and the %%({) is treated as
+described for tt(%G) below.
 )
 item(tt(%G))(
 Within a tt(%{)...tt(%}) sequence, include a `glitch': that is, assume
@@ -199,6 +202,9 @@
 indicates a character width other than one.  Hence tt(%{)var(seq)tt(%2G%})
 outputs var(seq) and assumes it takes up the width of two standard
 characters.
+
+Multiple uses of tt(%G) accumulate in the obvious fashion; the position
+of the tt(%G) is unimportant.  Negative integers are not handled.
 )
 enditem()
 
Index: Src/prompt.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/prompt.c,v
retrieving revision 1.45
diff -u -r1.45 prompt.c
--- Src/prompt.c	15 Feb 2008 23:59:09 -0000	1.45
+++ Src/prompt.c	17 Feb 2008 16:42:43 -0000
@@ -472,7 +472,10 @@
 		    addbufspc(1);
 		    *bp++ = Inpar;
 		}
-		break;
+		if (arg <= 0)
+		    break;
+		/* else */
+		/* FALLTHROUGH */
 	    case 'G':
 		if (arg > 0) {
 		    addbufspc(arg);
@@ -948,9 +951,11 @@
 		break;
 	    case MB_INVALID:
 		memset(&mbs, 0, sizeof mbs);
-		/* FALL THROUGH */
+		/* Invalid character: assume single width. */
+		multi = 0;
+		w++;
+		break;
 	    case 0:
-		/* Invalid character or null: assume no output. */
 		multi = 0;
 		break;
 	    default:

-- 
Peter Stephenson <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Phil's prompt is not working when LANG is set to UTF-8
  2008-02-17 16:43   ` Peter Stephenson
@ 2008-02-17 17:40     ` Peter Stephenson
  0 siblings, 0 replies; 8+ messages in thread
From: Peter Stephenson @ 2008-02-17 17:40 UTC (permalink / raw)
  To: Zsh Hackers' List

Peter Stephenson wrote:
> > Does it matter where %G appears?  %{...%7G...%} ?
> 
> Because they're indepdendent, it doesn't matter at all

Slight overstatement, since if we truncate the prompt the position of
the %G becomes important if it's not associated with the right
%{...%}, but the answer to the spirit of your original question is still
no, it doesn't matter where it appears within a %{...%}.

However, this, er, prompted me to look and see how we handle truncation
and there is code missing for this case.  The right thing to do must be
to copy the entire group, since we don't know how to divide it up.
Consequently it's a good idea to divide the groups as far as possible
into single characters.  This seems worth documenting.  This is an
updated patch.

Index: Doc/Zsh/prompt.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/prompt.yo,v
retrieving revision 1.10
diff -u -r1.10 prompt.yo
--- Doc/Zsh/prompt.yo	15 Feb 2008 23:59:09 -0000	1.10
+++ Doc/Zsh/prompt.yo	17 Feb 2008 17:39:39 -0000
@@ -187,6 +187,9 @@
 Include a string as a literal escape sequence.
 The string within the braces should not change the cursor
 position.  Brace pairs can nest.
+
+A positive numeric argument between the tt(%) and the %%({) is treated as
+described for tt(%G) below.
 )
 item(tt(%G))(
 Within a tt(%{)...tt(%}) sequence, include a `glitch': that is, assume
@@ -199,6 +202,13 @@
 indicates a character width other than one.  Hence tt(%{)var(seq)tt(%2G%})
 outputs var(seq) and assumes it takes up the width of two standard
 characters.
+
+Multiple uses of tt(%G) accumulate in the obvious fashion; the position
+of the tt(%G) is unimportant.  Negative integers are not handled.
+
+Note that when prompt truncation is in use it is advisable to divide up
+output into single characters within each tt(%{)...tt(%}) group so that
+the correct truncation point can be found.
 )
 enditem()
 
Index: Src/prompt.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/prompt.c,v
retrieving revision 1.45
diff -u -r1.45 prompt.c
--- Src/prompt.c	15 Feb 2008 23:59:09 -0000	1.45
+++ Src/prompt.c	17 Feb 2008 17:39:41 -0000
@@ -472,7 +472,10 @@
 		    addbufspc(1);
 		    *bp++ = Inpar;
 		}
-		break;
+		if (arg <= 0)
+		    break;
+		/* else */
+		/* FALLTHROUGH */
 	    case 'G':
 		if (arg > 0) {
 		    addbufspc(arg);
@@ -948,9 +951,11 @@
 		break;
 	    case MB_INVALID:
 		memset(&mbs, 0, sizeof mbs);
-		/* FALL THROUGH */
+		/* Invalid character: assume single width. */
+		multi = 0;
+		w++;
+		break;
 	    case 0:
-		/* Invalid character or null: assume no output. */
 		multi = 0;
 		break;
 	    default:
@@ -1124,14 +1129,19 @@
 			    /*
 			     * Text marked as invisible: copy
 			     * regardless, since we don't know what
-			     * this does but it shouldn't affect
-			     * the width.
+			     * this does.  It only affects the width
+			     * if there are Nularg's present.
+			     * However, even in that case we
+			     * can't break the sequence down, so
+			     * we still loop over the entire group.
 			     */
 			    for (;;) {
 				*ptr++ = *fulltextptr;
 				if (*fulltextptr == Outpar ||
 				    *fulltextptr == '\0')
 				    break;
+				if (*fulltextptr == Nularg)
+				    remw--;
 				fulltextptr++;
 			    }
 			} else {
@@ -1206,8 +1216,15 @@
 
 		    while (maxwidth > 0 && *skiptext) {
 			if (*skiptext == Inpar) {
-			    for (; *skiptext != Outpar && *skiptext;
-				 skiptext++);
+			    /* see comment on left truncation above */
+			    for (;;) {
+				if (*skiptext == Outpar ||
+				    *skiptext == '\0')
+				    break;
+				if (*skiptext == Nularg)
+				    maxwidth--;
+				skiptext++;
+			    }
 			} else {
 #ifdef MULTIBYTE_SUPPORT
 			    char inchar;


-- 
Peter Stephenson <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2008-02-17 17:42 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-02-15 23:52 Fw: Phil's prompt is not working when LANG is set to UTF-8 Peter Stephenson
2008-02-16  7:56 ` Andrey Borzenkov
2008-02-16  8:50   ` Wael Nasreddine
2008-02-16  9:00   ` Bart Schaefer
2008-02-16 19:13 ` Bart Schaefer
2008-02-16 19:32   ` Bart Schaefer
2008-02-17 16:43   ` Peter Stephenson
2008-02-17 17:40     ` Peter Stephenson

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).