From 7c3376ae6bbdd2ab7b2079a8ab61072a777ef219 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20J=C3=B6nsson?= Date: Thu, 21 May 2015 15:53:48 +0200 Subject: [PATCH] Use a rectangular selection as sort key. --- PowerEditor/src/MISC/Common/Sorters.h | 77 +++++++++++++++++++------- PowerEditor/src/NppCommands.cpp | 78 +++++++++++++++++---------- 2 files changed, 108 insertions(+), 47 deletions(-) diff --git a/PowerEditor/src/MISC/Common/Sorters.h b/PowerEditor/src/MISC/Common/Sorters.h index 68e0393f..82290438 100644 --- a/PowerEditor/src/MISC/Common/Sorters.h +++ b/PowerEditor/src/MISC/Common/Sorters.h @@ -34,6 +34,7 @@ class ISorter { private: bool _isDescending; + size_t _fromColumn, _toColumn; protected: bool isDescending() const @@ -41,8 +42,28 @@ protected: return _isDescending; } + generic_string getSortKey(const generic_string& input) + { + if (isSortingSpecificColumns()) + { + return input.substr(_fromColumn, 1 + _toColumn - _fromColumn); + } + else + { + return input; + } + } + + bool isSortingSpecificColumns() + { + return _fromColumn != 0 && _toColumn != 0; + } + public: - ISorter(bool isDescending) : _isDescending(isDescending) { }; + ISorter(bool isDescending, size_t fromColumn, size_t toColumn) : _isDescending(isDescending), _fromColumn(fromColumn), _toColumn(toColumn) + { + assert(_fromColumn <= _toColumn); + }; virtual ~ISorter() { }; virtual std::vector sort(std::vector lines) = 0; }; @@ -51,22 +72,42 @@ public: class LexicographicSorter : public ISorter { public: - LexicographicSorter(bool isDescending) : ISorter(isDescending) { }; + LexicographicSorter(bool isDescending, size_t fromColumn, size_t toColumn) : ISorter(isDescending, fromColumn, toColumn) { }; std::vector sort(std::vector lines) override { - const bool descending = isDescending(); - std::sort(lines.begin(), lines.end(), [descending](generic_string a, generic_string b) + // Note that both branches here are equivalent in the sense that they give 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()) { - if (descending) + std::sort(lines.begin(), lines.end(), [this](generic_string a, generic_string b) { - return a.compare(b) > 0; - } - else + if (isDescending()) + { + return getSortKey(a).compare(getSortKey(b)) > 0; + + } + else + { + return getSortKey(a).compare(getSortKey(b)) < 0; + } + }); + } + else + { + std::sort(lines.begin(), lines.end(), [this](generic_string a, generic_string b) { - return a.compare(b) < 0; - } - }); + if (isDescending()) + { + return a.compare(b) > 0; + } + else + { + return a.compare(b) < 0; + } + }); + } return lines; } }; @@ -77,7 +118,7 @@ template class NumericSorter : public ISorter { public: - NumericSorter(bool isDescending) : ISorter(isDescending) + NumericSorter(bool isDescending, size_t fromColumn, size_t toColumn) : ISorter(isDescending, fromColumn, toColumn) { _usLocale = ::_wcreate_locale(LC_NUMERIC, TEXT("en-US")); }; @@ -167,12 +208,12 @@ protected: class IntegerSorter : public NumericSorter { public: - IntegerSorter(bool isDescending) : NumericSorter(isDescending) { }; + IntegerSorter(bool isDescending, size_t fromColumn, size_t toColumn) : NumericSorter(isDescending, fromColumn, toColumn) { }; protected: virtual generic_string prepareStringForConversion(const generic_string& input) { - return stringTakeWhileAdmissable(input, TEXT(" \t\r\n0123456789-")); + return stringTakeWhileAdmissable(getSortKey(input), TEXT(" \t\r\n0123456789-")); } long long convertStringToNumber(const generic_string& input) override @@ -185,12 +226,12 @@ protected: class DecimalCommaSorter : public NumericSorter { public: - DecimalCommaSorter(bool isDescending) : NumericSorter(isDescending) { }; + DecimalCommaSorter(bool isDescending, size_t fromColumn, size_t toColumn) : NumericSorter(isDescending, fromColumn, toColumn) { }; protected: generic_string prepareStringForConversion(const generic_string& input) override { - generic_string admissablePart = stringTakeWhileAdmissable(input, TEXT(" \t\r\n0123456789,-")); + generic_string admissablePart = stringTakeWhileAdmissable(getSortKey(input), TEXT(" \t\r\n0123456789,-")); return stringReplace(admissablePart, TEXT(","), TEXT(".")); } @@ -204,12 +245,12 @@ protected: class DecimalDotSorter : public NumericSorter { public: - DecimalDotSorter(bool isDescending) : NumericSorter(isDescending) { }; + DecimalDotSorter(bool isDescending, size_t fromColumn, size_t toColumn) : NumericSorter(isDescending, fromColumn, toColumn) { }; protected: generic_string prepareStringForConversion(const generic_string& input) override { - return stringTakeWhileAdmissable(input, TEXT(" \t\r\n0123456789.-")); + return stringTakeWhileAdmissable(getSortKey(input), TEXT(" \t\r\n0123456789.-")); } double convertStringToNumber(const generic_string& input) override diff --git a/PowerEditor/src/NppCommands.cpp b/PowerEditor/src/NppCommands.cpp index dde77006..068e920f 100644 --- a/PowerEditor/src/NppCommands.cpp +++ b/PowerEditor/src/NppCommands.cpp @@ -354,31 +354,51 @@ void Notepad_plus::command(int id) case IDM_EDIT_SORTLINES_DECIMALDOT_ASCENDING: case IDM_EDIT_SORTLINES_DECIMALDOT_DESCENDING: { - // default: no selection - size_t fromLine = 0; - size_t toLine = _pEditView->execute(SCI_GETLINECOUNT) - 1; + size_t fromLine = 0, toLine = 0; + size_t fromColumn = 0, toColumn = 0; - // multi-selection is not allowed - if (_pEditView->execute(SCI_GETSELECTIONS) > 1) - return; - - // retangle-selection is not allowed - if (_pEditView->execute(SCI_SELECTIONISRECTANGLE)) - return; - - int selStart = _pEditView->execute(SCI_GETSELECTIONSTART); - int selEnd = _pEditView->execute(SCI_GETSELECTIONEND); - bool hasSelection = selStart != selEnd; - - pair lineRange = _pEditView->getSelectionLinesRange(); - - if (hasSelection) + bool hasLineSelection = false; + if (_pEditView->execute(SCI_GETSELECTIONS) > 1) { - // one single line selection is not allowed - if ((lineRange.second - lineRange.first) == 0) + if (_pEditView->execute(SCI_SELECTIONISRECTANGLE)) + { + ColumnModeInfos colInfos = _pEditView->getColumnModeSelectInfo(); + int leftPos = colInfos.begin()->_selLpos; + int rightPos = colInfos.rbegin()->_selRpos; + int startPos = min(leftPos, rightPos); + int endPos = max(leftPos, rightPos); + fromLine = _pEditView->execute(SCI_LINEFROMPOSITION, startPos); + toLine = _pEditView->execute(SCI_LINEFROMPOSITION, endPos); + fromColumn = _pEditView->execute(SCI_GETCOLUMN, leftPos); + toColumn = _pEditView->execute(SCI_GETCOLUMN, rightPos); + } + else + { return; - fromLine = lineRange.first; - toLine = lineRange.second; + } + } + else + { + int selStart = _pEditView->execute(SCI_GETSELECTIONSTART); + int selEnd = _pEditView->execute(SCI_GETSELECTIONEND); + hasLineSelection = selStart != selEnd; + if (hasLineSelection) + { + pair lineRange = _pEditView->getSelectionLinesRange(); + // One single line selection is not allowed. + if (lineRange.first == lineRange.second) + { + return; + } + fromLine = lineRange.first; + toLine = lineRange.second; + } + else + { + // No selection. + fromLine = 0; + toLine = _pEditView->execute(SCI_GETLINECOUNT) - 1; + } } bool isDescending = id == IDM_EDIT_SORTLINES_LEXICOGRAPHIC_DESCENDING || @@ -390,19 +410,19 @@ void Notepad_plus::command(int id) std::unique_ptr pSorter; if (id == IDM_EDIT_SORTLINES_LEXICOGRAPHIC_DESCENDING || id == IDM_EDIT_SORTLINES_LEXICOGRAPHIC_ASCENDING) { - pSorter = std::unique_ptr(new LexicographicSorter(isDescending)); + pSorter = std::unique_ptr(new LexicographicSorter(isDescending, fromColumn, toColumn)); } else if (id == IDM_EDIT_SORTLINES_INTEGER_DESCENDING || id == IDM_EDIT_SORTLINES_INTEGER_ASCENDING) { - pSorter = std::unique_ptr(new IntegerSorter(isDescending)); + pSorter = std::unique_ptr(new IntegerSorter(isDescending, fromColumn, toColumn)); } else if (id == IDM_EDIT_SORTLINES_DECIMALCOMMA_DESCENDING || id == IDM_EDIT_SORTLINES_DECIMALCOMMA_ASCENDING) { - pSorter = std::unique_ptr(new DecimalCommaSorter(isDescending)); + pSorter = std::unique_ptr(new DecimalCommaSorter(isDescending, fromColumn, toColumn)); } else { - pSorter = std::unique_ptr(new DecimalDotSorter(isDescending)); + pSorter = std::unique_ptr(new DecimalDotSorter(isDescending, fromColumn, toColumn)); } try { @@ -421,10 +441,10 @@ void Notepad_plus::command(int id) } _pEditView->execute(SCI_ENDUNDOACTION); - if (hasSelection) // there was 1 selection, so we restore it + if (hasLineSelection) // there was 1 selection, so we restore it { - int posStart = _pEditView->execute(SCI_POSITIONFROMLINE, lineRange.first); - int posEnd = _pEditView->execute(SCI_GETLINEENDPOSITION, lineRange.second); + int posStart = _pEditView->execute(SCI_POSITIONFROMLINE, fromLine); + int posEnd = _pEditView->execute(SCI_GETLINEENDPOSITION, toLine); _pEditView->execute(SCI_SETSELECTIONSTART, posStart); _pEditView->execute(SCI_SETSELECTIONEND, posEnd); }