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

Fix emacs backslash escaping behavior (#179)

This commit fixes the following:

1. Emacs mode ignores --nobackslashctrl (re: 24598fed) when in
   reverse search.

2. When entering more than one backslash, emacs reverse search mode
   deletes multiple backslashes after pressing backspace once.
   Reproducer:
   $ set --emacs --nobackslashctrl
   $ <Ctrl+R> \\\\<Backspace>

3. Except when in reverse search, the backslash fails to escape a
   subsequent interrupt character (^C). Reproducer:
   $ set --emacs --backslashctrl
   $ teststring \<Ctrl+C>

src/cmd/ksh93/edit/emacs.c:
- Disable escaping backslashes in emacs reverse search if
  'nobackslashctrl' is enabled.
- Fix the buggy behavior of backslashes in emacs reverse
  search by processing backslashes in a loop.

src/cmd/ksh93/tests/pty.sh:
- Add regression tests.

src/cmd/ksh93/sh.1:
- Fix a minor documentation error (^C is the usual interrupt
  character, not ^?).

Co-authored-by: Martijn Dekker <martijn@inlv.org>
This commit is contained in:
Johnothan King 2021-02-17 06:29:12 -08:00 committed by GitHub
parent fe74702766
commit a282ebc8fe
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 65 additions and 12 deletions

7
NEWS
View file

@ -3,6 +3,13 @@ For full details, see the git log at: https://github.com/ksh93/ksh
Any uppercase BUG_* names are modernish shell bug IDs. Any uppercase BUG_* names are modernish shell bug IDs.
2021-02-17:
- Emacs mode fixes:
1. Erasing a backslash while doing a reverse search (^R) no longer deletes
extra characters.
2. The backslash now escapes a subsequent interrupt (^C) as documented.
2021-02-15: 2021-02-15:
- Fixed a regression introduced by ksh93 (was not in ksh88): an empty 'case' - Fixed a regression introduced by ksh93 (was not in ksh88): an empty 'case'

View file

@ -1068,7 +1068,7 @@ int ed_getchar(register Edit_t *ep,int mode)
{ {
ed_flush(ep); ed_flush(ep);
ep->e_inmacro = 0; ep->e_inmacro = 0;
/* The while is necessary for reads of partial multbyte chars */ /* The while is necessary for reads of partial multibyte chars */
*ep->e_vi_insert = (mode==-2); *ep->e_vi_insert = (mode==-2);
if((n=ed_read(ep,ep->e_fd,readin,-LOOKAHEAD,0)) > 0) if((n=ed_read(ep,ep->e_fd,readin,-LOOKAHEAD,0)) > 0)
n = putstack(ep,readin,n,1); n = putstack(ep,readin,n,1);

View file

@ -281,11 +281,12 @@ int ed_emacsread(void *context, int fd,char *buff,int scend, int reedit)
#endif /* ESH_NFIRST */ #endif /* ESH_NFIRST */
} }
ep->CntrlO = 0; ep->CntrlO = 0;
while ((c = ed_getchar(ep->ed,0)) != (-1)) while ((c = ed_getchar(ep->ed,backslash)) != (-1))
{ {
if (backslash) if (backslash)
{ {
backslash = 0; if(c!='\\')
backslash = 0;
if (c==usrerase||c==usrkill||(!print(c) && if (c==usrerase||c==usrkill||(!print(c) &&
(c!='\r'&&c!='\n'))) (c!='\r'&&c!='\n')))
{ {
@ -1298,20 +1299,35 @@ static void search(Emacs_t* ep,genchar *out,int direction)
beep(); beep();
goto restore; goto restore;
} }
if (i == '\\') if (!sh_isoption(SH_NOBACKSLCTRL))
{ {
string[sl++] = '\\'; while (i == '\\')
string[sl] = '\0'; {
cur = sl; /*
draw(ep,APPEND); * Append the backslash to the command line, then escape
i = ed_getchar(ep->ed,1); * the next control character. Repeat the loop if the
string[--sl] = '\0'; * next input is another backslash (otherwise every
* second backslash is skipped).
*/
string[sl++] = '\\';
string[sl] = '\0';
cur = sl;
draw(ep,APPEND);
i = ed_getchar(ep->ed,1);
/* Backslashes don't affect newlines */
if (i == '\n' || i == '\r')
goto skip;
else if (i == usrerase || !print(i))
string[--sl] = '\0';
}
} }
string[sl++] = i; string[sl++] = i;
string[sl] = '\0'; string[sl] = '\0';
cur = sl; cur = sl;
draw(ep,APPEND); draw(ep,APPEND);
} }
skip:
i = genlen(string); i = genlen(string);
if(ep->prevdirection == -2 && i!=2 || direction!=1) if(ep->prevdirection == -2 && i!=2 || direction!=1)

View file

@ -20,7 +20,7 @@
#define SH_RELEASE_FORK "93u+m" /* only change if you develop a new ksh93 fork */ #define SH_RELEASE_FORK "93u+m" /* only change if you develop a new ksh93 fork */
#define SH_RELEASE_SVER "1.0.0-alpha" /* semantic version number: https://semver.org */ #define SH_RELEASE_SVER "1.0.0-alpha" /* semantic version number: https://semver.org */
#define SH_RELEASE_DATE "2021-02-15" /* must be in this format for $((.sh.version)) */ #define SH_RELEASE_DATE "2021-02-17" /* must be in this format for $((.sh.version)) */
#define SH_RELEASE_CPYR "(c) 2020-2021 Contributors to ksh " SH_RELEASE_FORK #define SH_RELEASE_CPYR "(c) 2020-2021 Contributors to ksh " SH_RELEASE_FORK
/* Scripts sometimes field-split ${.sh.version}, so don't change amount of whitespace. */ /* Scripts sometimes field-split ${.sh.version}, so don't change amount of whitespace. */

View file

@ -4969,7 +4969,7 @@ If the
shell option is on (which is the default setting), this escapes the next character. shell option is on (which is the default setting), this escapes the next character.
Editing characters, the user's erase, kill and Editing characters, the user's erase, kill and
interrupt (normally interrupt (normally
.BR ^? ) .BR ^C )
characters characters
may be entered may be entered
in a command line or in a search string if preceded by a in a command line or in a search string if preceded by a

View file

@ -640,5 +640,35 @@ r ^/dev/null\r\n$
r ^:test-2: r ^:test-2:
! !
# err_exit #
((SHOPT_ESH)) && [[ -o ?backslashctrl ]] && tst $LINENO <<"!"
L nobackslashctrl in emacs
d 10
w set -o emacs --nobackslashctrl
# --nobackslashctrl shouldn't be ignored by reverse search
p :test-2:
w \cR\\\cH\cH
r ^:test-2: \r\n$
!
# err_exit #
((SHOPT_ESH)) && tst $LINENO <<"!"
L emacs backslash escaping
d 10
w set -o emacs
# Test for too many backslash deletions in reverse-search mode
p :test-2:
w \cRset\\\\\\\\\cH\cH\cH\cH\cH
r ^:test-2: set -o emacs$
# \ should escape the interrupt character (usually Ctrl+C)
w true \\\cC
r true \^C
!
# ====== # ======
exit $((Errors<125?Errors:125)) exit $((Errors<125?Errors:125))