zsh-users
 help / color / mirror / code / Atom feed
* RFE: Brace expansion with single characters
@ 2014-01-07 21:49 Daniel Serodio
  2014-01-07 23:11 ` Simon Ruderich
  2014-01-08 12:13 ` Peter Stephenson
  0 siblings, 2 replies; 6+ messages in thread
From: Daniel Serodio @ 2014-01-07 21:49 UTC (permalink / raw)
  To: zsh-users

As a long time zsh user, I was surprised to find a bash feature missing 
from zsh: on bash, brace expansion also works with single characters, 
while on zsh only digits.

Please consider this request for enhancement.

Thanks in advance,
Daniel Serodio


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

* Re: RFE: Brace expansion with single characters
  2014-01-07 21:49 RFE: Brace expansion with single characters Daniel Serodio
@ 2014-01-07 23:11 ` Simon Ruderich
  2014-01-08  9:22   ` Vincent Lefevre
  2014-01-08  9:55   ` Jerry Rocteur
  2014-01-08 12:13 ` Peter Stephenson
  1 sibling, 2 replies; 6+ messages in thread
From: Simon Ruderich @ 2014-01-07 23:11 UTC (permalink / raw)
  To: zsh-users

[-- Attachment #1: Type: text/plain, Size: 526 bytes --]

On Tue, Jan 07, 2014 at 07:49:07PM -0200, Daniel Serodio wrote:
> As a long time zsh user, I was surprised to find a bash feature missing from
> zsh: on bash, brace expansion also works with single characters, while on
> zsh only digits.

Zsh also supports this, you just need to set the BRACE_CCL
option:

    % echo {a-j}
    {a-j}
    % setopt braceccl
    % echo {a-j}
    a b c d e f g h i j

Regards
Simon
-- 
+ privacy is necessary
+ using gnupg http://gnupg.org
+ public key id: 0x92FEFDB7E44C32F9

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: RFE: Brace expansion with single characters
  2014-01-07 23:11 ` Simon Ruderich
@ 2014-01-08  9:22   ` Vincent Lefevre
  2014-01-08  9:55   ` Jerry Rocteur
  1 sibling, 0 replies; 6+ messages in thread
From: Vincent Lefevre @ 2014-01-08  9:22 UTC (permalink / raw)
  To: zsh-users

On 2014-01-08 00:11:17 +0100, Simon Ruderich wrote:
> Zsh also supports this, you just need to set the BRACE_CCL
> option:
> 
>     % echo {a-j}
>     {a-j}
>     % setopt braceccl
>     % echo {a-j}
>     a b c d e f g h i j

Not the way bash behaves:

In bash:

$ echo {a..j}
a b c d e f g h i j

In zsh:
% echo {a..j}
{a..j}
% setopt braceccl
% echo {a..j}
. a j

That's buggy. And the support for "-" is a bad idea:

% echo {2014-01-08}
0 1 2 4 8

so that one cannot use dates in braces (very useful for svn users).
No problems with bash.

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <http://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <http://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)


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

* Re: RFE: Brace expansion with single characters
  2014-01-07 23:11 ` Simon Ruderich
  2014-01-08  9:22   ` Vincent Lefevre
@ 2014-01-08  9:55   ` Jerry Rocteur
  2014-01-08 11:25     ` Peter Stephenson
  1 sibling, 1 reply; 6+ messages in thread
From: Jerry Rocteur @ 2014-01-08  9:55 UTC (permalink / raw)
  To: Simon Ruderich; +Cc: zsh-users

On Wed, Jan 8, 2014 at 12:11 AM, Simon Ruderich <simon@ruderich.org> wrote:
> On Tue, Jan 07, 2014 at 07:49:07PM -0200, Daniel Serodio wrote:
>> As a long time zsh user, I was surprised to find a bash feature missing from
>> zsh: on bash, brace expansion also works with single characters, while on
>> zsh only digits.
>
> Zsh also supports this, you just need to set the BRACE_CCL
> option:
>
>     % echo {a-j}
>     {a-j}
>     % setopt braceccl
>     % echo {a-j}
>     a b c d e f g h i j

Sorry to butt in but doesn't this sound a bit rude to anyone ?

As in

echo {0..12}

Does what is expected

echo {a..z}

Does nothing as expected

setopt braceccl
echo {a-z}

does something somebody expected ?

Shouldn't there be some kind of uniformity or is this for a reason ?
The other two shells work as expected.

Thanks in advance,

Jerry


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

* Re: RFE: Brace expansion with single characters
  2014-01-08  9:55   ` Jerry Rocteur
@ 2014-01-08 11:25     ` Peter Stephenson
  0 siblings, 0 replies; 6+ messages in thread
From: Peter Stephenson @ 2014-01-08 11:25 UTC (permalink / raw)
  To: zsh-users

On Wed, 08 Jan 2014 10:55:05 +0100
Jerry Rocteur <jerry.rocteur@gmail.com> wrote:
> echo {0..12}
> 
> Does what is expected
> 
> echo {a..z}
> 
> Does nothing as expected
> 
> setopt braceccl
> echo {a-z}
> 
> does something somebody expected ?

Yes, that's how zsh works; OK so far...

> Shouldn't there be some kind of uniformity or is this for a reason ?

I'm not sure what you mean.  Bash and zsh have different extensions.
Are you saying "should they have the same set of extensions"?  Not
particularly, no.  They copy each other to some extent but also go
their own way to some exstent.  The history is something like:

- zsh invented the BRACECCL option (this has been there for donkey's
years) which expands everything in the brace as a single character (even
if the character is repeated in the base), except that "-" is a special
case to indicate a range.  This is rather different from the feature
required --- it makes braces without commas do rather more than you
expect, as noted by Vincent.   That's not a bug, however; its
significant additional effect is why it's an option.

- zsh invented the {<integer>..<integer>} syntax (vaguely inspired by
Perl).  This isn't an option because it's specific enough not to cause
problems.

- bash also started using that syntax, but added the extra feature
with single character ranges.

> The other two shells work as expected.

As far as I can see, and as your comments at the top suggest, everything
works as expected.  Are you saying both bash and zsh currently work as
documented?  I think that's correct.  The original post was simply a
request for a new feature.

It looks fairly straightforward to add the bash feature to zsh in this
case and I've just been looking at it.  I would imagine this will fit
in naturally enough not to cause complications.

pws


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

* Re: RFE: Brace expansion with single characters
  2014-01-07 21:49 RFE: Brace expansion with single characters Daniel Serodio
  2014-01-07 23:11 ` Simon Ruderich
@ 2014-01-08 12:13 ` Peter Stephenson
  1 sibling, 0 replies; 6+ messages in thread
From: Peter Stephenson @ 2014-01-08 12:13 UTC (permalink / raw)
  To: zsh-users

On Tue, 07 Jan 2014 19:49:07 -0200
Daniel Serodio <dserodio@dserodio.net> wrote:
> As a long time zsh user, I was surprised to find a bash feature missing 
> from zsh: on bash, brace expansion also works with single characters, 
> while on zsh only digits.
> 
> Please consider this request for enhancement.

As I said elsewhere, this looks straightforward and the tests I've added
suggest I haven't screwed up too badly.

diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo
index 5ba3e21..8bbe780 100644
--- a/Doc/Zsh/expn.yo
+++ b/Doc/Zsh/expn.yo
@@ -1539,6 +1539,16 @@ specified in any of the three numbers, specifying it in the third can be useful
 to pad for example `tt({-99..100..01})' which is not possible to specify by putting a
 0 on either of the first two numbers (i.e. pad to two characters).
 
+An expression of the form `tt({)var(c1)tt(..)var(c2)tt(})', where
+var(c1) and var(c2) are single characters (which may be multibyte
+characters), is expanded to every character in the range from var(c1) to
+var(c2) in whatever character sequence is used internally.  For
+characters with code points below 128 this is US ASCII (this is the only
+case most users will need).  If any intervening character is not
+printable, appropriate quotation is used to render it printable.
+If the character sequence is reversed, the output is in reverse
+order, e.g. `tt({d..a})' is substituted as `tt(d c b a)'.
+
 If a brace expression matches none of the above forms, it is left
 unchanged, unless the option tt(BRACE_CCL) (an abbreviation for `brace
 character class') is set.
diff --git a/Src/glob.c b/Src/glob.c
index e0d0cf6..f10c0ef 100644
--- a/Src/glob.c
+++ b/Src/glob.c
@@ -1895,6 +1895,8 @@ hasbraces(char *str)
 	switch (*str++) {
 	case Inbrace:
 	    if (!lbr) {
+		if (bracechardots(str-1, NULL, NULL, NULL))
+		    return 1;
 		lbr = str - 1;
 		if (*str == '-')
 		    str++;
@@ -2027,6 +2029,55 @@ xpandredir(struct redir *fn, LinkList redirtab)
     return ret;
 }
 
+/*
+ * Check for a brace expansion of the form {<char>..<char>}.
+ * On input str must be positioned at an Inbrace, but the sequence
+ * of characters beyond that has not necessarily been checked.
+ * Return 1 if found else 0.
+ *
+ * The other parameters are optionaland if the function returns 1 are
+ * used to return:
+ * - *c1p: the first character in the expansion.
+ * - *c2p: the final character in the expansion.
+ * - *pnext: pointer to the character after the closing brace.
+ */
+
+/**/
+static int
+bracechardots(char *str, convchar_t *c1p, convchar_t *c2p, char **pnextp)
+{
+    convchar_t cstart, cend;
+    char *pnext = str + 1, *pconv, convstr[2];
+    if (itok(*pnext)) {
+	convstr[0] = ztokens[*pnext - Pound];
+	convstr[1] = '\0';
+	pconv = convstr;
+    } else
+	pconv = pnext;
+    MB_METACHARINIT();
+    pnext += MB_METACHARLENCONV(pconv, &cstart);
+    if (cstart == WEOF || pnext[0] != '.' || pnext[1] != '.')
+	return 0;
+    pnext += 2;
+    if (itok(*pnext)) {
+	convstr[0] = ztokens[*pnext - Pound];
+	convstr[1] = '\0';
+	pconv = convstr;
+    } else
+	pconv = pnext;
+    MB_METACHARINIT();
+    pnext += MB_METACHARLENCONV(pconv, &cend);
+    if (cend == WEOF || *pnext != Outbrace)
+	return 0;
+    if (c1p)
+	*c1p = cstart;
+    if (c2p)
+	*c2p = cend;
+    if (pnextp)
+	*pnextp = pnext+1;
+    return 1;
+}
+
 /* brace expansion */
 
 /**/
@@ -2060,10 +2111,63 @@ xpandbraces(LinkList list, LinkNode *np)
 	char *dots, *p, *dots2 = NULL;
 	LinkNode olast = last;
 	/* Get the first number of the range */
-	zlong rstart = zstrtol(str+1,&dots,10), rend = 0;
+	zlong rstart, rend;
 	int err = 0, rev = 0, rincr = 1;
-	int wid1 = (dots - str) - 1, wid2 = (str2 - dots) - 2, wid3 = 0;
-	int strp = str - str3;
+	int wid1, wid2, wid3, strp;
+	convchar_t cstart, cend;
+	char *pnext;
+
+	if (bracechardots(str, &cstart, &cend, &pnext)) {
+	    int lenalloc;
+	    /*
+	     * This is a character range.
+	     */
+	    if (cend < cstart) {
+		convchar_t ctmp = cend;
+		cend = cstart;
+		cstart = ctmp;
+		rev = 1;
+	    }
+	    uremnode(list, node);
+	    strp = str - str3;
+	    lenalloc = strlen(str3) + 1;
+	    for (; cend >= cstart; cend--) {
+#ifdef MULTIBYTE_SUPPORT
+		char *ncptr;
+		int nclen;
+		mb_metacharinit();
+		ncptr = wcs_nicechar(cend, NULL, NULL);
+		/*
+		 * Be paranoid about allowing enough space
+		 * for metafied multibyte characters.  This
+		 * saves us having to do bug-prone calculations.
+		 */
+		nclen = strlen(ncptr);
+		p = zhalloc(lenalloc + nclen);
+		memcpy(p, str3, strp);
+		memcpy(p + strp, ncptr, nclen);
+		strcpy(p + strp + nclen, str2 + 1);
+#else
+		p = zhalloc(lenalloc);
+		memcpy(p, str3, strp);
+		sprintf(p + strp, "%c", cend);
+		strcat(p + strp, str2 + 1);
+#endif
+		insertlinknode(list, last, p);
+		if (rev)	/* decreasing:  add in reverse order. */
+		    last = nextnode(last);
+	    }
+	    *np = nextnode(olast);
+	    return;
+	}
+
+	/* Get the first number of the range */
+	rstart = zstrtol(str+1,&dots,10);
+	rend = 0;
+	wid1 = (dots - str) - 1;
+	wid2 = (str2 - dots) - 2;
+	wid3 = 0;
+	strp = str - str3;
 
 	if (dots == str + 1 || *dots != '.' || dots[1] != '.')
 	    err++;
diff --git a/Test/D09brace.ztst b/Test/D09brace.ztst
index d0ec93c..3e667a8 100644
--- a/Test/D09brace.ztst
+++ b/Test/D09brace.ztst
@@ -97,3 +97,18 @@
 0:BRACE_CCL off
 >X{za-q521}Y
 
+  print -r hey{a..j}there
+0:{char..char} ranges, simple case
+>heyathere heybthere heycthere heydthere heyethere heyfthere heygthere heyhthere heyithere heyjthere
+
+  print -r gosh{1,{Z..a},2}cripes
+0:{char..char} ranges, ASCII ordering
+>gosh1cripes goshZcripes gosh[cripes gosh\cripes gosh]cripes gosh^cripes gosh_cripes gosh`cripes goshacripes gosh2cripes
+
+  print -r crumbs{y..p}ooh
+0:{char..char} ranges, reverse
+>crumbsyooh crumbsxooh crumbswooh crumbsvooh crumbsuooh crumbstooh crumbssooh crumbsrooh crumbsqooh crumbspooh
+
+  print -r left{[..]}right
+0:{char..char} ranges with tokenized characters
+>left[right left\right left]right

pws


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

end of thread, other threads:[~2014-01-08 12:23 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-01-07 21:49 RFE: Brace expansion with single characters Daniel Serodio
2014-01-07 23:11 ` Simon Ruderich
2014-01-08  9:22   ` Vincent Lefevre
2014-01-08  9:55   ` Jerry Rocteur
2014-01-08 11:25     ` Peter Stephenson
2014-01-08 12:13 ` Peter Stephenson

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).