Commit 011d75a3 authored by Kåre Särs's avatar Kåre Särs

Add multi-line search&replace to search-in-open files

parent caf6c5bc
......@@ -668,7 +668,15 @@ void KatePluginSearchView::addMatchMark(KTextEditor::Document* doc, int line, in
if (ciface) searchColor = ciface->configValue("search-highlight-color").value<QColor>();
attr->setBackground(searchColor);
}
KTextEditor::Range range(line, column, line, column+matchLen);
// calculate end line in case of multi-line match
int endLine = line;
int endColumn = column+matchLen;
while ((endLine < doc->lines()) && (endColumn > doc->line(endLine).size())) {
endColumn -= doc->line(endLine).size();
endColumn--; // remove one for '\n'
endLine++;
}
KTextEditor::Range range(line, column, endLine, endColumn);
KTextEditor::MovingRange* mr = miface->newMovingRange(range);
mr->setAttribute(attr);
mr->setZDepth(-90000.0); // Set the z-depth to slightly worse than the selection
......@@ -692,8 +700,10 @@ void KatePluginSearchView::matchFound(const QString &url, int line, int column,
if (!m_curResults) {
return;
}
QString pre = Qt::escape(lineContent.left(column));
QString match = Qt::escape(lineContent.mid(column, matchLen));
match.replace('\n', "\\n");
QString post = Qt::escape(lineContent.mid(column + matchLen));
QStringList row;
row << i18n("Line: <b>%1</b>: %2", line+1, pre+"<b>"+match+"</b>"+post);
......
......@@ -96,36 +96,56 @@ void ReplaceMatches::doReplaceNextMatch()
KTextEditor::MovingInterface* miface = qobject_cast<KTextEditor::MovingInterface*>(doc);
int line;
int column;
int len;
int matchLen;
int endLine;
int endColumn;
QTreeWidgetItem *item;
QString matchLines;
// lines might be modified so search the document again
for (int i=0; i<rootItem->childCount(); i++) {
item = rootItem->child(i);
if (item->checkState(0) == Qt::Unchecked) continue;
line = item->data(1, Qt::UserRole).toInt();
line = endLine= item->data(1, Qt::UserRole).toInt();
column = item->data(2, Qt::UserRole).toInt();
len = item->data(3, Qt::UserRole).toInt();
if (m_regExp.indexIn(doc->line(line), column) != column) {
matchLen = item->data(3, Qt::UserRole).toInt();
matchLines = doc->line(line).mid(column);
while (matchLines.size() < matchLen) {
if (endLine+1 >= doc->lines()) break;
endLine++;
matchLines+= '\n' + doc->line(endLine);
}
if (m_regExp.indexIn(matchLines) != 0) {
kDebug() << "expression does not match";
continue;
}
QString replaceText = m_replaceText;
replaceText.replace("\\\\", "¤¤");
replaceText.replace("\\\\", Search&Replace¤");
for (int j=1; j<=m_regExp.captureCount(); j++) {
replaceText.replace(QString("\\%1").arg(j), m_regExp.cap(j));
}
replaceText.replace("¤¤", "\\\\");
replaceText.replace("\\n", "\n");
replaceText.replace("¤Search&Replace¤", "\\\\");
rTexts << replaceText;
replaceText.replace('\n', "\\n");
QString html = item->data(1, Qt::ToolTipRole).toString();
html += "<i><s>" + item->data(2, Qt::ToolTipRole).toString() + "</s></i> ";
html += "<b>" + replaceText + "</b>";
html += item->data(3, Qt::ToolTipRole).toString();
item->setData(0, Qt::DisplayRole, i18n("Line: <b>%1</b>: %2",line+1, html));
KTextEditor::Range range(line, column, line, column+len);
endLine = line;
endColumn = column+matchLen;
while ((endLine < doc->lines()) && (endColumn > doc->line(endLine).size())) {
endColumn -= doc->line(endLine).size();
endColumn--; // remove one for '\n'
endLine++;
}
KTextEditor::Range range(line, column, endLine, endColumn);
KTextEditor::MovingRange* mr = miface->newMovingRange(range);
rVector.append(mr);
}
......
......@@ -76,6 +76,15 @@ void SearchOpenFiles::doSearchNextFile(int startLine)
}
int SearchOpenFiles::searchOpenFile(KTextEditor::Document *doc, const QRegExp &regExp, int startLine)
{
if (regExp.pattern().contains("\\n")) {
return searchMultiLineRegExp(doc, regExp, startLine);
}
return searchSingleLineRegExp(doc, regExp, startLine);
}
int SearchOpenFiles::searchSingleLineRegExp(KTextEditor::Document *doc, const QRegExp &regExp, int startLine)
{
int column;
QTime time;
......@@ -97,3 +106,60 @@ int SearchOpenFiles::searchOpenFile(KTextEditor::Document *doc, const QRegExp &r
return 0;
}
int SearchOpenFiles::searchMultiLineRegExp(KTextEditor::Document *doc, const QRegExp &regExp, int startLine)
{
int column = 0;
int line = 0;
QTime time;
time.start();
if (startLine == 0) {
// Copy the whole file to a temporary buffer to be able to search newlines
m_fullDoc.clear();
m_lineStart.clear();
m_lineStart << 0;
for (int i=0; i<doc->lines(); i++) {
m_fullDoc += doc->line(i) + '\n';
m_lineStart << m_fullDoc.size();
}
m_fullDoc.remove(m_fullDoc.size()-1, 1);
}
else {
if (startLine>0 && startLine<m_lineStart.size()) {
column = m_lineStart[startLine];
line = startLine;
}
else {
return 0;
}
}
column = regExp.indexIn(m_fullDoc, column);
while (column != -1) {
if (regExp.cap().isEmpty()) break;
// search for the line number or the match
int i;
line = -1;
for (i=1; i<m_lineStart.size(); i++) {
if (m_lineStart[i] > column) {
line = i-1;
break;
}
}
if (line == -1) {
break;
}
emit matchFound(doc->url().pathOrUrl(),
line,
(column - m_lineStart[line]),
doc->line(line).left(column - m_lineStart[line])+regExp.cap(),
regExp.matchedLength());
column = regExp.indexIn(m_fullDoc, column + regExp.matchedLength());
if (time.elapsed() > 100) {
//kDebug() << "Search time exceeded" << time.elapsed() << line;
return line;
}
}
return 0;
}
......@@ -44,6 +44,10 @@ public Q_SLOTS:
private Q_SLOTS:
void doSearchNextFile(int startLine);
private:
int searchSingleLineRegExp(KTextEditor::Document *doc, const QRegExp &regExp, int startLine);
int searchMultiLineRegExp(KTextEditor::Document *doc, const QRegExp &regExp, int startLine);
Q_SIGNALS:
void searchNextFile(int startLine);
void matchFound(const QString &url, int line, int column, const QString &lineContent, int matchLen);
......@@ -54,7 +58,8 @@ private:
int m_nextIndex;
QRegExp m_regExp;
bool m_cancelSearch;
QString m_fullDoc;
QVector<int> m_lineStart;
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment