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

PATCH: PROMPT_SP



I've been doing some work on this new option I'm suggesting.  The
current name I'm leaning towards is PROMPT_SP, so that's what this
patch implements.  Please feel free to comment about this or suggest
a better name.

The patch was also changed to try to output fewer characters, and also
to try to prevent mouse selection from joining a partial line with the
prompt line that follows it (resulting in a lot of spaces being copied
to the clipboard).  So, this patch uses TCMULTRIGHT or TCRIGHT (when
available) to get to (or near) the right margin, outputs 2 spaces (which
might induce a wrap), and then (if save- and restore-cursor are there),
it outputs two backspaces and either tries to clear-to-EOL or to delete
a character before restoring the cursor position.

In my testing, as long as the cursor ends up on the previous line by the
backspaces, both xterm and konsole fix the selection problem using
either clear-to-EOL or delete-char.  However, the only way I currently
know of to enable a wrappable left margin is to run zsh under screen, so
suggestions are welcomed as to how to enable a soft left margin in a
modern day terminal emulator.

One thing I added while I was adding support for looking up the save-
and restore-cursor escapes was a lookup for the backspace character
("bc" is only supposed to be set if the "bs" flag is not set, but I just
made the code always look up "bc" and default the value to "\b" if it
wasn't found).  Since some other parts of zsh use literal \b characters,
this might be overkill and it is debatable if we really need it.

This patch is based on the CVS version, not my prior patch.

..wayne..
--- Doc/Zsh/options.yo	18 Mar 2005 22:40:17 -0000	1.37
+++ Doc/Zsh/options.yo	14 Jul 2005 17:49:54 -0000
@@ -906,6 +906,15 @@ Print a carriage return just before prin
 a prompt in the line editor.  This is on by default as multi-line editing
 is only possible if the editor knows where the start of the line appears.
 )
+pindex(PROMPT_SP)
+cindex(prompt, save partial lines)
+item(tt(PROMPT_SP) (tt(PLUS()V)) <D>)(
+Attempt to preserve any partially-output line (i.e. a line that did not end
+with a newline) by outputting a series of spaces prior to the carriage return
+that is output by PROMPT_CR.  This only works if your terminal has automatic
+margins.  Also, if the PROMPT_CR option is not set, enabling this option will
+have no effect.  This option is on by default.
+)
 pindex(PROMPT_PERCENT)
 cindex(prompt, % expansion)
 item(tt(PROMPT_PERCENT) <C> <Z>)(
--- Src/init.c	13 Jun 2005 14:59:37 -0000	1.53
+++ Src/init.c	14 Jul 2005 17:49:55 -0000
@@ -77,7 +77,7 @@ mod_export int tclen[TC_COUNT];
 /**/
 int tclines, tccolumns;
 /**/
-mod_export int hasam;
+mod_export int hasam, hasxn;
 
 /* Pointer to read-key function from zle */
 
@@ -518,7 +518,7 @@ static char *tccapnams[TC_COUNT] = {
     "cl", "le", "LE", "nd", "RI", "up", "UP", "do",
     "DO", "dc", "DC", "ic", "IC", "cd", "ce", "al", "dl", "ta",
     "md", "so", "us", "me", "se", "ue", "ch",
-    "ku", "kd", "kl", "kr"
+    "ku", "kd", "kl", "kr", "sc", "rc", "bc"
 };
 
 /* Initialise termcap */
@@ -573,6 +573,7 @@ init_term(void)
 
 	/* check whether terminal has automargin (wraparound) capability */
 	hasam = tgetflag("am");
+	hasxn = tgetflag("xn"); /* also check for newline wraparound glitch */
 
 	tclines = tgetnum("li");
 	tccolumns = tgetnum("co");
@@ -587,10 +588,22 @@ init_term(void)
 	    termflags |= TERM_NOUP;
 	}
 
-	/* if there's no termcap entry for cursor left, use \b. */
+	/* most termcaps don't define "bc" because they use \b. */
+	if (!tccan(TCBACKSPACE)) {
+	    tcstr[TCBACKSPACE] = ztrdup("\b");
+	    tclen[TCBACKSPACE] = 1;
+	}
+
+	/* if there's no termcap entry for cursor left, use backspace. */
 	if (!tccan(TCLEFT)) {
-	    tcstr[TCLEFT] = ztrdup("\b");
-	    tclen[TCLEFT] = 1;
+	    tcstr[TCLEFT] = tcstr[TCBACKSPACE];
+	    tclen[TCLEFT] = tclen[TCBACKSPACE];
+	}
+
+	if (tccan(TCSAVECURSOR) && !tccan(TCRESTRCURSOR)) {
+	    tclen[TCSAVECURSOR] = 0;
+	    zsfree(tcstr[TCSAVECURSOR]);
+	    tcstr[TCSAVECURSOR] = NULL;
 	}
 
 	/* if the termcap entry for down is \n, don't use it. */
--- Src/options.c	18 Mar 2005 22:40:26 -0000	1.22
+++ Src/options.c	14 Jul 2005 17:49:55 -0000
@@ -181,6 +181,7 @@ static struct optname optns[] = {
 {NULL, "promptbang",	      OPT_KSH,			 PROMPTBANG},
 {NULL, "promptcr",	      OPT_ALL,			 PROMPTCR},
 {NULL, "promptpercent",	      OPT_NONBOURNE,		 PROMPTPERCENT},
+{NULL, "promptsp",	      OPT_ALL,			 PROMPTSP},
 {NULL, "promptsubst",	      OPT_KSH,			 PROMPTSUBST},
 {NULL, "pushdignoredups",     OPT_EMULATE,		 PUSHDIGNOREDUPS},
 {NULL, "pushdminus",	      OPT_EMULATE,		 PUSHDMINUS},
--- Src/zsh.h	1 Jun 2005 10:45:42 -0000	1.74
+++ Src/zsh.h	14 Jul 2005 17:49:55 -0000
@@ -1594,6 +1594,7 @@ enum {
     PROMPTBANG,
     PROMPTCR,
     PROMPTPERCENT,
+    PROMPTSP,
     PROMPTSUBST,
     PUSHDIGNOREDUPS,
     PUSHDMINUS,
@@ -1716,7 +1717,10 @@ struct ttyinfo {
 #define TCDOWNCURSOR   26
 #define TCLEFTCURSOR   27
 #define TCRIGHTCURSOR  28
-#define TC_COUNT       29
+#define TCSAVECURSOR   29
+#define TCRESTRCURSOR  30
+#define TCBACKSPACE    31
+#define TC_COUNT       32
 
 #define tccan(X) (tclen[X])
 
--- Src/Zle/zle_main.c	8 Apr 2005 16:58:21 -0000	1.68
+++ Src/Zle/zle_main.c	14 Jul 2005 17:49:56 -0000
@@ -962,8 +962,30 @@ zleread(char **lp, char **rp, int flags,
 	}
     }
     initundo();
-    if (isset(PROMPTCR))
+    if (isset(PROMPTCR)) {
+	/* The PROMPT_SP heuristic will move the prompt down to a new line
+	 * if there was any dangling output on the line (assuming the terminal
+	 * has automatic margins, but we try even if hasam isn't set). */
+	if (isset(PROMPTSP)) {
+	    if (hasxn) /* w/o this, a delayed wrap might be lost by TCRIGHT */
+		putc(' ', shout);
+	    if (tccan(TCSAVECURSOR)
+	     && tcmultout(TCRIGHT, TCMULTRIGHT, columns - 3)) {
+		putc(' ', shout);
+		putc(' ', shout);
+		tcout(TCSAVECURSOR);
+		tcout(TCBACKSPACE);
+		tcout(TCBACKSPACE);
+		if (tccan(TCCLEAREOL))
+		    tcout(TCCLEAREOL);
+		else
+		    tcmultout(TCDEL, TCMULTDEL, 1);
+		tcout(TCRESTRCURSOR);
+	    } else
+		fprintf(shout, "%*s", (int)columns - 1, "");
+	}
 	putc('\r', shout);
+    }
     if (tmout)
 	alarm(tmout);
     zleactive = 1;


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