mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
Fix completion following $'foo\'bar'
On an interactive shell in emacs or vi, type a command with a $'…' quoted string that contains a backslash-escaped single quote, like: $ true $'foo\'bar' ▁ Then begin to type the name of a file present in the current working directory and press tab. Nothing happens as completion fails to work. The completion code does not recognise $'…' strings. Instead, it parses them as '…' strings in which there are no backslash escapes, so it considers the last ' to open a second quoted string which is not terminated. Plus, when replacing a $'…' string with a (backslash-escaped) completed string, the initial '$' is not replaced: $ $'/etc/hosts<Tab> $ $/etc/hosts src/cmd/ksh93/edit/completion.c: - find_begin(): - Learn how to recognise $'…' strings. A new local dollarquote flag variable is used to distinguish them from regular '…' strings. The difference is that backslash escapes (and only those) should be recognised as in "…". - Set a special type -1 for $'…' as the caller will need a way to distinguish those from '…'. - ed_expand(): When replacing a quoted string, remove an extra initial character (being the $ in $') if the type set by find_begin() is -1. Resolves: https://github.com/ksh93/ksh/issues/462
This commit is contained in:
parent
7a5423dfb6
commit
80f8cc497f
3 changed files with 27 additions and 8 deletions
3
NEWS
3
NEWS
|
@ -9,6 +9,9 @@ Any uppercase BUG_* names are modernish shell bug IDs.
|
|||
substitution after entering: '`something<TAB> or generate a spurious
|
||||
'end of file unexpected' syntax error after entering: '$(something<TAB>.
|
||||
|
||||
- Fixed bug where tab completion stopped working for arguments following a
|
||||
quoted string with an escaped backslash in the form $'foo\'bar'.
|
||||
|
||||
2022-06-04:
|
||||
|
||||
- Added a new --functrace long-form shell option which causes the -x/--xtrace
|
||||
|
|
|
@ -105,12 +105,17 @@ static char *overlaid(register char *str,register const char *newstr,int nocase)
|
|||
|
||||
/*
|
||||
* returns pointer to beginning of expansion and sets type of expansion
|
||||
*
|
||||
* Detects variable expansions, command substitutions, and three quoting styles:
|
||||
* 1. '...' inquote=='\'', dollarquote==0; no special characters
|
||||
* 2. $'...' inquote=='\'', dollarquote==1; skips \.
|
||||
* 3. "..." inquote=='"', dollarquote==0; skips \., $..., ${...}, $(...), `...`
|
||||
*/
|
||||
static char *find_begin(char outbuff[], char *last, int endchar, int *type)
|
||||
{
|
||||
register char *cp=outbuff, *bp, *xp;
|
||||
register int c,inquote = 0, inassign=0;
|
||||
int mode=*type;
|
||||
char inquote = 0, dollarquote = 0, inassign = 0;
|
||||
int mode=*type, c;
|
||||
bp = outbuff;
|
||||
*type = 0;
|
||||
mbinit();
|
||||
|
@ -127,10 +132,10 @@ static char *find_begin(char outbuff[], char *last, int endchar, int *type)
|
|||
break;
|
||||
}
|
||||
if(inquote==c)
|
||||
inquote = 0;
|
||||
inquote = dollarquote = 0;
|
||||
break;
|
||||
case '\\':
|
||||
if(inquote != '\'')
|
||||
if(inquote != '\'' || dollarquote)
|
||||
mbchar(cp);
|
||||
break;
|
||||
case '$':
|
||||
|
@ -177,6 +182,8 @@ static char *find_begin(char outbuff[], char *last, int endchar, int *type)
|
|||
if(*(cp=xp)!=')')
|
||||
bp = xp;
|
||||
}
|
||||
else if(c=='\'' && !inquote)
|
||||
dollarquote = 1;
|
||||
break;
|
||||
case '`':
|
||||
if(inquote=='\'')
|
||||
|
@ -214,7 +221,11 @@ static char *find_begin(char outbuff[], char *last, int endchar, int *type)
|
|||
}
|
||||
}
|
||||
if(inquote && *bp==inquote)
|
||||
*type = *bp++;
|
||||
{
|
||||
/* set special type -1 for $'...' */
|
||||
*type = dollarquote ? -1 : inquote;
|
||||
bp++;
|
||||
}
|
||||
return(bp);
|
||||
}
|
||||
|
||||
|
@ -360,7 +371,11 @@ int ed_expand(Edit_t *ep, char outbuff[],int *cur,int *eol,int mode, int count)
|
|||
com = sh_argbuild(&narg,comptr,0);
|
||||
/* special handling for leading quotes */
|
||||
if(begin>outbuff && (begin[-1]=='"' || begin[-1]=='\''))
|
||||
begin--;
|
||||
{
|
||||
begin--;
|
||||
if(var == -1) /* $'...' */
|
||||
begin--; /* also remove initial dollar */
|
||||
}
|
||||
}
|
||||
sh_offstate(SH_COMPLETE);
|
||||
/* allow a search to be aborted */
|
||||
|
|
|
@ -821,11 +821,12 @@ r \thist -lnN 1\r\n$
|
|||
((SHOPT_VSH || SHOPT_ESH)) && tst $LINENO <<"!"
|
||||
L tab completion while expanding ${.sh.*} variables
|
||||
# https://github.com/att/ast/issues/1461
|
||||
# also tests $'...' string: https://github.com/ksh93/ksh/issues/462
|
||||
|
||||
d 15
|
||||
p :test-1:
|
||||
w test \$\{.sh.level\t
|
||||
r ^:test-1: test \$\{.sh.level\}\r\n$
|
||||
w test \$'foo\\'bar' \$\{.sh.level\t
|
||||
r ^:test-1: test \$'foo\\'bar' \$\{.sh.level\}\r\n$
|
||||
!
|
||||
|
||||
((SHOPT_VSH || SHOPT_ESH)) && tst $LINENO <<"!"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue