[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [ktexteditor] src: Move CommandMode into its own source files.
From:       Simon St James <kdedevel () etotheipiplusone ! com>
Date:       2016-06-17 8:18:10
Message-ID: E1bDoyg-0002ZN-Mr () scm ! kde ! org
[Download RAW message or body]

Git commit 765d8e684c37432c17c0bde30473f472b64ea0f3 by Simon St James.
Committed on 17/06/2016 at 08:14.
Pushed by sstjames into branch 'master'.

Move CommandMode into its own source files.

M  +1    -0    src/CMakeLists.txt
M  +5    -3    src/include/ktexteditor/command.h
A  +394  -0    src/vimode/emulatedcommandbar/commandmode.cpp     [License: UNKNOWN]  \
* A  +80   -0    src/vimode/emulatedcommandbar/commandmode.h     [License: UNKNOWN]  \
* M  +1    -378  src/vimode/emulatedcommandbar/emulatedcommandbar.cpp
M  +1    -57   src/vimode/emulatedcommandbar/emulatedcommandbar.h

The files marked with a * at the end have a non valid license. Please read: \
http://techbase.kde.org/Policies/Licensing_Policy and use the headers which are \
listed at that page.


http://commits.kde.org/ktexteditor/765d8e684c37432c17c0bde30473f472b64ea0f3

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 51374c7..25ac61a 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -281,6 +281,7 @@ if (BUILD_VIMODE)
     vimode/emulatedcommandbar/activemode.cpp
     vimode/emulatedcommandbar/interactivesedreplacemode.cpp
     vimode/emulatedcommandbar/searchmode.cpp
+    vimode/emulatedcommandbar/commandmode.cpp
     vimode/commandrangeexpressionparser.cpp
     vimode/keymapper.cpp
     vimode/marks.cpp
diff --git a/src/include/ktexteditor/command.h b/src/include/ktexteditor/command.h
index f65d11b..3d57ef4 100644
--- a/src/include/ktexteditor/command.h
+++ b/src/include/ktexteditor/command.h
@@ -24,6 +24,8 @@
 
 #include <ktexteditor_export.h>
 #include <ktexteditor/range.h>
+#include <KCompletion>
+
 #include <QObject>
 
 class QStringList;
@@ -112,7 +114,7 @@ public:
     {
         return m_cmds;
     }
-    
+
     /**
      * Find out if a given command can act on a range. This is used for checking
      * if a command should be called when the user also gave a range or if an
@@ -130,7 +132,7 @@ public:
      * of replaced strings as \p msg, like "16 replacements made." If an error
      * occurred in the usage it would return \e false and set the \p msg to
      * something like "missing argument." or such.
-     * 
+     *
      * If a non-invalid range is given, the command shall be executed on that range.
      * supportsRange() tells if the command supports that.
      *
@@ -198,7 +200,7 @@ private:
      * the command list this command got constructed with
      */
     const QStringList m_cmds;
-    
+
     /**
      * Private d-pointer
      */
diff --git a/src/vimode/emulatedcommandbar/commandmode.cpp \
b/src/vimode/emulatedcommandbar/commandmode.cpp new file mode 100644
index 0000000..215b5d0
--- /dev/null
+++ b/src/vimode/emulatedcommandbar/commandmode.cpp
@@ -0,0 +1,394 @@
+#include "commandmode.h"
+
+#include "emulatedcommandbar.h"
+#include "interactivesedreplacemode.h"
+#include "searchmode.h"
+#include "../commandrangeexpressionparser.h"
+
+#include <vimode/appcommands.h>
+#include <vimode/cmds.h>
+#include <vimode/inputmodemanager.h>
+#include "../globalstate.h"
+#include "../history.h"
+
+#include "katescriptmanager.h"
+#include "katecmds.h"
+
+#include <KLocalizedString>
+
+#include <QLineEdit>
+#include <QWhatsThis>
+
+using namespace KateVi;
+
+CommandMode::CommandMode ( EmulatedCommandBar* emulatedCommandBar, MatchHighlighter* \
matchHighlighter, KTextEditor::ViewPrivate* view,  QLineEdit* edit, \
InteractiveSedReplaceMode *interactiveSedReplaceMode, Completer* completer) +    : \
ActiveMode ( emulatedCommandBar, matchHighlighter ), +      m_edit(edit),
+      m_view(view),
+      m_interactiveSedReplaceMode(interactiveSedReplaceMode),
+      m_completer(completer)
+{
+    QList<KTextEditor::Command *> cmds;
+
+    cmds.push_back(KateCommands::CoreCommands::self());
+    cmds.push_back(Commands::self());
+    cmds.push_back(AppCommands::self());
+    cmds.push_back(SedReplace::self());
+    cmds.push_back(BufferCommands::self());
+
+    Q_FOREACH (KTextEditor::Command *cmd, \
KateScriptManager::self()->commandLineScripts()) { +        cmds.push_back(cmd);
+    }
+
+    Q_FOREACH (KTextEditor::Command *cmd, cmds) {
+        QStringList l = cmd->cmds();
+
+        for (int z = 0; z < l.count(); z++) {
+            m_cmdDict.insert(l[z], cmd);
+        }
+
+        m_cmdCompletion.insertItems(l);
+    }
+}
+
+void CommandMode::setViInputModeManager ( InputModeManager* viInputModeManager )
+{
+    m_viInputModeManager = viInputModeManager;
+}
+
+bool CommandMode::handleKeyPress ( const QKeyEvent* keyEvent )
+{
+    if (keyEvent->modifiers() == Qt::ControlModifier && (keyEvent->key() == \
Qt::Key_D || keyEvent->key() == Qt::Key_F)) { +        \
CommandMode::ParsedSedExpression parsedSedExpression = parseAsSedExpression(); +      \
if (parsedSedExpression.parsedSuccessfully) { +            const bool clearFindTerm = \
(keyEvent->key() == Qt::Key_D); +            if (clearFindTerm) {
+                m_edit->setSelection(parsedSedExpression.findBeginPos, \
parsedSedExpression.findEndPos - parsedSedExpression.findBeginPos + 1); +             \
m_edit->insert(QString()); +            } else {
+                // Clear replace term.
+                m_edit->setSelection(parsedSedExpression.replaceBeginPos, \
parsedSedExpression.replaceEndPos - parsedSedExpression.replaceBeginPos + 1); +       \
m_edit->insert(QString()); +            }
+        }
+        return true;
+    }
+    return false;
+}
+
+void CommandMode::editTextChanged ( const QString& newText )
+{
+    Q_UNUSED(newText); // We read the current text from m_edit.
+    if (m_completer->isCompletionActive())
+        return;
+    // Command completion doesn't need to be manually invoked.
+    if (!withoutRangeExpression().isEmpty() && \
!m_completer->isNextTextChangeDueToCompletionChange()) { +        // ... However, \
command completion mode should not be automatically invoked if this is not the \
current leading +        // word in the text edit (it gets annoying if completion \
pops up after ":s/se" etc). +        const bool commandBeforeCursorIsLeading = \
(commandBeforeCursorBegin() == rangeExpression().length()); +        if \
(commandBeforeCursorIsLeading) { +            CompletionStartParams \
completionStartParams = activateCommandCompletion(); +            \
startCompletion(completionStartParams); +        }
+    }
+}
+
+void CommandMode::deactivate ( bool wasAborted )
+{
+    if (wasAborted) {
+        // Appending the command to the history when it is executed is handled \
elsewhere; we can't +        // do it inside closed() as we may still be showing the \
command response display. +        \
m_viInputModeManager->globalState()->commandHistory()->append(m_edit->text()); +      \
// With Vim, aborting a command returns us to Normal mode, even if we were in Visual \
Mode. +        // If we switch from Visual to Normal mode, we need to clear the \
selection. +        m_view->clearSelection();
+    }
+
+}
+
+CompletionStartParams CommandMode::completionInvoked(Completer::CompletionInvocation \
invocationType) +{
+    CompletionStartParams completionStartParams;
+    if (invocationType == Completer::CompletionInvocation::ExtraContext)
+    {
+        if (isCursorInFindTermOfSed()) {
+            completionStartParams = activateSedFindHistoryCompletion();
+        } else if (isCursorInReplaceTermOfSed()) {
+            completionStartParams = activateSedReplaceHistoryCompletion();
+        } else {
+            completionStartParams = activateCommandHistoryCompletion();
+        }
+    }
+    else
+    {
+        // Normal context, so boring, ordinary History completion.
+        completionStartParams = activateCommandHistoryCompletion();
+    }
+    return completionStartParams;
+}
+
+void CommandMode::completionChosen()
+{
+    QString commandToExecute = m_edit->text();
+    CommandMode::ParsedSedExpression parsedSedExpression = parseAsSedExpression();
+    if (parsedSedExpression.parsedSuccessfully) {
+        const QString originalFindTerm = sedFindTerm();
+        const QString convertedFindTerm = \
vimRegexToQtRegexPattern(originalFindTerm); +        const QString \
commandWithSedSearchRegexConverted = withSedFindTermReplacedWith(convertedFindTerm); \
+        m_viInputModeManager->globalState()->searchHistory()->append(originalFindTerm);
 +        const QString replaceTerm = sedReplaceTerm();
+        m_viInputModeManager->globalState()->replaceHistory()->append(replaceTerm);
+        commandToExecute = commandWithSedSearchRegexConverted;
+    }
+
+    const QString commandResponseMessage = executeCommand(commandToExecute);
+    // Don't close the bar if executing the command switched us to Interactive Sed \
Replace mode. +    if (!m_interactiveSedReplaceMode->isActive()) {
+        if (commandResponseMessage.isEmpty()) {
+            m_emulatedCommandBar->hideMe();
+        } else {
+            closeWithStatusMessage(commandResponseMessage);
+        }
+    }
+    m_viInputModeManager->globalState()->commandHistory()->append(m_edit->text());
+
+}
+
+QString CommandMode::executeCommand ( const QString& commandToExecute )
+{
+    // Silently ignore leading space characters and colon characters (for vi-heads).
+    uint n = 0;
+    const uint textlen = commandToExecute.length();
+    while ((n < textlen) && commandToExecute[n].isSpace()) {
+        n++;
+    }
+
+    if (n >= textlen) {
+        return QString();
+    }
+
+    QString commandResponseMessage;
+    QString cmd = commandToExecute.mid(n);
+
+    KTextEditor::Range range = \
CommandRangeExpressionParser(m_viInputModeManager).parseRange(cmd, cmd); +
+    if (cmd.length() > 0) {
+        KTextEditor::Command *p = queryCommand(cmd);
+        KateViCommandInterface *ci = dynamic_cast<KateViCommandInterface*>(p);
+
+        if (ci) {
+            ci->setViInputModeManager(m_viInputModeManager);
+            ci->setViGlobal(m_viInputModeManager->globalState());
+        }
+
+        // The following commands changes the focus themselves, so bar should be \
hidden before execution. +
+        // We got a range and a valid command, but the command does not inherit the \
RangeCommand +        // extension. Bail out.
+        if (range.isValid() && !p->supportsRange(cmd)) {
+            commandResponseMessage = i18n("Error: No range allowed for command \
\"%1\".",  cmd); +        } else {
+            if (p) {
+                if (p->exec(m_view, cmd, commandResponseMessage, range)) {
+
+                    if (commandResponseMessage.length() > 0) {
+                        commandResponseMessage = i18n("Success: ") + \
commandResponseMessage; +                    }
+                } else {
+                    if (commandResponseMessage.length() > 0) {
+                        if (commandResponseMessage.contains(QLatin1Char('\n'))) {
+                            // multiline error, use widget with more space
+                            \
QWhatsThis::showText(m_emulatedCommandBar->mapToGlobal(QPoint(0, 0)), \
commandResponseMessage); +                        }
+                    } else {
+                        commandResponseMessage = i18n("Command \"%1\" failed.",  \
cmd); +                    }
+                }
+            } else {
+                commandResponseMessage = i18n("No such command: \"%1\"",  cmd);
+            }
+        }
+    }
+
+    // the following commands change the focus themselves
+    if (!QRegExp(QLatin1String("buffer|b|new|vnew|bp|bprev|bn|bnext|bf|bfirst|bl|blast|edit|e")).exactMatch(cmd.split(QLatin1String(" \
")).at(0))) { +        m_view->setFocus();
+    }
+
+    m_viInputModeManager->reset();
+    return commandResponseMessage;
+
+}
+
+
+QString CommandMode::withoutRangeExpression()
+{
+    const QString originalCommand = m_edit->text();
+    return originalCommand.mid(rangeExpression().length());
+}
+
+QString CommandMode::rangeExpression()
+{
+    const QString command = m_edit->text();
+    return CommandRangeExpressionParser(m_viInputModeManager).parseRangeString(command);
 +}
+
+CommandMode::ParsedSedExpression CommandMode::parseAsSedExpression()
+{
+    const QString commandWithoutRangeExpression = withoutRangeExpression();
+    ParsedSedExpression parsedSedExpression;
+    QString delimiter;
+    parsedSedExpression.parsedSuccessfully = \
SedReplace::parse(commandWithoutRangeExpression, delimiter, \
parsedSedExpression.findBeginPos, parsedSedExpression.findEndPos, \
parsedSedExpression.replaceBeginPos, parsedSedExpression.replaceEndPos); +    if \
(parsedSedExpression.parsedSuccessfully) { +        parsedSedExpression.delimiter = \
delimiter.at(0); +        if (parsedSedExpression.replaceBeginPos == -1) {
+            if (parsedSedExpression.findBeginPos != -1) {
+                // The replace term was empty, and a quirk of the regex used is that \
replaceBeginPos will be -1. +                // It's actually the position after the \
first occurrence of the delimiter after the end of the find pos. +                \
parsedSedExpression.replaceBeginPos = \
commandWithoutRangeExpression.indexOf(delimiter, parsedSedExpression.findEndPos) + 1; \
+                parsedSedExpression.replaceEndPos = \
parsedSedExpression.replaceBeginPos - 1; +            } else {
+                // Both find and replace terms are empty; replace term is at the \
third occurrence of the delimiter. +                \
parsedSedExpression.replaceBeginPos = 0; +                for (int delimiterCount = \
1; delimiterCount <= 3; delimiterCount++) { +                    \
parsedSedExpression.replaceBeginPos = \
commandWithoutRangeExpression.indexOf(delimiter, parsedSedExpression.replaceBeginPos \
+ 1); +                }
+                parsedSedExpression.replaceEndPos = \
parsedSedExpression.replaceBeginPos - 1; +            }
+        }
+        if (parsedSedExpression.findBeginPos == -1) {
+            // The find term was empty, and a quirk of the regex used is that \
findBeginPos will be -1. +            // It's actually the position after the first \
occurrence of the delimiter. +            parsedSedExpression.findBeginPos = \
commandWithoutRangeExpression.indexOf(delimiter) + 1; +            \
parsedSedExpression.findEndPos = parsedSedExpression.findBeginPos - 1; +        }
+
+    }
+
+    if (parsedSedExpression.parsedSuccessfully) {
+        parsedSedExpression.findBeginPos += rangeExpression().length();
+        parsedSedExpression.findEndPos += rangeExpression().length();
+        parsedSedExpression.replaceBeginPos += rangeExpression().length();
+        parsedSedExpression.replaceEndPos += rangeExpression().length();
+    }
+    return parsedSedExpression;
+
+}
+
+QString CommandMode::sedFindTerm()
+{
+    const QString command = m_edit->text();
+    ParsedSedExpression parsedSedExpression = parseAsSedExpression();
+    Q_ASSERT(parsedSedExpression.parsedSuccessfully);
+    return command.mid(parsedSedExpression.findBeginPos, \
parsedSedExpression.findEndPos - parsedSedExpression.findBeginPos + 1); +}
+
+QString CommandMode::sedReplaceTerm()
+{
+    const QString command = m_edit->text();
+    ParsedSedExpression parsedSedExpression = parseAsSedExpression();
+    Q_ASSERT(parsedSedExpression.parsedSuccessfully);
+    return command.mid(parsedSedExpression.replaceBeginPos, \
parsedSedExpression.replaceEndPos - parsedSedExpression.replaceBeginPos + 1); +}
+
+QString CommandMode::withSedFindTermReplacedWith ( const QString& newFindTerm )
+{
+    const QString command = m_edit->text();
+    ParsedSedExpression parsedSedExpression = parseAsSedExpression();
+    Q_ASSERT(parsedSedExpression.parsedSuccessfully);
+    return command.mid(0, parsedSedExpression.findBeginPos) +
+    newFindTerm +
+    command.mid(parsedSedExpression.findEndPos + 1);
+}
+
+QString CommandMode::withSedDelimiterEscaped ( const QString& text )
+{
+    ParsedSedExpression parsedSedExpression = parseAsSedExpression();
+    QString delimiterEscaped = ensuredCharEscaped(text, \
parsedSedExpression.delimiter); +    return delimiterEscaped;
+}
+
+bool CommandMode::isCursorInFindTermOfSed()
+{
+    ParsedSedExpression parsedSedExpression = parseAsSedExpression();
+    return parsedSedExpression.parsedSuccessfully && (m_edit->cursorPosition() >= \
parsedSedExpression.findBeginPos && m_edit->cursorPosition() <= \
parsedSedExpression.findEndPos + 1); +}
+
+bool CommandMode::isCursorInReplaceTermOfSed()
+{
+    ParsedSedExpression parsedSedExpression = parseAsSedExpression();
+    return parsedSedExpression.parsedSuccessfully && m_edit->cursorPosition() >= \
parsedSedExpression.replaceBeginPos && m_edit->cursorPosition() <= \
parsedSedExpression.replaceEndPos + 1; +}
+
+int CommandMode::commandBeforeCursorBegin()
+{
+    const QString textWithoutRangeExpression = withoutRangeExpression();
+    const int cursorPositionWithoutRangeExpression = m_edit->cursorPosition() - \
rangeExpression().length(); +    int commandBeforeCursorBegin = \
cursorPositionWithoutRangeExpression - 1; +    while (commandBeforeCursorBegin >= 0 \
&& (textWithoutRangeExpression[commandBeforeCursorBegin].isLetterOrNumber() || \
textWithoutRangeExpression[commandBeforeCursorBegin] == QLatin1Char('_') || \
textWithoutRangeExpression[commandBeforeCursorBegin] == QLatin1Char('-'))) { +        \
commandBeforeCursorBegin--; +    }
+    commandBeforeCursorBegin++;
+    commandBeforeCursorBegin += rangeExpression().length();
+    return commandBeforeCursorBegin;
+}
+
+CompletionStartParams CommandMode::activateCommandCompletion()
+{
+    return CompletionStartParams::createModeSpecific(m_cmdCompletion.items(), \
commandBeforeCursorBegin()); +}
+
+CompletionStartParams CommandMode::activateCommandHistoryCompletion()
+{
+    return CompletionStartParams::createModeSpecific(reversed(m_viInputModeManager->globalState()->commandHistory()->items()), \
0); +}
+
+CompletionStartParams CommandMode::activateSedFindHistoryCompletion()
+{
+    if (m_viInputModeManager->globalState()->searchHistory()->isEmpty())
+    {
+        return CompletionStartParams::invalid();
+    }
+    CommandMode::ParsedSedExpression parsedSedExpression = parseAsSedExpression();
+    return CompletionStartParams::createModeSpecific(reversed(m_viInputModeManager->globalState()->searchHistory()->items()),
 +                                                     \
parsedSedExpression.findBeginPos, +                                                   \
[this] (const  QString& completion) -> QString { return \
withCaseSensitivityMarkersStripped(withSedDelimiterEscaped(completion)); }); +}
+
+CompletionStartParams CommandMode::activateSedReplaceHistoryCompletion()
+{
+    if (m_viInputModeManager->globalState()->replaceHistory()->isEmpty())
+    {
+        return CompletionStartParams::invalid();
+    }
+    CommandMode::ParsedSedExpression parsedSedExpression = parseAsSedExpression();
+    return CompletionStartParams::createModeSpecific(reversed(m_viInputModeManager->globalState()->replaceHistory()->items()),
 +                                                     \
parsedSedExpression.replaceBeginPos, +                                                \
[this] (const  QString& completion) -> QString { return \
withCaseSensitivityMarkersStripped(withSedDelimiterEscaped(completion)); }); +}
+
+KTextEditor::Command* CommandMode::queryCommand ( const QString& cmd ) const
+{
+    // a command can be named ".*[\w\-]+" with the constrain that it must
+    // contain at least one letter.
+    int f = 0;
+    bool b = false;
+
+    // special case: '-' and '_' can be part of a command name, but if the
+    // command is 's' (substitute), it should be considered the delimiter and
+    // should not be counted as part of the command name
+    if (cmd.length() >= 2 && cmd.at(0) == QLatin1Char('s') && (cmd.at(1) == \
QLatin1Char('-') || cmd.at(1) == QLatin1Char('_'))) { +        return \
m_cmdDict.value(QStringLiteral("s")); +    }
+
+    for (; f < cmd.length(); f++) {
+        if (cmd[f].isLetter()) {
+            b = true;
+        }
+        if (b && (! cmd[f].isLetterOrNumber() && cmd[f] != QLatin1Char('-') && \
cmd[f] != QLatin1Char('_'))) { +            break;
+        }
+    }
+    return m_cmdDict.value(cmd.left(f));
+
+}
diff --git a/src/vimode/emulatedcommandbar/commandmode.h \
b/src/vimode/emulatedcommandbar/commandmode.h new file mode 100644
index 0000000..f160315
--- /dev/null
+++ b/src/vimode/emulatedcommandbar/commandmode.h
@@ -0,0 +1,80 @@
+#ifndef KATEVI_EMULATED_COMMAND_BAR_COMMANDMODE_H
+#define KATEVI_EMULATED_COMMAND_BAR_COMMANDMODE_H
+
+#include "activemode.h"
+
+#include <KTextEditor/Command>
+
+#include <QHash>
+
+namespace KTextEditor {
+    class ViewPrivate;
+}
+
+namespace KateVi
+{
+class EmulatedCommandBar;
+class MatchHighlighter;
+class InteractiveSedReplaceMode;
+class Completer;
+class InputModeManager;
+
+class CommandMode : public ActiveMode
+{
+public:
+    CommandMode(EmulatedCommandBar* emulatedCommandBar, MatchHighlighter* \
matchHighlighter, KTextEditor::ViewPrivate* view,  QLineEdit* edit, \
InteractiveSedReplaceMode *interactiveSedReplaceMode, Completer* completer); +    \
virtual ~CommandMode() +    {
+    }
+    void setViInputModeManager(InputModeManager *viInputModeManager);
+    virtual bool handleKeyPress ( const QKeyEvent* keyEvent );
+    virtual void editTextChanged(const QString &newText);
+    virtual CompletionStartParams completionInvoked(Completer::CompletionInvocation \
invocationType); +    virtual void completionChosen();
+    void deactivate(bool wasAborted);
+    QString executeCommand(const QString &commandToExecute);
+private:
+    CompletionStartParams activateCommandCompletion();
+    CompletionStartParams activateCommandHistoryCompletion();
+    CompletionStartParams activateSedFindHistoryCompletion();
+    CompletionStartParams activateSedReplaceHistoryCompletion();
+    QString withoutRangeExpression();
+    QString rangeExpression();
+    QString withSedFindTermReplacedWith(const QString &newFindTerm);
+    QString withSedDelimiterEscaped(const QString &text);
+    bool isCursorInFindTermOfSed();
+    bool isCursorInReplaceTermOfSed();
+    QString sedFindTerm();
+    QString sedReplaceTerm();
+    /**
+        * Stuff to do with expressions of the form:
+        *
+        *   s/find/replace/<sedflags>
+        */
+    struct ParsedSedExpression {
+        bool parsedSuccessfully;
+        int findBeginPos;
+        int findEndPos;
+        int replaceBeginPos;
+        int replaceEndPos;
+        QChar delimiter;
+    };
+    /**
+        * The "range expression" is the (optional) expression before the command \
that describes +        * the range over which the command should be run e.g. '<,'>.  \
@see CommandRangeExpressionParser +        */
+    CommandMode::ParsedSedExpression parseAsSedExpression();
+    void replaceCommandBeforeCursorWith(const QString &newCommand);
+    int commandBeforeCursorBegin();
+    QLineEdit *m_edit;
+    InputModeManager *m_viInputModeManager = nullptr;
+    KTextEditor::ViewPrivate *m_view;
+    InteractiveSedReplaceMode *m_interactiveSedReplaceMode;
+    Completer *m_completer;
+    KCompletion m_cmdCompletion;
+    QHash<QString, KTextEditor::Command *> m_cmdDict;
+    KTextEditor::Command *queryCommand(const QString &cmd) const;
+};
+}
+
+#endif
diff --git a/src/vimode/emulatedcommandbar/emulatedcommandbar.cpp \
b/src/vimode/emulatedcommandbar/emulatedcommandbar.cpp index 513de48..7ee21a1 100644
--- a/src/vimode/emulatedcommandbar/emulatedcommandbar.cpp
+++ b/src/vimode/emulatedcommandbar/emulatedcommandbar.cpp
@@ -31,24 +31,18 @@
 #include "matchhighlighter.h"
 #include "interactivesedreplacemode.h"
 #include "searchmode.h"
+#include "commandmode.h"
 
-#include <vimode/cmds.h>
 #include <vimode/modes/visualvimode.h>
-#include <vimode/appcommands.h>
 #include "../history.h"
 
-#include "katecmds.h"
-#include "katescriptmanager.h"
 #include "../registers.h"
 #include "../searcher.h"
 
-#include <KLocalizedString>
-
 #include <QLineEdit>
 #include <QVBoxLayout>
 #include <QLabel>
 #include <QApplication>
-#include <QWhatsThis>
 
 #include <algorithm>
 
@@ -435,374 +429,3 @@ void EmulatedCommandBar::hideAllWidgetsExcept(QWidget* \
widgetToKeepVisible)  
 }
 
-EmulatedCommandBar::CommandMode::CommandMode ( EmulatedCommandBar* \
emulatedCommandBar, MatchHighlighter* matchHighlighter, KTextEditor::ViewPrivate* \
view,  QLineEdit* edit, InteractiveSedReplaceMode *interactiveSedReplaceMode, \
                Completer* completer)
-    : ActiveMode ( emulatedCommandBar, matchHighlighter ),
-      m_edit(edit),
-      m_view(view),
-      m_interactiveSedReplaceMode(interactiveSedReplaceMode),
-      m_completer(completer)
-{
-    QList<KTextEditor::Command *> cmds;
-
-    cmds.push_back(KateCommands::CoreCommands::self());
-    cmds.push_back(Commands::self());
-    cmds.push_back(AppCommands::self());
-    cmds.push_back(SedReplace::self());
-    cmds.push_back(BufferCommands::self());
-
-    Q_FOREACH (KTextEditor::Command *cmd, \
                KateScriptManager::self()->commandLineScripts()) {
-        cmds.push_back(cmd);
-    }
-
-    Q_FOREACH (KTextEditor::Command *cmd, cmds) {
-        QStringList l = cmd->cmds();
-
-        for (int z = 0; z < l.count(); z++) {
-            m_cmdDict.insert(l[z], cmd);
-        }
-
-        m_cmdCompletion.insertItems(l);
-    }
-}
-
-void EmulatedCommandBar::CommandMode::setViInputModeManager ( InputModeManager* \
                viInputModeManager )
-{
-    m_viInputModeManager = viInputModeManager;
-}
-
-bool EmulatedCommandBar::CommandMode::handleKeyPress ( const QKeyEvent* keyEvent )
-{
-    if (keyEvent->modifiers() == Qt::ControlModifier && (keyEvent->key() == \
                Qt::Key_D || keyEvent->key() == Qt::Key_F)) {
-        CommandMode::ParsedSedExpression parsedSedExpression = \
                parseAsSedExpression();
-        if (parsedSedExpression.parsedSuccessfully) {
-            const bool clearFindTerm = (keyEvent->key() == Qt::Key_D);
-            if (clearFindTerm) {
-                m_edit->setSelection(parsedSedExpression.findBeginPos, \
                parsedSedExpression.findEndPos - parsedSedExpression.findBeginPos + \
                1);
-                m_edit->insert(QString());
-            } else {
-                // Clear replace term.
-                m_edit->setSelection(parsedSedExpression.replaceBeginPos, \
                parsedSedExpression.replaceEndPos - \
                parsedSedExpression.replaceBeginPos + 1);
-                m_edit->insert(QString());
-            }
-        }
-        return true;
-    }
-    return false;
-}
-
-void EmulatedCommandBar::CommandMode::editTextChanged ( const QString& newText )
-{
-    Q_UNUSED(newText); // We read the current text from m_edit.
-    if (m_completer->isCompletionActive())
-        return;
-    // Command completion doesn't need to be manually invoked.
-    if (!withoutRangeExpression().isEmpty() && \
                !m_completer->isNextTextChangeDueToCompletionChange()) {
-        // ... However, command completion mode should not be automatically invoked \
                if this is not the current leading
-        // word in the text edit (it gets annoying if completion pops up after \
                ":s/se" etc).
-        const bool commandBeforeCursorIsLeading = (commandBeforeCursorBegin() == \
                rangeExpression().length());
-        if (commandBeforeCursorIsLeading) {
-            CompletionStartParams completionStartParams = \
                activateCommandCompletion();
-            startCompletion(completionStartParams);
-        }
-    }
-}
-
-void EmulatedCommandBar::CommandMode::deactivate ( bool wasAborted )
-{
-    if (wasAborted) {
-        // Appending the command to the history when it is executed is handled \
                elsewhere; we can't
-        // do it inside closed() as we may still be showing the command response \
                display.
-        m_viInputModeManager->globalState()->commandHistory()->append(m_edit->text());
                
-        // With Vim, aborting a command returns us to Normal mode, even if we were \
                in Visual Mode.
-        // If we switch from Visual to Normal mode, we need to clear the selection.
-        m_view->clearSelection();
-    }
-
-}
-
-CompletionStartParams \
EmulatedCommandBar::CommandMode::completionInvoked(Completer::CompletionInvocation \
                invocationType)
-{
-    CompletionStartParams completionStartParams;
-    if (invocationType == Completer::CompletionInvocation::ExtraContext)
-    {
-        if (isCursorInFindTermOfSed()) {
-            completionStartParams = activateSedFindHistoryCompletion();
-        } else if (isCursorInReplaceTermOfSed()) {
-            completionStartParams = activateSedReplaceHistoryCompletion();
-        } else {
-            completionStartParams = activateCommandHistoryCompletion();
-        }
-    }
-    else
-    {
-        // Normal context, so boring, ordinary History completion.
-        completionStartParams = activateCommandHistoryCompletion();
-    }
-    return completionStartParams;
-}
-
-void EmulatedCommandBar::CommandMode::completionChosen()
-{
-    QString commandToExecute = m_edit->text();
-    CommandMode::ParsedSedExpression parsedSedExpression = parseAsSedExpression();
-    if (parsedSedExpression.parsedSuccessfully) {
-        const QString originalFindTerm = sedFindTerm();
-        const QString convertedFindTerm = \
                vimRegexToQtRegexPattern(originalFindTerm);
-        const QString commandWithSedSearchRegexConverted = \
                withSedFindTermReplacedWith(convertedFindTerm);
-        m_viInputModeManager->globalState()->searchHistory()->append(originalFindTerm);
                
-        const QString replaceTerm = sedReplaceTerm();
-        m_viInputModeManager->globalState()->replaceHistory()->append(replaceTerm);
-        commandToExecute = commandWithSedSearchRegexConverted;
-    }
-
-    const QString commandResponseMessage = executeCommand(commandToExecute);
-    // Don't close the bar if executing the command switched us to Interactive Sed \
                Replace mode.
-    if (!m_interactiveSedReplaceMode->isActive()) {
-        if (commandResponseMessage.isEmpty()) {
-            m_emulatedCommandBar->hideMe();
-        } else {
-            closeWithStatusMessage(commandResponseMessage);
-        }
-    }
-    m_viInputModeManager->globalState()->commandHistory()->append(m_edit->text());
-
-}
-
-QString EmulatedCommandBar::CommandMode::executeCommand ( const QString& \
                commandToExecute )
-{
-    // Silently ignore leading space characters and colon characters (for vi-heads).
-    uint n = 0;
-    const uint textlen = commandToExecute.length();
-    while ((n < textlen) && commandToExecute[n].isSpace()) {
-        n++;
-    }
-
-    if (n >= textlen) {
-        return QString();
-    }
-
-    QString commandResponseMessage;
-    QString cmd = commandToExecute.mid(n);
-
-    KTextEditor::Range range = \
                CommandRangeExpressionParser(m_viInputModeManager).parseRange(cmd, \
                cmd);
-
-    if (cmd.length() > 0) {
-        KTextEditor::Command *p = queryCommand(cmd);
-        KateViCommandInterface *ci = dynamic_cast<KateViCommandInterface*>(p);
-
-        if (ci) {
-            ci->setViInputModeManager(m_viInputModeManager);
-            ci->setViGlobal(m_viInputModeManager->globalState());
-        }
-
-        // The following commands changes the focus themselves, so bar should be \
                hidden before execution.
-
-        // We got a range and a valid command, but the command does not inherit the \
                RangeCommand
-        // extension. Bail out.
-        if (range.isValid() && !p->supportsRange(cmd)) {
-            commandResponseMessage = i18n("Error: No range allowed for command \
                \"%1\".",  cmd);
-        } else {
-            if (p) {
-                if (p->exec(m_view, cmd, commandResponseMessage, range)) {
-
-                    if (commandResponseMessage.length() > 0) {
-                        commandResponseMessage = i18n("Success: ") + \
                commandResponseMessage;
-                    }
-                } else {
-                    if (commandResponseMessage.length() > 0) {
-                        if (commandResponseMessage.contains(QLatin1Char('\n'))) {
-                            // multiline error, use widget with more space
-                            \
QWhatsThis::showText(m_emulatedCommandBar->mapToGlobal(QPoint(0, 0)), \
                commandResponseMessage);
-                        }
-                    } else {
-                        commandResponseMessage = i18n("Command \"%1\" failed.",  \
                cmd);
-                    }
-                }
-            } else {
-                commandResponseMessage = i18n("No such command: \"%1\"",  cmd);
-            }
-        }
-    }
-
-    // the following commands change the focus themselves
-    if (!QRegExp(QLatin1String("buffer|b|new|vnew|bp|bprev|bn|bnext|bf|bfirst|bl|blast|edit|e")).exactMatch(cmd.split(QLatin1String(" \
                ")).at(0))) {
-        m_view->setFocus();
-    }
-
-    m_viInputModeManager->reset();
-    return commandResponseMessage;
-
-}
-
-
-QString EmulatedCommandBar::CommandMode::withoutRangeExpression()
-{
-    const QString originalCommand = m_edit->text();
-    return originalCommand.mid(rangeExpression().length());
-}
-
-QString EmulatedCommandBar::CommandMode::rangeExpression()
-{
-    const QString command = m_edit->text();
-    return CommandRangeExpressionParser(m_viInputModeManager).parseRangeString(command);
                
-}
-
-EmulatedCommandBar::CommandMode::ParsedSedExpression \
                EmulatedCommandBar::CommandMode::parseAsSedExpression()
-{
-    const QString commandWithoutRangeExpression = withoutRangeExpression();
-    ParsedSedExpression parsedSedExpression;
-    QString delimiter;
-    parsedSedExpression.parsedSuccessfully = \
SedReplace::parse(commandWithoutRangeExpression, delimiter, \
parsedSedExpression.findBeginPos, parsedSedExpression.findEndPos, \
                parsedSedExpression.replaceBeginPos, \
                parsedSedExpression.replaceEndPos);
-    if (parsedSedExpression.parsedSuccessfully) {
-        parsedSedExpression.delimiter = delimiter.at(0);
-        if (parsedSedExpression.replaceBeginPos == -1) {
-            if (parsedSedExpression.findBeginPos != -1) {
-                // The replace term was empty, and a quirk of the regex used is that \
                replaceBeginPos will be -1.
-                // It's actually the position after the first occurrence of the \
                delimiter after the end of the find pos.
-                parsedSedExpression.replaceBeginPos = \
                commandWithoutRangeExpression.indexOf(delimiter, \
                parsedSedExpression.findEndPos) + 1;
-                parsedSedExpression.replaceEndPos = \
                parsedSedExpression.replaceBeginPos - 1;
-            } else {
-                // Both find and replace terms are empty; replace term is at the \
                third occurrence of the delimiter.
-                parsedSedExpression.replaceBeginPos = 0;
-                for (int delimiterCount = 1; delimiterCount <= 3; delimiterCount++) \
                {
-                    parsedSedExpression.replaceBeginPos = \
commandWithoutRangeExpression.indexOf(delimiter, parsedSedExpression.replaceBeginPos \
                + 1);
-                }
-                parsedSedExpression.replaceEndPos = \
                parsedSedExpression.replaceBeginPos - 1;
-            }
-        }
-        if (parsedSedExpression.findBeginPos == -1) {
-            // The find term was empty, and a quirk of the regex used is that \
                findBeginPos will be -1.
-            // It's actually the position after the first occurrence of the \
                delimiter.
-            parsedSedExpression.findBeginPos = \
                commandWithoutRangeExpression.indexOf(delimiter) + 1;
-            parsedSedExpression.findEndPos = parsedSedExpression.findBeginPos - 1;
-        }
-
-    }
-
-    if (parsedSedExpression.parsedSuccessfully) {
-        parsedSedExpression.findBeginPos += rangeExpression().length();
-        parsedSedExpression.findEndPos += rangeExpression().length();
-        parsedSedExpression.replaceBeginPos += rangeExpression().length();
-        parsedSedExpression.replaceEndPos += rangeExpression().length();
-    }
-    return parsedSedExpression;
-
-}
-
-QString EmulatedCommandBar::CommandMode::sedFindTerm()
-{
-    const QString command = m_edit->text();
-    ParsedSedExpression parsedSedExpression = parseAsSedExpression();
-    Q_ASSERT(parsedSedExpression.parsedSuccessfully);
-    return command.mid(parsedSedExpression.findBeginPos, \
                parsedSedExpression.findEndPos - parsedSedExpression.findBeginPos + \
                1);
-}
-
-QString EmulatedCommandBar::CommandMode::sedReplaceTerm()
-{
-    const QString command = m_edit->text();
-    ParsedSedExpression parsedSedExpression = parseAsSedExpression();
-    Q_ASSERT(parsedSedExpression.parsedSuccessfully);
-    return command.mid(parsedSedExpression.replaceBeginPos, \
                parsedSedExpression.replaceEndPos - \
                parsedSedExpression.replaceBeginPos + 1);
-}
-
-QString EmulatedCommandBar::CommandMode::withSedFindTermReplacedWith ( const \
                QString& newFindTerm )
-{
-    const QString command = m_edit->text();
-    ParsedSedExpression parsedSedExpression = parseAsSedExpression();
-    Q_ASSERT(parsedSedExpression.parsedSuccessfully);
-    return command.mid(0, parsedSedExpression.findBeginPos) +
-           newFindTerm +
-           command.mid(parsedSedExpression.findEndPos + 1);
-}
-
-QString EmulatedCommandBar::CommandMode::withSedDelimiterEscaped ( const QString& \
                text )
-{
-    ParsedSedExpression parsedSedExpression = parseAsSedExpression();
-    QString delimiterEscaped = ensuredCharEscaped(text, \
                parsedSedExpression.delimiter);
-    return delimiterEscaped;
-}
-
-bool EmulatedCommandBar::CommandMode::isCursorInFindTermOfSed()
-{
-    ParsedSedExpression parsedSedExpression = parseAsSedExpression();
-    return parsedSedExpression.parsedSuccessfully && (m_edit->cursorPosition() >= \
parsedSedExpression.findBeginPos && m_edit->cursorPosition() <= \
                parsedSedExpression.findEndPos + 1);
-}
-
-bool EmulatedCommandBar::CommandMode::isCursorInReplaceTermOfSed()
-{
-    ParsedSedExpression parsedSedExpression = parseAsSedExpression();
-    return parsedSedExpression.parsedSuccessfully && m_edit->cursorPosition() >= \
parsedSedExpression.replaceBeginPos && m_edit->cursorPosition() <= \
                parsedSedExpression.replaceEndPos + 1;
-}
-
-int EmulatedCommandBar::CommandMode::commandBeforeCursorBegin()
-{
-    const QString textWithoutRangeExpression = withoutRangeExpression();
-    const int cursorPositionWithoutRangeExpression = m_edit->cursorPosition() - \
                rangeExpression().length();
-    int commandBeforeCursorBegin = cursorPositionWithoutRangeExpression - 1;
-    while (commandBeforeCursorBegin >= 0 && \
(textWithoutRangeExpression[commandBeforeCursorBegin].isLetterOrNumber() || \
textWithoutRangeExpression[commandBeforeCursorBegin] == QLatin1Char('_') || \
                textWithoutRangeExpression[commandBeforeCursorBegin] == \
                QLatin1Char('-'))) {
-        commandBeforeCursorBegin--;
-    }
-    commandBeforeCursorBegin++;
-    commandBeforeCursorBegin += rangeExpression().length();
-    return commandBeforeCursorBegin;
-}
-
-CompletionStartParams EmulatedCommandBar::CommandMode::activateCommandCompletion()
-{
-    return CompletionStartParams::createModeSpecific(m_cmdCompletion.items(), \
                commandBeforeCursorBegin());
-}
-
-CompletionStartParams \
                EmulatedCommandBar::CommandMode::activateCommandHistoryCompletion()
-{
-    return CompletionStartParams::createModeSpecific(reversed(m_viInputModeManager->globalState()->commandHistory()->items()), \
                0);
-}
-
-CompletionStartParams \
                EmulatedCommandBar::CommandMode::activateSedFindHistoryCompletion()
-{
-    if (m_viInputModeManager->globalState()->searchHistory()->isEmpty())
-    {
-        return CompletionStartParams::invalid();
-    }
-    CommandMode::ParsedSedExpression parsedSedExpression = parseAsSedExpression();
-    return CompletionStartParams::createModeSpecific(reversed(m_viInputModeManager->globalState()->searchHistory()->items()),
                
-                                                     \
                parsedSedExpression.findBeginPos,
-                                                     [this] (const  QString& \
completion) -> QString { return \
                withCaseSensitivityMarkersStripped(withSedDelimiterEscaped(completion)); \
                });
-}
-
-CompletionStartParams \
                EmulatedCommandBar::CommandMode::activateSedReplaceHistoryCompletion()
                
-{
-    if (m_viInputModeManager->globalState()->replaceHistory()->isEmpty())
-    {
-        return CompletionStartParams::invalid();
-    }
-    CommandMode::ParsedSedExpression parsedSedExpression = parseAsSedExpression();
-    return CompletionStartParams::createModeSpecific(reversed(m_viInputModeManager->globalState()->replaceHistory()->items()),
                
-                                                     \
                parsedSedExpression.replaceBeginPos,
-                                                     [this] (const  QString& \
completion) -> QString { return \
                withCaseSensitivityMarkersStripped(withSedDelimiterEscaped(completion)); \
                });
-}
-
-KTextEditor::Command* EmulatedCommandBar::CommandMode::queryCommand ( const QString& \
                cmd ) const
-{
-    // a command can be named ".*[\w\-]+" with the constrain that it must
-    // contain at least one letter.
-    int f = 0;
-    bool b = false;
-
-    // special case: '-' and '_' can be part of a command name, but if the
-    // command is 's' (substitute), it should be considered the delimiter and
-    // should not be counted as part of the command name
-    if (cmd.length() >= 2 && cmd.at(0) == QLatin1Char('s') && (cmd.at(1) == \
                QLatin1Char('-') || cmd.at(1) == QLatin1Char('_'))) {
-        return m_cmdDict.value(QStringLiteral("s"));
-    }
-
-    for (; f < cmd.length(); f++) {
-        if (cmd[f].isLetter()) {
-            b = true;
-        }
-        if (b && (! cmd[f].isLetterOrNumber() && cmd[f] != QLatin1Char('-') && \
                cmd[f] != QLatin1Char('_'))) {
-            break;
-        }
-    }
-    return m_cmdDict.value(cmd.left(f));
-
-}
diff --git a/src/vimode/emulatedcommandbar/emulatedcommandbar.h \
b/src/vimode/emulatedcommandbar/emulatedcommandbar.h index 3831f0b..09d4485 100644
--- a/src/vimode/emulatedcommandbar/emulatedcommandbar.h
+++ b/src/vimode/emulatedcommandbar/emulatedcommandbar.h
@@ -41,6 +41,7 @@ namespace KateVi
 class MatchHighlighter;
 class InteractiveSedReplaceMode;
 class SearchMode;
+class CommandMode;
 
 /**
  * A KateViewBarWidget that attempts to emulate some of the features of Vim's own \
command bar, @@ -87,63 +88,6 @@ private:
     friend class ActiveMode;
     QScopedPointer<MatchHighlighter> m_matchHighligher;
     QScopedPointer<Completer> m_completer;
-
-    class CommandMode : public ActiveMode
-    {
-    public:
-        CommandMode(EmulatedCommandBar* emulatedCommandBar, MatchHighlighter* \
matchHighlighter, KTextEditor::ViewPrivate* view,  QLineEdit* edit, \
                InteractiveSedReplaceMode *interactiveSedReplaceMode, Completer* \
                completer);
-        virtual ~CommandMode()
-        {
-        }
-        void setViInputModeManager(InputModeManager *viInputModeManager);
-        virtual bool handleKeyPress ( const QKeyEvent* keyEvent );
-        virtual void editTextChanged(const QString &newText);
-        virtual CompletionStartParams \
                completionInvoked(Completer::CompletionInvocation invocationType);
-        virtual void completionChosen();
-        void deactivate(bool wasAborted);
-        QString executeCommand(const QString &commandToExecute);
-    private:
-        CompletionStartParams activateCommandCompletion();
-        CompletionStartParams activateCommandHistoryCompletion();
-        CompletionStartParams activateSedFindHistoryCompletion();
-        CompletionStartParams activateSedReplaceHistoryCompletion();
-        QString withoutRangeExpression();
-        QString rangeExpression();
-        QString withSedFindTermReplacedWith(const QString &newFindTerm);
-        QString withSedDelimiterEscaped(const QString &text);
-        bool isCursorInFindTermOfSed();
-        bool isCursorInReplaceTermOfSed();
-        QString sedFindTerm();
-        QString sedReplaceTerm();
-        /**
-        * Stuff to do with expressions of the form:
-        *
-        *   s/find/replace/<sedflags>
-        */
-        struct ParsedSedExpression {
-            bool parsedSuccessfully;
-            int findBeginPos;
-            int findEndPos;
-            int replaceBeginPos;
-            int replaceEndPos;
-            QChar delimiter;
-        };
-        /**
-        * The "range expression" is the (optional) expression before the command \
                that describes
-        * the range over which the command should be run e.g. '<,'>.  @see \
                CommandRangeExpressionParser
-        */
-        CommandMode::ParsedSedExpression parseAsSedExpression();
-        void replaceCommandBeforeCursorWith(const QString &newCommand);
-        int commandBeforeCursorBegin();
-        QLineEdit *m_edit;
-        InputModeManager *m_viInputModeManager = nullptr;
-        KTextEditor::ViewPrivate *m_view;
-        InteractiveSedReplaceMode *m_interactiveSedReplaceMode;
-        Completer *m_completer;
-        KCompletion m_cmdCompletion;
-        QHash<QString, KTextEditor::Command *> m_cmdDict;
-        KTextEditor::Command *queryCommand(const QString &cmd) const;
-    };
     QScopedPointer<InteractiveSedReplaceMode> m_interactiveSedReplaceMode;
     QScopedPointer<SearchMode> m_searchMode;
     QScopedPointer<CommandMode> m_commandMode;


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic