From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 26314 invoked by alias); 5 Dec 2010 16:10:03 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: X-Seq: 28474 Received: (qmail 9714 invoked from network); 5 Dec 2010 16:09:50 -0000 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-2.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.1 Received-SPF: pass (ns1.primenet.com.au: SPF record at _spf.google.com designates 209.85.216.43 as permitted sender) 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= MIME-Version: 1.0 Date: Sun, 5 Dec 2010 16:41:20 +0100 Message-ID: Subject: extended braces syntax, {1..32..-03} From: Mikael Magnusson To: zsh workers Content-Type: text/plain; charset=UTF-8 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 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