diff options
author | Peter Stephenson <p.w.stephenson@ntlworld.com> | 2020-07-03 21:05:46 +0100 |
---|---|---|
committer | Peter Stephenson <p.w.stephenson@ntlworld.com> | 2020-07-03 21:05:46 +0100 |
commit | 4e0058afc5ea040a788d70edbfa43593295816d1 (patch) | |
tree | 2ddff880e422a30b17333a329df25d24a902e975 | |
parent | 19390a1ba8dc983b0a1379058e90cd51ce156815 (diff) | |
download | zsh-4e0058afc5ea040a788d70edbfa43593295816d1.tar.gz zsh-4e0058afc5ea040a788d70edbfa43593295816d1.tar.xz zsh-4e0058afc5ea040a788d70edbfa43593295816d1.zip |
users/24971: ${(-)var} sorts on signed integers
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | Doc/Zsh/expn.yo | 12 | ||||
-rw-r--r-- | Src/sort.c | 25 | ||||
-rw-r--r-- | Src/subst.c | 4 | ||||
-rw-r--r-- | Src/zsh.h | 7 | ||||
-rw-r--r-- | Test/D04parameter.ztst | 7 |
6 files changed, 49 insertions, 12 deletions
diff --git a/ChangeLog b/ChangeLog index b2d94f38c..5161ef6d7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2020-07-03 Peter Stephenson <p.w.stephenson@ntlworld.com> + + * users/24971: Doc/Zsh/expn.yo, Src/sort.c, Src/subst.c, + Src/zsh.h, Test/D04parameter.ztst: Add parameter flag (-) + to allow signed numeric sorting. + 2020-06-28 zsugabubus <zsugabubus> * 46097: Completion/Unix/Command/_rm: Fix "assignment to invalid diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index a637b78a1..79b6037df 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -1097,17 +1097,23 @@ 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(-))( +As tt(n), but a leading minus sign indicates a negative decimal +integer. A `tt(-)' 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 renders it case-insensitive). Sorting in ascending order is the default for other forms of sorting, so this is ignored if combined -with `tt(a)', `tt(i)' or `tt(n)'. +with `tt(a)', `tt(i)', `tt(n)' or `tt(DASH())'. ) item(tt(O))( Sort the resulting words in descending order; `tt(O)' without `tt(a)', -`tt(i)' or `tt(n)' sorts in reverse lexical order. May be combined -with `tt(a)', `tt(i)' or `tt(n)' to reverse the order of sorting. +`tt(i)', `tt(n)' or `tt(DASH())' sorts in reverse lexical order. May be +combined with `tt(a)', `tt(i)', `tt(n)' or tt(DASH()) to reverse the +order of sorting. ) item(tt(P))( This forces the value of the parameter var(name) to be interpreted as a 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 ed3f4a82b..b98ddaf02 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 ed123f2b9..c48be4ffd 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -2997,17 +2997,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 |