32 #include <QtGui/QLineEdit> 
   33 #include <QtGui/QVBoxLayout> 
   34 #include <QtGui/QLabel> 
   35 #include <QtGui/QCompleter> 
   36 #include <QtGui/QApplication> 
   37 #include <KDE/KColorScheme> 
   44     return s1.toLower() < s2.toLower();
 
   47   bool isCharEscaped(
const QString& 
string, 
int charPos)
 
   53     int numContiguousBackslashesToLeft = 0;
 
   55     while (charPos >= 0 && 
string[charPos] == 
'\\')
 
   57       numContiguousBackslashesToLeft++;
 
   60     return ((numContiguousBackslashesToLeft % 2) == 1);
 
   63   QString toggledEscaped(
const QString& originalString, QChar escapeChar)
 
   66     QString toggledEscapedString = originalString;
 
   69       const int indexOfEscapeChar = toggledEscapedString.indexOf(escapeChar , searchFrom);
 
   70       if (indexOfEscapeChar == -1)
 
   74       if (!isCharEscaped(toggledEscapedString, indexOfEscapeChar))
 
   77         toggledEscapedString.replace(indexOfEscapeChar, 1, 
QString(
"\\") + escapeChar);
 
   78         searchFrom = indexOfEscapeChar + 2;
 
   83         toggledEscapedString.remove(indexOfEscapeChar - 1, 1);
 
   84         searchFrom = indexOfEscapeChar;
 
   88     return toggledEscapedString;
 
   91   QString ensuredCharEscaped(
const QString& originalString, QChar charToEscape)
 
   93       QString escapedString = originalString;
 
   94       for (
int i = 0; i < escapedString.length(); i++)
 
   96         if (escapedString[i] == charToEscape && !isCharEscaped(escapedString, i))
 
   98           escapedString.replace(i, 1, 
QString(
"\\") + charToEscape);
 
  101       return escapedString;
 
  106     QString qtRegexPattern = vimRegexPattern;
 
  107     qtRegexPattern = toggledEscaped(qtRegexPattern, 
'(');
 
  108     qtRegexPattern = toggledEscaped(qtRegexPattern, 
')');
 
  109     qtRegexPattern = toggledEscaped(qtRegexPattern, 
'+');
 
  110     qtRegexPattern = toggledEscaped(qtRegexPattern, 
'|');
 
  111     qtRegexPattern = ensuredCharEscaped(qtRegexPattern, 
'?');
 
  115       bool lookingForMatchingCloseBracket = 
false;
 
  116       QList<int> matchingClosedCurlyBracketPositions;
 
  117       for (
int i = 0; i < qtRegexPattern.length(); i++)
 
  119         if (qtRegexPattern[i] == 
'{' && isCharEscaped(qtRegexPattern, i))
 
  121           lookingForMatchingCloseBracket = 
true;
 
  123         if (qtRegexPattern[i] == 
'}' && lookingForMatchingCloseBracket && qtRegexPattern[i - 1] != 
'\\')
 
  125           matchingClosedCurlyBracketPositions.append(i);
 
  128       if (matchingClosedCurlyBracketPositions.isEmpty())
 
  131         qtRegexPattern = toggledEscaped(qtRegexPattern, 
'{');
 
  132         qtRegexPattern = toggledEscaped(qtRegexPattern, 
'}');
 
  138         QString qtRegexPatternNonMatchingCurliesToggled;
 
  139         int previousNonMatchingClosedCurlyPos = 0; 
 
  142         foreach (
int matchingClosedCurlyPos, matchingClosedCurlyBracketPositions)
 
  144           QString chunkExcludingMatchingCurlyClosed = qtRegexPattern.mid(previousNonMatchingClosedCurlyPos, matchingClosedCurlyPos - previousNonMatchingClosedCurlyPos);
 
  145           chunkExcludingMatchingCurlyClosed = toggledEscaped(chunkExcludingMatchingCurlyClosed, 
'{');
 
  146           chunkExcludingMatchingCurlyClosed = toggledEscaped(chunkExcludingMatchingCurlyClosed, 
'}');
 
  147           qtRegexPatternNonMatchingCurliesToggled += chunkExcludingMatchingCurlyClosed +
 
  148                                                      qtRegexPattern[matchingClosedCurlyPos];
 
  149           previousNonMatchingClosedCurlyPos = matchingClosedCurlyPos + 1;
 
  151         QString chunkAfterLastMatchingClosedCurly = qtRegexPattern.mid(matchingClosedCurlyBracketPositions.last() + 1);
 
  152         chunkAfterLastMatchingClosedCurly = toggledEscaped(chunkAfterLastMatchingClosedCurly, 
'{');
 
  153         chunkAfterLastMatchingClosedCurly = toggledEscaped(chunkAfterLastMatchingClosedCurly, 
'}');
 
  154         qtRegexPatternNonMatchingCurliesToggled += chunkAfterLastMatchingClosedCurly;
 
  156         qtRegexPattern = qtRegexPatternNonMatchingCurliesToggled;
 
  163     bool lookingForMatchingCloseBracket = 
false;
 
  164     int openingBracketPos = -1;
 
  166     for (
int i = 0; i < qtRegexPattern.length(); i++)
 
  168       if (qtRegexPattern[i] == 
'[' && !isCharEscaped(qtRegexPattern, i) && !lookingForMatchingCloseBracket)
 
  170         lookingForMatchingCloseBracket = 
true;
 
  171         openingBracketPos = i;
 
  173       if (qtRegexPattern[i] == 
']' && lookingForMatchingCloseBracket && !isCharEscaped(qtRegexPattern, i))
 
  175         lookingForMatchingCloseBracket = 
false;
 
  176         matchingSquareBracketPositions.append(openingBracketPos);
 
  177         matchingSquareBracketPositions.append(i);
 
  181     if (matchingSquareBracketPositions.isEmpty())
 
  184       qtRegexPattern = ensuredCharEscaped(qtRegexPattern, 
'[');
 
  185       qtRegexPattern = ensuredCharEscaped(qtRegexPattern, 
']');
 
  191       QString qtRegexPatternNonMatchingSquaresMadeLiteral;
 
  192       int previousNonMatchingSquareBracketPos = 0; 
 
  195       foreach (
int matchingSquareBracketPos, matchingSquareBracketPositions)
 
  197         QString chunkExcludingMatchingSquareBrackets = qtRegexPattern.mid(previousNonMatchingSquareBracketPos, matchingSquareBracketPos - previousNonMatchingSquareBracketPos);
 
  198         chunkExcludingMatchingSquareBrackets = ensuredCharEscaped(chunkExcludingMatchingSquareBrackets, 
'[');
 
  199         chunkExcludingMatchingSquareBrackets = ensuredCharEscaped(chunkExcludingMatchingSquareBrackets, 
']');
 
  200         qtRegexPatternNonMatchingSquaresMadeLiteral += chunkExcludingMatchingSquareBrackets + qtRegexPattern[matchingSquareBracketPos];
 
  201         previousNonMatchingSquareBracketPos = matchingSquareBracketPos + 1;
 
  203       QString chunkAfterLastMatchingSquareBracket = qtRegexPattern.mid(matchingSquareBracketPositions.last() + 1);
 
  204       chunkAfterLastMatchingSquareBracket = ensuredCharEscaped(chunkAfterLastMatchingSquareBracket, 
'[');
 
  205       chunkAfterLastMatchingSquareBracket = ensuredCharEscaped(chunkAfterLastMatchingSquareBracket, 
']');
 
  206       qtRegexPatternNonMatchingSquaresMadeLiteral += chunkAfterLastMatchingSquareBracket;
 
  208       qtRegexPattern = qtRegexPatternNonMatchingSquaresMadeLiteral;
 
  212     qtRegexPattern = qtRegexPattern.replace(
"\\>", 
"\\b");
 
  213     qtRegexPattern = qtRegexPattern.replace(
"\\<", 
"\\b");
 
  215     return qtRegexPattern;
 
  222   QString escapedForSearchingAsLiteral(
const QString& originalQtRegex)
 
  224     QString escapedForSearchingAsLiteral = originalQtRegex;
 
  225     escapedForSearchingAsLiteral.replace(
'\\', 
"\\\\");
 
  226     escapedForSearchingAsLiteral.replace(
'$', 
"\\$");
 
  227     escapedForSearchingAsLiteral.replace(
'^', 
"\\^");
 
  228     escapedForSearchingAsLiteral.replace(
'.', 
"\\.");
 
  229     escapedForSearchingAsLiteral.replace(
'*', 
"\\*");
 
  230     escapedForSearchingAsLiteral.replace(
'/', 
"\\/");
 
  231     escapedForSearchingAsLiteral.replace(
'[', 
"\\[");
 
  232     escapedForSearchingAsLiteral.replace(
']', 
"\\]");
 
  233     escapedForSearchingAsLiteral.replace(
'\n', 
"\\n");
 
  234     return escapedForSearchingAsLiteral;
 
  240     std::reverse(reversedList.begin(), reversedList.end());
 
  245   QString withCaseSensitivityMarkersStripped(
const QString& originalSearchTerm)
 
  249     QString caseSensitivityMarkersStripped = originalSearchTerm;
 
  250     while (pos < caseSensitivityMarkersStripped.length())
 
  252       if (caseSensitivityMarkersStripped.at(pos) == 
'C' && isCharEscaped(caseSensitivityMarkersStripped, pos))
 
  254         caseSensitivityMarkersStripped.replace(pos - 1, 2, 
"");
 
  259     return caseSensitivityMarkersStripped;
 
  262   int findPosOfSearchConfigMarker(
const QString& searchText, 
const bool isSearchBackwards)
 
  264     const QChar searchConfigMarkerChar = (isSearchBackwards ? 
'?' : 
'/');
 
  265     for (
int pos = 0; pos < searchText.length(); pos++)
 
  267       if (searchText.at(pos) == searchConfigMarkerChar)
 
  269         if (!isCharEscaped(searchText, pos))
 
  278   bool isRepeatLastSearch(
const QString& searchText, 
const bool isSearchBackwards)
 
  280     const int posOfSearchConfigMarker = findPosOfSearchConfigMarker(searchText, isSearchBackwards);
 
  281     if (posOfSearchConfigMarker != -1)
 
  283       if (searchText.left(posOfSearchConfigMarker).isEmpty())
 
  291   bool shouldPlaceCursorAtEndOfMatch(
const QString& searchText, 
const bool isSearchBackwards)
 
  293     const int posOfSearchConfigMarker = findPosOfSearchConfigMarker(searchText, isSearchBackwards);
 
  294     if (posOfSearchConfigMarker != -1)
 
  296       if (searchText.length() > posOfSearchConfigMarker + 1 && searchText.at(posOfSearchConfigMarker + 1) == 
'e')
 
  304   QString withSearchConfigRemoved(
const QString& originalSearchText, 
const bool isSearchBackwards)
 
  306     const int posOfSearchConfigMarker = findPosOfSearchConfigMarker(originalSearchText, isSearchBackwards);
 
  307     if (posOfSearchConfigMarker == -1)
 
  309       return originalSearchText;
 
  313       return originalSearchText.left(posOfSearchConfigMarker);
 
  324       m_suspendEditEventFiltering(false),
 
  325       m_waitingForRegister(false),
 
  326       m_insertedTextShouldBeEscapedForSearchingAsLiteral(false),
 
  327       m_commandResponseMessageTimeOutMS(4000),
 
  328       m_isNextTextChangeDueToCompletionChange(false),
 
  329       m_currentCompletionType(
None),
 
  330       m_currentSearchIsCaseSensitive(false),
 
  331       m_currentSearchIsBackwards(false),
 
  332       m_currentSearchPlacesCursorAtEndOfMatch(false),
 
  333       m_isSendingSyntheticSearchCompletedKeypress(false)
 
  335   QHBoxLayout * layout = 
new QHBoxLayout();
 
  337   m_barTypeIndicator = 
new QLabel(
this);
 
  338   m_barTypeIndicator->setObjectName(
"bartypeindicator");
 
  339   layout->addWidget(m_barTypeIndicator);
 
  342   m_edit->setObjectName(
"commandtext");
 
  343   layout->addWidget(m_edit);
 
  345   m_commandResponseMessageDisplay = 
new QLabel(
this);
 
  346   m_commandResponseMessageDisplay->setObjectName(
"commandresponsemessage");
 
  347   m_commandResponseMessageDisplay->setAlignment(Qt::AlignLeft);
 
  348   layout->addWidget(m_commandResponseMessageDisplay);
 
  350   m_waitingForRegisterIndicator = 
new QLabel(
this);
 
  351   m_waitingForRegisterIndicator->setObjectName(
"waitingforregisterindicator");
 
  352   m_waitingForRegisterIndicator->setVisible(
false);
 
  353   m_waitingForRegisterIndicator->setText(
"\"");
 
  354   layout->addWidget(m_waitingForRegisterIndicator);
 
  356   m_interactiveSedReplaceLabel = 
new QLabel(
this);
 
  357   m_interactiveSedReplaceLabel->setObjectName(
"interactivesedreplace");
 
  358   m_interactiveSedReplaceActive = 
false;
 
  359   layout->addWidget(m_interactiveSedReplaceLabel);
 
  361   updateMatchHighlightAttrib();
 
  363   m_highlightedMatch->
setView(m_view); 
 
  366   m_highlightedMatch->
setZDepth (-10000.0);
 
  367   m_highlightedMatch->
setAttribute(m_highlightMatchAttribute);
 
  368   connect(m_view, SIGNAL(configChanged()),
 
  369           this, SLOT(updateMatchHighlightAttrib()));
 
  371   m_edit->installEventFilter(
this);
 
  372   connect(m_edit, SIGNAL(textChanged(
QString)), 
this, SLOT(editTextChanged(
QString)));
 
  374   m_completer = 
new QCompleter(
QStringList(), m_edit);
 
  377   m_completer->setWidget(m_edit);
 
  378   m_completer->setObjectName(
"completer");
 
  379   m_completionModel = 
new QStringListModel;
 
  380   m_completer->setModel(m_completionModel);
 
  381   m_completer->setCaseSensitivity(Qt::CaseInsensitive);
 
  382   m_completer->popup()->installEventFilter(
this);
 
  384   m_commandResponseMessageDisplayHide = 
new QTimer(
this);
 
  385   m_commandResponseMessageDisplayHide->setSingleShot(
true);
 
  386   connect(m_commandResponseMessageDisplayHide, SIGNAL(
timeout()),
 
  391   connect(m_view, SIGNAL(focusOut(
KTextEditor::View*)), m_commandResponseMessageDisplayHide, SLOT(
stop()));
 
  393   connect(m_view, SIGNAL(focusIn(
KTextEditor::View*)), 
this, SLOT(startHideCommandResponseTimer()));
 
  398   delete m_highlightedMatch;
 
  403   m_currentCompletionType = None;
 
  408   showBarTypeIndicator(mode);
 
  410   setBarBackground(Normal);
 
  414   m_interactiveSedReplaceActive = 
false;
 
  415   m_interactiveSedReplaceLabel->hide();
 
  418   m_edit->setText(initialText);
 
  421   m_commandResponseMessageDisplay->hide();
 
  422   m_commandResponseMessageDisplayHide->stop();
 
  428   while(QApplication::hasPendingEvents())
 
  430     QApplication::processEvents();
 
  441   m_commandResponseMessageTimeOutMS = commandResponseMessageTimeOutMS;
 
  447   if (m_startingCursorPos.
isValid())
 
  451       moveCursorTo(m_startingCursorPos);
 
  455   updateMatchHighlight(Range::invalid());
 
  456   m_completer->popup()->hide();
 
  464     const Qt::Key syntheticSearchCompletedKey = (m_wasAborted ? 
static_cast<Qt::Key
>(0) : Qt::Key_Enter);
 
  465     QKeyEvent syntheticSearchCompletedKeyPress(QEvent::KeyPress, syntheticSearchCompletedKey, Qt::NoModifier);
 
  466     m_isSendingSyntheticSearchCompletedKeypress = 
true;
 
  467     QApplication::sendEvent(m_view->focusProxy(), &syntheticSearchCompletedKeyPress);
 
  468     m_isSendingSyntheticSearchCompletedKeypress = 
false;
 
  492 void KateViEmulatedCommandBar::updateMatchHighlightAttrib()
 
  495   if (!m_highlightMatchAttribute)
 
  499   m_highlightMatchAttribute->setBackground(matchColour);
 
  505 void KateViEmulatedCommandBar::updateMatchHighlight(
const Range& matchRange)
 
  509   m_highlightedMatch->
setRange(matchRange);
 
  512 void KateViEmulatedCommandBar::setBarBackground(KateViEmulatedCommandBar::BarBackgroundStatus status)
 
  514     QPalette barBackground(m_edit->palette());
 
  529         barBackground = QPalette();
 
  533     m_edit->setPalette(barBackground);
 
  536 bool KateViEmulatedCommandBar::eventFilter(
QObject* 
object, 
QEvent* event)
 
  538   Q_ASSERT(
object == m_edit || 
object == m_completer->popup());
 
  539   if (m_suspendEditEventFiltering)
 
  544   if (event->type() == QEvent::KeyPress)
 
  553 void KateViEmulatedCommandBar::deleteSpacesToLeftOfCursor()
 
  555   while (m_edit->cursorPosition() != 0 && m_edit->text()[m_edit->cursorPosition() - 1] == 
' ')
 
  561 void KateViEmulatedCommandBar::deleteWordCharsToLeftOfCursor()
 
  563   while (m_edit->cursorPosition() != 0)
 
  565     const QChar charToTheLeftOfCursor = m_edit->text()[m_edit->cursorPosition() - 1];
 
  566     if (!charToTheLeftOfCursor.isLetterOrNumber() && charToTheLeftOfCursor != 
'_')
 
  575 bool KateViEmulatedCommandBar::deleteNonWordCharsToLeftOfCursor()
 
  577   bool deletionsMade = 
false;
 
  578   while (m_edit->cursorPosition() != 0)
 
  580     const QChar charToTheLeftOfCursor = m_edit->text()[m_edit->cursorPosition() - 1];
 
  581     if (charToTheLeftOfCursor.isLetterOrNumber() || charToTheLeftOfCursor == 
'_' || charToTheLeftOfCursor == 
' ')
 
  587     deletionsMade = 
true;
 
  589   return deletionsMade;
 
  592 QString KateViEmulatedCommandBar::wordBeforeCursor()
 
  594   int wordBeforeCursorBegin = m_edit->cursorPosition() - 1;
 
  595   while (wordBeforeCursorBegin >= 0 && (m_edit->text()[wordBeforeCursorBegin].isLetterOrNumber() || m_edit->text()[wordBeforeCursorBegin] == 
'_'))
 
  597     wordBeforeCursorBegin--;
 
  599   wordBeforeCursorBegin++;
 
  600   return m_edit->text().mid(wordBeforeCursorBegin, m_edit->cursorPosition() - wordBeforeCursorBegin);
 
  603 QString KateViEmulatedCommandBar::commandBeforeCursor()
 
  605   const QString textWithoutRangeExpression = withoutRangeExpression();
 
  606   const int cursorPositionWithoutRangeExpression = m_edit->cursorPosition() - rangeExpression().length();
 
  607   int commandBeforeCursorBegin = cursorPositionWithoutRangeExpression - 1;
 
  608   while (commandBeforeCursorBegin >= 0 && (textWithoutRangeExpression[commandBeforeCursorBegin].isLetterOrNumber() || textWithoutRangeExpression[commandBeforeCursorBegin] == 
'_' || textWithoutRangeExpression[commandBeforeCursorBegin] == 
'-'))
 
  610     commandBeforeCursorBegin--;
 
  612   commandBeforeCursorBegin++;
 
  613   return textWithoutRangeExpression.mid(commandBeforeCursorBegin, cursorPositionWithoutRangeExpression - commandBeforeCursorBegin);
 
  617 void KateViEmulatedCommandBar::replaceWordBeforeCursorWith(
const QString& newWord)
 
  619   const int wordBeforeCursorStart = m_edit->cursorPosition() - wordBeforeCursor().length();
 
  620   const QString newText = m_edit->text().left(m_edit->cursorPosition() - wordBeforeCursor().length()) +
 
  622   m_edit->text().mid(m_edit->cursorPosition());
 
  623   m_edit->setText(newText);
 
  624   m_edit->setCursorPosition(wordBeforeCursorStart + newWord.length());
 
  627 void KateViEmulatedCommandBar::replaceCommandBeforeCursorWith(
const QString& newCommand)
 
  629   const QString newText = m_edit->text().left(m_edit->cursorPosition() - commandBeforeCursor().length()) +
 
  631   m_edit->text().mid(m_edit->cursorPosition());
 
  632   m_edit->setText(newText);
 
  636 void KateViEmulatedCommandBar::activateSearchHistoryCompletion()
 
  638   m_currentCompletionType = SearchHistory;
 
  639   m_completionModel->setStringList(reversed(
KateGlobal::self()->viInputModeGlobal()->searchHistory()));
 
  640   updateCompletionPrefix();
 
  641   m_completer->complete();
 
  644 void KateViEmulatedCommandBar::activateWordFromDocumentCompletion()
 
  646   m_currentCompletionType = WordFromDocument;
 
  647   QRegExp wordRegEx(
"\\w{1,}");
 
  652   for (
int lineNum = startLine; lineNum < endLine; lineNum++)
 
  655     int wordSearchBeginPos = 0;
 
  656     while (wordRegEx.indexIn(line, wordSearchBeginPos) != -1)
 
  658       const QString foundWord = wordRegEx.cap(0);
 
  659       foundWords << foundWord;
 
  660       wordSearchBeginPos = wordRegEx.indexIn(line, wordSearchBeginPos) + wordRegEx.matchedLength();
 
  664   qSort(foundWords.begin(), foundWords.end(), caseInsensitiveLessThan);
 
  665   m_completionModel->setStringList(foundWords);
 
  666   updateCompletionPrefix();
 
  667   m_completer->complete();
 
  670 void KateViEmulatedCommandBar::activateCommandCompletion()
 
  672   m_completionModel->setStringList(
KateCmd::self()->commandCompletionObject()->items());
 
  673   m_currentCompletionType = Commands;
 
  676 void KateViEmulatedCommandBar::activateCommandHistoryCompletion()
 
  678   m_currentCompletionType = CommandHistory;
 
  679   m_completionModel->setStringList(reversed(
KateGlobal::self()->viInputModeGlobal()->commandHistory()));
 
  680   updateCompletionPrefix();
 
  681   m_completer->complete();
 
  684 void KateViEmulatedCommandBar::activateSedFindHistoryCompletion()
 
  688     m_currentCompletionType = SedFindHistory;
 
  689     m_completionModel->setStringList(reversed(
KateGlobal::self()->viInputModeGlobal()->searchHistory()));
 
  690     m_completer->setCompletionPrefix(sedFindTerm());
 
  691     m_completer->complete();
 
  695 void KateViEmulatedCommandBar::activateSedReplaceHistoryCompletion()
 
  699     m_currentCompletionType = SedReplaceHistory;
 
  700     m_completionModel->setStringList(reversed(
KateGlobal::self()->viInputModeGlobal()->replaceHistory()));
 
  701     m_completer->setCompletionPrefix(sedReplaceTerm());
 
  702     m_completer->complete();
 
  706 void KateViEmulatedCommandBar::deactivateCompletion()
 
  708   kDebug(13070) << 
"Manually dismissing completions";
 
  709   m_completer->popup()->hide();
 
  710   m_currentCompletionType = None;
 
  713 void KateViEmulatedCommandBar::abortCompletionAndResetToPreCompletion()
 
  715   deactivateCompletion();
 
  716   m_isNextTextChangeDueToCompletionChange = 
true;
 
  717   m_edit->setText(m_textToRevertToIfCompletionAborted);
 
  718   m_edit->setCursorPosition(m_cursorPosToRevertToIfCompletionAborted);
 
  719   m_isNextTextChangeDueToCompletionChange = 
false;
 
  722 void KateViEmulatedCommandBar::updateCompletionPrefix()
 
  725   if (m_currentCompletionType == WordFromDocument)
 
  727     m_completer->setCompletionPrefix(wordBeforeCursor());
 
  729   else if (m_currentCompletionType == SearchHistory)
 
  731     m_completer->setCompletionPrefix(m_edit->text());
 
  733   else if (m_currentCompletionType == CommandHistory)
 
  735     m_completer->setCompletionPrefix(m_edit->text());
 
  737   else if (m_currentCompletionType == Commands)
 
  739     m_completer->setCompletionPrefix(commandBeforeCursor());
 
  743     Q_ASSERT(
false && 
"Unhandled completion type");
 
  746   m_completer->complete();
 
  749 void KateViEmulatedCommandBar::currentCompletionChanged()
 
  752   const QString newCompletion = m_completer->currentCompletion();
 
  753   if (newCompletion.isEmpty())
 
  757   m_isNextTextChangeDueToCompletionChange = 
true;
 
  758   if (m_currentCompletionType == WordFromDocument)
 
  760     replaceWordBeforeCursorWith(newCompletion);
 
  762   else if (m_currentCompletionType == SearchHistory)
 
  764     m_edit->setText(newCompletion);
 
  766   else if (m_currentCompletionType == CommandHistory)
 
  768     m_edit->setText(newCompletion);
 
  770   else if (m_currentCompletionType == Commands)
 
  772     const int newCursorPosition = m_edit->cursorPosition() + (newCompletion.length() - commandBeforeCursor().length());
 
  773     replaceCommandBeforeCursorWith(newCompletion);
 
  774     m_edit->setCursorPosition(newCursorPosition);
 
  776   else if (m_currentCompletionType == SedFindHistory)
 
  778     m_edit->setText(withSedFindTermReplacedWith(withCaseSensitivityMarkersStripped(withSedDelimiterEscaped(newCompletion))));
 
  779     ParsedSedExpression parsedSedExpression = parseAsSedExpression();
 
  780     m_edit->setCursorPosition(parsedSedExpression.findEndPos + 1);
 
  782   else if (m_currentCompletionType == SedReplaceHistory)
 
  784     m_edit->setText(withSedReplaceTermReplacedWith(withSedDelimiterEscaped(newCompletion)));
 
  785     ParsedSedExpression parsedSedExpression = parseAsSedExpression();
 
  786     m_edit->setCursorPosition(parsedSedExpression.replaceEndPos + 1);
 
  790     Q_ASSERT(
false && 
"Something went wrong, here - completion with unrecognised completion type");
 
  792   m_isNextTextChangeDueToCompletionChange = 
false;
 
  795 void KateViEmulatedCommandBar::setCompletionIndex(
int index)
 
  797   const QModelIndex modelIndex = m_completer->popup()->model()->index(index, 0);
 
  799   m_completer->popup()->setCurrentIndex(modelIndex);
 
  800   m_completer->setCurrentRow(index);
 
  802   m_completer->popup()->scrollTo(modelIndex);
 
  804   currentCompletionChanged();
 
  807 KateViEmulatedCommandBar::ParsedSedExpression KateViEmulatedCommandBar::parseAsSedExpression()
 
  809   const QString commandWithoutRangeExpression = withoutRangeExpression();
 
  810   ParsedSedExpression parsedSedExpression;
 
  812   parsedSedExpression.parsedSuccessfully = 
KateCommands::SedReplace::parse(commandWithoutRangeExpression, delimiter, parsedSedExpression.findBeginPos, parsedSedExpression.findEndPos, parsedSedExpression.replaceBeginPos, parsedSedExpression.replaceEndPos);
 
  813   if (parsedSedExpression.parsedSuccessfully)
 
  815     parsedSedExpression.delimiter = delimiter.at(0);
 
  816     if (parsedSedExpression.replaceBeginPos == -1)
 
  818       if (parsedSedExpression.findBeginPos != -1)
 
  822         parsedSedExpression.replaceBeginPos = commandWithoutRangeExpression.indexOf(delimiter, parsedSedExpression.findEndPos) + 1;
 
  823         parsedSedExpression.replaceEndPos = parsedSedExpression.replaceBeginPos - 1;
 
  828         parsedSedExpression.replaceBeginPos = 0;
 
  829         for (
int delimiterCount = 1; delimiterCount <= 3; delimiterCount++)
 
  831           parsedSedExpression.replaceBeginPos = commandWithoutRangeExpression.indexOf(delimiter, parsedSedExpression.replaceBeginPos + 1);
 
  833         parsedSedExpression.replaceEndPos = parsedSedExpression.replaceBeginPos - 1;
 
  836     if (parsedSedExpression.findBeginPos == -1)
 
  840       parsedSedExpression.findBeginPos = commandWithoutRangeExpression.indexOf(delimiter) + 1;
 
  841       parsedSedExpression.findEndPos = parsedSedExpression.findBeginPos - 1;
 
  846   if (parsedSedExpression.parsedSuccessfully)
 
  848     parsedSedExpression.findBeginPos += rangeExpression().length();
 
  849     parsedSedExpression.findEndPos += rangeExpression().length();
 
  850     parsedSedExpression.replaceBeginPos += rangeExpression().length();
 
  851     parsedSedExpression.replaceEndPos += rangeExpression().length();
 
  853   return parsedSedExpression;
 
  856 QString KateViEmulatedCommandBar::withSedFindTermReplacedWith(
const QString& newFindTerm)
 
  858   const QString command = m_edit->text();
 
  859   ParsedSedExpression parsedSedExpression = parseAsSedExpression();
 
  860   Q_ASSERT(parsedSedExpression.parsedSuccessfully);
 
  861   return command.mid(0, parsedSedExpression.findBeginPos) +
 
  863     command.mid(parsedSedExpression.findEndPos + 1);
 
  867 QString KateViEmulatedCommandBar::withSedReplaceTermReplacedWith(
const QString& newReplaceTerm)
 
  869   const QString command = m_edit->text();
 
  870   ParsedSedExpression parsedSedExpression = parseAsSedExpression();
 
  871   Q_ASSERT(parsedSedExpression.parsedSuccessfully);
 
  872   return command.mid(0, parsedSedExpression.replaceBeginPos) +
 
  874     command.mid(parsedSedExpression.replaceEndPos + 1);
 
  877 QString KateViEmulatedCommandBar::sedFindTerm()
 
  879   const QString command = m_edit->text();
 
  880   ParsedSedExpression parsedSedExpression = parseAsSedExpression();
 
  881   Q_ASSERT(parsedSedExpression.parsedSuccessfully);
 
  882   return command.mid(parsedSedExpression.findBeginPos, parsedSedExpression.findEndPos - parsedSedExpression.findBeginPos + 1);
 
  885 QString KateViEmulatedCommandBar::sedReplaceTerm()
 
  887   const QString command = m_edit->text();
 
  888   ParsedSedExpression parsedSedExpression = parseAsSedExpression();
 
  889   Q_ASSERT(parsedSedExpression.parsedSuccessfully);
 
  890   return command.mid(parsedSedExpression.replaceBeginPos, parsedSedExpression.replaceEndPos - parsedSedExpression.replaceBeginPos + 1);
 
  893 QString KateViEmulatedCommandBar::withSedDelimiterEscaped(
const QString& text)
 
  895   ParsedSedExpression parsedSedExpression = parseAsSedExpression();
 
  896   QString delimiterEscaped = ensuredCharEscaped(text, parsedSedExpression.delimiter);
 
  897   return delimiterEscaped;
 
  900 bool KateViEmulatedCommandBar::isCursorInFindTermOfSed()
 
  902   ParsedSedExpression parsedSedExpression = parseAsSedExpression();
 
  903   return parsedSedExpression.parsedSuccessfully && (m_edit->cursorPosition() >= parsedSedExpression.findBeginPos && m_edit->cursorPosition() <= parsedSedExpression.findEndPos + 1);
 
  906 bool KateViEmulatedCommandBar::isCursorInReplaceTermOfSed()
 
  908   ParsedSedExpression parsedSedExpression = parseAsSedExpression();
 
  909   return parsedSedExpression.parsedSuccessfully && m_edit->cursorPosition() >= parsedSedExpression.replaceBeginPos && m_edit->cursorPosition() <= parsedSedExpression.replaceEndPos + 1;
 
  912 QString KateViEmulatedCommandBar::withoutRangeExpression()
 
  914   const QString originalCommand = m_edit->text();
 
  915   return originalCommand.mid(rangeExpression().length());
 
  918 QString KateViEmulatedCommandBar::rangeExpression()
 
  922   const QString command = m_edit->text();
 
  924   return rangeExpression;
 
  929   if (keyEvent->modifiers() == Qt::ControlModifier && (keyEvent->key() == Qt::Key_C || keyEvent->key() == Qt::Key_BracketLeft) && !m_waitingForRegister)
 
  931     if (m_currentCompletionType == None || !m_completer->popup()->isVisible())
 
  937       abortCompletionAndResetToPreCompletion();
 
  941   if (m_interactiveSedReplaceActive)
 
  946     if (keyEvent->text() == 
"y" || keyEvent->text() == 
"n")
 
  948       const Cursor cursorPosIfFinalMatch = m_interactiveSedReplacer->currentMatch().start();
 
  949       if (keyEvent->text() == 
"y")
 
  951         m_interactiveSedReplacer->replaceCurrentMatch();
 
  955         m_interactiveSedReplacer->skipCurrentMatch();
 
  957       updateMatchHighlight(m_interactiveSedReplacer->currentMatch());
 
  958       updateInteractiveSedReplaceLabelText();
 
  959       moveCursorTo(m_interactiveSedReplacer->currentMatch().start());
 
  961       if (!m_interactiveSedReplacer->currentMatch().isValid())
 
  963         moveCursorTo(cursorPosIfFinalMatch);
 
  964         finishInteractiveSedReplace();
 
  968     else if (keyEvent->text() == 
"l")
 
  970       m_interactiveSedReplacer->replaceCurrentMatch();
 
  971       finishInteractiveSedReplace();
 
  974     else if (keyEvent->text() == 
"q")
 
  976       finishInteractiveSedReplace();
 
  979     else if (keyEvent->text() == 
"a")
 
  981       m_interactiveSedReplacer->replaceAllRemaining();
 
  982       finishInteractiveSedReplace();
 
  987   if (keyEvent->modifiers() == Qt::ControlModifier && keyEvent->key() == Qt::Key_Space)
 
  989     activateWordFromDocumentCompletion();
 
  992   if (keyEvent->modifiers() == Qt::ControlModifier && keyEvent->key() == Qt::Key_P)
 
  994     if (!m_completer->popup()->isVisible())
 
  998         if (isCursorInFindTermOfSed())
 
 1000           activateSedFindHistoryCompletion();
 
 1002         else if (isCursorInReplaceTermOfSed())
 
 1004           activateSedReplaceHistoryCompletion();
 
 1008           activateCommandHistoryCompletion();
 
 1013         activateSearchHistoryCompletion();
 
 1015       if (m_currentCompletionType != None)
 
 1017         setCompletionIndex(0);
 
 1023       if (m_completer->currentRow() + 1 == m_completer->completionCount())
 
 1025         setCompletionIndex(0);
 
 1029         setCompletionIndex(m_completer->currentRow() + 1);
 
 1034   if (keyEvent->modifiers() == Qt::ControlModifier && keyEvent->key() == Qt::Key_N)
 
 1036     if (!m_completer->popup()->isVisible())
 
 1040         activateCommandHistoryCompletion();
 
 1044         activateSearchHistoryCompletion();
 
 1046       setCompletionIndex(m_completer->completionCount() - 1);
 
 1051       if (m_completer->currentRow() == 0)
 
 1053         setCompletionIndex(m_completer->completionCount() - 1);
 
 1057         setCompletionIndex(m_completer->currentRow() - 1);
 
 1062   if (m_waitingForRegister)
 
 1064     if (keyEvent->key() != Qt::Key_Shift && keyEvent->key() != Qt::Key_Control)
 
 1068       const int oldCursorPosition = m_edit->cursorPosition();
 
 1070       if (keyEvent->modifiers() == Qt::ControlModifier && keyEvent->key() == Qt::Key_W)
 
 1078       if (m_insertedTextShouldBeEscapedForSearchingAsLiteral)
 
 1080         textToInsert = escapedForSearchingAsLiteral(textToInsert);
 
 1081         m_insertedTextShouldBeEscapedForSearchingAsLiteral = 
false;
 
 1083       m_edit->setText(m_edit->text().insert(m_edit->cursorPosition(), textToInsert));
 
 1084       m_edit->setCursorPosition(oldCursorPosition + textToInsert.length());
 
 1085       m_waitingForRegister = 
false;
 
 1086       m_waitingForRegisterIndicator->setVisible(
false);
 
 1089   else if ((keyEvent->modifiers() == Qt::ControlModifier && keyEvent->key() == Qt::Key_H) || keyEvent->key() == Qt::Key_Backspace)
 
 1091     if (m_edit->text().isEmpty())
 
 1095     m_edit->backspace();
 
 1098   else if (keyEvent->modifiers() == Qt::ControlModifier)
 
 1100     if (keyEvent->key() == Qt::Key_B)
 
 1102       m_edit->setCursorPosition(0);
 
 1105     else if (keyEvent->key() == Qt::Key_W)
 
 1107       deleteSpacesToLeftOfCursor();
 
 1108       if(!deleteNonWordCharsToLeftOfCursor())
 
 1110         deleteWordCharsToLeftOfCursor();
 
 1114     else if (keyEvent->key() == Qt::Key_R || keyEvent->key() == Qt::Key_G)
 
 1116       m_waitingForRegister = 
true;
 
 1117       m_waitingForRegisterIndicator->setVisible(
true);
 
 1118       if (keyEvent->key() == Qt::Key_G)
 
 1120         m_insertedTextShouldBeEscapedForSearchingAsLiteral = 
true;
 
 1124     else if (keyEvent->key() == Qt::Key_D || keyEvent->key() == Qt::Key_F)
 
 1128         ParsedSedExpression parsedSedExpression = parseAsSedExpression();
 
 1129         if (parsedSedExpression.parsedSuccessfully)
 
 1131           const bool clearFindTerm = (keyEvent->key() == Qt::Key_D);
 
 1134             m_edit->setSelection(parsedSedExpression.findBeginPos, parsedSedExpression.findEndPos - parsedSedExpression.findBeginPos + 1);
 
 1140             m_edit->setSelection(parsedSedExpression.replaceBeginPos, parsedSedExpression.replaceEndPos - parsedSedExpression.replaceBeginPos + 1);
 
 1149   else if (keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return)
 
 1151     if (m_completer->popup()->isVisible() && m_currentCompletionType == KateViEmulatedCommandBar::WordFromDocument)
 
 1153       deactivateCompletion();
 
 1157       m_wasAborted = 
false;
 
 1158       deactivateCompletion();
 
 1161         kDebug(13070) << 
"Executing: " << m_edit->text();
 
 1162         QString commandToExecute = m_edit->text();
 
 1163         ParsedSedExpression parsedSedExpression = parseAsSedExpression();
 
 1164         qDebug() << 
"text:\n" << m_edit->text() << 
"\n is sed replace: " << parsedSedExpression.parsedSuccessfully;
 
 1165         if (parsedSedExpression.parsedSuccessfully)
 
 1167           const QString originalFindTerm = sedFindTerm();
 
 1168           const QString convertedFindTerm = vimRegexToQtRegexPattern(originalFindTerm);
 
 1169           const QString commandWithSedSearchRegexConverted = withSedFindTermReplacedWith(convertedFindTerm);
 
 1171           const QString replaceTerm = sedReplaceTerm();
 
 1173           commandToExecute = commandWithSedSearchRegexConverted;
 
 1174           kDebug(13070) << 
"Command to execute after replacing search term: "<< commandToExecute;
 
 1177         const QString commandResponseMessage = executeCommand(commandToExecute);
 
 1178         if (!m_interactiveSedReplaceActive)
 
 1180           if (commandResponseMessage.isEmpty() && !m_interactiveSedReplaceActive)
 
 1186             switchToCommandResponseDisplay(commandResponseMessage);
 
 1200     m_suspendEditEventFiltering = 
true;
 
 1207     QKeyEvent keyEventCopy(keyEvent->type(), keyEvent->key(), keyEvent->modifiers(), keyEvent->text(), keyEvent->isAutoRepeat(), keyEvent->count());
 
 1208     if (!m_interactiveSedReplaceActive)
 
 1210       qApp->notify(m_edit, &keyEventCopy);
 
 1212     m_suspendEditEventFiltering = 
false;
 
 1219   return m_isSendingSyntheticSearchCompletedKeypress;
 
 1224   m_interactiveSedReplaceActive = 
true;
 
 1225   m_interactiveSedReplacer = interactiveSedReplace;
 
 1226   if (!interactiveSedReplace->currentMatch().isValid())
 
 1230     finishInteractiveSedReplace();
 
 1233   kDebug(13070) << 
"Starting incremental search and replace";
 
 1234   m_commandResponseMessageDisplay->hide();
 
 1236   m_barTypeIndicator->hide();
 
 1237   m_interactiveSedReplaceLabel->show();
 
 1238   updateMatchHighlight(interactiveSedReplace->currentMatch());
 
 1239   updateInteractiveSedReplaceLabelText();
 
 1240   moveCursorTo(interactiveSedReplace->currentMatch().start());
 
 1245   QChar barTypeIndicator = QChar::Null;
 
 1249       barTypeIndicator = 
'/';
 
 1252       barTypeIndicator = 
'?';
 
 1255       barTypeIndicator = 
':';
 
 1258       Q_ASSERT(
false && 
"Unknown mode!");
 
 1260   m_barTypeIndicator->setText(barTypeIndicator);
 
 1261   m_barTypeIndicator->show();
 
 1264 QString KateViEmulatedCommandBar::executeCommand(
const QString& commandToExecute)
 
 1272   Q_ASSERT(kateCommandLineEdit);
 
 1273   const QString commandResponseMessage = kateCommandLineEdit->text();
 
 1274   return commandResponseMessage;
 
 1277 void KateViEmulatedCommandBar::switchToCommandResponseDisplay(
const QString& commandResponseMessage)
 
 1282   m_interactiveSedReplaceLabel->hide();
 
 1283   m_barTypeIndicator->hide();
 
 1284   m_commandResponseMessageDisplay->show();
 
 1285   m_commandResponseMessageDisplay->setText(commandResponseMessage);
 
 1286   m_commandResponseMessageDisplayHide->start(m_commandResponseMessageTimeOutMS);
 
 1289 void KateViEmulatedCommandBar::updateInteractiveSedReplaceLabelText()
 
 1291   m_interactiveSedReplaceLabel->setText(m_interactiveSedReplacer->currentMatchReplacementConfirmationMessage() + 
" (y/n/a/q/l)");
 
 1294 void KateViEmulatedCommandBar::finishInteractiveSedReplace()
 
 1296   switchToCommandResponseDisplay(m_interactiveSedReplacer->finalStatusReportMessage());
 
 1297   m_interactiveSedReplacer.clear();
 
 1300 void KateViEmulatedCommandBar::moveCursorTo(
const Cursor& cursorPos)
 
 1309 void KateViEmulatedCommandBar::editTextChanged(
const QString& newText)
 
 1311   Q_ASSERT(!m_interactiveSedReplaceActive);
 
 1312   qDebug() << 
"New text: " << newText;
 
 1313   if (!m_isNextTextChangeDueToCompletionChange)
 
 1315     m_textToRevertToIfCompletionAborted = newText;
 
 1316     m_cursorPosToRevertToIfCompletionAborted = m_edit->cursorPosition();
 
 1320     QString qtRegexPattern = newText;
 
 1322     const bool placeCursorAtEndOfMatch = shouldPlaceCursorAtEndOfMatch(qtRegexPattern, searchBackwards);
 
 1323     if (isRepeatLastSearch(qtRegexPattern, searchBackwards))
 
 1329       qtRegexPattern = withSearchConfigRemoved(qtRegexPattern, searchBackwards);
 
 1330       qtRegexPattern = vimRegexToQtRegexPattern(qtRegexPattern);
 
 1335     bool caseSensitive = 
true;
 
 1336     if (qtRegexPattern.toLower() == qtRegexPattern)
 
 1338       caseSensitive = 
false;
 
 1341     qtRegexPattern = withCaseSensitivityMarkersStripped(qtRegexPattern);
 
 1343     qDebug() << 
"Final regex: " << qtRegexPattern;
 
 1345     m_currentSearchPattern = qtRegexPattern;
 
 1346     m_currentSearchIsCaseSensitive = caseSensitive;
 
 1347     m_currentSearchIsBackwards = searchBackwards;
 
 1348     m_currentSearchPlacesCursorAtEndOfMatch = placeCursorAtEndOfMatch;
 
 1358       if (realMatchEnd.
column() == -1)
 
 1362       moveCursorTo(placeCursorAtEndOfMatch ? realMatchEnd :  match.
start());
 
 1363       setBarBackground(MatchFound);
 
 1367       moveCursorTo(m_startingCursorPos);
 
 1368       if (!m_edit->text().isEmpty())
 
 1370         setBarBackground(NoMatchFound);
 
 1374         setBarBackground(Normal);
 
 1378     updateMatchHighlight(match);
 
 1382   if (m_mode == 
Command && m_currentCompletionType == None && !withoutRangeExpression().isEmpty())
 
 1384     activateCommandCompletion();
 
 1390   const bool commandBeforeCursorIsLeading = (m_edit->cursorPosition() - commandBeforeCursor().length() == rangeExpression().length());
 
 1391   if (m_mode == 
Command && !commandBeforeCursorIsLeading && m_currentCompletionType == Commands && !m_isNextTextChangeDueToCompletionChange)
 
 1393     deactivateCompletion();
 
 1398   if (!m_isNextTextChangeDueToCompletionChange && m_completer->popup()->currentIndex().row() != -1)
 
 1400     deactivateCompletion();
 
 1403   if (m_currentCompletionType != None && !m_isNextTextChangeDueToCompletionChange)
 
 1405     updateCompletionPrefix();
 
 1409 void KateViEmulatedCommandBar::startHideCommandResponseTimer()
 
 1411   if (m_commandResponseMessageDisplay->isVisible() && !m_commandResponseMessageDisplayHide->isActive())
 
 1413     m_commandResponseMessageDisplayHide->start(m_commandResponseMessageTimeOutMS);
 
void startInteractiveSearchAndReplace(QSharedPointer< KateCommands::SedReplace::InteractiveSedReplacer > interactiveSedReplace)
 
virtual KTextEditor::MovingRange * newMovingRange(const KTextEditor::Range &range, KTextEditor::MovingRange::InsertBehaviors insertBehaviors=KTextEditor::MovingRange::DoNotExpand, KTextEditor::MovingRange::EmptyBehavior emptyBehavior=KTextEditor::MovingRange::AllowEmpty)
Create a new moving range for this document. 
 
KateRenderer * renderer()
 
KTextEditor::Document * document() const 
 
virtual bool isValid() const 
 
virtual int lineLength(int line) const 
 
void setText(const QString &text, bool selected=true)
 
static KateGlobal * self()
Kate Part Internal stuff ;) 
 
bool isSendingSyntheticSearchCompletedKeypress()
 
const QChar KeyEventToQChar(const QKeyEvent &keyEvent)
 
bool setCursorPosition(KTextEditor::Cursor position)
 
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
 
KateViInputModeManager * getViInputModeManager()
 
static KTextEditor::Range parseRangeExpression(const QString &command, KateView *view, QString &destRangeExpression, QString &destTransformedCommand)
Attempt to parse any leading range expression (e.g. 
 
virtual void setAttributeOnlyForViews(bool onlyForViews)=0
 
void goToPos(const Cursor &c)
 
virtual bool isValid() const 
 
KateRendererConfig * config() const 
Configuration. 
 
void setCommandResponseMessageTimeout(long commandResponseMessageTimeOutMS)
 
KateCommandLineBar * cmdLineBar()
 
void init(Mode mode, const QString &initialText=QString())
 
virtual void setAttribute(Attribute::Ptr attribute)=0
 
Range findPattern(const QString &pattern, bool backwards, bool caseSensitive, const Cursor &startFrom, int count=-1) const 
 
virtual void setRange(const KTextEditor::Range &range)=0
 
virtual void setView(View *view)=0
 
KTextEditor::Cursor cursorPosition() const 
 
virtual QString line(int line) const =0
 
KateViGlobal * viInputModeGlobal()
vi input mode global 
 
bool handleKeyPress(const QKeyEvent *keyEvent)
 
QString getWord(const KTextEditor::Cursor &cursor)
 
static void adjustBackground(QPalette &, BackgroundRole newRole=NormalBackground, QPalette::ColorRole color=QPalette::Base, ColorSet set=View, KSharedConfigPtr=KSharedConfigPtr())
 
ViMode getCurrentViMode() const 
 
KateViEmulatedCommandBar(KateView *view, QWidget *parent=0)
 
virtual void setZDepth(qreal zDepth)=0
 
const QColor & searchHighlightColor() const 
 
void appendReplaceHistoryItem(const QString &replaceHistoryItem)
 
void appendCommandHistoryItem(const QString &commandHistoryItem)
 
KateDocument * doc()
accessor to katedocument pointer 
 
void appendSearchHistoryItem(const QString &searchHistoryItem)
 
static KateViKeyParser * self()
 
QString getRegisterContent(const QChar ®) const 
 
virtual ~KateViEmulatedCommandBar()
 
void execute(const QString &text)
 
static bool parse(const QString &sedReplaceString, QString &destDelim, int &destFindBeginPos, int &destFindEndPos, int &destReplaceBeginPos, int &destReplaceEndPos)
Parses sedReplaceString to see if it is a valid sed replace expression (e.g. 
 
virtual int lines() const =0