Improve "Remove consecutive duplicate lines" command performance
Rewrite "Remove consecutive duplicate lines" without using regex. Fix #5538, fix #12548, close #13558
This commit is contained in:
parent
5f2e93ee5f
commit
ecb10712c1
|
@ -1676,22 +1676,81 @@ void Notepad_plus::removeEmptyLine(bool isBlankContained)
|
|||
|
||||
void Notepad_plus::removeDuplicateLines()
|
||||
{
|
||||
// whichPart : line head or line tail
|
||||
FindOption env;
|
||||
intptr_t mainSelAnchor = _pEditView->execute(SCI_GETANCHOR);
|
||||
intptr_t mainSelCaretPos = _pEditView->execute(SCI_GETCURRENTPOS);
|
||||
bool isEntireDoc = (mainSelAnchor == mainSelCaretPos);
|
||||
|
||||
env._str2Search = TEXT("^([^\\r\\n]*(?>\\r?\\n|\\r))(?>\\1)+");
|
||||
env._str4Replace = TEXT("\\1");
|
||||
env._searchType = FindRegex;
|
||||
auto mainSelStart = _pEditView->execute(SCI_GETSELECTIONSTART);
|
||||
auto mainSelEnd = _pEditView->execute(SCI_GETSELECTIONEND);
|
||||
auto mainSelLength = mainSelEnd - mainSelStart;
|
||||
bool isEntireDoc = mainSelLength == 0;
|
||||
env._isInSelection = !isEntireDoc;
|
||||
_findReplaceDlg.processAll(ProcessReplaceAll, &env, isEntireDoc);
|
||||
intptr_t startLine = 0;
|
||||
intptr_t endLine = _pEditView->lastZeroBasedLineNumber();
|
||||
|
||||
if (!isEntireDoc)
|
||||
{
|
||||
intptr_t startPos = _pEditView->execute(SCI_GETSELECTIONSTART);
|
||||
startLine = _pEditView->execute(SCI_LINEFROMPOSITION, startPos);
|
||||
intptr_t endPos = _pEditView->execute(SCI_GETSELECTIONEND);
|
||||
endLine = _pEditView->execute(SCI_LINEFROMPOSITION, endPos);
|
||||
if (endPos == _pEditView->execute(SCI_POSITIONFROMLINE, endLine))
|
||||
endLine -= 1;
|
||||
}
|
||||
|
||||
if (startLine == endLine)
|
||||
return;
|
||||
|
||||
intptr_t firstMatchLineNr = 0;
|
||||
intptr_t lastMatchLineNr = 0;
|
||||
generic_string firstMatchLineStr;
|
||||
generic_string lastMatchLineStr;
|
||||
|
||||
for (intptr_t i = startLine; i <= endLine; i++)
|
||||
{
|
||||
if (firstMatchLineStr.empty())
|
||||
{
|
||||
firstMatchLineNr = lastMatchLineNr = i;
|
||||
firstMatchLineStr = _pEditView->getLine(i);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
lastMatchLineStr = _pEditView->getLine(i);
|
||||
|
||||
if (firstMatchLineStr == lastMatchLineStr)
|
||||
{
|
||||
lastMatchLineNr = i;
|
||||
if (i != endLine)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (firstMatchLineNr != lastMatchLineNr)
|
||||
{
|
||||
intptr_t startPos = _pEditView->execute(SCI_POSITIONFROMLINE, firstMatchLineNr + 1);
|
||||
intptr_t endPos = _pEditView->execute(SCI_POSITIONFROMLINE, lastMatchLineNr) + _pEditView->execute(SCI_LINELENGTH, lastMatchLineNr);
|
||||
_pEditView->execute(SCI_DELETERANGE, startPos, endPos - startPos);
|
||||
intptr_t removedLines = lastMatchLineNr - firstMatchLineNr;
|
||||
i -= removedLines;
|
||||
endLine -= removedLines;
|
||||
}
|
||||
|
||||
firstMatchLineStr = lastMatchLineStr;
|
||||
firstMatchLineNr = lastMatchLineNr = i;
|
||||
|
||||
}
|
||||
|
||||
// correct the last line (without EOL) if it's a duplicate line
|
||||
intptr_t endLineStartPos = _pEditView->execute(SCI_POSITIONFROMLINE, endLine);
|
||||
intptr_t endLineEndPos = _pEditView->execute(SCI_GETLINEENDPOSITION, endLine);
|
||||
intptr_t endLineLength = _pEditView->execute(SCI_LINELENGTH, endLine);
|
||||
|
||||
if (endLine == _pEditView->lastZeroBasedLineNumber() && endLineLength && ((endLineEndPos - endLineStartPos) == endLineLength))
|
||||
{
|
||||
intptr_t prevLine = endLine - 1;
|
||||
intptr_t prevLineStartPos = _pEditView->execute(SCI_POSITIONFROMLINE, prevLine);
|
||||
intptr_t prevLineEndPos = _pEditView->execute(SCI_GETLINEENDPOSITION, prevLine);
|
||||
intptr_t prevLineLength = _pEditView->execute(SCI_LINELENGTH, prevLine);
|
||||
const generic_string endLineStr = _pEditView->getLine(endLine);
|
||||
const generic_string prevLineStr = _pEditView->getGenericTextAsString(prevLineStartPos, prevLineEndPos);
|
||||
if (endLineStr == prevLineStr)
|
||||
_pEditView->execute(SCI_DELETERANGE, prevLineStartPos, prevLineLength);
|
||||
}
|
||||
|
||||
// remove the last line if it's a duplicate line.
|
||||
env._str2Search = TEXT("^([^\\r\\n]+)(?>\\r?\\n|\\r)(?>\\1)$");
|
||||
_findReplaceDlg.processAll(ProcessReplaceAll, &env, isEntireDoc);
|
||||
}
|
||||
|
||||
void Notepad_plus::getMatchedFileNames(const TCHAR *dir, size_t level, const vector<generic_string> & patterns, vector<generic_string> & fileNames, bool isRecursive, bool isInHiddenDir)
|
||||
|
|
Loading…
Reference in New Issue