1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-02-13 11:42:21 +00:00

Fix bugs with backslash escaping in interactive vi mode (#57)

This commit fixes the following bugs in the 'vi' editing mode
backslash escape feature. Ref.: Bolsky & Korn (1995), p. 113, which
states for \: "Similar to Control+V [...] except that it escapes
only the next Erase or Kill charactrer".

1. The vi mode now only escapes the next character if the last
   character input was a backslash, fixing the bug demonstrated at:
   https://asciinema.org/a/E3Rq3et07MMQG5BaF7vkXQTg0
2. Escaping backslashes are now disabled in vi.c if the vi mode is
   disabled (note that vi.c handles raw editing mode in UTF-8
   locales). This makes the behavior of the raw editing mode
   consistent in C/POSIX and UTF-8 locales.
3. An odd interaction with Backspace when the character prior to a
   separate buffer entered with Shift-C was a backslash has been
   fixed. Demonstration at: https://asciinema.org/a/314833
   ^? will no longer be output repeatedly when attempting to erase
   a separate buffer with a Backspace, although, to be consistent
   with vi(1), you still cannot backspace past it before escaping
   out of it. Ref.:
   https://github.com/ksh93/ksh/issues/56#issuecomment-653586994

src/cmd/ksh93/edit/vi.c:
- Prevent a backslash from escaping the next input if the previous
  input wasn't a backslash. This is done by unsetting a variable
  named backslash if a backslash escaped a character. backslash is
  set to the result of c == '\\' when the user enters a new
  character.
- Disable escaping backslashes in the raw editing mode because
  it should not be enabled there.

src/cmd/ksh93/tests/pty.sh:
- Add some tests for how ksh handles backslashes in each
  editing mode to test for the bugs fixed by this commit.

Fixes #56.
This commit is contained in:
Johnothan King 2020-07-03 12:08:00 -07:00 committed by Martijn Dekker
parent 035a4cb3f4
commit a0dcdeeade
3 changed files with 57 additions and 3 deletions

18
NEWS
View file

@ -3,6 +3,24 @@ For full details, see the git log at: https://github.com/ksh93/ksh
Any uppercase BUG_* names are modernish shell bug IDs.
2020-07-03:
- Backslashes are no longer escaped in the raw Bourne Shell-like editing
mode in multibyte locales, i.e. backslashes are no longer treated like
Control-V if the emacs and vi modes are disabled.
- Deleting a backslash in vi mode with Control-H or Backspace now only
escapes a backslash if it was the previous input. This means erasing a
string such as 'ab\\\' will only cause the first backslash to escape a
Backspace as '^?', like in emacs mode.
- An odd interaction with Backspace when the last character of a separate
buffer created with Shift-C was '\' has been fixed. '^?' will no longer
be output repeatedly when attempting to erase a separate buffer with
a Backspace. Note that buffers created with Shift-C are not meant to be
erasable:
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/vi.html#tag_20_152_13_49
2020-07-02:
- Fixed a crash that occurred if a directory named '.paths' existed in any

View file

@ -1363,7 +1363,7 @@ static void getline(register Vi_t* vp,register int mode)
{
register int c;
register int tmp;
int max_virt=0, last_save=0;
int max_virt=0, last_save=0, backslash=0;
genchar saveline[MAXLINE];
vp->addnl = 1;
@ -1460,8 +1460,9 @@ static void getline(register Vi_t* vp,register int mode)
/*** treat as backspace ***/
case '\b': /** backspace **/
if( virtual[cur_virt] == '\\' )
if( sh_isoption(SH_VI) && backslash && virtual[cur_virt] == '\\' )
{
backslash = 0;
cdelete(vp,1, BAD);
append(vp,usrerase, mode);
}
@ -1505,8 +1506,9 @@ static void getline(register Vi_t* vp,register int mode)
break;
case UKILL: /** user kill line char **/
if( virtual[cur_virt] == '\\' )
if( sh_isoption(SH_VI) && backslash && virtual[cur_virt] == '\\' )
{
backslash = 0;
cdelete(vp,1, BAD);
append(vp,usrkill, mode);
}
@ -1580,6 +1582,7 @@ static void getline(register Vi_t* vp,register int mode)
mode = APPEND;
max_virt = last_virt+3;
}
backslash = (c == '\\');
append(vp,c, mode);
break;
}

View file

@ -505,5 +505,38 @@ r ^:test-2: true (/de\tv/nu\tl\tl|/de v/nu l l)\r\n$
p :test-3:
!
LC_ALL=C.UTF8 tst $LINENO <<"!"
L raw Bourne mode backslash handling
# The escaping backslash feature should be disabled in the raw Bourne mode.
# This is tested with both erase and kill characters.
d 10
p :test-1:
w set +o vi +o emacs; stty erase ^H kill ^X
p :test-2:
w true string\\\\\cH\cH
r ^:test-2: true string\r\n$
p :test-3:
w true incorrect\\\cXtrue correct
r ^:test-3: true correct\r\n$
!
for mode in emacs vi; do
tst $LINENO << !
L escaping backslashes in $mode mode
# Backslashes should only be escaped if the previous input was a backslash.
# Other backslashes stored in the input buffer should be erased normally.
d 10
p :test-1:
w set -o $mode; stty erase ^H
p :test-2:
w true string\\\\\\\\\\cH\\cH\\cH
r ^:test-2: true string\\r\\n$
!
done
# ======
exit $((Errors<125?Errors:125))