1 | /* |
2 | SPDX-FileCopyrightText: 2010 Bernhard Beschow <bbeschow@cs.tu-berlin.de> |
3 | SPDX-FileCopyrightText: 2007 Sebastian Pipping <webmaster@hartwork.org> |
4 | |
5 | SPDX-License-Identifier: LGPL-2.0-or-later |
6 | */ |
7 | |
8 | #include "katematch.h" |
9 | |
10 | #include "katedocument.h" |
11 | #include "kateregexpsearch.h" |
12 | |
13 | KateMatch::KateMatch(KTextEditor::DocumentPrivate *document, KTextEditor::SearchOptions options) |
14 | : m_document(document) |
15 | , m_options(options) |
16 | { |
17 | m_resultRanges.append(t: KTextEditor::Range::invalid()); |
18 | } |
19 | |
20 | KTextEditor::Range KateMatch::searchText(KTextEditor::Range range, const QString &pattern) |
21 | { |
22 | m_resultRanges = m_document->searchText(range, pattern, options: m_options); |
23 | |
24 | return m_resultRanges[0]; |
25 | } |
26 | |
27 | KTextEditor::Range KateMatch::replace(const QString &replacement, bool blockMode, int replacementCounter) |
28 | { |
29 | // Placeholders depending on search mode |
30 | // skip place-holder stuff if we have no \ at all inside the replacement, the buildReplacement is expensive |
31 | const bool usePlaceholders = |
32 | (m_options.testFlag(flag: KTextEditor::Regex) || m_options.testFlag(flag: KTextEditor::EscapeSequences)) && replacement.contains(c: QLatin1Char('\\')); |
33 | |
34 | const QString finalReplacement = usePlaceholders ? buildReplacement(replacement, blockMode, replacementCounter) : replacement; |
35 | |
36 | // Track replacement operation, reuse range if already there |
37 | if (m_afterReplaceRange) { |
38 | m_afterReplaceRange->setRange(range()); |
39 | } else { |
40 | m_afterReplaceRange.reset(p: m_document->newMovingRange(range: range(), insertBehaviors: KTextEditor::MovingRange::ExpandLeft | KTextEditor::MovingRange::ExpandRight)); |
41 | } |
42 | |
43 | // replace and return results range |
44 | m_document->replaceText(range: range(), s: finalReplacement, block: blockMode && !range().onSingleLine()); |
45 | return m_afterReplaceRange->toRange(); |
46 | } |
47 | |
48 | KTextEditor::Range KateMatch::range() const |
49 | { |
50 | if (!m_resultRanges.isEmpty()) { |
51 | return m_resultRanges[0]; |
52 | } |
53 | |
54 | return KTextEditor::Range::invalid(); |
55 | } |
56 | |
57 | bool KateMatch::isEmpty() const |
58 | { |
59 | return range().isEmpty(); |
60 | } |
61 | |
62 | bool KateMatch::isValid() const |
63 | { |
64 | return range().isValid(); |
65 | } |
66 | |
67 | QString KateMatch::buildReplacement(const QString &replacement, bool blockMode, int replacementCounter) const |
68 | { |
69 | QStringList capturedTexts; |
70 | capturedTexts.reserve(asize: m_resultRanges.size()); |
71 | for (KTextEditor::Range captureRange : std::as_const(t: m_resultRanges)) { |
72 | // Copy capture content |
73 | capturedTexts << m_document->text(range: captureRange, blockwise: blockMode); |
74 | } |
75 | |
76 | return KateRegExpSearch::buildReplacement(text: replacement, capturedTexts, replacementCounter); |
77 | } |
78 | |