about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBarton E. Schaefer <schaefer@zsh.org>2014-08-07 09:26:09 -0700
committerBarton E. Schaefer <schaefer@zsh.org>2014-08-07 09:26:09 -0700
commit6fc3b67b80c5bef6b1241657f7d1e5f55f6af1bf (patch)
tree6cbdb1cabecc04d7efc21187eae596fcc777c398
parentc810a072e220914444b38b87aaee5ae40edb6466 (diff)
downloadzsh-6fc3b67b80c5bef6b1241657f7d1e5f55f6af1bf.tar.gz
zsh-6fc3b67b80c5bef6b1241657f7d1e5f55f6af1bf.tar.xz
zsh-6fc3b67b80c5bef6b1241657f7d1e5f55f6af1bf.zip
32971: negative argument with %(l..) and with %<< or %>> calculates space available before right margin
-rw-r--r--ChangeLog7
-rw-r--r--Doc/Zsh/prompt.yo29
-rw-r--r--Src/prompt.c16
3 files changed, 43 insertions, 9 deletions
diff --git a/ChangeLog b/ChangeLog
index cceb5df50..e2f5dbcd7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2014-08-07  Barton E. Schaefer  <schaefer@zsh.org>
+
+	* 32971 (plus doc tweak): Doc/Zsh/prompt.yo, Src/prompt.c:
+	negative argument with %(l..) conditional and with %<< or %>>
+	truncation calculates space available before right margin
+	(positive argument still counts space used since left margin).
+
 2014-08-04  Barton E. Schaefer  <schaefer@brasslantern.com>
 
 	* Miles Ohlrich: 32958: Src/Zle/compctl.c: bitwise logic fix
diff --git a/Doc/Zsh/prompt.yo b/Doc/Zsh/prompt.yo
index 36f351b96..5d75a365a 100644
--- a/Doc/Zsh/prompt.yo
+++ b/Doc/Zsh/prompt.yo
@@ -302,7 +302,8 @@ sitem(tt(g))(True if the effective gid of the current process is var(n).)
 sitem(tt(j))(True if the number of jobs is at least var(n).)
 sitem(tt(L))(True if the tt(SHLVL) parameter is at least var(n).)
 sitem(tt(l))(True if at least var(n) characters have already been
-printed on the current line.)
+printed on the current line.  When var(n) is negative, true if at least
+tt(abs)tt(LPAR())var(n)tt(RPAR()) characters remain before the right margin.)
 sitem(tt(S))(True if the tt(SECONDS) parameter is at least var(n).)
 sitem(tt(T))(True if the time in hours is equal to var(n).)
 sitem(tt(t))(True if the time in minutes is equal to var(n).)
@@ -318,13 +319,21 @@ item(tt(%[)var(xstring)tt(]))(
 Specifies truncation behaviour for the remainder of the prompt string.
 The third, deprecated, form is equivalent to `tt(%)var(xstringx)',
 i.e. var(x) may be `tt(<)' or `tt(>)'.
-The numeric argument, which in the third form may appear immediately
-after the `tt([)', specifies the maximum permitted length of
-the various strings that can be displayed in the prompt.
 The var(string) will be displayed in
 place of the truncated portion of any string; note this does not
 undergo prompt expansion.
 
+The numeric argument, which in the third form may appear immediately
+after the `tt([)', specifies the maximum permitted length of
+the various strings that can be displayed in the prompt.
+In the first two forms, this numeric argument may be negative, in which
+case the truncation length is determined by subtracting the absolute
+value of the numeric argument from the number of character positions
+remaining on the current prompt line.  If this results in a zero or
+negative length, a length of 1 is used.  In other words, a negative
+argument arranges that after truncation at least var(n) characters
+remain before the right margin.
+
 The forms with `tt(<)' truncate at the left of the string,
 and the forms with `tt(>)' truncate at the right of the string.
 For example, if the current directory is `tt(/home/pike)',
@@ -344,11 +353,19 @@ string, or to the end of the next enclosing group of the `tt(%LPAR())'
 construct, or to the next truncation encountered at the same grouping
 level (i.e. truncations inside a `tt(%LPAR())' are separate), which
 ever comes first.  In particular, a truncation with argument zero
-(e.g. `tt(%<<)') marks the end of the range of the string to be
+(e.g., `tt(%<<)') marks the end of the range of the string to be
 truncated while turning off truncation from there on. For example, the
 prompt '%10<...<%~%<<%# ' will print a truncated representation of the
 current directory, followed by a `tt(%)' or `tt(#)', followed by a
 space.  Without the `tt(%<<)', those two characters would be included
-in the string to be truncated.
+in the string to be truncated.  Note that `tt(%-0<<)' is a distinct
+
+Truncation applies only within each individual line of the prompt, as
+delimited by embedded newlines (if any).  If the total length of any line
+of the prompt after truncation is greater than the terminal width, or if
+the part to be truncated contains embedded newlines, truncation behavior
+is undefined and may change in a future version of the shell.  Use
+`tt(%-var(n)LPAR()l.var(true-text).var(false-text)RPAR())' to remove parts
+of the prompt when the available space is less than var(n).
 )
 enditem()
diff --git a/Src/prompt.c b/Src/prompt.c
index c16d78163..328ae3c66 100644
--- a/Src/prompt.c
+++ b/Src/prompt.c
@@ -367,6 +367,8 @@ putpromptchar(int doprint, int endchar, unsigned int *txtchangep)
 		case 'l':
 		    *bv->bp = '\0';
 		    countprompt(bv->bufline, &t0, 0, 0);
+		    if (minus)
+			t0 = zterm_columns - t0;
 		    if (t0 >= arg)
 			test = 1;
 		    break;
@@ -560,6 +562,14 @@ putpromptchar(int doprint, int endchar, unsigned int *txtchangep)
 		break;
 	    case '<':
 	    case '>':
+		/* Test (minus) here so -0 means "at the right margin" */
+		if (minus) {
+		    *bv->bp = '\0';
+		    countprompt(bv->bufline, &t0, 0, 0);
+		    arg = zterm_columns - t0 + arg;
+		    if (arg <= 0)
+			arg = 1;
+		}
 		if (!prompttrunc(arg, *bv->fm, doprint, endchar, txtchangep))
 		    return *bv->fm;
 		break;
@@ -1174,7 +1184,7 @@ prompttrunc(int arg, int truncchar, int doprint, int endchar,
 	    addbufspc(1);
 	    *bv->bp++ = '<';
 	}
-	ptr = bv->buf + w;		/* addbv->bufspc() may have realloc()'d bv->buf */
+	ptr = bv->buf + w;	/* addbufspc() may have realloc()'d bv->buf */
 	/*
 	 * Now:
 	 *   bv->buf is the start of the output prompt buffer
@@ -1189,7 +1199,7 @@ prompttrunc(int arg, int truncchar, int doprint, int endchar,
 	bv->trunccount = bv->dontcount;
 	putpromptchar(doprint, endchar, txtchangep);
 	bv->trunccount = 0;
-	ptr = bv->buf + w;		/* putpromptchar() may have realloc()'d */
+	ptr = bv->buf + w;	/* putpromptchar() may have realloc()'d */
 	*bv->bp = '\0';
 	/*
 	 * Now:
@@ -1475,7 +1485,7 @@ prompttrunc(int arg, int truncchar, int doprint, int endchar,
 	/* Now we have to trick it into matching endchar again */
 	bv->fm--;
     } else {
-	if (*bv->fm != ']')
+	if (*bv->fm != endchar)
 	    bv->fm++;
 	while(*bv->fm && *bv->fm != truncchar) {
 	    if (*bv->fm == '\\' && bv->fm[1])