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)