1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00

Parse quotes when extracting words from command history (#291)

This avoids splitting on quoted whitespace when extracting words
from the command history using the emacs M-. or vi _ command.

Example: if the prior command is

$ ls Stairway\ To\ Heaven.mp3

then, M-. in Emacs editing mode (and _ in vi mode) now inserts
Stairway\ To\ Heaven.mp3 instead of Heaven.mp3. The behavior is
similar for 'Stairway To Heaven.mp3' and "Stairway To Heaven.mp3".

src/cmd/ksh93/edit/history.c: hist_word():
- Skip over single-quoted and double-quoted strings and
  backslash-escaped characters.

src/cmd/ksh93/tests/pty.sh:
- Add regression test for this feature in vi mode. Since emacs and
  vi both use the same code for this, that should be good enough.

Co-authored-by: Martijn Dekker <martijn@inlv.org>
This commit is contained in:
Govind Kamat 2021-04-30 11:45:50 -07:00 committed by Martijn Dekker
parent d087b031f0
commit 7439e3dffe
3 changed files with 36 additions and 4 deletions

View file

@ -1057,6 +1057,8 @@ int hist_copy(char *s1,int size,int command,int line)
char *hist_word(char *string,int size,int word)
{
register int c;
register int is_space;
register int quoted;
register char *s1 = string;
register unsigned char *cp = (unsigned char*)s1;
register int flag = 0;
@ -1064,21 +1066,32 @@ char *hist_word(char *string,int size,int word)
if(!hp)
return(NIL(char*));
hist_copy(string,size,(int)hp->histind-1,-1);
for(;c = *cp;cp++)
for(quoted=0;c = *cp;cp++)
{
c = isspace(c);
if(c && flag)
is_space = isspace(c) && !quoted;
if(is_space && flag)
{
*cp = 0;
if(--word==0)
break;
flag = 0;
}
else if(c==0 && flag==0)
else if(is_space==0 && flag==0)
{
s1 = (char*)cp;
flag++;
}
if (c=='\'' && !quoted)
{
for(cp++;*cp && *cp != c;cp++)
;
}
else if (c=='\"' && !quoted)
{
for(cp++;*cp && (*cp != c || quoted);cp++)
quoted = *cp=='\\' ? !quoted : 0;
}
quoted = *cp=='\\' ? !quoted : 0;
}
*cp = 0;
if(s1 != string)

View file

@ -812,5 +812,19 @@ r ^:test-1: echo ok\r\n$
r ^ok\r\n$
!
# err_exit #
((SHOPT_VSH)) && tst $LINENO <<"!"
L split on quoted whitespace when extracting words from command history
# https://github.com/ksh93/ksh/pull/291
d 15
p :test-1:
w true ls One\\ "Two Three"$'Four Five'.mp3
r ^:test-1: true ls One\\ "Two Three"\$'Four Five'\.mp3\r\n$
p :test-2:
w :\E_
r ^:test-2: : One\\ "Two Three"\$'Four Five'\.mp3\r\n$
!
# ======
exit $((Errors<125?Errors:125))