Merge topic 'sort_list_natural_20563'
da99eca1e7
list: add NATURAL sorting on SORT sub-command
Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !4602
This commit is contained in:
commit
734238d64f
@ -308,6 +308,13 @@ The ``<compare>`` option should be one of:
|
||||
* ``STRING``: Sorts a list of strings alphabetically. This is the
|
||||
default behavior if the ``COMPARE`` option is not given.
|
||||
* ``FILE_BASENAME``: Sorts a list of pathnames of files by their basenames.
|
||||
* ``NATURAL``: Sorts a list of strings using natural order
|
||||
(see ``strverscmp(3)`` manual), i.e. such that contiguous digits
|
||||
are compared as whole numbers.
|
||||
For example: the following list `10.0 1.1 2.1 8.0 2.0 3.1`
|
||||
will be sorted as `1.1 2.0 2.1 3.1 8.0 10.0` if the ``NATURAL``
|
||||
comparison is selected where it will be sorted as
|
||||
`1.1 10.0 2.0 2.1 3.1 8.0` with the ``STRING`` comparison.
|
||||
|
||||
Use the ``CASE`` keyword to select a case sensitive or case insensitive
|
||||
sort mode. The ``<case>`` option should be one of:
|
||||
|
5
Help/release/dev/list_natural_sort.rst
Normal file
5
Help/release/dev/list_natural_sort.rst
Normal file
@ -0,0 +1,5 @@
|
||||
list_natural_sort
|
||||
-----------------
|
||||
|
||||
* The :command:`list` operation ``SORT`` gained the ``NATURAL`` sort
|
||||
option to sort using natural order (see ``strverscmp(3)`` manual).
|
@ -1051,6 +1051,7 @@ public:
|
||||
UNINITIALIZED,
|
||||
STRING,
|
||||
FILE_BASENAME,
|
||||
NATURAL,
|
||||
};
|
||||
enum class CaseSensitivity
|
||||
{
|
||||
@ -1074,10 +1075,25 @@ protected:
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
using ComparisonFunction =
|
||||
std::function<bool(const std::string&, const std::string&)>;
|
||||
ComparisonFunction GetComparisonFunction(Compare compare)
|
||||
{
|
||||
if (compare == Compare::NATURAL) {
|
||||
return std::function<bool(const std::string&, const std::string&)>(
|
||||
[](const std::string& x, const std::string& y) {
|
||||
return cmSystemTools::strverscmp(x, y) < 0;
|
||||
});
|
||||
}
|
||||
return std::function<bool(const std::string&, const std::string&)>(
|
||||
[](const std::string& x, const std::string& y) { return x < y; });
|
||||
}
|
||||
|
||||
public:
|
||||
cmStringSorter(Compare compare, CaseSensitivity caseSensitivity,
|
||||
Order desc = Order::ASCENDING)
|
||||
: filters{ GetCompareFilter(compare), GetCaseFilter(caseSensitivity) }
|
||||
, sortMethod(GetComparisonFunction(compare))
|
||||
, descending(desc == Order::DESCENDING)
|
||||
{
|
||||
}
|
||||
@ -1099,15 +1115,16 @@ public:
|
||||
std::string bf = ApplyFilter(b);
|
||||
bool result;
|
||||
if (descending) {
|
||||
result = bf < af;
|
||||
result = sortMethod(bf, af);
|
||||
} else {
|
||||
result = af < bf;
|
||||
result = sortMethod(af, bf);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected:
|
||||
StringFilter filters[2] = { nullptr, nullptr };
|
||||
ComparisonFunction sortMethod;
|
||||
bool descending;
|
||||
};
|
||||
|
||||
@ -1142,6 +1159,8 @@ bool HandleSortCommand(std::vector<std::string> const& args,
|
||||
sortCompare = cmStringSorter::Compare::STRING;
|
||||
} else if (argument == "FILE_BASENAME") {
|
||||
sortCompare = cmStringSorter::Compare::FILE_BASENAME;
|
||||
} else if (argument == "NATURAL") {
|
||||
sortCompare = cmStringSorter::Compare::NATURAL;
|
||||
} else {
|
||||
std::string error =
|
||||
cmStrCat(messageHint, "value \"", argument, "\" for option \"",
|
||||
|
@ -85,6 +85,9 @@ set(result ken bill andy brad)
|
||||
list(SORT result)
|
||||
TEST("SORT result" "andy;bill;brad;ken")
|
||||
|
||||
list(SORT result COMPARE NATURAL)
|
||||
TEST("SORT result COMPARE NATURAL" "andy;bill;brad;ken")
|
||||
|
||||
set(result andy bill brad ken)
|
||||
list(REVERSE result)
|
||||
TEST("REVERSE result" "ken;brad;bill;andy")
|
||||
@ -104,6 +107,26 @@ TEST("REVERSE empty result" "")
|
||||
list(SORT result)
|
||||
TEST("SORT empty result" "")
|
||||
|
||||
list(SORT result COMPARE NATURAL)
|
||||
TEST("SORT result COMPARE NATURAL" "")
|
||||
|
||||
set(result 1.1 10.0 11.0 12.0 12.1 2.0 2.1 3.0 3.1 3.2 8.0 9.0)
|
||||
|
||||
list(SORT result COMPARE NATURAL)
|
||||
TEST("SORT result COMPARE NATURAL" "1.1;2.0;2.1;3.0;3.1;3.2;8.0;9.0;10.0;11.0;12.0;12.1")
|
||||
|
||||
list(SORT result)
|
||||
TEST("SORT result" "1.1;10.0;11.0;12.0;12.1;2.0;2.1;3.0;3.1;3.2;8.0;9.0")
|
||||
|
||||
list(SORT result COMPARE NATURAL ORDER DESCENDING)
|
||||
TEST("SORT result COMPARE NATURAL ORDER DESCENDING" "12.1;12.0;11.0;10.0;9.0;8.0;3.2;3.1;3.0;2.1;2.0;1.1")
|
||||
|
||||
set(result b-1.1 a-10.0 c-2.0 d 1 00 0)
|
||||
|
||||
list(SORT result COMPARE NATURAL)
|
||||
TEST("SORT result COMPARE NATURAL" "00;0;1;a-10.0;b-1.1;c-2.0;d")
|
||||
|
||||
|
||||
# these trigger top-level condition
|
||||
foreach(cmd IN ITEMS Append Find Get Insert Length Reverse Remove_At Remove_Duplicates Remove_Item Sort)
|
||||
set(${cmd}-No-Arguments-RESULT 1)
|
||||
|
Loading…
Reference in New Issue
Block a user