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 | #ifndef _KATE_REGEXPSEARCH_H_ |
9 | #define _KATE_REGEXPSEARCH_H_ |
10 | |
11 | #include <QObject> |
12 | #include <QRegularExpression> |
13 | |
14 | #include <ktexteditor/range.h> |
15 | |
16 | #include <ktexteditor_export.h> |
17 | |
18 | namespace KTextEditor |
19 | { |
20 | class Document; |
21 | } |
22 | |
23 | /** |
24 | * Object to help to search for regexp. |
25 | * This should be NO QObject, it is created to often! |
26 | * I measured that, if you create it 20k times to replace for example " " in a document, that takes seconds on a modern machine! |
27 | */ |
28 | class KTEXTEDITOR_EXPORT KateRegExpSearch |
29 | { |
30 | public: |
31 | explicit KateRegExpSearch(const KTextEditor::Document *document); |
32 | ~KateRegExpSearch() = default; |
33 | |
34 | // |
35 | // KTextEditor::SearchInterface stuff |
36 | // |
37 | public: |
38 | /** |
39 | * Search for the regular expression \p pattern inside the range |
40 | * \p inputRange. If \p backwards is \e true, the search direction will |
41 | * be reversed. \p options is a set of QRegularExpression::PatternOptions |
42 | * OR flags that control certain aspects of the search, e.g. case |
43 | * sensitivity and if the dot "." metacharacter matches any character |
44 | * including a newline. |
45 | * |
46 | * Note: Unicode support is always enabled (QRegularExpression::UseUnicodePropertiesOption). |
47 | * If the pattern is multi-line the QRegularExpression::MultilineOption is enabled. |
48 | * |
49 | * \param pattern text to search for |
50 | * \param inputRange Range to search in |
51 | * \param backwards if \e true, the search will be backwards |
52 | * \param options QRegularExpression pattern options, we will internally add QRegularExpression::UseUnicodePropertiesOption |
53 | * \return Vector of ranges, one for each capture group. The first range (index |
54 | * zero) spans the whole match. If no matches are found, the vector will |
55 | * contain one element, an invalid range (see Range::isValid()). |
56 | * \see KTextEditor::Range, QRegularExpression |
57 | */ |
58 | QList<KTextEditor::Range> search(const QString &pattern, |
59 | KTextEditor::Range inputRange, |
60 | bool backwards = false, |
61 | QRegularExpression::PatternOptions options = QRegularExpression::NoPatternOption); |
62 | |
63 | /** |
64 | * Returns a modified version of text where escape sequences are resolved, e.g. "\\n" to "\n". |
65 | * |
66 | * \param text text containing escape sequences |
67 | * \return text with resolved escape sequences |
68 | */ |
69 | static QString escapePlaintext(const QString &text); |
70 | |
71 | /** |
72 | * Returns a modified version of text where |
73 | * \li escape sequences are resolved, e.g. "\\n" to "\n", |
74 | * \li references are resolved, e.g. "\\1" to <i>1st entry in capturedTexts</i>, and |
75 | * \li counter sequences are resolved, e.g. "\\#...#" to <i>replacementCounter</i>. |
76 | * |
77 | * \param text text containing escape sequences, references, and counter sequences |
78 | * \param capturedTexts list of substitutes for references |
79 | * \param replacementCounter value for replacement counter |
80 | * \return resolved text |
81 | */ |
82 | static QString buildReplacement(const QString &text, const QStringList &capturedTexts, int replacementCounter); |
83 | |
84 | private: |
85 | /** |
86 | * Implementation of escapePlainText() and public buildReplacement(). |
87 | * |
88 | * \param text text containing escape sequences and possibly references and counters |
89 | * \param capturedTexts list of substitutes for references |
90 | * \param replacementCounter value for replacement counter (only used when replacementGoodies == true) |
91 | * \param replacementGoodies @c true for buildReplacement(), @c false for escapePlainText() |
92 | * \return resolved text |
93 | */ |
94 | KTEXTEDITOR_NO_EXPORT |
95 | static QString buildReplacement(const QString &text, const QStringList &capturedTexts, int replacementCounter, bool replacementGoodies); |
96 | |
97 | /** |
98 | * Checks the pattern for special characters and escape sequences that can |
99 | * make a match span multiple lines; if any are found, \p stillMultiLine is |
100 | * set to true. |
101 | * |
102 | * "\s" is treated specially so that it doesn't match new line characters; this |
103 | * is achieved by replacing any occurences of "\s" with "[ \t]" in the search |
104 | * \p pattern. |
105 | * |
106 | * \param pattern the regular expression search pattern |
107 | * \param stillMultiLine is set to \c true if the search pattern may still match |
108 | * multiple lines even after replacing "\s" with "[ \t]"; otherwise it's set to false |
109 | * \return the modified pattern |
110 | */ |
111 | KTEXTEDITOR_NO_EXPORT |
112 | static QString repairPattern(const QString &pattern, bool &stillMultiLine); |
113 | |
114 | private: |
115 | const KTextEditor::Document *const m_document; |
116 | class ReplacementStream; |
117 | }; |
118 | |
119 | #endif |
120 | |