Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
extended braces syntax, {1..32..-03}
- X-seq: zsh-workers 28474
- From: Mikael Magnusson <mikachu@xxxxxxxxx>
- To: zsh workers <zsh-workers@xxxxxxx>
- Subject: extended braces syntax, {1..32..-03}
- Date: Sun, 5 Dec 2010 16:41:20 +0100
- Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:received:received:date:message-id :subject:from:to:content-type; bh=+Of/FQ2f3zSJ1+R8is/mDfgA8qYfJwh9tY3aJGDDlZc=; b=DTUc2Ce0bKF6mLS3GXygulTFY8Pe31cQz+1nOR2y0o+niBaokEHbJcQ4PJEOwS//Sq A5g79DLeXnGNUyaEYNPFRqwEWvjYiJ+81BRkxXddyrWWgcyfF1CuKwlVJ8OKUpKqj8F6 6qejRqLo+/g3Ec26Na0zfEOfdoXihuFINnhZM=
- Domainkey-signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:date:message-id:subject:from:to:content-type; b=Yml89Ij/XyNkfP/Qz0RuEfKTlofS/c/LF4BwU8a+64+D+7WO0btE0iY4yjNnjc9USq v5XKCC/ge9ESEJ2S3dLMOEpJ8ofU1+LFlasyEayNOOilheMyoYLK+0lWvEKPRTki0TaI KJvz7QYPG4VQws/8j2xFeLeWRmmXfGd73Ay4k=
- 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
This patch adds the syntax {start..end..step} to brace expansion. It
also allows negative numbers to be used (this was allowed when
braceccl was set before, which worked inconsistently). It also fixes
up zero-padding with negative numbers. You can specify zeropadding in
the step, as well as a negative step. Using a negative step rather
than reversing the order makes a difference as shown here:
% echo {1..32..4}
1 5 9 13 17 21 25 29
% echo {1..32..-4}
29 25 21 17 13 9 5 1
% echo {32..1..4}
32 28 24 20 16 12 8 4
% echo {32..1..-4}
4 8 12 16 20 24 28 32
The basic syntax is stolen/borrowed from bash, but bash does not allow
negative steps.
Missing still is documentation, but I've had this lying around since
august so I figured I'd post it and see if anyone wants to change
anything first.
Zero-padding works like this:
% echo {01..4}
01 02 03 04
% echo {01..-4}
01 00 -1 -2 -3 -4
% echo {1..-04}
001 000 -01 -02 -03 -04
% echo {1..-4..01}
01 00 -1 -2 -3 -4
% echo {1..-4..-02}
-03 -01 001
Originally i had the same number of zeroes regardless of the minus
sign, but bash does it this way, so I figured I'd be consistent with
that.
The code is admittedly somewhat cryptic in places.
Here's a link to the patch,
http://mika.l3ib.org/patches/zsh-extended-braces.patch
And here's the patch
From 6fa4a778632320f234f0b9c1f477f5cd3a66a5ff Mon Sep 17 00:00:00 2001
From: Mikael Magnusson <mikachu@xxxxxxxxx>
Date: Wed, 7 Jul 2010 00:12:25 +0200
Subject: [PATCH] Add {1..10..2} syntax, allow negative numbers without
braceccl set
---
Src/glob.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++----------
1 files changed, 59 insertions(+), 12 deletions(-)
diff --git a/Src/glob.c b/Src/glob.c
index c552e6c..5f68135 100644
--- a/Src/glob.c
+++ b/Src/glob.c
@@ -1924,14 +1924,29 @@ hasbraces(char *str)
case Inbrace:
if (!lbr) {
lbr = str - 1;
+ if (*str == '-')
+ str++;
while (idigit(*str))
str++;
if (*str == '.' && str[1] == '.') {
- str++;
- while (idigit(*++str));
+ str++; str++;
+ if (*str == '-')
+ str++;
+ while (idigit(*str))
+ str++;
if (*str == Outbrace &&
(idigit(lbr[1]) || idigit(str[-1])))
return 1;
+ else if (*str == '.' && str[1] == '.') {
+ str++; str++;
+ if (*str == '-')
+ str++;
+ while (idigit(*str))
+ str++;
+ if (*str == Outbrace &&
+ (idigit(lbr[1]) || idigit(str[-1])))
+ return 1;
+ }
}
} else {
char *s = --str;
@@ -2061,18 +2076,20 @@ xpandbraces(LinkList list, LinkNode *np)
} else if (bc == 1) {
if (*str2 == Comma)
++comma; /* we have {foo,bar} */
- else if (*str2 == '.' && str2[1] == '.')
+ else if (*str2 == '.' && str2[1] == '.') {
dotdot++; /* we have {num1..num2} */
+ ++str2;
+ }
}
DPUTS(bc, "BUG: unmatched brace in xpandbraces()");
if (!comma && dotdot) {
/* Expand range like 0..10 numerically: comma or recursive
brace expansion take precedence. */
- char *dots, *p;
+ char *dots, *p, *dots2 = NULL;
LinkNode olast = last;
/* Get the first number of the range */
- int rstart = zstrtol(str+1,&dots,10), rend = 0, err = 0, rev = 0;
- int wid1 = (dots - str) - 1, wid2 = (str2 - dots) - 2;
+ int rstart = zstrtol(str+1,&dots,10), rend = 0, err = 0, rev = 0, rincr = 1;
+ int wid1 = (dots - str) - 1, wid2 = (str2 - dots) - 2, wid3 = 0;
int strp = str - str3;
if (dots == str + 1 || *dots != '.' || dots[1] != '.')
@@ -2080,23 +2097,53 @@ xpandbraces(LinkList list, LinkNode *np)
else {
/* Get the last number of the range */
rend = zstrtol(dots+2,&p,10);
- if (p == dots+2 || p != str2)
+ if (p == dots+2)
err++;
+ /* check for {num1..num2..incr} */
+ if (p != str2) {
+ wid2 = (p - dots) - 2;
+ dots2 = p;
+ if (dotdot == 2 && *p == '.' && p[1] == '.') {
+ rincr = zstrtol(p+2, &p, 10);
+ wid3 = p - dots2 - 2;
+ if (p != str2 || !rincr)
+ err++;
+ } else
+ err++;
+ }
}
if (!err) {
/* If either no. begins with a zero, pad the output with *
- * zeroes. Otherwise, choose a min width to suppress them. */
- int minw = (str[1] == '0') ? wid1 : (dots[2] == '0' ) ? wid2 :
- (wid2 > wid1) ? wid1 : wid2;
+ * zeroes. Otherwise, set min width to 0 to suppress them.
+ * str+1 is the first number in the range, dots+2 the last,
+ * and dots2+2 is the increment if that's given. */
+ /* TODO: sorry about this */
+ int minw = (str[1] == '0' || (str[1] == '-' && str[2] == '0'))
+ ? wid1
+ : (dots[2] == '0' || (dots[2] == '-' && dots[3] == '0'))
+ ? wid2
+ : (dots2 && (dots2[2] == '0' ||
+ (dots2[2] == '-' && dots2[3] == '0')))
+ ? wid3
+ : 0;
+ if (rincr < 0) {
+ /* Handle negative increment */
+ rincr = -rincr;
+ rev = !rev;
+ }
if (rstart > rend) {
/* Handle decreasing ranges correctly. */
int rt = rend;
rend = rstart;
rstart = rt;
- rev = 1;
+ rev = !rev;
+ } else if (rincr > 1) {
+ /* when incr > 1, range is aligned to the highest number of str1,
+ * compensate for this so that it is aligned to the first number */
+ rend -= (rend - rstart) % rincr;
}
uremnode(list, node);
- for (; rend >= rstart; rend--) {
+ for (; rend >= rstart; rend -= rincr) {
/* Node added in at end, so do highest first */
p = dupstring(str3);
sprintf(p + strp, "%0*d", minw, rend);
--
1.7.3
--
Mikael Magnusson
Messages sorted by:
Reverse Date,
Date,
Thread,
Author