From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=MAILING_LIST_MULTI, RCVD_IN_DNSWL_NONE autolearn=ham autolearn_force=no version=3.4.4 Received: (qmail 25860 invoked from network); 1 Jul 2020 19:43:34 -0000 Received: from ns1.primenet.com.au (HELO primenet.com.au) (203.24.36.2) by inbox.vuxu.org with ESMTPUTF8; 1 Jul 2020 19:43:34 -0000 Received: (qmail 772 invoked by alias); 1 Jul 2020 19:43:26 -0000 Mailing-List: contact zsh-users-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Users List List-Post: List-Help: List-Unsubscribe: Sender: zsh-users@zsh.org X-Seq: 24971 Received: (qmail 22820 invoked by uid 1010); 1 Jul 2020 19:43:26 -0000 X-Qmail-Scanner-Diagnostics: from know-smtprelay-omc-7.server.virginmedia.net by f.primenet.com.au (envelope-from , uid 7791) with qmail-scanner-2.11 (clamdscan: 0.102.3/25857. spamassassin: 3.4.4. Clear:RC:0(80.0.253.71):SA:0(-2.0/5.0):. Processed in 3.190601 secs); 01 Jul 2020 19:43:26 -0000 X-Envelope-From: p.w.stephenson@ntlworld.com X-Qmail-Scanner-Mime-Attachments: | X-Qmail-Scanner-Zip-Files: | Received-SPF: pass (ns1.primenet.com.au: SPF record at _smtprelay.virginmedia.com designates 80.0.253.71 as permitted sender) X-Originating-IP: [86.16.88.158] X-Authenticated-User: p.w.stephenson@ntlworld.com X-Spam: 0 X-Authority: v=2.3 cv=Is0wjo3g c=1 sm=1 tr=0 a=MiHCjVqLJ44lE3bxSlffFQ==:117 a=MiHCjVqLJ44lE3bxSlffFQ==:17 a=IkcTkHD0fZMA:10 a=j00lp7otDFw0VhKtvcUA:9 a=QEXdDO2ut3YA:10 Message-ID: <3580763ca2a81e24786f92071be073833b820b83.camel@ntlworld.com> Subject: Re: How to impose a numeric sort on negative numbers? From: Peter Stephenson To: zsh-users@zsh.org Date: Wed, 01 Jul 2020 20:42:43 +0100 In-Reply-To: References: Content-Type: text/plain; charset="UTF-8" X-Mailer: Evolution 3.28.5-0ubuntu0.18.04.2 Mime-Version: 1.0 Content-Transfer-Encoding: 7bit X-CMAE-Envelope: MS4wfBWZcRK2YOV+09nXJvLrHQkJ5GLkFtr0WOh5i2RJqkeToikibNzP+s0go6pvzhyuTtyOvyh+6l7oAYOe4YZIpCmoL4vA8SMCCWzdtriM8yyxI4wjsw/6 oUOvKiT9cMblstG12WhRNF+92hTqWBCeR2JNt01ael2gp1bB59vjsdsO On Wed, 2020-07-01 at 20:02 +0200, Mikael Magnusson wrote: > Works fine here, > % arr=( -1A -2b -3B 0 1A 2C 3B ) > % print -rl ${(on)arr} > -1A > -2b > -3B > 0 > 1A > 2C > 3B If you look a bit more closely I think you'll see there's a problem even there... We could do something like the following. Feel free to suggest a more comprehensive test. pws diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index 69cb0b08a..8db97ab5d 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -1097,6 +1097,11 @@ are sorted before those with fewer or none. Hence the array `tt(foo1 foo02 foo2 foo3 foo20 foo23)' is sorted into the order shown. May be combined with `tt(i)' or `tt(O)'. ) +item(tt(DASH()))( +As tt(n), but a leading minus sign indicates a negative decimal +integer. A solo `tt(DASH())' not followed by an integer does +not trigger numeric sorting. +) item(tt(o))( Sort the resulting words in ascending order; if this appears on its own the sorting is lexical and case-sensitive (unless the locale diff --git a/Src/sort.c b/Src/sort.c index 8faf9349c..26949ad9c 100644 --- a/Src/sort.c +++ b/Src/sort.c @@ -135,12 +135,23 @@ eltpcmp(const void *a, const void *b) #endif if (sortnumeric) { + int mul = 0; for (; *as == *bs && *as; as++, bs++); #ifndef HAVE_STRCOLL cmp = (int)STOUC(*as) - (int)STOUC(*bs); #endif - if (idigit(*as) || idigit(*bs)) { + if (sortnumeric < 0) { + if (*as == '-' && idigit(as[1]) && idigit(*bs)) { + cmp = -1; + mul = 1; + } else if (*bs == '-' && idigit(bs[1]) && idigit(*as)) { + cmp = 1; + mul = 1; + } + } + if (!mul && (idigit(*as) || idigit(*bs))) { for (; as > ao && idigit(as[-1]); as--, bs--); + mul = (sortnumeric < 0 && as > ao && as[-1] == '-') ? -1 : 1; if (idigit(*as) && idigit(*bs)) { while (*as == '0') as++; @@ -148,13 +159,13 @@ eltpcmp(const void *a, const void *b) bs++; for (; idigit(*as) && *as == *bs; as++, bs++); if (idigit(*as) || idigit(*bs)) { - cmp = (int)STOUC(*as) - (int)STOUC(*bs); + cmp = mul * ((int)STOUC(*as) - (int)STOUC(*bs)); while (idigit(*as) && idigit(*bs)) as++, bs++; if (idigit(*as) && !idigit(*bs)) - return sortdir; + return mul * sortdir; if (idigit(*bs) && !idigit(*as)) - return -sortdir; + return -mul * sortdir; } } } @@ -195,7 +206,8 @@ zstrcmp(const char *as, const char *bs, int sortflags) sortdir = 1; sortnobslash = (sortflags & SORTIT_IGNORING_BACKSLASHES) ? 1 : 0; - sortnumeric = (sortflags & SORTIT_NUMERICALLY) ? 1 : 0; + sortnumeric = (sortflags & SORTIT_NUMERICALLY_SIGNED) ? -1 : + (sortflags & SORTIT_NUMERICALLY) ? 1 : 0; ret = eltpcmp(&aeptr, &beptr); @@ -389,7 +401,8 @@ strmetasort(char **array, int sortwhat, int *unmetalenp) oldsortnumeric = sortnumeric; sortdir = (sortwhat & SORTIT_BACKWARDS) ? -1 : 1; - sortnumeric = (sortwhat & SORTIT_NUMERICALLY) ? 1 : 0; + sortnumeric = (sortwhat & SORTIT_NUMERICALLY_SIGNED) ? -1 : + (sortwhat & SORTIT_NUMERICALLY) ? 1 : 0; qsort(sortptrarr, nsort, sizeof(SortElt), eltpcmp); diff --git a/Src/subst.c b/Src/subst.c index 90b5fc121..d7ede9cb1 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -1979,6 +1979,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags, case 'n': sortit |= SORTIT_NUMERICALLY; break; + case '-': + case Dash: + sortit |= SORTIT_NUMERICALLY_SIGNED; + break; case 'a': sortit |= SORTIT_SOMEHOW; indord = 1; diff --git a/Src/zsh.h b/Src/zsh.h index 1f2d774a1..8c156bf77 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -2996,17 +2996,18 @@ enum { SORTIT_ANYOLDHOW = 0, /* Defaults */ SORTIT_IGNORING_CASE = 1, SORTIT_NUMERICALLY = 2, - SORTIT_BACKWARDS = 4, + SORTIT_NUMERICALLY_SIGNED = 4, + SORTIT_BACKWARDS = 8, /* * Ignore backslashes that quote another character---which may * be another backslash; the second backslash is active. */ - SORTIT_IGNORING_BACKSLASHES = 8, + SORTIT_IGNORING_BACKSLASHES = 16, /* * Ignored by strmetasort(); used by paramsubst() to indicate * there is some sorting to do. */ - SORTIT_SOMEHOW = 16, + SORTIT_SOMEHOW = 32, }; /* diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst index e51c955ee..ac99ff0e3 100644 --- a/Test/D04parameter.ztst +++ b/Test/D04parameter.ztst @@ -1398,6 +1398,13 @@ >a6 a17 a117 b6 b17 b117 >b117 b17 b6 a117 a17 a6 + foo=(a-6 a117 a-17 a-34 b6 b-117 b17 b-2) + print ${(-)foo} + print ${(O-)foo} +0:Numeric sorting of signed integers +>a-34 a-17 a-6 a117 b-117 b-2 b6 b17 +>b17 b6 b-2 b-117 a117 a-6 a-17 a-34 + x=sprodj x[-10]=scrumf print $x