diff --git a/NEWS b/NEWS index 638e062a5..4f8d9d91b 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,10 @@ Any uppercase BUG_* names are modernish shell bug IDs. 2021-04-04: +- A bug was fixed that caused a broken prompt display upon redrawing the + command line if the last line of the prompt includes an xterm escape + sequence that is terminated by $'\a' (the bell character). + - Harden readonly variables. Readonly variables or arrays no longer allow attribute changes which would otherwise allow their value to be altered. Expanded support for readonly variables within multidimensional arrays. diff --git a/src/cmd/ksh93/edit/edit.c b/src/cmd/ksh93/edit/edit.c index b4883ef6b..f6586adf4 100644 --- a/src/cmd/ksh93/edit/edit.c +++ b/src/cmd/ksh93/edit/edit.c @@ -651,6 +651,10 @@ void ed_setup(register Edit_t *ep, int fd, int reedit) ep->e_winsz = ep->e_wsize+2; ep->e_crlf = 1; ep->e_plen = 0; + /* + * Prepare e_prompt buffer for use when redrawing the command line. + * Use only the last line of the potentially multi-line prompt. + */ pp = ep->e_prompt; ppmax = pp+PRSIZE-1; *pp++ = '\r'; @@ -661,9 +665,40 @@ void ed_setup(register Edit_t *ep, int fd, int reedit) case ESC: { int skip=0; + if(*last == ']') + { + /* + * Cut out dtterm/xterm Operating System Commands that set window/icon title, etc. + * See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html + */ + char *cp = last + 1; + while(*cp >= '0' && *cp <= '9') + cp++; + if(*cp++ == ';') + { + while(c = *cp++) + { + if(c == '\a') /* legacy terminator */ + break; + if(c == ESC && *cp == '\\') /* recommended terminator */ + { + cp++; + break; + } + } + if(!c) + break; + last = cp; + continue; + } + } + /* + * Try to add the length of included escape sequences to qlen + * which is subtracted from the physical length of the prompt. + */ ep->e_crlf = 0; if(pp1 && c==';') + if(n==3 && (c=='?' || c=='!')) + continue; + else if(n>1 && c==';') skip = 1; - else if(n>2 || (c!= '[' && c!= ']')) + else if(n>2 || (c!='[' && c!=']' && c!='(')) break; } if(c==0 || c==ESC || c=='\r') diff --git a/src/cmd/ksh93/include/edit.h b/src/cmd/ksh93/include/edit.h index 1732bbed1..7c80ee9bb 100644 --- a/src/cmd/ksh93/include/edit.h +++ b/src/cmd/ksh93/include/edit.h @@ -108,7 +108,7 @@ typedef struct edit char *e_outptr; /* pointer to position in output buffer */ char *e_outlast; /* pointer to end of output buffer */ genchar *e_inbuf; /* pointer to input buffer */ - char *e_prompt; /* pointer to buffer containing the prompt */ + char *e_prompt; /* pointer to trimmed final line of PS1 prompt, used when redrawing command line */ genchar *e_killbuf; /* pointer to delete buffer */ char e_search[SEARCHSIZE]; /* search string */ genchar *e_physbuf; /* temporary workspace buffer */ diff --git a/src/cmd/ksh93/sh.1 b/src/cmd/ksh93/sh.1 index 9c9bf8246..0c6f5c1a5 100644 --- a/src/cmd/ksh93/sh.1 +++ b/src/cmd/ksh93/sh.1 @@ -2122,9 +2122,12 @@ if executing under .TP .SM .B PS1 -The value of this variable is expanded for parameter -expansion, command substitution, and arithmetic substitution to define the -primary prompt string which by default is +Every time a new command line is started on an interactive shell, +the value of this variable is expanded to resolve +backslash escaping, parameter expansion, command substitution, +and arithmetic substitution. +The result defines the primary prompt string for that command line. +The default is .RB `` "$ \|\|\|" ''. The character .B ! @@ -2138,6 +2141,12 @@ Two successive occurrences of will produce a single .B ! when the prompt string is printed. +Note that any terminal escape sequences used in the +.B PS1 +prompt thus need every instance of +.B ! +in them to be changed to +.BR !! . .TP .SM .B PS2