diff --git a/NEWS b/NEWS index b81d7e5d0..6beb4f674 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,11 @@ Any uppercase BUG_* names are modernish shell bug IDs. 2021-04-30: +- The emacs 'ESC .' (M-.) and vi '_' commands now take shell quoting into + account when repeating a word from the previous command line. For example, if + the previous command is 'ls Stairway\ To\ Heaven.mp3', then they now insert + 'Stairway\ To\ Heaven.mp3' instead of 'Heaven.mp3'. Thanks to Govind Kamat. + - Fixed a bug introduced on 2020-09-05 that caused "echo ${var:+'{}'}" to be misparsed. diff --git a/src/cmd/ksh93/edit/history.c b/src/cmd/ksh93/edit/history.c index 8856f146f..e7cd8540a 100644 --- a/src/cmd/ksh93/edit/history.c +++ b/src/cmd/ksh93/edit/history.c @@ -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) diff --git a/src/cmd/ksh93/tests/pty.sh b/src/cmd/ksh93/tests/pty.sh index 5b22376b3..ac897196f 100755 --- a/src/cmd/ksh93/tests/pty.sh +++ b/src/cmd/ksh93/tests/pty.sh @@ -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))