mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-02-13 03:32:24 +00:00
Fix bell character handling when redrawing command line (#250)
To set a window title in bash and zsh, the $PS1 prompt can be set with the title placed between $'\E]0;' and $'\a': set -o emacs # Or vi mode typeset -A fmt=( [start_title]=$'\E]0;' [end_title]=$'\a' ) PS1="${fmt[start_title]}$(hostname): $(uname)${fmt[end_title]}\$ " This also works in ksh unless the shell receives SIGWINCH. With a $PS1 that sets a window title, the prompt breaks until two interrupts are received. This is caused by ed_setup() skipping $'\a' (the bell character) when setting up the e_prompt buffer which is an edited version of the final line of the PS1 prompt for use when redrawing the command line. One fix would be to avoid cutting out the bell character. But if the prompt contains a bell, we only want the terminal to beep when a new prompt is printed, and not upon refreshing the command line, e.g. when receiving SIGWINCH or pressing Ctrl+L. To avoid the problem, this commit adds code that cuts out sequences of the form ESC ] <number> ; <text> BELL from the prompt redraw buffer altogether. They are not needed there because these sequences will already have taken effect when the full prompt was printed by io_prompt(). This commit also adds a tweak that should improve the recognition of other escape sequences to count their length. src/cmd/ksh93/edit/edit.c: ed_setup(): - When preparing the e_prompt buffer, cut out dtterm/xterm Operating System Commands that set window/icon title, etc. See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html - When counting the length of escape sequences in that part of PS1, try to recognize some more types of sequences. These changes are part of a ksh2020 patch: https://github.com/att/ast/issues/399 src/cmd/ksh93/sh.1: - Document that any '!' in escape sequences in the PS1 prompt needs to be changed to '!!'. To avoid breaking compatibility, this requirement is documented instead of backporting the changes to io_prompt() from https://github.com/att/ast/issues/399 which try to remove that requirement for specific escape sequences. Co-authored-by: Martijn Dekker <martijn@inlv.org>
This commit is contained in:
parent
ee34a96b8f
commit
56b530c433
4 changed files with 57 additions and 7 deletions
4
NEWS
4
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.
|
||||
|
|
|
@ -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(pp<ppmax)
|
||||
*pp++ = c;
|
||||
*pp++ = ESC;
|
||||
for(n=1; c = *last++; n++)
|
||||
{
|
||||
if(pp < ppmax)
|
||||
|
@ -675,9 +710,11 @@ void ed_setup(register Edit_t *ep, int fd, int reedit)
|
|||
skip = 0;
|
||||
continue;
|
||||
}
|
||||
if(n>1 && 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')
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue