summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2007-10-30 14:01:32 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2007-10-30 14:01:32 +0000
commita232ab562423eccb9523c190c5e03242320cc3fd (patch)
tree78161b5cbd651fd5174689950c226b301addd653
parent12a38ba4f725e423e9f5ab4c87af7fc03663b90e (diff)
downloadzsh-a232ab562423eccb9523c190c5e03242320cc3fd.tar.gz
zsh-a232ab562423eccb9523c190c5e03242320cc3fd.zip
users/12149: "@" with splitting in double quotes retains empty fields
-rw-r--r--ChangeLog6
-rw-r--r--Doc/Zsh/expn.yo11
-rw-r--r--Src/subst.c23
-rw-r--r--Test/D04parameter.ztst32
4 files changed, 62 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog
index cf9096faa..757821aff 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
2007-10-30 Peter Stephenson <pws@csr.com>
+ * users/12149: Doc/Zsh/expn.yo, Src/subst.c,
+ Test/D04parameter.ztst: "${(@s.:.)...}" retains empty
+ fields, although "${(s.:.)...}" remains backward compatible.
+
+2007-10-30 Peter Stephenson <pws@csr.com>
+
* 24030, adapted: Src/Modules/curses.c: turning off a key timeout
on Solaris 8 seemed to need leaving and re-entering cbreak mode.
This can't be done per-window, so make this specific to Solaris
diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo
index cc87ebe6f..f48616580 100644
--- a/Doc/Zsh/expn.yo
+++ b/Doc/Zsh/expn.yo
@@ -960,6 +960,17 @@ separator var(string). Note that a var(string) of two or more
characters means that all of them must match in sequence; this differs from
the treatment of two or more characters in the tt(IFS) parameter.
See also the tt(=) flag and the tt(SH_WORD_SPLIT) option.
+
+For historical reasons, the usual behaviour that empty array elements
+are retained inside double quotes is disabled for arrays generated
+by splitting; hence the following:
+
+example(line="one::three"
+print -l "${(s.:.)line}")
+
+produces two lines of output for tt(one) and tt(three) and elides the
+empty field. To override this behaviour, supply the "(@)" flag as well,
+i.e. tt("${(@s.:.)line}").
)
enditem()
diff --git a/Src/subst.c b/Src/subst.c
index 6ce723acd..e586ede9a 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -1260,13 +1260,16 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
* parameter (the value v) to storing them in val and aval.
* However, sometimes you find v reappearing temporarily.
*
- * The values -1 and 2 are special to isarr. It looks like 2 is
- * some kind of an internal flag to do with whether the array's been
- * copied, in which case I don't know why we don't use the copied
- * flag, but they do both occur close together so they presumably
- * have different effects. The value -1 is used to force us to
- * keep an empty array. It's tested in the YUK chunk (I mean the
- * one explicitly marked as such).
+ * The values -1 and 2 are special to isarr. The value -1 is used
+ * to force us to keep an empty array. It's tested in the YUK chunk
+ * (I mean the one explicitly marked as such). The value 2
+ * indicates an array has come from splitting a scalar. We use
+ * that to override the usual rule that in double quotes we don't
+ * remove empty elements (so "${(s.:):-foo::bar}" produces two
+ * words). This seems to me to be quite the wrong thing to do,
+ * but it looks like code may be relying on it. So we require (@)
+ * as well before we keep the empty fields (look for assignments
+ * like "isarr = nojoin ? 1 : 2").
*/
int isarr = 0;
/*
@@ -2453,7 +2456,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
char *arr[2], **t, **a, **p;
if (spsep || spbreak) {
aval = sepsplit(val, spsep, 0, 1);
- isarr = 2;
+ isarr = nojoin ? 1 : 2;
l = arrlen(aval);
if (l && !*(aval[l-1]))
l--;
@@ -2772,7 +2775,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
else if (!aval[1])
val = aval[0];
else
- isarr = 2;
+ isarr = nojoin ? 1 : 2;
}
if (isarr)
l->list.flags |= LF_ARRAY;
@@ -2974,7 +2977,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
val = getdata(firstnode(list));
else {
aval = hlinklist2array(list, 0);
- isarr = 2;
+ isarr = nojoin ? 1 : 2;
l->list.flags |= LF_ARRAY;
}
copied = 1;
diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst
index 1910e60be..e8718a691 100644
--- a/Test/D04parameter.ztst
+++ b/Test/D04parameter.ztst
@@ -942,3 +942,35 @@
>some
>sunny
>day
+
+ foo="line:with::missing::fields:in:it"
+ print -l ${(s.:.)foo}
+0:Removal of empty fields in unquoted splitting
+>line
+>with
+>missing
+>fields
+>in
+>it
+
+ foo="line:with::missing::fields:in:it"
+ print -l "${(s.:.)foo}"
+0:Hacky removal of empty fields in quoted splitting with no "@"
+>line
+>with
+>missing
+>fields
+>in
+>it
+
+ foo="line:with::missing::fields:in:it"
+ print -l "${(@s.:.)foo}"
+0:Retention of empty fields in quoted splitting with "@"
+>line
+>with
+>
+>missing
+>
+>fields
+>in
+>it