From 61bf9bd3c496c8b891597ccaaf9ef9d73b3e3d3c Mon Sep 17 00:00:00 2001
From: Scott Sumner <30118311+sasumner@users.noreply.github.com>
Date: Fri, 18 Sep 2020 18:04:14 -0400
Subject: [PATCH] Add case insensitive lines sorting
Close #4479, close #8869
---
PowerEditor/installer/nativeLang/english.xml | 2 +
PowerEditor/src/MISC/Common/Sorters.h | 47 +++++++++++++++++++-
PowerEditor/src/Notepad_plus.rc | 2 +
PowerEditor/src/NppCommands.cpp | 11 ++++-
PowerEditor/src/Parameters.cpp | 2 +
PowerEditor/src/menuCmdID.h | 2 +
6 files changed, 63 insertions(+), 3 deletions(-)
diff --git a/PowerEditor/installer/nativeLang/english.xml b/PowerEditor/installer/nativeLang/english.xml
index 7390fcc9b..ba2bb101c 100644
--- a/PowerEditor/installer/nativeLang/english.xml
+++ b/PowerEditor/installer/nativeLang/english.xml
@@ -115,6 +115,8 @@
+
+
diff --git a/PowerEditor/src/MISC/Common/Sorters.h b/PowerEditor/src/MISC/Common/Sorters.h
index cc4cff636..afc870e6a 100644
--- a/PowerEditor/src/MISC/Common/Sorters.h
+++ b/PowerEditor/src/MISC/Common/Sorters.h
@@ -94,7 +94,7 @@ public:
std::vector sort(std::vector lines) override
{
- // Note that both branches here are equivalent in the sense that they give always give the same answer.
+ // Note that both branches here are equivalent in the sense that they always give the same answer.
// However, if we are *not* sorting specific columns, then we get a 40% speed improvement by not calling
// getSortKey() so many times.
if (isSortingSpecificColumns())
@@ -130,6 +130,49 @@ public:
}
};
+// Implementation of lexicographic sorting of lines, ignoring character casing
+class LexicographicCaseInsensitiveSorter : public ISorter
+{
+public:
+ LexicographicCaseInsensitiveSorter(bool isDescending, size_t fromColumn, size_t toColumn) : ISorter(isDescending, fromColumn, toColumn) { };
+
+ std::vector sort(std::vector lines) override
+ {
+ // Note that both branches here are equivalent in the sense that they always give the same answer.
+ // However, if we are *not* sorting specific columns, then we get a 40% speed improvement by not calling
+ // getSortKey() so many times.
+ if (isSortingSpecificColumns())
+ {
+ std::sort(lines.begin(), lines.end(), [this](generic_string a, generic_string b)
+ {
+ if (isDescending())
+ {
+ return OrdinalIgnoreCaseCompareStrings(getSortKey(a).c_str(), getSortKey(b).c_str()) > 0;
+ }
+ else
+ {
+ return OrdinalIgnoreCaseCompareStrings(getSortKey(a).c_str(), getSortKey(b).c_str()) < 0;
+ }
+ });
+ }
+ else
+ {
+ std::sort(lines.begin(), lines.end(), [this](generic_string a, generic_string b)
+ {
+ if (isDescending())
+ {
+ return OrdinalIgnoreCaseCompareStrings(a.c_str(), b.c_str()) > 0;
+ }
+ else
+ {
+ return OrdinalIgnoreCaseCompareStrings(a.c_str(), b.c_str()) < 0;
+ }
+ });
+ }
+ return lines;
+ }
+};
+
// Treat consecutive numerals as one number
// Otherwise it is a lexicographic sort
class NaturalSorter : public ISorter
@@ -139,7 +182,7 @@ public:
std::vector sort(std::vector lines) override
{
- // Note that both branches here are equivalent in the sense that they give always give the same answer.
+ // Note that both branches here are equivalent in the sense that they always give the same answer.
// However, if we are *not* sorting specific columns, then we get a 40% speed improvement by not calling
// getSortKey() so many times.
if (isSortingSpecificColumns())
diff --git a/PowerEditor/src/Notepad_plus.rc b/PowerEditor/src/Notepad_plus.rc
index 41d332faa..cfd643269 100644
--- a/PowerEditor/src/Notepad_plus.rc
+++ b/PowerEditor/src/Notepad_plus.rc
@@ -316,11 +316,13 @@ BEGIN
MENUITEM "Insert Blank Line Below Current", IDM_EDIT_BLANKLINEBELOWCURRENT
MENUITEM SEPARATOR
MENUITEM "Sort Lines Lexicographically Ascending", IDM_EDIT_SORTLINES_LEXICOGRAPHIC_ASCENDING
+ MENUITEM "Sort Lines Lex. Ascending Ignoring Case", IDM_EDIT_SORTLINES_LEXICO_CASE_INSENS_ASCENDING
MENUITEM "Sort Lines As Integers Ascending", IDM_EDIT_SORTLINES_INTEGER_ASCENDING
MENUITEM "Sort Lines As Decimals (Comma) Ascending", IDM_EDIT_SORTLINES_DECIMALCOMMA_ASCENDING
MENUITEM "Sort Lines As Decimals (Dot) Ascending", IDM_EDIT_SORTLINES_DECIMALDOT_ASCENDING
MENUITEM SEPARATOR
MENUITEM "Sort Lines Lexicographically Descending", IDM_EDIT_SORTLINES_LEXICOGRAPHIC_DESCENDING
+ MENUITEM "Sort Lines Lex. Descending Ignoring Case", IDM_EDIT_SORTLINES_LEXICO_CASE_INSENS_DESCENDING
MENUITEM "Sort Lines As Integers Descending", IDM_EDIT_SORTLINES_INTEGER_DESCENDING
MENUITEM "Sort Lines As Decimals (Comma) Descending", IDM_EDIT_SORTLINES_DECIMALCOMMA_DESCENDING
MENUITEM "Sort Lines As Decimals (Dot) Descending", IDM_EDIT_SORTLINES_DECIMALDOT_DESCENDING
diff --git a/PowerEditor/src/NppCommands.cpp b/PowerEditor/src/NppCommands.cpp
index 3bc6b800d..8ddff2cd4 100644
--- a/PowerEditor/src/NppCommands.cpp
+++ b/PowerEditor/src/NppCommands.cpp
@@ -565,6 +565,8 @@ void Notepad_plus::command(int id)
case IDM_EDIT_SORTLINES_LEXICOGRAPHIC_ASCENDING:
case IDM_EDIT_SORTLINES_LEXICOGRAPHIC_DESCENDING:
+ case IDM_EDIT_SORTLINES_LEXICO_CASE_INSENS_ASCENDING:
+ case IDM_EDIT_SORTLINES_LEXICO_CASE_INSENS_DESCENDING:
case IDM_EDIT_SORTLINES_INTEGER_ASCENDING:
case IDM_EDIT_SORTLINES_INTEGER_DESCENDING:
case IDM_EDIT_SORTLINES_DECIMALCOMMA_ASCENDING:
@@ -625,7 +627,8 @@ void Notepad_plus::command(int id)
bool isDescending = id == IDM_EDIT_SORTLINES_LEXICOGRAPHIC_DESCENDING ||
id == IDM_EDIT_SORTLINES_INTEGER_DESCENDING ||
id == IDM_EDIT_SORTLINES_DECIMALCOMMA_DESCENDING ||
- id == IDM_EDIT_SORTLINES_DECIMALDOT_DESCENDING;
+ id == IDM_EDIT_SORTLINES_DECIMALDOT_DESCENDING ||
+ id == IDM_EDIT_SORTLINES_LEXICO_CASE_INSENS_DESCENDING;
_pEditView->execute(SCI_BEGINUNDOACTION);
std::unique_ptr pSorter;
@@ -633,6 +636,10 @@ void Notepad_plus::command(int id)
{
pSorter = std::unique_ptr(new LexicographicSorter(isDescending, fromColumn, toColumn));
}
+ else if (id == IDM_EDIT_SORTLINES_LEXICO_CASE_INSENS_DESCENDING || id == IDM_EDIT_SORTLINES_LEXICO_CASE_INSENS_ASCENDING)
+ {
+ pSorter = std::unique_ptr(new LexicographicCaseInsensitiveSorter(isDescending, fromColumn, toColumn));
+ }
else if (id == IDM_EDIT_SORTLINES_INTEGER_DESCENDING || id == IDM_EDIT_SORTLINES_INTEGER_ASCENDING)
{
pSorter = std::unique_ptr(new NaturalSorter(isDescending, fromColumn, toColumn));
@@ -3532,6 +3539,8 @@ void Notepad_plus::command(int id)
case IDM_EDIT_BEGINENDSELECT:
case IDM_EDIT_SORTLINES_LEXICOGRAPHIC_ASCENDING:
case IDM_EDIT_SORTLINES_LEXICOGRAPHIC_DESCENDING:
+ case IDM_EDIT_SORTLINES_LEXICO_CASE_INSENS_ASCENDING:
+ case IDM_EDIT_SORTLINES_LEXICO_CASE_INSENS_DESCENDING:
case IDM_EDIT_SORTLINES_INTEGER_ASCENDING:
case IDM_EDIT_SORTLINES_INTEGER_DESCENDING:
case IDM_EDIT_SORTLINES_DECIMALCOMMA_ASCENDING:
diff --git a/PowerEditor/src/Parameters.cpp b/PowerEditor/src/Parameters.cpp
index 5c266f2e1..3ab4547e4 100644
--- a/PowerEditor/src/Parameters.cpp
+++ b/PowerEditor/src/Parameters.cpp
@@ -138,6 +138,8 @@ static const WinMenuKeyDefinition winKeyDefs[] =
{ VK_RETURN, IDM_EDIT_BLANKLINEBELOWCURRENT, true, true, true, nullptr },
{ VK_NULL, IDM_EDIT_SORTLINES_LEXICOGRAPHIC_ASCENDING, false, false, false, nullptr },
{ VK_NULL, IDM_EDIT_SORTLINES_LEXICOGRAPHIC_DESCENDING, false, false, false, nullptr },
+ { VK_NULL, IDM_EDIT_SORTLINES_LEXICO_CASE_INSENS_ASCENDING, false, false, false, nullptr },
+ { VK_NULL, IDM_EDIT_SORTLINES_LEXICO_CASE_INSENS_DESCENDING, false, false, false, nullptr },
{ VK_NULL, IDM_EDIT_SORTLINES_INTEGER_ASCENDING, false, false, false, nullptr },
{ VK_NULL, IDM_EDIT_SORTLINES_INTEGER_DESCENDING, false, false, false, nullptr },
{ VK_NULL, IDM_EDIT_SORTLINES_DECIMALCOMMA_ASCENDING, false, false, false, nullptr },
diff --git a/PowerEditor/src/menuCmdID.h b/PowerEditor/src/menuCmdID.h
index 0c741027d..2efc2245e 100644
--- a/PowerEditor/src/menuCmdID.h
+++ b/PowerEditor/src/menuCmdID.h
@@ -132,6 +132,8 @@
#define IDM_EDIT_SORTLINES_DECIMALDOT_ASCENDING (IDM_EDIT + 65)
#define IDM_EDIT_SORTLINES_DECIMALDOT_DESCENDING (IDM_EDIT + 66)
#define IDM_EDIT_SORTLINES_RANDOMLY (IDM_EDIT + 78)
+ #define IDM_EDIT_SORTLINES_LEXICO_CASE_INSENS_ASCENDING (IDM_EDIT + 80)
+ #define IDM_EDIT_SORTLINES_LEXICO_CASE_INSENS_DESCENDING (IDM_EDIT + 81)
#define IDM_EDIT_OPENASFILE (IDM_EDIT + 73)
#define IDM_EDIT_OPENINFOLDER (IDM_EDIT + 74)