From dc9d78c65971e9c6c7faf4488f4da6efb73bded1 Mon Sep 17 00:00:00 2001 From: Sven Wischnowsky Date: Tue, 15 May 2001 13:52:22 +0000 Subject: (14350) --- ChangeLog | 7 +++++++ Completion/Base/Completer/_expand | 27 +++++++++++++++++++++++++-- Src/Zle/zle_tricky.c | 33 +++++++++++++++++++++++++-------- 3 files changed, 57 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0dbee373e..ddbe6c859 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2001-05-15 Sven Wischnowsky + + * 14350: Completion/Base/Completer/_expand, Src/Zle/zle_tricky.c: + don't remove single and double quotes that are inside parameter + expansions; hopefully better handling of brace expansions in + _expand + 2001-05-15 Peter Stephenson * 14348: Src/builtin.c: some idiot forgot to make GLOBAL_EXPORT diff --git a/Completion/Base/Completer/_expand b/Completion/Base/Completer/_expand index ebb8a905b..0e7b5820c 100644 --- a/Completion/Base/Completer/_expand +++ b/Completion/Base/Completer/_expand @@ -55,8 +55,31 @@ exp=("$word") if [[ "$force" = *s* ]] || zstyle -T ":completion:${curcontext}:" substitute; then - [[ ! -o ignorebraces && "${#${exp}//[^\{]}" = "${#${exp}//[^\}]}" ]] && - eval exp\=\( ${${(q)exp}:gs/\\{/\{/:gs/\\}/\}/} \) 2>/dev/null + +### We once used this: +### +### [[ ! -o ignorebraces && "${#${exp}//[^\{]}" = "${#${exp}//[^\}]}" ]] && +### eval exp\=\( ${${(q)exp}:gs/\\{/\{/:gs/\\}/\}/} \) 2>/dev/null +### +### instead of the following loop to expand braces. But that made +### parameter expressions such as ${foo} be expanded like brace +### expansions, too (and with braceccl set...). + + if [[ ! -o ignorebraces && "${#${exp}//[^\{]}" = "${#${exp}//[^\}]}" ]]; then + local otmp + + tmp=${(q)word} + while [[ $#tmp != $#otmp ]]; do + otmp=$tmp + tmp=${tmp//(#b)\\\$\\\{(([^\{\}]|\\\\{|\\\\})#)([^\\])\\\}/\\$\\\\{${match[1]}${match[3]}\\\\}} + done + eval exp\=\( ${tmp:gs/\\{/\{/:gs/\\}/\}/} \) 2>/dev/null + fi + +### There's a bug: spaces resulting from brace expansion are quoted in +### the following expression, too. We don't want that, but I have no +### idea how to fix it. + eval 'exp=( ${${(e)exp//\\[ ]/ }//(#b)([ ])/\\$match[1]} )' 2>/dev/null diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c index e30bf45e5..afd9c409a 100644 --- a/Src/Zle/zle_tricky.c +++ b/Src/Zle/zle_tricky.c @@ -1020,13 +1020,10 @@ get_comp_string(void) * the previously massaged command line using the lexer. It stores * * each token in each command (commands being regarded, roughly, as * * being separated by tokens | & &! |& || &&). The loop stops when * - * the end of the command containing the cursor is reached. It's a * - * simple way to do things, but suffers from an inability to * - * distinguish actual command arguments from, for example, * - * filenames in redirections. (But note that code elsewhere checks * - * if we are completing *in* a redirection.) The only way to fix * - * this would be to pass the command line through the parser too, * - * and get the arguments that way. Maybe in 3.1... */ + * the end of the command containing the cursor is reached. What * + * makes this messy is checking for things like redirections, loops * + * and whatnot. */ + do { lincmd = ((incmdpos && !ins && !incond) || (oins == 2 && i == 2) || (ins == 3 && i == 1)); @@ -1343,6 +1340,19 @@ get_comp_string(void) *p = '"'; else if (*p == Snull) *p = '\''; + } else { + int level = 0; + + for (p = s; *p; p++) { + if (level && *p == Snull) + *p = '\''; + else if (level && *p == Dnull) + *p = '"'; + else if (*p == String && p[1] == Inbrace) + level++; + else if (*p == Outbrace) + level--; + } } if ((*s == Snull || *s == Dnull) && !has_real_token(s + 1)) { char *q = (*s == Snull ? "'" : "\""), *n = tricat(qipre, q, ""); @@ -1673,11 +1683,18 @@ doexpansion(char *s, int lst, int olst, int explincmd) { int ret = 1, first = 1; LinkList vl; - char *ss; + char *ss, *ts; pushheap(); vl = newlinklist(); ss = dupstring(s); + /* get_comp_string() leaves these quotes unchanged when they are + * inside parameter expansions. */ + for (ts = ss; *ts; ts++) + if (*ts == '"') + *ts = Dnull; + else if (*ts == '\'') + *ts = Snull; addlinknode(vl, ss); prefork(vl, 0); if (errflag) -- cgit 1.4.1