Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: Is this a bug? Why not?
- X-seq: zsh-workers 27889
- From: Peter Stephenson <p.w.stephenson@xxxxxxxxxxxx>
- To: zsh-workers@xxxxxxx
- Subject: Re: Is this a bug? Why not?
- Date: Sun, 18 Apr 2010 20:11:12 +0100
- In-reply-to: <n2h237967ef1004170606i78e9dee8s31606fdd62ab25c7@xxxxxxxxxxxxxx>
- List-help: <mailto:zsh-workers-help@zsh.org>
- List-id: Zsh Workers List <zsh-workers.zsh.org>
- List-post: <mailto:zsh-workers@zsh.org>
- Mailing-list: contact zsh-workers-help@xxxxxxx; run by ezmlm
- References: <100330224612.ZM1818@xxxxxxxxxxxxxxxxxxxxxx> <20100331060602.GA91691@xxxxxxxxxxxxxxxxxxxx> <100331081153.ZM2688@xxxxxxxxxxxxxxxxxxxxxx> <20100401082624.GA56998@xxxxxxxxxxxxxxxxxxxx> <100401073618.ZM10593@xxxxxxxxxxxxxxxxxxxxxx> <20100401215752.GA34619@xxxxxxxxxxxxxxxxxxxx> <100401155118.ZM11873@xxxxxxxxxxxxxxxxxxxxxx> <20100409153754.76d0f6a6@news01> <n2h237967ef1004170606i78e9dee8s31606fdd62ab25c7@xxxxxxxxxxxxxx>
On Sat, 17 Apr 2010 15:06:53 +0200
Mikael Magnusson <mikachu@xxxxxxxxx> wrote:
> This patch
(resetting globsubst for the argument of a variable substitution when
the pattern matching is already done)
> breaks at least cd ~-/<tab>
realpath=${~:-\~$linepath}/
doesn't expand the second "~" despite the first "~" because the second
tilde is quoted. Strictly this new behaviour is probably correct
because the quote should indeed stop the second tilde being active, but
actually the hack below fixes this so I've left it (even though removing
the backslash seemed to work in this case, too).
> and anything using _pids for me.
That's because given
desc=' PID TTY TIME CMD'
out=( ' 2591 pts/1 00:00:02 zsh'
' 2600 pts/1 00:00:01 dropbox'
' 3271 pts/1 00:00:00 zsh'
' 3272 pts/1 00:00:00 ps' )
this expression:
pids=( "${(@)${(@M)out#${(l.${#desc[1,(r)(#i)[[:blank:]]pid]}..?.)~:-}[^[:blank:]]#}##*[[:blank:]]}" )
sets
pids=( '' '' '' '' )
Er... obviously. What's happening is
${(l.${#desc[1,(r)(#i)[[:blank:]]pid]}..?.)~:-}
should turn into ????? which are activated for use in patterns, because
of the "~", but it isn't because globsubst is now turned off when we get
to padding because we already handled the value as the right hand side
of ":-" (i.e. the empty string) so there was no value to activate.
One fix is to leave globsubst on when it's forced by the "~" flag. That
doesn't screw up sh compatibility, which knows nothing about the flag,
but it's not really the right thing to do, which would be to track
through to see where the text came from and conditionally tokenize it,
yeugh. The difference is in the case where GLOB_SUBST is set but you're
using zsh substitution syntax, which is not typical (and is the sort of
complicated hybrid I'd dearly love to forbid but will never be able to).
As I'm definitely not doing any major surgery on paramsubst() to
preserve different notions of globsubst at different points in the
function myself (feel free to volunteer) it may be all you will get in
any case. See the test file for a simpler indication of implications.
Ultimately, I think this hack may actually be the right thing to do
because it preserves traditional zsh behaviour in typical cases (where
the option isn't set and ~ is used to force it) as well as any script
adhering to sh syntax.
I'll think about some documentation.
"Ceterum censeo functio de substitutione parametrum esse rescribenda"
("Furthermore, I am of the opinion that paramsubst() ought to be
rewritten") --- Marcus Porcius Cato the Elder
Index: Src/subst.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/subst.c,v
retrieving revision 1.103
diff -p -u -r1.103 subst.c
--- Src/subst.c 9 Apr 2010 15:40:14 -0000 1.103
+++ Src/subst.c 18 Apr 2010 19:03:01 -0000
@@ -1386,7 +1386,8 @@ paramsubst(LinkList l, LinkNode n, char
int plan9 = isset(RCEXPANDPARAM);
/*
* Likwise, but with ~ and ~~. Also, we turn it off later
- * on if qt is passed down.
+ * on if qt is passed down. The value can go to 2 if we
+ * use ~ to force this on.
*/
int globsubst = isset(GLOBSUBST);
/*
@@ -1899,12 +1900,12 @@ paramsubst(LinkList l, LinkNode n, char
* spsep, NULL means $IFS.
*/
} else if (c == '~' || c == Tilde) {
- /* GLOB_SUBST on or off (doubled) */
+ /* GLOB_SUBST (forced) on or off (doubled) */
if ((c = *++s) == '~' || c == Tilde) {
globsubst = 0;
s++;
} else
- globsubst = 1;
+ globsubst = 2;
} else if (c == '+') {
/*
* Return whether indicated parameter is set.
@@ -1935,7 +1936,8 @@ paramsubst(LinkList l, LinkNode n, char
break;
}
/* Don't activate special pattern characters if inside quotes */
- globsubst = globsubst && !qt;
+ if (qt)
+ globsubst = 0;
/*
* At this point, we usually expect a parameter name.
@@ -2417,7 +2419,10 @@ paramsubst(LinkList l, LinkNode n, char
multsub(&val, spbreak && !aspar, (aspar ? NULL : &aval), &isarr, NULL);
opts[SHWORDSPLIT] = ws;
copied = 1;
- spbreak = globsubst = 0;
+ spbreak = 0;
+ /* Leave globsubst on if forced */
+ if (globsubst != 2)
+ globsubst = 0;
}
break;
case ':':
Index: Test/D04parameter.ztst
===================================================================
RCS file: /cvsroot/zsh/zsh/Test/D04parameter.ztst,v
retrieving revision 1.41
diff -p -u -r1.41 D04parameter.ztst
--- Test/D04parameter.ztst 9 Apr 2010 15:40:14 -0000 1.41
+++ Test/D04parameter.ztst 18 Apr 2010 19:03:01 -0000
@@ -226,10 +226,12 @@
foo="boring*"
print ${foo+$foo}
print ${foo+"$foo"}
+ print ${~foo+"$foo"}
)
0:globsubst together with nested quoted expansion
>boringfile
>boring*
+>boringfile
print -l "${$(print one word)}" "${=$(print two words)}"
0:splitting of $(...) inside ${...}
--
Peter Stephenson <p.w.stephenson@xxxxxxxxxxxx>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/
Messages sorted by:
Reverse Date,
Date,
Thread,
Author