zsh-workers
 help / color / mirror / code / Atom feed
* destructive list-expand
@ 2001-05-15  2:30 Clint Adams
  2001-05-15  4:48 ` Bart Schaefer
  0 siblings, 1 reply; 17+ messages in thread
From: Clint Adams @ 2001-05-15  2:30 UTC (permalink / raw)
  To: zsh-workers

If I type a command such as

echo ${(M)${(f)"$(<listofthings)"}:#*subthing*}

Then invoke list-expand, the appropriate expansion will be displayed,
and the command line will change to

echo ${(M)${(f)$(<listofthings)}:#*subthing*}

That is, the double quotes disappear, and I become very perplexed
and aggravated until I notice this.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: destructive list-expand
  2001-05-15  2:30 destructive list-expand Clint Adams
@ 2001-05-15  4:48 ` Bart Schaefer
  2001-05-15  5:32   ` Bart Schaefer
  0 siblings, 1 reply; 17+ messages in thread
From: Bart Schaefer @ 2001-05-15  4:48 UTC (permalink / raw)
  To: zsh-workers

On May 14, 10:30pm, Clint Adams wrote:
}
} If I type a command such as
} 
} echo ${(M)${(f)"$(<listofthings)"}:#*subthing*}
} 
} Then invoke list-expand, the appropriate expansion will be displayed,
} and the command line will change to
} 
} echo ${(M)${(f)$(<listofthings)}:#*subthing*}

Hmm; this is interesting.

list-expand (C-x g) doesn't use the new completion system, and exhibits
the above-described behavior at least as far back as 3.0.6 and probably
farther.

_list_expansions (C-x d) from _expand_word should be the new completion
system equivalent, but it doesn't appear to work at all. Even just plain
_expand_word (C-x e) beeps at me, but old-style expand-word properly
expands to everything listed by list-expand.

It's a bit hard to tell from the _complete_debug trace, but it looks as
if the double quotes have already been stripped from $PREFIX by the time
_expand is called -- e.g.

: _expand:24:else; word=${(M)${(f)$(<listofthings)}:#*subthing*} 

and then a bit later

: _expand:60:then; exp=: _expand:60:then cmdsubst; print -l CVS ChangeLog
ChangeLog-Release ChangeLog.3.0 Completion Config Doc Etc Functions INSTALL
LICENCE META-FAQ Makefile.in Misc README Src StartupFiles Test Util acconfig.h
aclocal.m4 aczsh.m4 config.guess config.h.in config.log config.sub configure
configure.in full.diff install-sh mkinstalldirs stamp-h.in
: _expand:60:then; exp=( ) 

I don't quite see where the quotes are getting stripped off, unless it's
actually get_comp_string() that's at fault.  (Somebody (hi, Sven) should
update the comment around line 1028 of zle_tricky.c in any event.)

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

Zsh: http://www.zsh.org | PHPerl Project: http://phperl.sourceforge.net   


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: destructive list-expand
  2001-05-15  4:48 ` Bart Schaefer
@ 2001-05-15  5:32   ` Bart Schaefer
  2001-05-15  9:28     ` Sven Wischnowsky
  0 siblings, 1 reply; 17+ messages in thread
From: Bart Schaefer @ 2001-05-15  5:32 UTC (permalink / raw)
  To: zsh-workers

On May 15,  4:48am, Bart Schaefer wrote:
}
} : _expand:24:else; word=${(M)${(f)$(<listofthings)}:#*subthing*} 
} 
} and then a bit later
} 
} : _expand:60:then; exp=: _expand:60:then cmdsubst; print -l CVS ChangeLog

Oops, I cut bits from two different traces there.  The first bit should
have read:

: _expand:24:else; word=${(M)${(f)$(<=(print -l *))}:#*conf*}

} I don't quite see where the quotes are getting stripped off, unless it's
} actually get_comp_string() that's at fault.

Guess what ... around line 1376 of zle_tricky.c ... I'm at a loss for
what that code is meant to be doing or when it is ever the right thing.

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

Zsh: http://www.zsh.org | PHPerl Project: http://phperl.sourceforge.net   


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: destructive list-expand
  2001-05-15  5:32   ` Bart Schaefer
@ 2001-05-15  9:28     ` Sven Wischnowsky
  2001-05-15 13:48       ` Sven Wischnowsky
  0 siblings, 1 reply; 17+ messages in thread
From: Sven Wischnowsky @ 2001-05-15  9:28 UTC (permalink / raw)
  To: zsh-workers

Bart Schaefer wrote:

> ...
> 
> } I don't quite see where the quotes are getting stripped off, unless it's
> } actually get_comp_string() that's at fault.
> 
> Guess what ... around line 1376 of zle_tricky.c ... I'm at a loss for
> what that code is meant to be doing or when it is ever the right thing.

All this is so disgusting... sigh.

That code is there to turn turn null tokens inside parameter expansions
into their original forms (single or double quotes) so that later code
can use them correctly because they won't be removed in the following
loop.

Unfortunately, this will only be done if we are completing *inside* the
parameter expansion (the parameter name). I'll have to try if it is
correct to change that part of the code to re-install quotes anywhere in
a parameter expansion in the word (well, it sounds right, doesn't it?).

But even with that there's still something fishy with list-expand which
I haven't any further into yet. And with _expand and functions that call
it:

  beta% e=( '${(M)${(f)"$(<x)"}:#*2*}' )
  beta% echo ${(e)e}
   
  beta% echo ${(e)~e}
  111 222 333
  beta%

Oh well. Anyone interested in fixing that?


No patch yet...

Bye
  Sven


-- 
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: destructive list-expand
  2001-05-15  9:28     ` Sven Wischnowsky
@ 2001-05-15 13:48       ` Sven Wischnowsky
  2001-05-15 13:57         ` Peter Stephenson
  0 siblings, 1 reply; 17+ messages in thread
From: Sven Wischnowsky @ 2001-05-15 13:48 UTC (permalink / raw)
  To: zsh-workers

I wrote:

> ...
> 
> All this is so disgusting... sigh.

Agreed.

> That code is there to turn turn null tokens inside parameter expansions
> into their original forms (single or double quotes) so that later code
> can use them correctly because they won't be removed in the following
> loop.

The patch makes it keep all quotes *inside* parameter expansions when
*not* completing a parameter name.  For the simple things I tried, this
worked.  And for the case we were discussing, this gives the right
string to the shell code.

> ...
> 
> But even with that there's still something fishy with list-expand which
> I haven't any further into yet. And with _expand and functions that call
> it:
> 
>   beta% e=( '${(M)${(f)"$(<x)"}:#*2*}' )
>   beta% echo ${(e)e}
>    
>   beta% echo ${(e)~e}
>   111 222 333
>   beta%

This is the reason why, even with this patch, the test case still
doesn't work.

That mighty hunk in _expand is a fix for our brace expansion handling. 
Once I got the right string reported to the shell code I had to find out
that the code blindly expanded braces -- even those from a `${foo}'. 
But they were not expanded as a parameter expansion by that code, they
were expanded like a brace expansion (with braceccl set that gave me the
expansions `$f' and `$o').  There is now a loop that protects parameter
expansions from brace expansion (adding one more backslash before their
braces) -- can someone think of a better way?


Bye
  Sven

Index: Completion/Base/Completer/_expand
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/Base/Completer/_expand,v
retrieving revision 1.6
diff -u -r1.6 _expand
--- Completion/Base/Completer/_expand	2001/05/09 12:06:10	1.6
+++ Completion/Base/Completer/_expand	2001/05/15 13:37:00
@@ -55,8 +55,31 @@
 
 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
Index: Src/Zle/zle_tricky.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_tricky.c,v
retrieving revision 1.25
diff -u -r1.25 zle_tricky.c
--- Src/Zle/zle_tricky.c	2001/05/08 08:14:34	1.25
+++ Src/Zle/zle_tricky.c	2001/05/15 13:37:01
@@ -1020,13 +1020,10 @@
      * 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 @@
 		*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 @@
 {
     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)

-- 
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: destructive list-expand
  2001-05-15 13:48       ` Sven Wischnowsky
@ 2001-05-15 13:57         ` Peter Stephenson
  2001-05-15 14:18           ` Sven Wischnowsky
  0 siblings, 1 reply; 17+ messages in thread
From: Peter Stephenson @ 2001-05-15 13:57 UTC (permalink / raw)
  To: Zsh hackers list

Sven wrote:
> The patch makes it keep all quotes *inside* parameter expansions when
> *not* completing a parameter name.  For the simple things I tried, this
> worked.  And for the case we were discussing, this gives the right
> string to the shell code.

Are we sure the zle_tricky.c change doesn't cause some knock-on problem,
e.g. in old-style completion?  Lots of people who install 4.0 for the first
time will still be using that to begin with.  I don't think most of us
have been testing this much, but under the present circumstances it's
important it still works at least as well as before, unfortunately.

-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
CSR Ltd., Unit 300, Science Park, Milton Road,
Cambridge, CB4 0XL, UK                          Tel: +44 (0)1223 392070


**********************************************************************
The information transmitted is intended only for the person or
entity to which it is addressed and may contain confidential 
and/or privileged material. 
Any review, retransmission, dissemination or other use of, or
taking of any action in reliance upon, this information by 
persons or entities other than the intended recipient is 
prohibited.  
If you received this in error, please contact the sender and 
delete the material from any computer.
**********************************************************************


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: destructive list-expand
  2001-05-15 13:57         ` Peter Stephenson
@ 2001-05-15 14:18           ` Sven Wischnowsky
  2001-05-15 14:41             ` Bart Schaefer
  0 siblings, 1 reply; 17+ messages in thread
From: Sven Wischnowsky @ 2001-05-15 14:18 UTC (permalink / raw)
  To: zsh-workers

Peter Stephenson wrote:

> Sven wrote:
> > The patch makes it keep all quotes *inside* parameter expansions when
> > *not* completing a parameter name.  For the simple things I tried, this
> > worked.  And for the case we were discussing, this gives the right
> > string to the shell code.
> 
> Are we sure the zle_tricky.c change doesn't cause some knock-on problem,
> e.g. in old-style completion? 

The change affects only completion of words with quotes in them and
that's something that has been changed before (I mean in 3.1.x).  I also
tried some of the cases with old-style completion (as with new-style)
and didn't find any immediate problems.

Of course, it's hard to `be sure' here.

Bye
  Sven


-- 
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: destructive list-expand
  2001-05-15 14:18           ` Sven Wischnowsky
@ 2001-05-15 14:41             ` Bart Schaefer
  2001-05-15 15:05               ` Bart Schaefer
  2001-05-16 10:24               ` Sven Wischnowsky
  0 siblings, 2 replies; 17+ messages in thread
From: Bart Schaefer @ 2001-05-15 14:41 UTC (permalink / raw)
  To: Sven Wischnowsky, zsh-workers

On May 15,  4:18pm, Sven Wischnowsky wrote:
} Subject: Re: destructive list-expand
}
} Peter Stephenson wrote:
} 
} > Sven wrote:
} > > The patch makes it keep all quotes *inside* parameter expansions when
} > > *not* completing a parameter name.  For the simple things I tried, this
} > > worked.  And for the case we were discussing, this gives the right
} > > string to the shell code.

This now gives the right thing for me with list-expand, but still fails
on _list_expansions (or _expand_word).  The command line isn't de-quoted
in either case, but _expand_word still just feeps at me.

schaefer<506> echo ${(M)${(f)"$(<=(print -l *))"}:#*conf*}<TAB>
No matches for `file' or `corrections'
schaefer<506> echo ${(M)${(f)"$(<=(print -l *))"}:#*conf*}<C-x g>
acconfig.h    config.h.in   config.sub    configure.in  
config.guess  config.log    configure     

Then there's this problem -- move the quotes outside the parameter:

schaefer<507> echo "${(M)${(f)$(<=(print -l *))}:#*conf*}"<C-x g>
[expansion elided]
schaefer<507> echo ${(M)${(f)$(<=(print -l *))}:#*conf*}"

Now the leading quote has been removed, but the trailing quote is there.
(They used to both disappear.)

} > Are we sure the zle_tricky.c change doesn't cause some knock-on problem,
} > e.g. in old-style completion? 

Obviously we're not.

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

Zsh: http://www.zsh.org | PHPerl Project: http://phperl.sourceforge.net   


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: destructive list-expand
  2001-05-15 14:41             ` Bart Schaefer
@ 2001-05-15 15:05               ` Bart Schaefer
  2001-05-16 10:24               ` Sven Wischnowsky
  1 sibling, 0 replies; 17+ messages in thread
From: Bart Schaefer @ 2001-05-15 15:05 UTC (permalink / raw)
  To: zsh-workers

On May 15,  2:41pm, Bart Schaefer wrote:
} Subject: Re: destructive list-expand
}
} schaefer<507> echo "${(M)${(f)$(<=(print -l *))}:#*conf*}"<C-x g>
} [expansion elided]
} schaefer<507> echo ${(M)${(f)$(<=(print -l *))}:#*conf*}"
} 
} Now the leading quote has been removed, but the trailing quote is there.
} (They used to both disappear.)

Just to be clear ... both of them disappearing is wrong too, of course.

Why is it ever correct to delete quotes _anywhere_?

Here's an even worse error:

schaefer<510> echo '${(@M)${(f)$(<=(print -l *))}:#*conf*}'<C-x g>
schaefer<510> echo ${(@M)${(f)$(<=(print -l *))}:#*conf*}

Now both *single* quotes are gone.  Bad news.

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

Zsh: http://www.zsh.org | PHPerl Project: http://phperl.sourceforge.net   


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: destructive list-expand
  2001-05-15 14:41             ` Bart Schaefer
  2001-05-15 15:05               ` Bart Schaefer
@ 2001-05-16 10:24               ` Sven Wischnowsky
  2001-05-16 11:05                 ` Peter Stephenson
                                   ` (2 more replies)
  1 sibling, 3 replies; 17+ messages in thread
From: Sven Wischnowsky @ 2001-05-16 10:24 UTC (permalink / raw)
  To: zsh-workers

Bart Schaefer wrote:

> On May 15,  4:18pm, Sven Wischnowsky wrote:
> } Subject: Re: destructive list-expand
> }
> } Peter Stephenson wrote:
> } 
> } > Sven wrote:
> } > > The patch makes it keep all quotes *inside* parameter expansions when
> } > > *not* completing a parameter name.  For the simple things I tried, this
> } > > worked.  And for the case we were discussing, this gives the right
> } > > string to the shell code.
> 
> This now gives the right thing for me with list-expand, but still fails
> on _list_expansions (or _expand_word).  The command line isn't de-quoted
> in either case, but _expand_word still just feeps at me.
> 
> schaefer<506> echo ${(M)${(f)"$(<=(print -l *))"}:#*conf*}<TAB>
> No matches for `file' or `corrections'
> schaefer<506> echo ${(M)${(f)"$(<=(print -l *))"}:#*conf*}<C-x g>
> acconfig.h    config.h.in   config.sub    configure.in  
> config.guess  config.log    configure     

Yes, I pointed that out and the reason for it: _expand uses

      eval 'exp=( ${${(e)exp//\\[ 	
    ]/ }//(#b)([ 	
    ])/\\$match[1]} )' 2>/dev/null

But that doesn't work here:

    beta% echo ${(M)${(f)"$(<=(print -l *))"}:#*conf*}
    acconfig.h conf config.cache config.guess config.h config.h.in config.log config.moduls config.status config.sub configure configure.in sconf
    beta% foo='${(M)${(f)"$(<=(print -l *))"}:#*conf*}'
    beta% echo ${(e)foo}
 
    beta% echo ${(e)~foo}
    CVS ChangeLog ChangeLog-Release ChangeLog.3.0 ChangeLog~ Completion Config Doc Etc Functions INSTALL LICENCE META-FAQ Makefile Makefile.in Misc README Src StartupFiles Test Util a acconfig.h aclocal.m4 aczsh.m4 conf config.cache config.guess config.h config.h.in config.log config.modules config.status config.sub configure configure.in core install-sh mkinstalldirs sconf so_locations stamp-h stamp-h.in

I don't know if this is a bug (it looks like one, in a certain sense),
nor do I know how to fix this (at least without looking at the parameter
code again).

> Then there's this problem -- move the quotes outside the parameter:
> 
> schaefer<507> echo "${(M)${(f)$(<=(print -l *))}:#*conf*}"<C-x g>
> [expansion elided]
> schaefer<507> echo ${(M)${(f)$(<=(print -l *))}:#*conf*}"
> 
> Now the leading quote has been removed, but the trailing quote is there.
> (They used to both disappear.)

The real reason for this was that my change didn't look out for
Qstring's, only for String tokens, fix below.

> } > Are we sure the zle_tricky.c change doesn't cause some knock-on problem,
> } > e.g. in old-style completion? 
> 
> Obviously we're not.

Yes, but it was already broken before. Still, I offer to back out the
last patch and this one if you or Peter decide that you prefer it.


In another mail:

> On May 15,  2:41pm, Bart Schaefer wrote:
> } Subject: Re: destructive list-expand
> }
> } schaefer<507> echo "${(M)${(f)$(<=(print -l *))}:#*conf*}"<C-x g>
> } [expansion elided]
> } schaefer<507> echo ${(M)${(f)$(<=(print -l *))}:#*conf*}"
> } 
> } Now the leading quote has been removed, but the trailing quote is there.
> } (They used to both disappear.)
> 
> Just to be clear ... both of them disappearing is wrong too, of course.

Yes.

> Why is it ever correct to delete quotes _anywhere_?

Think about *completion*, not expansion. There we *need* to remove the
quotes at some time to be able to complete `"foo<TAB>' and things like
that. We had quite a bit of discussion about all this quoting stuff
which I don't want to revive. The result was that we want to try to keep
starting single and double quotes if possible and otherwise use what
could probably be called a normalised quoted form (backslashes instead
of single or double quotes). I had several very miserable days to at
least reach the state we have now.

> Here's an even worse error:
> 
> schaefer<510> echo '${(@M)${(f)$(<=(print -l *))}:#*conf*}'<C-x g>
> schaefer<510> echo ${(@M)${(f)$(<=(print -l *))}:#*conf*}
> 
> Now both *single* quotes are gone.  Bad news.

The patch below just blindly changes the command line back to the
original when expansion didn't change anything (because we were only
listing or because the word couldn't be expanded).


Anyway, here's the patch which hopefully fixes at least most problems.
The expansion stuff in _expand is not yet handled.


And all this is really ugly to work on. That's why I said I would like
to move more stuff into shell code, which might make this much easier to
fix.


Bye
  Sven

Index: Src/Zle/zle_tricky.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_tricky.c,v
retrieving revision 1.26
diff -u -r1.26 zle_tricky.c
--- Src/Zle/zle_tricky.c	2001/05/15 13:52:23	1.26
+++ Src/Zle/zle_tricky.c	2001/05/16 10:22:22
@@ -783,8 +783,20 @@
 			}
 		}
 		ret = docompletion(s, lst, lincmd);
-	    } else if (ret)
-		clearlist = 1;
+            } else {
+                if (ret)
+                    clearlist = 1;
+                if (!strcmp(ol, (char *)line)) {
+                    /* We may have removed some quotes. For completion, other
+                     * parts of the code re-install them, but for expansion
+                     * we have to do it here. */
+                    cs = 0;
+                    foredel(ll);
+                    spaceinline(origll);
+                    memcpy(line, origline, origll);
+                    cs = origcs;
+                }
+            }
 	} else
 	    /* Just do completion. */
 	    ret = docompletion(s, lst, lincmd);
@@ -1348,7 +1360,7 @@
                 *p = '\'';
             else if (level && *p == Dnull)
                 *p = '"';
-            else if (*p == String && p[1] == Inbrace)
+            else if ((*p == String || *p == Qstring) && p[1] == Inbrace)
                 level++;
             else if (*p == Outbrace)
                 level--;
@@ -1722,9 +1734,15 @@
 	goto end;
     }
     if (lst == COMP_LIST_EXPAND) {
-	/* Only the list of expansions was requested. */
-	ret = listlist(vl);
-	showinglist = 0;
+	/* Only the list of expansions was requested. Restore the 
+         * command line. */
+        cs = 0;
+        foredel(ll);
+        spaceinline(origll);
+        memcpy(line, origline, origll);
+        cs = origcs;
+        ret = listlist(vl);
+        showinglist = 0;
 	goto end;
     }
     /* Remove the current word and put the expansions there. */

-- 
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: destructive list-expand
  2001-05-16 10:24               ` Sven Wischnowsky
@ 2001-05-16 11:05                 ` Peter Stephenson
  2001-05-16 12:49                 ` Sven Wischnowsky
  2001-05-16 19:14                 ` destructive list-expand Bart Schaefer
  2 siblings, 0 replies; 17+ messages in thread
From: Peter Stephenson @ 2001-05-16 11:05 UTC (permalink / raw)
  To: Zsh hackers list

Sven wrote:
> > } > Are we sure the zle_tricky.c change doesn't cause some knock-on problem
> ,
> > } > e.g. in old-style completion? 
> > 
> > Obviously we're not.
> 
> Yes, but it was already broken before. Still, I offer to back out the
> last patch and this one if you or Peter decide that you prefer it.

I'm perfectly happy with the change, I'm just worried in case it tickles
something else.  If it doesn't affect anything other than quotes, then I'm
not concerned, since I realise that's always been hairy.

-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
CSR Ltd., Unit 300, Science Park, Milton Road,
Cambridge, CB4 0XL, UK                          Tel: +44 (0)1223 392070


**********************************************************************
The information transmitted is intended only for the person or
entity to which it is addressed and may contain confidential 
and/or privileged material. 
Any review, retransmission, dissemination or other use of, or
taking of any action in reliance upon, this information by 
persons or entities other than the intended recipient is 
prohibited.  
If you received this in error, please contact the sender and 
delete the material from any computer.
**********************************************************************


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: destructive list-expand
  2001-05-16 10:24               ` Sven Wischnowsky
  2001-05-16 11:05                 ` Peter Stephenson
@ 2001-05-16 12:49                 ` Sven Wischnowsky
  2001-05-16 19:10                   ` Quoting and ${(e)param} (was Re: destructive list-expand) Bart Schaefer
  2001-05-16 19:14                 ` destructive list-expand Bart Schaefer
  2 siblings, 1 reply; 17+ messages in thread
From: Sven Wischnowsky @ 2001-05-16 12:49 UTC (permalink / raw)
  To: zsh-workers

I wrote:

> ...
> 
> Yes, I pointed that out and the reason for it: _expand uses
> 
>       eval 'exp=( ${${(e)exp//\\[ 	
>     ]/ }//(#b)([ 	
>     ])/\\$match[1]} )' 2>/dev/null
> 
> But that doesn't work here:
> 
>     beta% echo ${(M)${(f)"$(<=(print -l *))"}:#*conf*}
>     acconfig.h conf config.cache config.guess config.h config.h.in config.log config.moduls config.status config.sub configure configure.in sconf
>     beta% foo='${(M)${(f)"$(<=(print -l *))"}:#*conf*}'
>     beta% echo ${(e)foo}
>  
>     beta% echo ${(e)~foo}
>     CVS ChangeLog ChangeLog-Release ChangeLog.3.0 ChangeLog~ Completion Config Doc Etc Functions INSTALL LICENCE META-FAQ Makefile Makefile.in Misc README Src StartupFiles Test Util a acconfig.h aclocal.m4 aczsh.m4 conf config.cache config.guess config.h config.h.in config.log config.modules config.status config.sub configure configure.in core install-sh mkinstalldirs sconf so_locations stamp-h stamp-h.in


Part of the reason may probably be fixed by this (not to be committed
until some knowledgeable person comments):

Index: Src/subst.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/subst.c,v
retrieving revision 1.17
diff -u -r1.17 subst.c
--- Src/subst.c	2001/04/28 17:38:01	1.17
+++ Src/subst.c	2001/05/16 12:39:51
@@ -720,9 +720,13 @@
 
     if (!(err ? parsestr(s) : parsestrnoerr(s))) {
 	if (!single) {
+            int qt = 0;
+
 	    for (; *s; s++)
-		if (*s == Qstring)
+		if (!qt && *s == Qstring)
 		    *s = String;
+                else if (*s == Dnull)
+                    qt = !qt;
 	}
 	return 0;
     }


That loop is in subst_parse_str() and turns all Qstring tokens into
String, even the one inside those double quotes in the parameter
expression. That makes the inner substitution return a string instead
of an array.

The patch leaves all Qstring's inside Dnull's unchanged.

The other part of the problem (not tackled by the patch) is that the
pattern after `:#...' is not tokenized. In paramsubst() is some code
that tokenizes the pattern, but only if it things the whole parameter
expansion is inside quotes. But the result of a ${(e)...} is not
considered to be in double quotes exactly because of the loop above.
There must be some reason for this because, of course, we never ever
even think about doing things that are not needed. Ahem.

I'm not sure how to fix this. We don't want the string from a ${(e)...}
being completely tokenized (that's the ~-modifier's job), but having the
patterns used inside parameter expansions be tokenized would be the
right thing, I think, wouldn't it? But where and when exactly would that
have to happen? So that it doesn't interfere with whatever made us add
that loop above?


Bye
  Sven


-- 
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Quoting and ${(e)param} (was Re: destructive list-expand)
  2001-05-16 12:49                 ` Sven Wischnowsky
@ 2001-05-16 19:10                   ` Bart Schaefer
  2001-05-17  9:03                     ` Sven Wischnowsky
  0 siblings, 1 reply; 17+ messages in thread
From: Bart Schaefer @ 2001-05-16 19:10 UTC (permalink / raw)
  To: zsh-workers

On May 16,  2:49pm, Sven Wischnowsky wrote:
} Subject: Re: destructive list-expand
}
} Part of the reason may probably be fixed by this (not to be committed
} until some knowledgeable person comments):
} 
} Index: Src/subst.c
} ===================================================================
} RCS file: /cvsroot/zsh/zsh/Src/subst.c,v
} retrieving revision 1.17
} diff -u -r1.17 subst.c
} --- Src/subst.c	2001/04/28 17:38:01	1.17
} +++ Src/subst.c	2001/05/16 12:39:51
} @@ -720,9 +720,13 @@
}  
}      if (!(err ? parsestr(s) : parsestrnoerr(s))) {
}  	if (!single) {
} +            int qt = 0;
} +
}  	    for (; *s; s++)
} -		if (*s == Qstring)
} +		if (!qt && *s == Qstring)
}  		    *s = String;
} +                else if (*s == Dnull)
} +                    qt = !qt;
}  	}
}  	return 0;
}      }
} 
} 
} That loop is in subst_parse_str() and turns all Qstring tokens into
} String, even the one inside those double quotes in the parameter
} expression. That makes the inner substitution return a string instead
} of an array.
} 
} The patch leaves all Qstring's inside Dnull's unchanged.

Probably the Qstring should change to String when (err == 0), as in
that case parsestrnoerr() will not have complained about unmatched
quotes.  Or will that mean that there are no Qstring to begin with?
Hrm.
 
} The other part of the problem (not tackled by the patch) is that the
} pattern after `:#...' is not tokenized. In paramsubst() is some code
} that tokenizes the pattern, but only if it things the whole parameter
} expansion is inside quotes.

I believe that's because in the normal [non-(e)] case, the pattern will
already have been tokenized when the expansion is not in quotes, so it
would be redundant to tokenize it again.  I'm pretty far from sure about
this, though.

But, not tokenized where?  parsestr() untokenizes and re-tokenizes its
whole argument ... as if it were in double quotes ...

} But the result of a ${(e)...} is not
} considered to be in double quotes exactly because of the loop above.

Right, that loop must be attempting to undo the implicit double-quoting
from parsestr().  It just doesn't undo enough of it.

} I'm not sure how to fix this.

It looks to me as though the only "right" way is to create a new flavor
of parsestr() that parses as if NOT in quotes, and call the appropriate
one from subst_parse_str() (which means passing in `qt' and not just
`single', I suspect).

Does anyone remember anything else that might bear on this?  Peter?

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

Zsh: http://www.zsh.org | PHPerl Project: http://phperl.sourceforge.net   


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: destructive list-expand
  2001-05-16 10:24               ` Sven Wischnowsky
  2001-05-16 11:05                 ` Peter Stephenson
  2001-05-16 12:49                 ` Sven Wischnowsky
@ 2001-05-16 19:14                 ` Bart Schaefer
  2 siblings, 0 replies; 17+ messages in thread
From: Bart Schaefer @ 2001-05-16 19:14 UTC (permalink / raw)
  To: zsh-workers

On May 16, 12:24pm, Sven Wischnowsky wrote:
} Subject: Re: destructive list-expand
}
} Bart Schaefer wrote:
} 
} > This now gives the right thing for me with list-expand, but still fails
} > on _list_expansions (or _expand_word).
} 
} Yes, I pointed that out and the reason for it: _expand uses
} 
}       eval 'exp=( ${${(e)exp//\\[ 	
}     ]/ }//(#b)([ 	
}     ])/\\$match[1]} )' 2>/dev/null

Could we change that to:

	eval "exp=( $exp )" 2>/dev/null
	eval 'exp=( ${$exp//\\[
	]/ }//(#b)([
	])/\\$match[1]} )' 2>/dev/null

Or is that going to break something else?  (It fixes the specific example
we've been using, but I haven't tried any other examples e.g. that really
do have carriage-returns or other backslashed-whitespace in the results.)

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

Zsh: http://www.zsh.org | PHPerl Project: http://phperl.sourceforge.net   


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Quoting and ${(e)param} (was Re: destructive list-expand)
  2001-05-16 19:10                   ` Quoting and ${(e)param} (was Re: destructive list-expand) Bart Schaefer
@ 2001-05-17  9:03                     ` Sven Wischnowsky
  2001-05-18  9:55                       ` Bart Schaefer
  0 siblings, 1 reply; 17+ messages in thread
From: Sven Wischnowsky @ 2001-05-17  9:03 UTC (permalink / raw)
  To: zsh-workers

I probably should have said some more.

Actually, the current state really isn't that far away from the right
thing. The (e) flag should make only the $-expansions from the value be
done on the result. Because of that parsing the string as in double
quotes is the right thing. Using parse_subst_string() or adding the
`parsestr()-as-if-not-in-quotes' Bart suggested would make glob pattern
be expanded, too.

There are only two problems: we have to handle the case when the
expansion stored in the parameter value (the one we have to expand after
(e) has done its work) needs to expand to more than one word. In that
case we have to selectively `de-quote' some of the string -- and that's
what the loop we're discussing does. It just de-quotes too many
Qstring's, namely those inside quoted nested expansions. That would be
fixed by the patch I sent (and that makes me like that patch quite a bit).

The other problem is the tokenization of pattern *inside* parameter
expansions only (it isn't a problem if the parameter we are using the
(e) flag on contains $(..) or $((..)) expansions -- both of them take
care of tokenization themselves).

As Bart correctly pointed out (I knew that and probably should have
explained it some more), there are two things playing together.
subst_parse_string() tokenizes as if in double quotes (which, as I said
above, I think is correct), which also means that the patterns inside
parameter expansions are not tokenized. Normally if one does `"${x$*}"',
paramsubst() will take of that because the `$' is turned into a Qstring
token, so paramsubst() knows that the pattern isn't tokenized and does
it itself. But if that string comes from subst_parse_string(), the
Qstring will be turned into a String token, but the pattern will not be
tokenized -- and hence paramsubst() will not tokenize it itself.

Completely tokenizing the string resulting from a (e)ed parameter
expansion isn't an option, because that would also tokenize patterns
outside of parameter expansions -- we get globbing which we don't want
to have there, that's the job of `${~x}'. At least, it would be quite a
serious change if we modified this to do, e.g., globbing if the `${(e)x}'
isn't in quotes and only the other expansions if one uses `"${(e)x}"'.

So, subst_parse_string() has to do the de-quoting to be able to take
into account the way the expansion with the (e) was quoted or not.

I think all this could be solved if we find a way to tell the
paramsubst() doing the expansion in the value of the (e)ed parameter
that it has to tokenize the pattern even if there is a String token and
not a Qstring token. But currently we don't have a way to do that, or at
least none I can think of. It's problematic, because the first
paramsubst() just passes the resulting words back to it's calling
function which then re-examines them, expanding the now tokenized
expansions.

So the easiest solution would be to just make paramsubst() always
tokenize the pattern strings, not only if it knows that the parameter
expansion is in quotes. I was fearing that this might result in some
quoting problems (having to double backslashes or some such), but it
seems to work, including handling of parameter expansions inside
patterns.

Just so that everyone interested can easily play with it, I'll add a
patch below containing both changes (just #if'ed out the test).

The tests at least still work for me...

Bye
  Sven

Index: Src/subst.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/subst.c,v
retrieving revision 1.17
diff -u -r1.17 subst.c
--- Src/subst.c	2001/04/28 17:38:01	1.17
+++ Src/subst.c	2001/05/17 09:03:40
@@ -720,9 +720,13 @@
 
     if (!(err ? parsestr(s) : parsestrnoerr(s))) {
 	if (!single) {
+            int qt = 0;
+
 	    for (; *s; s++)
-		if (*s == Qstring)
+		if (!qt && *s == Qstring)
 		    *s = String;
+                else if (*s == Dnull)
+                    qt = !qt;
 	}
 	return 0;
     }
@@ -1483,7 +1487,11 @@
 	case '#':
 	case Pound:
 	case '/':
+#if 0
 	    if (qt) {
+#else
+            {
+#endif
 		int one = noerrs, oef = errflag, haserr;
 
 		if (!quoteerr)

-- 
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Quoting and ${(e)param} (was Re: destructive list-expand)
  2001-05-17  9:03                     ` Sven Wischnowsky
@ 2001-05-18  9:55                       ` Bart Schaefer
  2001-05-18 12:36                         ` PATCH: " Sven Wischnowsky
  0 siblings, 1 reply; 17+ messages in thread
From: Bart Schaefer @ 2001-05-18  9:55 UTC (permalink / raw)
  To: Sven Wischnowsky, zsh-workers

(Hello, it's nearly 3am here and I'm waiting for my Windows machine to
repair its disk ... if I leave it alone I can't answer the dialogs that it
throws up periodically, and not answering causes it to lock up and have to
be reset, which of course only makes matters worse ...)

On May 17, 11:03am, Sven Wischnowsky wrote:
}
} Actually, the current state really isn't that far away from the right
} thing. The (e) flag should make only the $-expansions from the value be
} done on the result. Because of that parsing the string as in double
} quotes is the right thing. Using parse_subst_string() or adding the
} `parsestr()-as-if-not-in-quotes' Bart suggested would make glob pattern
} be expanded, too.

OK, that's obviously not ideal ...

} So the easiest solution would be to just make paramsubst() always
} tokenize the pattern strings, not only if it knows that the parameter
} expansion is in quotes. I was fearing that this might result in some
} quoting problems (having to double backslashes or some such), but it
} seems to work, including handling of parameter expansions inside
} patterns.

Yes, it's pretty obvious that it should work:  parse_subst_str() does
an untokenize() before it lexes the string, so it won't matter if the
string is or is not already tokenized.  All that your patch is doing is
removing an optimization.

Consequently I think it would be OK to include it (possibly with the #if
replaced by an explanatory comment).  It'll slow down expansion of un-
quoted parameters slightly in the name of correctness, a tradeoff I made
several times in my subscript-parsing changes.

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

Zsh: http://www.zsh.org | PHPerl Project: http://phperl.sourceforge.net   


^ permalink raw reply	[flat|nested] 17+ messages in thread

* PATCH: Re: Quoting and ${(e)param} (was Re: destructive list-expand)
  2001-05-18  9:55                       ` Bart Schaefer
@ 2001-05-18 12:36                         ` Sven Wischnowsky
  0 siblings, 0 replies; 17+ messages in thread
From: Sven Wischnowsky @ 2001-05-18 12:36 UTC (permalink / raw)
  To: zsh-workers

Bart Schaefer wrote:

> ...
> 
> } So the easiest solution would be to just make paramsubst() always
> } tokenize the pattern strings, not only if it knows that the parameter
> } expansion is in quotes. I was fearing that this might result in some
> } quoting problems (having to double backslashes or some such), but it
> } seems to work, including handling of parameter expansions inside
> } patterns.
> 
> Yes, it's pretty obvious that it should work:  parse_subst_str() does
> an untokenize() before it lexes the string, so it won't matter if the
> string is or is not already tokenized.  All that your patch is doing is
> removing an optimization.

Yes, I was hoping to be able somehow to keep that optimization. Sigh.

> Consequently I think it would be OK to include it (possibly with the #if
> replaced by an explanatory comment).  It'll slow down expansion of un-
> quoted parameters slightly in the name of correctness, a tradeoff I made
> several times in my subscript-parsing changes.

Ok, then, here's the final version of the patch.

Bye
  Sven

Index: Src/subst.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/subst.c,v
retrieving revision 1.17
diff -u -r1.17 subst.c
--- Src/subst.c	2001/04/28 17:38:01	1.17
+++ Src/subst.c	2001/05/18 12:36:31
@@ -720,9 +720,13 @@
 
     if (!(err ? parsestr(s) : parsestrnoerr(s))) {
 	if (!single) {
+            int qt = 0;
+
 	    for (; *s; s++)
-		if (*s == Qstring)
+		if (!qt && *s == Qstring)
 		    *s = String;
+                else if (*s == Dnull)
+                    qt = !qt;
 	}
 	return 0;
     }
@@ -1483,7 +1487,14 @@
 	case '#':
 	case Pound:
 	case '/':
-	    if (qt) {
+            /* This once was executed only `if (qt) ...'. But with that
+             * patterns in a expansion resulting from a ${(e)...} aren't
+             * tokenized even though this function thinks they are (it thinks
+             * they are because subst_parse_string() turns Qstring tokens
+             * into String tokens and for unquoted parameter expansions the
+             * lexer normally does tokenize patterns inside parameter
+             * expansions). */
+            {
 		int one = noerrs, oef = errflag, haserr;
 
 		if (!quoteerr)

-- 
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2001-05-18 12:37 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-05-15  2:30 destructive list-expand Clint Adams
2001-05-15  4:48 ` Bart Schaefer
2001-05-15  5:32   ` Bart Schaefer
2001-05-15  9:28     ` Sven Wischnowsky
2001-05-15 13:48       ` Sven Wischnowsky
2001-05-15 13:57         ` Peter Stephenson
2001-05-15 14:18           ` Sven Wischnowsky
2001-05-15 14:41             ` Bart Schaefer
2001-05-15 15:05               ` Bart Schaefer
2001-05-16 10:24               ` Sven Wischnowsky
2001-05-16 11:05                 ` Peter Stephenson
2001-05-16 12:49                 ` Sven Wischnowsky
2001-05-16 19:10                   ` Quoting and ${(e)param} (was Re: destructive list-expand) Bart Schaefer
2001-05-17  9:03                     ` Sven Wischnowsky
2001-05-18  9:55                       ` Bart Schaefer
2001-05-18 12:36                         ` PATCH: " Sven Wischnowsky
2001-05-16 19:14                 ` destructive list-expand Bart Schaefer

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).