• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • applications API Reference
  • KDE Home
  • Contact Us
 

Kate

  • kde-4.14
  • applications
  • kate
  • part
  • search
kateregexpsearch.cpp
Go to the documentation of this file.
1 /* This file is part of the KDE libraries and the Kate part.
2  *
3  * Copyright (C) 2010 Bernhard Beschow <bbeschow@cs.tu-berlin.de>
4  * Copyright (C) 2007 Sebastian Pipping <webmaster@hartwork.org>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this library; see the file COPYING.LIB. If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21 
22 //BEGIN includes
23 #include "kateregexpsearch.h"
24 #include "kateregexp.h"
25 
26 #include <ktexteditor/document.h>
27 //END includes
28 
29 
30 
31 // Turn debug messages on/off here
32 // #define FAST_DEBUG_ENABLE
33 
34 #ifdef FAST_DEBUG_ENABLE
35 # define FAST_DEBUG(x) kDebug( 13020 ) << x
36 #else
37 # define FAST_DEBUG(x)
38 #endif
39 
40 
41 class KateRegExpSearch::ReplacementStream
42 {
43 public:
44  struct counter {
45  counter(int value, int minWidth)
46  : value(value)
47  , minWidth(minWidth)
48  {}
49 
50  const int value;
51  const int minWidth;
52  };
53 
54  struct cap {
55  cap(int n)
56  : n(n)
57  {}
58 
59  const int n;
60  };
61 
62  enum CaseConversion {
63  upperCase,
64  upperCaseFirst,
65  lowerCase,
66  lowerCaseFirst,
67  keepCase
68  };
69 
70 public:
71  ReplacementStream(const QStringList &capturedTexts);
72 
73  QString str() const { return m_str; }
74 
75  ReplacementStream &operator<<(const QString &);
76  ReplacementStream &operator<<(const counter &);
77  ReplacementStream &operator<<(const cap &);
78  ReplacementStream &operator<<(CaseConversion);
79 
80 private:
81  const QStringList m_capturedTexts;
82  CaseConversion m_caseConversion;
83  QString m_str;
84 };
85 
86 
87 KateRegExpSearch::ReplacementStream::ReplacementStream(const QStringList &capturedTexts)
88  : m_capturedTexts(capturedTexts)
89  , m_caseConversion(keepCase)
90 {
91 }
92 
93 KateRegExpSearch::ReplacementStream &KateRegExpSearch::ReplacementStream::operator<<(const QString &str)
94 {
95  switch (m_caseConversion) {
96  case upperCase:
97  // Copy as uppercase
98  m_str.append(str.toUpper());
99  break;
100 
101  case upperCaseFirst:
102  if (str.length() > 0) {
103  m_str.append(str.at(0).toUpper());
104  m_str.append(str.mid(1));
105  m_caseConversion = keepCase;
106  }
107  break;
108 
109  case lowerCase:
110  // Copy as lowercase
111  m_str.append(str.toLower());
112  break;
113 
114  case lowerCaseFirst:
115  if (str.length() > 0) {
116  m_str.append(str.at(0).toLower());
117  m_str.append(str.mid(1));
118  m_caseConversion = keepCase;
119  }
120  break;
121 
122  case keepCase: // FALLTHROUGH
123  default:
124  // Copy unmodified
125  m_str.append(str);
126  break;
127 
128  }
129 
130  return *this;
131 }
132 
133 
134 KateRegExpSearch::ReplacementStream &KateRegExpSearch::ReplacementStream::operator<<(const counter &c)
135 {
136  // Zero padded counter value
137  m_str.append(QString("%1").arg(c.value, c.minWidth, 10, QLatin1Char('0')));
138 
139  return *this;
140 }
141 
142 
143 KateRegExpSearch::ReplacementStream &KateRegExpSearch::ReplacementStream::operator<<(const cap &cap)
144 {
145  if (0 <= cap.n && cap.n < m_capturedTexts.size()) {
146  (*this) << m_capturedTexts[cap.n];
147  } else {
148  // Insert just the number to be consistent with QRegExp ("\c" becomes "c")
149  m_str.append(QString::number(cap.n));
150  }
151 
152  return *this;
153 }
154 
155 
156 KateRegExpSearch::ReplacementStream &KateRegExpSearch::ReplacementStream::operator<<(CaseConversion caseConversion)
157 {
158  m_caseConversion = caseConversion;
159 
160  return *this;
161 }
162 
163 
164 //BEGIN d'tor, c'tor
165 //
166 // KateSearch Constructor
167 //
168 KateRegExpSearch::KateRegExpSearch ( KTextEditor::Document *document, Qt::CaseSensitivity caseSensitivity )
169 : m_document (document)
170 , m_caseSensitivity (caseSensitivity)
171 {
172 }
173 
174 //
175 // KateSearch Destructor
176 //
177 KateRegExpSearch::~KateRegExpSearch()
178 {
179 }
180 
181 
182 // helper structs for captures re-construction
183 struct TwoViewCursor {
184  int index;
185  int openLine;
186  int openCol;
187  int closeLine;
188  int closeCol;
189  // note: open/close distinction does not seem needed
190  // anymore. i keep it to make a potential way back
191  // easier. overhead is minimal.
192 };
193 
194 struct IndexPair {
195  int openIndex;
196  int closeIndex;
197 };
198 
199 
200 
201 QVector<KTextEditor::Range> KateRegExpSearch::search(
202  const QString &pattern,
203  const KTextEditor::Range & inputRange,
204  bool backwards)
205 {
206  // regex search
207  KateRegExp regexp(pattern, m_caseSensitivity);
208 
209  if (regexp.isEmpty() || !regexp.isValid() || !inputRange.isValid() || (inputRange.start() == inputRange.end()))
210  {
211  QVector<KTextEditor::Range> result;
212  result.append(KTextEditor::Range::invalid());
213  return result;
214  }
215 
216 
217  // detect pattern type (single- or mutli-line)
218  bool isMultiLine;
219 
220  // detect '.' and '\s' and fix them
221  const bool dotMatchesNewline = false; // TODO
222  const int replacements = regexp.repairPattern(isMultiLine);
223  if (dotMatchesNewline && (replacements > 0))
224  {
225  isMultiLine = true;
226  }
227 
228  const int firstLineIndex = inputRange.start().line();
229  const int minColStart = inputRange.start().column();
230 // const int maxColEnd = inputRange.end().column();
231  if (isMultiLine)
232  {
233  // multi-line regex search (both forward and backward mode)
234  QString wholeDocument;
235  const int inputLineCount = inputRange.end().line() - inputRange.start().line() + 1;
236  FAST_DEBUG("multi line search (lines " << firstLineIndex << ".." << firstLineIndex + inputLineCount - 1 << ")");
237 
238  // nothing to do...
239  if (firstLineIndex >= m_document->lines())
240  {
241  QVector<KTextEditor::Range> result;
242  result.append(KTextEditor::Range::invalid());
243  return result;
244  }
245 
246  QVector<int> lineLens (inputLineCount);
247 
248  // first line
249  if (firstLineIndex < 0 || m_document->lines() <= firstLineIndex)
250  {
251  QVector<KTextEditor::Range> result;
252  result.append(KTextEditor::Range::invalid());
253  return result;
254  }
255 
256  const QString firstLine = m_document->line(firstLineIndex);
257 
258  const int firstLineLen = firstLine.length() - minColStart;
259  wholeDocument.append(firstLine.right(firstLineLen));
260  lineLens[0] = firstLineLen;
261  FAST_DEBUG(" line" << 0 << "has length" << lineLens[0]);
262 
263  // second line and after
264  const QString sep("\n");
265  for (int i = 1; i < inputLineCount; i++)
266  {
267  const int lineNum = firstLineIndex + i;
268  if (lineNum < 0 || m_document->lines() <= lineNum)
269  {
270  QVector<KTextEditor::Range> result;
271  result.append(KTextEditor::Range::invalid());
272  return result;
273  }
274  const QString text = m_document->line(lineNum);
275 
276  lineLens[i] = text.length();
277  wholeDocument.append(sep);
278  wholeDocument.append(text);
279  FAST_DEBUG(" line" << i << "has length" << lineLens[i]);
280  }
281 
282  const int pos = backwards
283  ? regexp.lastIndexIn(wholeDocument, 0, wholeDocument.length())
284  : regexp.indexIn(wholeDocument, 0, wholeDocument.length());
285  if (pos == -1)
286  {
287  // no match
288  FAST_DEBUG("not found");
289  {
290  QVector<KTextEditor::Range> result;
291  result.append(KTextEditor::Range::invalid());
292  return result;
293  }
294  }
295 
296 #ifdef FAST_DEBUG_ENABLE
297  const int matchLen = regexp.matchedLength();
298  FAST_DEBUG("found at relative pos " << pos << ", length " << matchLen);
299 #endif
300 
301  // save opening and closing indices and build a map.
302  // the correct values will be written into it later.
303  QMap<int, TwoViewCursor *> indicesToCursors;
304  const int numCaptures = regexp.numCaptures();
305  QVector<IndexPair> indexPairs(1 + numCaptures);
306  for (int z = 0; z <= numCaptures; z++)
307  {
308  const int openIndex = regexp.pos(z);
309  IndexPair & pair = indexPairs[z];
310  if (openIndex == -1)
311  {
312  // empty capture gives invalid
313  pair.openIndex = -1;
314  pair.closeIndex = -1;
315  FAST_DEBUG("capture []");
316  }
317  else
318  {
319  const int closeIndex = openIndex + regexp.cap(z).length();
320  pair.openIndex = openIndex;
321  pair.closeIndex = closeIndex;
322  FAST_DEBUG("capture [" << pair.openIndex << ".." << pair.closeIndex << "]");
323 
324  // each key no more than once
325  if (!indicesToCursors.contains(openIndex))
326  {
327  TwoViewCursor * twoViewCursor = new TwoViewCursor;
328  twoViewCursor->index = openIndex;
329  indicesToCursors.insert(openIndex, twoViewCursor);
330  FAST_DEBUG(" border index added: " << openIndex);
331  }
332  if (!indicesToCursors.contains(closeIndex))
333  {
334  TwoViewCursor * twoViewCursor = new TwoViewCursor;
335  twoViewCursor->index = closeIndex;
336  indicesToCursors.insert(closeIndex, twoViewCursor);
337  FAST_DEBUG(" border index added: " << closeIndex);
338  }
339  }
340  }
341 
342  // find out where they belong
343  int curRelLine = 0;
344  int curRelCol = 0;
345  int curRelIndex = 0;
346  QMap<int, TwoViewCursor *>::const_iterator iter = indicesToCursors.constBegin();
347  while (iter != indicesToCursors.constEnd())
348  {
349  // forward to index, save line/col
350  const int index = (*iter)->index;
351  FAST_DEBUG("resolving position" << index);
352  TwoViewCursor & twoViewCursor = *(*iter);
353  while (curRelIndex <= index)
354  {
355  FAST_DEBUG("walk pos (" << curRelLine << "," << curRelCol << ") = "
356  << curRelIndex << "relative, steps more to go" << index - curRelIndex);
357  const int curRelLineLen = lineLens[curRelLine];
358  const int curLineRemainder = curRelLineLen - curRelCol;
359  const int lineFeedIndex = curRelIndex + curLineRemainder;
360  if (index <= lineFeedIndex) {
361  if (index == lineFeedIndex) {
362  // on this line _on_ line feed
363  FAST_DEBUG(" on line feed");
364  const int absLine = curRelLine + firstLineIndex;
365  twoViewCursor.openLine
366  = twoViewCursor.closeLine
367  = absLine;
368  twoViewCursor.openCol
369  = twoViewCursor.closeCol
370  = ((curRelLine == 0) ? minColStart : 0) + curRelLineLen;
371 
372  // advance to next line
373  const int advance = (index - curRelIndex) + 1;
374  curRelLine++;
375  curRelCol = 0;
376  curRelIndex += advance;
377  } else { // index < lineFeedIndex
378  // on this line _before_ line feed
379  FAST_DEBUG(" before line feed");
380  const int diff = (index - curRelIndex);
381  const int absLine = curRelLine + firstLineIndex;
382  const int absCol = ((curRelLine == 0) ? minColStart : 0) + curRelCol + diff;
383  twoViewCursor.openLine
384  = twoViewCursor.closeLine
385  = absLine;
386  twoViewCursor.openCol
387  = twoViewCursor.closeCol
388  = absCol;
389 
390  // advance on same line
391  const int advance = diff + 1;
392  curRelCol += advance;
393  curRelIndex += advance;
394  }
395  FAST_DEBUG("open(" << twoViewCursor.openLine << "," << twoViewCursor.openCol
396  << ") close(" << twoViewCursor.closeLine << "," << twoViewCursor.closeCol << ")");
397  }
398  else // if (index > lineFeedIndex)
399  {
400  // not on this line
401  // advance to next line
402  FAST_DEBUG(" not on this line");
403  const int advance = curLineRemainder + 1;
404  curRelLine++;
405  curRelCol = 0;
406  curRelIndex += advance;
407  }
408  }
409 
410  ++iter;
411  }
412 
413  // build result array
414  QVector<KTextEditor::Range> result(1 + numCaptures);
415  for (int y = 0; y <= numCaptures; y++)
416  {
417  IndexPair & pair = indexPairs[y];
418  if ((pair.openIndex == -1) || (pair.closeIndex == -1))
419  {
420  result[y] = KTextEditor::Range::invalid();
421  }
422  else
423  {
424  const TwoViewCursor * const openCursors = indicesToCursors[pair.openIndex];
425  const TwoViewCursor * const closeCursors = indicesToCursors[pair.closeIndex];
426  const int startLine = openCursors->openLine;
427  const int startCol = openCursors->openCol;
428  const int endLine = closeCursors->closeLine;
429  const int endCol = closeCursors->closeCol;
430  FAST_DEBUG("range " << y << ": (" << startLine << ", " << startCol << ")..(" << endLine << ", " << endCol << ")");
431  result[y] = KTextEditor::Range(startLine, startCol, endLine, endCol);
432  }
433  }
434 
435  // free structs allocated for indicesToCursors
436  iter = indicesToCursors.constBegin();
437  while (iter != indicesToCursors.constEnd())
438  {
439  TwoViewCursor * const twoViewCursor = *iter;
440  delete twoViewCursor;
441  ++iter;
442  }
443  return result;
444  }
445  else
446  {
447  // single-line regex search (both forward of backward mode)
448  const int minLeft = inputRange.start().column();
449  const uint maxRight = inputRange.end().column(); // first not included
450  const int forMin = inputRange.start().line();
451  const int forMax = inputRange.end().line();
452  const int forInit = backwards ? forMax : forMin;
453  const int forInc = backwards ? -1 : +1;
454  FAST_DEBUG("single line " << (backwards ? forMax : forMin) << ".."
455  << (backwards ? forMin : forMax));
456  for (int j = forInit; (forMin <= j) && (j <= forMax); j += forInc)
457  {
458  if (j < 0 || m_document->lines() <= j)
459  {
460  FAST_DEBUG("searchText | line " << j << ": no");
461  QVector<KTextEditor::Range> result;
462  result.append(KTextEditor::Range::invalid());
463  return result;
464  }
465  const QString textLine = m_document->line(j);
466 
467  // Find (and don't match ^ in between...)
468  const int first = (j == forMin) ? minLeft : 0;
469  const int last = (j == forMax) ? maxRight : textLine.length();
470  const int foundAt = (backwards ? regexp.lastIndexIn(textLine, first, last)
471  : regexp.indexIn(textLine, first, last));
472  const bool found = (foundAt != -1);
473 
474  /*
475  TODO do we still need this?
476 
477  // A special case which can only occur when searching with a regular expression consisting
478  // only of a lookahead (e.g. ^(?=\{) for a function beginning without selecting '{').
479  if (myMatchLen == 0 && line == startPosition.line() && foundAt == (uint) col)
480  {
481  if (col < lineLength(line))
482  col++;
483  else {
484  line++;
485  col = 0;
486  }
487  continue;
488  }
489  */
490 
491  if (found)
492  {
493  FAST_DEBUG("line " << j << ": yes");
494 
495  // build result array
496  const int numCaptures = regexp.numCaptures();
497  QVector<KTextEditor::Range> result(1 + numCaptures);
498  result[0] = KTextEditor::Range(j, foundAt, j, foundAt + regexp.matchedLength());
499  FAST_DEBUG("result range " << 0 << ": (" << j << ", " << foundAt << ")..(" << j << ", " <<
500  foundAt + regexp.matchedLength() << ")");
501  for (int y = 1; y <= numCaptures; y++)
502  {
503  const int openIndex = regexp.pos(y);
504  if (openIndex == -1)
505  {
506  result[y] = KTextEditor::Range::invalid();
507  FAST_DEBUG("capture []");
508  }
509  else
510  {
511  const int closeIndex = openIndex + regexp.cap(y).length();
512  FAST_DEBUG("result range " << y << ": (" << j << ", " << openIndex << ")..(" << j << ", " << closeIndex << ")");
513  result[y] = KTextEditor::Range(j, openIndex, j, closeIndex);
514  }
515  }
516  return result;
517  }
518  else
519  {
520  FAST_DEBUG("searchText | line " << j << ": no");
521  }
522  }
523  }
524 
525  QVector<KTextEditor::Range> result;
526  result.append(KTextEditor::Range::invalid());
527  return result;
528 }
529 
530 
531 /*static*/ QString KateRegExpSearch::escapePlaintext(const QString & text)
532 {
533  return buildReplacement(text, QStringList(), 0, false);
534 }
535 
536 
537 /*static*/ QString KateRegExpSearch::buildReplacement(const QString & text, const QStringList &capturedTexts, int replacementCounter)
538 {
539  return buildReplacement(text, capturedTexts, replacementCounter, true);
540 }
541 
542 
543 /*static*/ QString KateRegExpSearch::buildReplacement(const QString & text, const QStringList &capturedTexts, int replacementCounter, bool replacementGoodies) {
544  // get input
545  const int inputLen = text.length();
546  int input = 0; // walker index
547 
548  // prepare output
549  ReplacementStream out(capturedTexts);
550 
551  while (input < inputLen)
552  {
553  switch (text[input].unicode())
554  {
555  case L'\n':
556  out << text[input];
557  input++;
558  break;
559 
560  case L'\\':
561  if (input + 1 >= inputLen)
562  {
563  // copy backslash
564  out << text[input];
565  input++;
566  break;
567  }
568 
569  switch (text[input + 1].unicode())
570  {
571  case L'0': // "\0000".."\0377"
572  if (input + 4 >= inputLen)
573  {
574  out << ReplacementStream::cap(0);
575  input += 2;
576  }
577  else
578  {
579  bool stripAndSkip = false;
580  const ushort text_2 = text[input + 2].unicode();
581  if ((text_2 >= L'0') && (text_2 <= L'3'))
582  {
583  const ushort text_3 = text[input + 3].unicode();
584  if ((text_3 >= L'0') && (text_3 <= L'7'))
585  {
586  const ushort text_4 = text[input + 4].unicode();
587  if ((text_4 >= L'0') && (text_4 <= L'7'))
588  {
589  int digits[3];
590  for (int i = 0; i < 3; i++)
591  {
592  digits[i] = 7 - (L'7' - text[input + 2 + i].unicode());
593  }
594  const int ch = 64 * digits[0] + 8 * digits[1] + digits[2];
595  out << QChar(ch);
596  input += 5;
597  }
598  else
599  {
600  stripAndSkip = true;
601  }
602  }
603  else
604  {
605  stripAndSkip = true;
606  }
607  }
608  else
609  {
610  stripAndSkip = true;
611  }
612 
613  if (stripAndSkip)
614  {
615  out << ReplacementStream::cap(0);
616  input += 2;
617  }
618  }
619  break;
620 
621  case L'1':
622  case L'2':
623  case L'3':
624  case L'4':
625  case L'5':
626  case L'6':
627  case L'7':
628  case L'8':
629  case L'9':
630  out << ReplacementStream::cap(9 - (L'9' - text[input + 1].unicode()));
631  input += 2;
632  break;
633 
634  case L'E': // FALLTHROUGH
635  case L'L': // FALLTHROUGH
636  case L'l': // FALLTHROUGH
637  case L'U': // FALLTHROUGH
638  case L'u':
639  if (!replacementGoodies) {
640  // strip backslash ("\?" -> "?")
641  out << text[input + 1];
642  } else {
643  // handle case switcher
644  switch (text[input + 1].unicode()) {
645  case L'L':
646  out << ReplacementStream::lowerCase;
647  break;
648 
649  case L'l':
650  out << ReplacementStream::lowerCaseFirst;
651  break;
652 
653  case L'U':
654  out << ReplacementStream::upperCase;
655  break;
656 
657  case L'u':
658  out << ReplacementStream::upperCaseFirst;
659  break;
660 
661  case L'E': // FALLTHROUGH
662  default:
663  out << ReplacementStream::keepCase;
664 
665  }
666  }
667  input += 2;
668  break;
669 
670  case L'#':
671  if (!replacementGoodies) {
672  // strip backslash ("\?" -> "?")
673  out << text[input + 1];
674  input += 2;
675  } else {
676  // handle replacement counter
677  // eat and count all following hash marks
678  // each hash stands for a leading zero: \### will produces 001, 002, ...
679  int minWidth = 1;
680  while ((input + minWidth + 1 < inputLen) && (text[input + minWidth + 1].unicode() == L'#')) {
681  minWidth++;
682  }
683  out << ReplacementStream::counter(replacementCounter, minWidth);
684  input += 1 + minWidth;
685  }
686  break;
687 
688  case L'a':
689  out << QChar(0x07);
690  input += 2;
691  break;
692 
693  case L'f':
694  out << QChar(0x0c);
695  input += 2;
696  break;
697 
698  case L'n':
699  out << QChar(0x0a);
700  input += 2;
701  break;
702 
703  case L'r':
704  out << QChar(0x0d);
705  input += 2;
706  break;
707 
708  case L't':
709  out << QChar(0x09);
710  input += 2;
711  break;
712 
713  case L'v':
714  out << QChar(0x0b);
715  input += 2;
716  break;
717 
718  case L'x': // "\x0000".."\xffff"
719  if (input + 5 >= inputLen)
720  {
721  // strip backslash ("\x" -> "x")
722  out << text[input + 1];
723  input += 2;
724  }
725  else
726  {
727  bool stripAndSkip = false;
728  const ushort text_2 = text[input + 2].unicode();
729  if (((text_2 >= L'0') && (text_2 <= L'9'))
730  || ((text_2 >= L'a') && (text_2 <= L'f'))
731  || ((text_2 >= L'A') && (text_2 <= L'F')))
732  {
733  const ushort text_3 = text[input + 3].unicode();
734  if (((text_3 >= L'0') && (text_3 <= L'9'))
735  || ((text_3 >= L'a') && (text_3 <= L'f'))
736  || ((text_3 >= L'A') && (text_3 <= L'F')))
737  {
738  const ushort text_4 = text[input + 4].unicode();
739  if (((text_4 >= L'0') && (text_4 <= L'9'))
740  || ((text_4 >= L'a') && (text_4 <= L'f'))
741  || ((text_4 >= L'A') && (text_4 <= L'F')))
742  {
743  const ushort text_5 = text[input + 5].unicode();
744  if (((text_5 >= L'0') && (text_5 <= L'9'))
745  || ((text_5 >= L'a') && (text_5 <= L'f'))
746  || ((text_5 >= L'A') && (text_5 <= L'F')))
747  {
748  int digits[4];
749  for (int i = 0; i < 4; i++)
750  {
751  const ushort cur = text[input + 2 + i].unicode();
752  if ((cur >= L'0') && (cur <= L'9'))
753  {
754  digits[i] = 9 - (L'9' - cur);
755  }
756  else if ((cur >= L'a') && (cur <= L'f'))
757  {
758  digits[i] = 15 - (L'f' - cur);
759  }
760  else // if ((cur >= L'A') && (cur <= L'F')))
761  {
762  digits[i] = 15 - (L'F' - cur);
763  }
764  }
765 
766  const int ch = 4096 * digits[0] + 256 * digits[1] + 16 * digits[2] + digits[3];
767  out << QChar(ch);
768  input += 6;
769  }
770  else
771  {
772  stripAndSkip = true;
773  }
774  }
775  else
776  {
777  stripAndSkip = true;
778  }
779  }
780  else
781  {
782  stripAndSkip = true;
783  }
784  }
785 
786  if (stripAndSkip)
787  {
788  // strip backslash ("\x" -> "x")
789  out << text[input + 1];
790  input += 2;
791  }
792  }
793  break;
794 
795  default:
796  // strip backslash ("\?" -> "?")
797  out << text[input + 1];
798  input += 2;
799 
800  }
801  break;
802 
803  default:
804  out << text[input];
805  input++;
806 
807  }
808  }
809 
810  return out.str();
811 }
812 
813 
814 // Kill our helpers again
815 #ifdef FAST_DEBUG_ENABLE
816 # undef FAST_DEBUG_ENABLE
817 #endif
818 #undef FAST_DEBUG
819 
820 // kate: space-indent on; indent-width 2; replace-tabs on;
KateRegExp::lastIndexIn
int lastIndexIn(const QString &str, int offset, int end) const
This function is a replacement for QRegExp.lastIndexIn that returns the last match that would have be...
Definition: kateregexp.cpp:315
KateRegExp::numCaptures
int numCaptures() const
Definition: kateregexp.h:36
QString::append
QString & append(QChar ch)
QString::toUpper
QString toUpper() const
KateRegExp::pos
int pos(int nth=0) const
Definition: kateregexp.h:37
KateRegExp
Definition: kateregexp.h:27
KateRegExpSearch::buildReplacement
static QString buildReplacement(const QString &text, const QStringList &capturedTexts, int replacementCounter)
Returns a modified version of text where.
Definition: kateregexpsearch.cpp:537
KateRegExp::repairPattern
int repairPattern(bool &stillMultiLine)
Repairs a regular Expression pattern.
Definition: kateregexp.cpp:35
QMap::contains
bool contains(const Key &key) const
QString::end
iterator end()
QVector::append
void append(const T &value)
QChar
QMap::constBegin
const_iterator constBegin() const
QMap
KateRegExp::matchedLength
int matchedLength() const
Definition: kateregexp.h:39
KateRegExpSearch::escapePlaintext
static QString escapePlaintext(const QString &text)
Returns a modified version of text where escape sequences are resolved, e.g.
Definition: kateregexpsearch.cpp:531
KateRegExp::isValid
bool isValid() const
Definition: kateregexp.h:34
KateRegExp::cap
QString cap(int nth=0) const
Definition: kateregexp.h:38
FAST_DEBUG
#define FAST_DEBUG(x)
Definition: kateregexpsearch.cpp:37
kateregexpsearch.h
kateregexp.h
QString::number
QString number(int n, int base)
QMap::constEnd
const_iterator constEnd() const
QMap::const_iterator
QString
KateRegExp::isEmpty
bool isEmpty() const
Definition: kateregexp.h:33
QStringList
KateRegExpSearch::~KateRegExpSearch
~KateRegExpSearch()
Definition: kateregexpsearch.cpp:177
QString::right
QString right(int n) const
QString::toLower
QString toLower() const
KateRegExpSearch::KateRegExpSearch
KateRegExpSearch(KTextEditor::Document *document, Qt::CaseSensitivity caseSensitivity)
Definition: kateregexpsearch.cpp:168
QLatin1Char
QChar::toLower
QChar toLower() const
KateRegExpSearch::search
QVector< KTextEditor::Range > search(const QString &pattern, const KTextEditor::Range &inputRange, bool backwards=false)
Search for the regular expression regexp inside the range inputRange.
Definition: kateregexpsearch.cpp:201
QString::mid
QString mid(int position, int n) const
QVector< KTextEditor::Range >
QChar::toUpper
QChar toUpper() const
QString::at
const QChar at(int position) const
QString::length
int length() const
KateRegExp::indexIn
int indexIn(const QString &str, int offset, int end) const
Definition: kateregexp.cpp:308
QMap::insert
iterator insert(const Key &key, const T &value)
QVector::end
iterator end()
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Sat May 9 2020 03:56:58 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

Kate

Skip menu "Kate"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

applications API Reference

Skip menu "applications API Reference"
  •   kate
  •       kate
  •   KTextEditor
  •   Kate
  • Konsole

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal