From 4fec045073a9964996f41e13454334290e1b6ab0 Mon Sep 17 00:00:00 2001 From: Fabian Homborg Date: Thu, 7 Apr 2022 16:09:28 +0200 Subject: [PATCH] sort: Use a stable sort This allows e.g. sorting first by dirname and then by basename. --- src/builtins/path.cpp | 16 ++++++++++++---- tests/checks/path.fish | 14 ++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/builtins/path.cpp b/src/builtins/path.cpp index af734a4f6..59b91fcfd 100644 --- a/src/builtins/path.cpp +++ b/src/builtins/path.cpp @@ -736,16 +736,24 @@ static int path_sort(parser_t &parser, io_streams_t &streams, int argc, const wc funced[arg] = func(arg); } - std::sort(list.begin(), list.end(), + // We use a stable sort here, and also explicit < and >, + // to avoid changing the order so you can chain calls. + std::stable_sort(list.begin(), list.end(), [&](const wcstring &a, const wcstring &b) { - return (wcsfilecmp_glob(funced[a].c_str(), funced[b].c_str()) < 0) != opts.invert; + if (!opts.invert) + return (wcsfilecmp_glob(funced[a].c_str(), funced[b].c_str()) < 0); + else + return (wcsfilecmp_glob(funced[a].c_str(), funced[b].c_str()) > 0); }); } else { // Without --what, we just sort by the entire path, // so we have no need to transform and such. - std::sort(list.begin(), list.end(), + std::stable_sort(list.begin(), list.end(), [&](const wcstring &a, const wcstring &b) { - return (wcsfilecmp_glob(a.c_str(), b.c_str()) < 0) != opts.invert; + if (!opts.invert) + return (wcsfilecmp_glob(a.c_str(), b.c_str()) < 0); + else + return (wcsfilecmp_glob(a.c_str(), b.c_str()) > 0); }); } diff --git a/tests/checks/path.fish b/tests/checks/path.fish index 426625fcc..7ba7f126e 100644 --- a/tests/checks/path.fish +++ b/tests/checks/path.fish @@ -141,3 +141,17 @@ string replace -r "^"(pwd -P | string escape --style=regex)'/' "" -- $path path resolve /banana//terracota/terracota/booooo/../pie # CHECK: /banana/terracota/terracota/pie + +path sort --what=basename {def,abc}/{456,123,789,abc,def,0} | path sort --what=dirname -v +# CHECK: def/0 +# CHECK: def/123 +# CHECK: def/456 +# CHECK: def/789 +# CHECK: def/abc +# CHECK: def/def +# CHECK: abc/0 +# CHECK: abc/123 +# CHECK: abc/456 +# CHECK: abc/789 +# CHECK: abc/abc +# CHECK: abc/def