[kde-doc-english] [ktexteditor] /: normal mode and vi-mode separation

Michal Humpula michal.humpula at hudrydum.cz
Sun Mar 23 11:47:40 UTC 2014


Git commit ce4a5776838a08edfe9b73977081b5d527683a8a by Michal Humpula.
Committed on 12/03/2014 at 19:54.
Pushed by michalhumpula into branch 'master'.

normal mode and vi-mode separation

This changes hides vi-mode behind generic input mode interface, which
means that internals of ktexteditor no longer depends on vi-mode. There
are no "if"s and only single one #ifdef. And yes there is
a BUILDE_VIMODE cmake option now, which enables building ktexteditor
without the vi-mode.

==  Why ==

Reason for doing this is the reduction of coupling and removal of those
"if(viInputMode())" cases.

== How it does ==

There is a new directory "inputmode", where the interfaces are. The
KateAbstractInputModeFactory is ment to by initialized in KateGlobal.
The view can then use it and ask it for KateAbstractInputMode instance,
which it can then use in special places like "findNext" or
"handleKeyPress", etc. The KateViInputModeFactory now hides KateViGlobal
and KateViInputMode hides the KateViInputModeManager from the rest of
the system.

The interface of KateAbstractInputMode is currently in very bad shape,
but that can be cleaned up easily. Lots of the places are oneliners,
either changing because there is no KateView::getViModeManager anymore
or because there are now multiple input modes (and yes, it means that
adding EmacsInputMode after this would not be that much of a nightmare).

== Notes ==

As for the:
* relative line numbers - plan is to let IconBar call the InputMode for
  rendering that specific part
* vi-mode specific config options - they are left alone and can be
  refactored afterwards into KateViInputModeFactory
* input mode specific actions - I would like to see them in Factories
  only, but that might not play well with the shortcut config UI. For
  now I think it's not important.

REVIEW: 116770
GUI: changes menu "Vi Input Mode" actions

M  +2    -0    CMakeLists.txt
M  +4    -1    autotests/CMakeLists.txt
M  +25   -21   autotests/src/vimode_test.cpp
M  +2    -0    autotests/src/vimode_test.h
M  +1    -0    config.h.cmake
M  +39   -23   src/CMakeLists.txt
M  +1    -1    src/data/katepartui.rc
M  +32   -0    src/dialogs/editconfigwidget.ui
M  +1    -0    src/dialogs/kateconfigpage.h
M  +37   -8    src/dialogs/katedialogs.cpp
M  +1    -3    src/dialogs/katedialogs.h
M  +8    -13   src/document/katedocument.cpp
C  +26   -24   src/inputmode/kateabstractinputmode.cpp [from: src/dialogs/kateconfigpage.h - 051% similarity]
A  +101  -0    src/inputmode/kateabstractinputmode.h     [License: LGPL (v2+)]
C  +7    -26   src/inputmode/kateabstractinputmodefactory.cpp [from: src/dialogs/kateconfigpage.h - 060% similarity]
C  +18   -20   src/inputmode/kateabstractinputmodefactory.h [from: src/dialogs/kateconfigpage.h - 055% similarity]
A  +254  -0    src/inputmode/katenormalinputmode.cpp     [License: LGPL (v2+)]
A  +88   -0    src/inputmode/katenormalinputmode.h     [License: LGPL (v2+)]
C  +28   -22   src/inputmode/katenormalinputmodefactory.cpp [from: src/dialogs/kateconfigpage.h - 050% similarity]
C  +11   -21   src/inputmode/katenormalinputmodefactory.h [from: src/dialogs/kateconfigpage.h - 059% similarity]
A  +330  -0    src/inputmode/kateviinputmode.cpp     [License: LGPL (v2+)]
A  +97   -0    src/inputmode/kateviinputmode.h     [License: LGPL (v2+)]
A  +56   -0    src/inputmode/kateviinputmodefactory.cpp     [License: LGPL (v2+)]
C  +17   -21   src/inputmode/kateviinputmodefactory.h [from: src/dialogs/kateconfigpage.h - 055% similarity]
M  +2    -6    src/script/katescriptaction.cpp
M  +3    -2    src/utils/katebookmarks.cpp
M  +18   -18   src/utils/kateconfig.cpp
M  +6    -4    src/utils/kateconfig.h
M  +19   -5    src/utils/kateglobal.cpp
M  +13   -15   src/utils/kateglobal.h
M  +0    -2    src/utils/katesedcmd.cpp
M  +3    -4    src/view/katestatusbar.cpp
M  +92   -259  src/view/kateview.cpp
M  +9    -77   src/view/kateview.h
M  +2    -4    src/view/kateviewhelpers.cpp
M  +19   -70   src/view/kateviewinternal.cpp
M  +5    -28   src/view/kateviewinternal.h
M  +3    -2    src/vimode/katevicmds.cpp
M  +6    -5    src/vimode/kateviglobal.cpp
M  +3    -1    src/vimode/kateviglobal.h
M  +0    -4    src/vimode/kateviinputmodeconfigtab.cpp
M  +24   -27   src/vimode/kateviinputmodemanager.cpp
M  +9    -1    src/vimode/kateviinputmodemanager.h
M  +3    -3    src/vimode/katevikeymapper.cpp
M  +10   -20   src/vimode/katevimodebase.cpp
M  +7    -6    src/vimode/katevinormalmode.cpp
M  +3    -0    src/vimode/katevinormalmode.h
M  +6    -1    src/vimode/katevivisualmode.cpp
M  +0    -10   src/vimode/viinputmodeconfigwidget.ui

http://commits.kde.org/ktexteditor/ce4a5776838a08edfe9b73977081b5d527683a8a

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 366d3b0..7ee5803 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -41,6 +41,8 @@ find_package(KF5KIO ${KF5_VERSION} REQUIRED)
 find_package(KF5Parts ${KF5_VERSION} REQUIRED)
 find_package(KF5Sonnet ${KF5_VERSION} REQUIRED)
 
+option (BUILD_VIMODE "Build vimode in" ON)
+
 # Subdirectories
 add_subdirectory(src)
 if (BUILD_TESTING)
diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt
index 9b91f18..9c99aa6 100644
--- a/autotests/CMakeLists.txt
+++ b/autotests/CMakeLists.txt
@@ -109,7 +109,6 @@ ktexteditor_unit_tests(
   plaintextsearch_test
   regexpsearch_test
   scriptdocument_test
-  vimode_test
   wordcompletiontest
   searchbar_test
   movingcursor_test
@@ -127,6 +126,10 @@ ktexteditor_unit_tests(
   katewildcardmatcher_test
 )
 
+if (BUILD_VIMODE)
+  ktexteditor_unit_tests(vimode_test)
+endif()
+
 ktexteditor_unit_test(completion_test src/codecompletiontestmodel.cpp src/codecompletiontestmodels.cpp)
 ktexteditor_unit_test(indenttest src/script_test_base.cpp src/testutils.cpp)
 ktexteditor_unit_test(commands_test src/script_test_base.cpp src/testutils.cpp)
diff --git a/autotests/src/vimode_test.cpp b/autotests/src/vimode_test.cpp
index 869a34f..44254ad 100644
--- a/autotests/src/vimode_test.cpp
+++ b/autotests/src/vimode_test.cpp
@@ -39,6 +39,7 @@
 #include <ktexteditor/codecompletionmodel.h>
 #include <katewordcompletion.h>
 #include <katecompletionwidget.h>
+#include "inputmode/kateviinputmode.h"
 
 #include <QLabel>
 #include <QCompleter>
@@ -304,11 +305,12 @@ void ViModeTest::init()
     
     kate_view = new KTextEditor::ViewPrivate(kate_document, mainWindow);
     mainWindowLayout->addWidget(kate_view);
-    kate_view->config()->setViInputMode(true);
-    Q_ASSERT(kate_view->viInputMode());
-    vi_input_mode_manager = kate_view->getViInputModeManager();
+    kate_view->setInputMode(View::ViInputMode);
+    Q_ASSERT(kate_view->currentInputMode()->viewInputMode() == KTextEditor::View::ViInputMode);
+    vi_input_mode = dynamic_cast<KateViInputMode *>(kate_view->currentInputMode());
+    vi_input_mode_manager = vi_input_mode->viInputModeManager();
     Q_ASSERT(vi_input_mode_manager);
-    vi_global = vi_input_mode_manager->viGlobal();
+    vi_global = vi_input_mode->viGlobal();
     Q_ASSERT(vi_global);
     kate_document->config()->setShowSpaces(true); // Flush out some issues in the KateRenderer when rendering spaces.
 
@@ -357,7 +359,7 @@ ViModeTest::~ViModeTest()
 void ViModeTest::BeginTest(const QString &original_text)
 {
     vi_input_mode_manager->viEnterNormalMode();
-    vi_input_mode_manager = kate_view->resetViInputModeManager();
+    vi_input_mode_manager = vi_input_mode->resetViInputModeManager();
     kate_document->setText(original_text);
     kate_document->undoManager()->clearUndo();
     kate_document->undoManager()->clearRedo();
@@ -431,7 +433,7 @@ void ViModeTest::TestPressKey(QString str)
                 }
                 const QString commandToExecute = str.mid(start_cmd, i - start_cmd).replace("\\\\", "\\");
                 qDebug() << "Executing command directly from ViModeTest:\n" << commandToExecute;
-                kate_view->viModeEmulatedCommandBar()->executeCommand(commandToExecute);
+                vi_input_mode->viModeEmulatedCommandBar()->executeCommand(commandToExecute);
                 // We've handled the command; go back round the loop, avoiding sending
                 // the closing \ to vi_input_mode_manager.
                 continue;
@@ -699,10 +701,11 @@ void ViModeTest::VisualModeTests()
     kate_document->setText("foo bar");
     kate_view->setSelection(Range(Cursor(0, 1), Cursor(0, 4)));
     QCOMPARE(kate_document->text(kate_view->selectionRange()), QString("oo "));
-    kate_view->config()->setViInputMode(true);
+    kate_view->setInputMode(View::ViInputMode);
     qDebug() << "selected: " << kate_document->text(kate_view->selectionRange());
-    QVERIFY(kate_view->viInputMode());
-    vi_input_mode_manager = kate_view->getViInputModeManager();
+    QVERIFY(kate_view->currentInputMode()->viewInputMode() == View::ViInputMode);
+    vi_input_mode = dynamic_cast<KateViInputMode *>(kate_view->currentInputMode());
+    vi_input_mode_manager = vi_input_mode->viInputModeManager();
     QVERIFY(vi_input_mode_manager->getCurrentViMode() == VisualMode);
     TestPressKey("l");
     QCOMPARE(kate_document->text(kate_view->selectionRange()), QString("oo b"));
@@ -2302,8 +2305,8 @@ void ViModeTest::CommandModeTests()
 class VimStyleCommandBarTestsSetUpAndTearDown
 {
 public:
-    VimStyleCommandBarTestsSetUpAndTearDown(KTextEditor::ViewPrivate *kateView, QMainWindow *mainWindow)
-        : m_kateView(kateView), m_mainWindow(mainWindow), m_windowKeepActive(mainWindow)
+    VimStyleCommandBarTestsSetUpAndTearDown(KateViInputMode *inputMode, KTextEditor::ViewPrivate *kateView, QMainWindow *mainWindow)
+        : m_kateView(kateView), m_mainWindow(mainWindow), m_windowKeepActive(mainWindow), m_viInputMode(inputMode)
     {
         m_mainWindow->show();
         m_kateView->show();
@@ -2319,7 +2322,7 @@ public:
     {
         m_mainWindow->removeEventFilter(&m_windowKeepActive);
         // Use invokeMethod to avoid having to export KateViewBar for testing.
-        QMetaObject::invokeMethod(m_kateView->viModeEmulatedCommandBar(), "hideMe");
+        QMetaObject::invokeMethod(m_viInputMode->viModeEmulatedCommandBar(), "hideMe");
         m_kateView->hide();
         m_mainWindow->hide();
         KateViewConfig::global()->setViInputModeStealKeys(false);
@@ -2331,6 +2334,7 @@ private:
     KTextEditor::ViewPrivate *m_kateView;
     QMainWindow *m_mainWindow;
     WindowKeepActive m_windowKeepActive;
+    KateViInputMode *m_viInputMode;
 };
 
 void ViModeTest::MappingTests()
@@ -2664,7 +2668,7 @@ void ViModeTest::MappingTests()
     }
 
     {
-        VimStyleCommandBarTestsSetUpAndTearDown vimStyleCommandBarTestsSetUpAndTearDown(kate_view, mainWindow);
+        VimStyleCommandBarTestsSetUpAndTearDown vimStyleCommandBarTestsSetUpAndTearDown(vi_input_mode, kate_view, mainWindow);
         // Can have mappings in Emulated Command Bar.
         clearAllMappings();
         vi_global->addMapping(KateViGlobal::CommandModeMapping, "a", "xyz", KateViGlobal::NonRecursive);
@@ -2793,7 +2797,7 @@ void ViModeTest::MappingTests()
         DoTest("", "\\:iunmap l\\ilm\\esc", "le");
 
         {
-            VimStyleCommandBarTestsSetUpAndTearDown vimStyleCommandBarTestsSetUpAndTearDown(kate_view, mainWindow);
+            VimStyleCommandBarTestsSetUpAndTearDown vimStyleCommandBarTestsSetUpAndTearDown(vi_input_mode, kate_view, mainWindow);
             // cmap works in emulated command bar and is recursive.
             // NOTE: need to do the cmap call using the direct execution (i.e. \\:cmap blah blah\\), *not* using
             // the emulated command bar (:cmap blah blah\\enter), as this will be subject to mappings, which
@@ -2911,7 +2915,7 @@ void ViModeTest::yankHighlightingTests()
     QCOMPARE(rangesOnFirstLine().size(), rangesInitial.size() + 1);
     kate_document->documentReload();
     kate_document->clear();
-    vi_input_mode_manager = kate_view->resetViInputModeManager(); // This implicitly deletes KateViNormal
+    vi_input_mode_manager = vi_input_mode->resetViInputModeManager(); // This implicitly deletes KateViNormal
     FinishTest("");
 }
 
@@ -2919,10 +2923,10 @@ void ViModeTest::VimStyleCommandBarTests()
 {
     // Ensure that some preconditions for these tests are setup, and (more importantly)
     // ensure that they are reverted no matter how these tests end.
-    VimStyleCommandBarTestsSetUpAndTearDown vimStyleCommandBarTestsSetUpAndTearDown(kate_view, mainWindow);
+    VimStyleCommandBarTestsSetUpAndTearDown vimStyleCommandBarTestsSetUpAndTearDown(vi_input_mode, kate_view, mainWindow);
 
     // Verify that we can get a non-null pointer to the emulated command bar.
-    KateViEmulatedCommandBar *emulatedCommandBar = kate_view->viModeEmulatedCommandBar();
+    KateViEmulatedCommandBar *emulatedCommandBar = vi_input_mode->viModeEmulatedCommandBar();
     QVERIFY(emulatedCommandBar);
 
     // Should initially be hidden.
@@ -6546,7 +6550,7 @@ void ViModeTest::MacroTests()
     {
         // Ensure that we can call emulated command bar searches, and that we don't record
         // synthetic keypresses.
-        VimStyleCommandBarTestsSetUpAndTearDown vimStyleCommandBarTestsSetUpAndTearDown(kate_view, mainWindow);
+        VimStyleCommandBarTestsSetUpAndTearDown vimStyleCommandBarTestsSetUpAndTearDown(vi_input_mode, kate_view, mainWindow);
         clearAllMacros();
         DoTest("foo bar\nblank line", "qa/bar\\enterqgg at arX", "foo Xar\nblank line");
         // More complex searching stuff.
@@ -6614,7 +6618,7 @@ void ViModeTest::MacroTests()
     DoTest("XXXX\nXXXX\nXXXX\nXXXX", "qarOljq3 at au", "OXXX\nXXXX\nXXXX\nXXXX");
 
     {
-        VimStyleCommandBarTestsSetUpAndTearDown vimStyleCommandBarTestsSetUpAndTearDown(kate_view, mainWindow);
+        VimStyleCommandBarTestsSetUpAndTearDown vimStyleCommandBarTestsSetUpAndTearDown(vi_input_mode, kate_view, mainWindow);
         // Make sure we can macro-ise an interactive sed replace.
         clearAllMacros();
         DoTest("foo foo foo foo\nfoo foo foo foo", "qa:s/foo/bar/gc\\enteryynyAdone\\escqggj at a", "bar bar foo bardone\nbar bar foo bardone");
@@ -7331,7 +7335,7 @@ void ViModeTest::waitForCompletionWidgetToActivate(KTextEditor::ViewPrivate *kat
 
 KateViEmulatedCommandBar *ViModeTest::emulatedCommandBar()
 {
-    KateViEmulatedCommandBar *emulatedCommandBar = kate_view->viModeEmulatedCommandBar();
+    KateViEmulatedCommandBar *emulatedCommandBar = vi_input_mode->viModeEmulatedCommandBar();
     Q_ASSERT(emulatedCommandBar);
     return emulatedCommandBar;
 }
@@ -7440,7 +7444,7 @@ void ViModeTest::clearAllMacros()
 
 QCompleter *ViModeTest::emulatedCommandBarCompleter()
 {
-    return kate_view->viModeEmulatedCommandBar()->findChild<QCompleter *>("completer");
+    return vi_input_mode->viModeEmulatedCommandBar()->findChild<QCompleter *>("completer");
 }
 
 void ViModeTest::verifyCommandBarCompletionVisible()
diff --git a/autotests/src/vimode_test.h b/autotests/src/vimode_test.h
index 5e9d480..a70f4af 100644
--- a/autotests/src/vimode_test.h
+++ b/autotests/src/vimode_test.h
@@ -32,6 +32,7 @@ class QLineEdit;
 class QLabel;
 class QCompleter;
 class QMainWindow;
+class KateViEmulatedCommandBar;
 
 class WindowKeepActive : public QObject
 {
@@ -190,6 +191,7 @@ private:
     KTextEditor::ViewPrivate *kate_view;
     QMainWindow *mainWindow;
     QVBoxLayout *mainWindowLayout;
+    KateViInputMode *vi_input_mode;
     KateViGlobal *vi_global;
     KateViInputModeManager *vi_input_mode_manager;
 
diff --git a/config.h.cmake b/config.h.cmake
index 0e01a43..e1c9f34 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -4,5 +4,6 @@
 /* config.h. Generated by cmake from config.h.cmake */
 
 #cmakedefine HAVE_FDATASYNC 1
+#cmakedefine BUILD_VIMODE 1
 
 #endif
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index d21101f..8fd0178 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -25,7 +25,7 @@ include_directories(
   ${CMAKE_CURRENT_SOURCE_DIR}/schema
   ${CMAKE_CURRENT_SOURCE_DIR}/undo
   ${CMAKE_CURRENT_SOURCE_DIR}/utils
-  ${CMAKE_CURRENT_SOURCE_DIR}/vimode
+  ${CMAKE_CURRENT_SOURCE_DIR}/inputmode
   ${CMAKE_CURRENT_SOURCE_DIR}/view
   ${CMAKE_CURRENT_SOURCE_DIR}/swapfile
   ${CMAKE_CURRENT_SOURCE_DIR}/variableeditor)
@@ -57,6 +57,7 @@ completion/expandingtree/expandingtree.cpp
 completion/katewordcompletion.cpp
 
 # dialogs
+dialogs/kateconfigpage.cpp
 dialogs/katedialogs.cpp
 dialogs/kateconfigpage.cpp
 
@@ -132,25 +133,6 @@ view/kateanimation.cpp
 view/katetextanimation.cpp
 view/katestatusbar.cpp
 
-# vi input mode
-vimode/kateviappcommands.cpp
-vimode/katevicmds.cpp
-vimode/kateviinputmodemanager.cpp
-vimode/katevimodebase.cpp
-vimode/katevinormalmode.cpp
-vimode/kateviinsertmode.cpp
-vimode/katevicommand.cpp
-vimode/katevimotion.cpp
-vimode/katevirange.cpp
-vimode/katevikeyparser.cpp
-vimode/kateviglobal.cpp
-vimode/katevivisualmode.cpp
-vimode/katevireplacemode.cpp
-vimode/kateviemulatedcommandbar.cpp
-vimode/katevicommandrangeexpressionparser.cpp
-vimode/katevikeymapper.cpp
-vimode/kateviinputmodeconfigtab.cpp
-
 # spell checking
 spellcheck/prefixstore.h
 spellcheck/prefixstore.cpp
@@ -207,7 +189,14 @@ swapfile/kateswapfile.cpp
 
 # export as HTML
 export/exporter.cpp
-export/htmlexporter.cpp)
+export/htmlexporter.cpp
+
+# input modes
+inputmode/kateabstractinputmode.cpp
+inputmode/kateabstractinputmodefactory.cpp
+inputmode/katenormalinputmode.cpp
+inputmode/katenormalinputmodefactory.cpp
+)
 
 qt5_wrap_ui(ktexteditor_LIB_SRCS 
 dialogs/textareaappearanceconfigwidget.ui
@@ -226,10 +215,37 @@ dialogs/completionconfigwidget.ui
 search/searchbarincremental.ui
 search/searchbarpower.ui
 spellcheck/spellcheckbar.ui
-vimode/viinputmodeconfigwidget.ui
 dialogs/spellcheckconfigwidget.ui
 schema/howtoimportschema.ui )
-   
+
+if (BUILD_VIMODE)
+  include_directories(${CMAKE_CURRENT_SOURCE_DIR}/vimode)
+  qt5_wrap_ui(ktexteditor_LIB_SRCS vimode/viinputmodeconfigwidget.ui)
+  set(ktexteditor_LIB_SRCS ${ktexteditor_LIB_SRCS}
+    inputmode/kateviinputmode.cpp
+    inputmode/kateviinputmodefactory.cpp
+
+    # vi input mode
+    vimode/kateviappcommands.cpp
+    vimode/katevicmds.cpp
+    vimode/kateviinputmodemanager.cpp
+    vimode/katevimodebase.cpp
+    vimode/katevinormalmode.cpp
+    vimode/kateviinsertmode.cpp
+    vimode/katevicommand.cpp
+    vimode/katevimotion.cpp
+    vimode/katevirange.cpp
+    vimode/katevikeyparser.cpp
+    vimode/kateviglobal.cpp
+    vimode/katevivisualmode.cpp
+    vimode/katevireplacemode.cpp
+    vimode/kateviemulatedcommandbar.cpp
+    vimode/katevicommandrangeexpressionparser.cpp
+    vimode/katevikeymapper.cpp
+    vimode/kateviinputmodeconfigtab.cpp
+  )
+endif()
+
 add_library(KF5TextEditor ${ktexteditor_LIB_SRCS} ${KTEXTEDITOR_PUBLIC_HEADERS})
 generate_export_header(KF5TextEditor BASE_NAME KTextEditor)
 add_library(KF5::TextEditor ALIAS KF5TextEditor)
diff --git a/src/data/katepartui.rc b/src/data/katepartui.rc
index 303cd2f..75f6525 100644
--- a/src/data/katepartui.rc
+++ b/src/data/katepartui.rc
@@ -28,7 +28,7 @@
     <Action name="edit_deselect" group="edit_select_merge" />
     <Action name="set_verticalSelect" group="edit_select_merge" />
     <Separator group="edit_select_merge" />
-    <Action name="view_vi_input_mode" group="edit_select_merge" />
+    <Action name="view_input_modes" group="edit_select_merge" />
     <Action name="set_insert" group="edit_select_merge" />
     <Separator group="edit_select_merge" />
     <Action name="edit_find" group="edit_find_merge" />
diff --git a/src/dialogs/editconfigwidget.ui b/src/dialogs/editconfigwidget.ui
index 2b8813f..3ccbb2c 100644
--- a/src/dialogs/editconfigwidget.ui
+++ b/src/dialogs/editconfigwidget.ui
@@ -82,6 +82,38 @@
     </widget>
    </item>
    <item>
+    <widget class="QGroupBox" name="gbInputMode">
+     <property name="title">
+      <string>InputMode</string>
+     </property>
+     <layout class="QHBoxLayout" name="horizontalLayout">
+      <item>
+       <widget class="QLabel" name="lblInputMode">
+        <property name="text">
+         <string>Default input mode</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QComboBox" name="cmbInputMode"/>
+      </item>
+      <item>
+       <spacer name="horizontalSpacer">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>40</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
     <widget class="QGroupBox" name="gbMisc">
      <property name="title">
       <string>Misc</string>
diff --git a/src/dialogs/kateconfigpage.h b/src/dialogs/kateconfigpage.h
index ddb0975..6a73e85 100644
--- a/src/dialogs/kateconfigpage.h
+++ b/src/dialogs/kateconfigpage.h
@@ -28,6 +28,7 @@ class KateConfigPage : public KTextEditor::ConfigPage
 public:
     explicit KateConfigPage(QWidget *parent = 0, const char *name = 0);
     virtual ~KateConfigPage();
+    virtual void reload() = 0;
 
 public:
     bool hasChanged()
diff --git a/src/dialogs/katedialogs.cpp b/src/dialogs/katedialogs.cpp
index 59817af..f6807ad 100644
--- a/src/dialogs/katedialogs.cpp
+++ b/src/dialogs/katedialogs.cpp
@@ -62,6 +62,7 @@
 #include <KColorCombo>
 #include <KComboBox>
 #include "katepartdebug.h"
+#include "kateabstractinputmodefactory.h"
 #include <KIconLoader>
 #include <KShortcutsDialog>
 #include <KLineEdit>
@@ -452,12 +453,18 @@ KateEditGeneralConfigTab::KateEditGeneralConfigTab(QWidget *parent)
     ui = new Ui::EditConfigWidget();
     ui->setupUi(newWidget);
 
+    QList<KateAbstractInputModeFactory *> inputModes = KTextEditor::EditorPrivate::self()->inputModeFactories();
+    Q_FOREACH(KateAbstractInputModeFactory *fact, inputModes) {
+        ui->cmbInputMode->addItem(fact->name(), static_cast<int>(fact->inputMode()));
+    }
+
     reload();
 
     connect(ui->chkStaticWordWrap, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
     connect(ui->chkShowStaticWordWrapMarker, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
     connect(ui->sbWordWrap, SIGNAL(valueChanged(int)), this, SLOT(slotChanged()));
     connect(ui->chkSmartCopyCut, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
+    connect(ui->cmbInputMode, SIGNAL(currentIndexChanged(int)), this, SLOT(slotChanged()));
 
     // "What's this?" help is in the ui-file
 
@@ -489,6 +496,8 @@ void KateEditGeneralConfigTab::apply()
     KateDocumentConfig::global()->configEnd();
     KateViewConfig::global()->setSmartCopyCut(ui->chkSmartCopyCut->isChecked());
     KateViewConfig::global()->configEnd();
+
+    KateViewConfig::global()->setInputModeRaw(ui->cmbInputMode->currentData().toInt());
 }
 
 void KateEditGeneralConfigTab::reload()
@@ -500,6 +509,9 @@ void KateEditGeneralConfigTab::reload()
     ui->sbWordWrap->setSuffix(ki18nc("suffix for spinbox >1 wrap words at (value is at 20 or larger)", " characters").toString());
     ui->sbWordWrap->setValue(KateDocumentConfig::global()->wordWrapAt());
     ui->chkSmartCopyCut->setChecked(KateViewConfig::global()->smartCopyCut());
+
+    const int id = static_cast<int>(KateViewConfig::global()->inputMode());
+    ui->cmbInputMode->setCurrentIndex(ui->cmbInputMode->findData(id));
 }
 
 QString KateEditGeneralConfigTab::name() const
@@ -516,7 +528,6 @@ KateEditConfigTab::KateEditConfigTab(QWidget *parent)
     , navigationConfigTab(new KateNavigationConfigTab(this))
     , indentConfigTab(new KateIndentConfigTab(this))
     , completionConfigTab(new KateCompletionConfigTab(this))
-    , viInputModeConfigTab(new KateViInputModeConfigTab(this, KTextEditor::EditorPrivate::self()->viInputModeGlobal()))
     , spellCheckConfigTab(new KateSpellCheckConfigTab(this))
 {
     QVBoxLayout *layout = new QVBoxLayout;
@@ -528,22 +539,32 @@ KateEditConfigTab::KateEditConfigTab(QWidget *parent)
     tabWidget->insertTab(1, navigationConfigTab, navigationConfigTab->name());
     tabWidget->insertTab(2, indentConfigTab, indentConfigTab->name());
     tabWidget->insertTab(3, completionConfigTab, completionConfigTab->name());
-    tabWidget->insertTab(4, viInputModeConfigTab, viInputModeConfigTab->name());
-    tabWidget->insertTab(5, spellCheckConfigTab, spellCheckConfigTab->name());
+    tabWidget->insertTab(4, spellCheckConfigTab, spellCheckConfigTab->name());
 
     connect(editConfigTab, SIGNAL(changed()), this, SLOT(slotChanged()));
     connect(navigationConfigTab, SIGNAL(changed()), this, SLOT(slotChanged()));
     connect(indentConfigTab, SIGNAL(changed()), this, SLOT(slotChanged()));
     connect(completionConfigTab, SIGNAL(changed()), this, SLOT(slotChanged()));
-    connect(viInputModeConfigTab, SIGNAL(changed()), this, SLOT(slotChanged()));
     connect(spellCheckConfigTab, SIGNAL(changed()), this, SLOT(slotChanged()));
 
+    int i = tabWidget->count();
+    Q_FOREACH(KateAbstractInputModeFactory *factory, KTextEditor::EditorPrivate::self()->inputModeFactories()) {
+        KateConfigPage *tab = factory->createConfigPage(this);
+        if (tab) {
+            m_inputModeConfigTabs << tab;
+            tabWidget->insertTab(i, tab, tab->name());
+            connect(tab, SIGNAL(changed()), this, SLOT(slotChanged()));
+            i++;
+        }
+    }
+
     layout->addWidget(tabWidget);
     setLayout(layout);
 }
 
 KateEditConfigTab::~KateEditConfigTab()
 {
+    qDeleteAll(m_inputModeConfigTabs);
 }
 
 void KateEditConfigTab::apply()
@@ -553,8 +574,10 @@ void KateEditConfigTab::apply()
     navigationConfigTab->apply();
     indentConfigTab->apply();
     completionConfigTab->apply();
-    viInputModeConfigTab->apply();
     spellCheckConfigTab->apply();
+    Q_FOREACH(KateConfigPage *tab, m_inputModeConfigTabs) {
+        tab->apply();
+    }
 }
 
 void KateEditConfigTab::reload()
@@ -563,8 +586,10 @@ void KateEditConfigTab::reload()
     navigationConfigTab->reload();
     indentConfigTab->reload();
     completionConfigTab->reload();
-    viInputModeConfigTab->reload();
     spellCheckConfigTab->reload();
+    Q_FOREACH(KateConfigPage *tab, m_inputModeConfigTabs) {
+        tab->reload();
+    }
 }
 
 void KateEditConfigTab::reset()
@@ -573,8 +598,10 @@ void KateEditConfigTab::reset()
     navigationConfigTab->reset();
     indentConfigTab->reset();
     completionConfigTab->reset();
-    viInputModeConfigTab->reset();
     spellCheckConfigTab->reset();
+    Q_FOREACH(KateConfigPage *tab, m_inputModeConfigTabs) {
+        tab->reset();
+    }
 }
 
 void KateEditConfigTab::defaults()
@@ -583,8 +610,10 @@ void KateEditConfigTab::defaults()
     navigationConfigTab->defaults();
     indentConfigTab->defaults();
     completionConfigTab->defaults();
-    viInputModeConfigTab->defaults();
     spellCheckConfigTab->defaults();
+    Q_FOREACH(KateConfigPage *tab, m_inputModeConfigTabs) {
+        tab->defaults();
+    }
 }
 
 QString KateEditConfigTab::name() const
diff --git a/src/dialogs/katedialogs.h b/src/dialogs/katedialogs.h
index 16add02..b639f5f 100644
--- a/src/dialogs/katedialogs.h
+++ b/src/dialogs/katedialogs.h
@@ -81,8 +81,6 @@ class CompletionConfigTab;
 class SpellCheckConfigWidget;
 }
 
-class KateViInputModeConfigTab;
-
 class KateGotoBar : public KateViewBarWidget
 {
     Q_OBJECT
@@ -250,8 +248,8 @@ private:
     KateNavigationConfigTab *navigationConfigTab;
     KateIndentConfigTab *indentConfigTab;
     KateCompletionConfigTab *completionConfigTab;
-    KateViInputModeConfigTab *viInputModeConfigTab;
     KateSpellCheckConfigTab *spellCheckConfigTab;
+    QList<KateConfigPage *> m_inputModeConfigTabs;
 };
 
 class KateViewDefaultsConfig : public KateConfigPage
diff --git a/src/document/katedocument.cpp b/src/document/katedocument.cpp
index e196395..0ec11d3 100644
--- a/src/document/katedocument.cpp
+++ b/src/document/katedocument.cpp
@@ -41,7 +41,6 @@
 #include "kateschema.h"
 #include "katebuffer.h"
 #include "kateundomanager.h"
-#include "katevireplacemode.h"
 #include "spellcheck/prefixstore.h"
 #include "spellcheck/ontheflycheck.h"
 #include "spellcheck/spellcheck.h"
@@ -49,6 +48,7 @@
 #include "kateswapfile.h"
 #include "katepartdebug.h"
 #include "printing/kateprinter.h"
+#include "kateabstractinputmode.h"
 
 #include <KTextEditor/DocumentCursor>
 #include <KTextEditor/Attribute>
@@ -2778,17 +2778,14 @@ bool KTextEditor::DocumentPrivate::typeChars(KTextEditor::ViewPrivate *view, con
 
     KTextEditor::Cursor oldCur(view->cursorPosition());
 
-    if (config()->ovr()
-            || (view->viInputMode() && view->getViInputModeManager()->getCurrentViMode() == ReplaceMode)) {
-
+    if (view->currentInputMode()->overwrite()) {
         KTextEditor::Range r = KTextEditor::Range(view->cursorPosition(), qMin(chars.length(),
                                textLine->length() - view->cursorPosition().column()));
 
         // replace mode needs to know what was removed so it can be restored with backspace
-        if (view->viInputMode() && view->getViInputModeManager()->getCurrentViMode() == ReplaceMode
-                && oldCur.column() < line(view->cursorPosition().line()).length()) {
+        if (oldCur.column() < line(view->cursorPosition().line()).length()) {
             QChar removed = line(view->cursorPosition().line()).at(r.start().column());
-            view->getViInputModeManager()->getViReplaceMode()->overwrittenChar(removed);
+            view->currentInputMode()->overwrittenChar(removed);
         }
 
         removeText(r);
@@ -3085,14 +3082,12 @@ void KTextEditor::DocumentPrivate::insertTab(KTextEditor::ViewPrivate *view, con
 
     if (!view->config()->persistentSelection() && view->selection()) {
         view->removeSelectedText();
-    } else if (config()->ovr() && c.column() < lineLen) {
+    } else if (view->currentInputMode()->overwrite() && c.column() < lineLen) {
         KTextEditor::Range r = KTextEditor::Range(view->cursorPosition(), 1);
 
-        if (view->viInputMode() && view->getViInputModeManager()->getCurrentViMode() == ReplaceMode) {
-            // vi replace mode needs to know what was removed so it can be restored with backspace
-            QChar removed = line(view->cursorPosition().line()).at(r.start().column());
-            view->getViInputModeManager()->getViReplaceMode()->overwrittenChar(removed);
-        }
+        // replace mode needs to know what was removed so it can be restored with backspace
+        QChar removed = line(view->cursorPosition().line()).at(r.start().column());
+        view->currentInputMode()->overwrittenChar(removed);
         removeText(r);
     }
 
diff --git a/src/dialogs/kateconfigpage.h b/src/inputmode/kateabstractinputmode.cpp
similarity index 51%
copy from src/dialogs/kateconfigpage.h
copy to src/inputmode/kateabstractinputmode.cpp
index ddb0975..5cbf222 100644
--- a/src/dialogs/kateconfigpage.h
+++ b/src/inputmode/kateabstractinputmode.cpp
@@ -1,4 +1,4 @@
-/* This file is part of the KDE libraries
+/*  This file is part of the KDE libraries and the Kate part.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -16,33 +16,35 @@
  *  Boston, MA 02110-1301, USA.
  */
 
-#ifndef __KATE_CONFIG_PAGE_H__
-#define __KATE_CONFIG_PAGE_H__
+#include "kateabstractinputmode.h"
+#include "kateviewinternal.h"
 
-#include <ktexteditor/configpage.h>
-
-class KateConfigPage : public KTextEditor::ConfigPage
+KateAbstractInputMode::~KateAbstractInputMode()
 {
-    Q_OBJECT
-
-public:
-    explicit KateConfigPage(QWidget *parent = 0, const char *name = 0);
-    virtual ~KateConfigPage();
+}
 
-public:
-    bool hasChanged()
-    {
-        return m_changed;
-    }
+KateAbstractInputMode::KateAbstractInputMode(KateViewInternal *viewInternal)
+    : m_viewInternal(viewInternal)
+    , m_view(viewInternal->view())
+{
+}
 
-protected Q_SLOTS:
-    void slotChanged();
+KateLayoutCache *KateAbstractInputMode::layoutCache() const
+{
+    return m_viewInternal->cache();
+}
 
-private Q_SLOTS:
-    void somethingHasChanged();
+void KateAbstractInputMode::updateCursor(const KTextEditor::Cursor &c)
+{
+    m_viewInternal->updateCursor(c);
+}
 
-protected:
-    bool m_changed;
-};
+int KateAbstractInputMode::linesDisplayed() const
+{
+    return m_viewInternal->linesDisplayed();
+}
 
-#endif
+void KateAbstractInputMode::scrollViewLines(int offset)
+{
+    return m_viewInternal->scrollViewLines(offset);
+}
diff --git a/src/inputmode/kateabstractinputmode.h b/src/inputmode/kateabstractinputmode.h
new file mode 100644
index 0000000..70d9512
--- /dev/null
+++ b/src/inputmode/kateabstractinputmode.h
@@ -0,0 +1,101 @@
+/*  This file is part of the KDE libraries and the Kate part.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __KATE_ABSTRACT_INPUT_MODE_H__
+#define __KATE_ABSTRACT_INPUT_MODE_H__
+
+class KateLayoutCache;
+class KateViewInternal;
+
+#include "katerenderer.h"
+#include "ktexteditor/view.h"
+#include "ktexteditor_export.h" // for tests
+
+#include <KConfigGroup>
+
+#include <QKeyEvent>
+
+class KateViewInternal;
+namespace KTextEditor { class ViewPrivate; }
+
+class KTEXTEDITOR_EXPORT KateAbstractInputMode
+{
+protected:
+    KateAbstractInputMode(KateViewInternal *);
+
+public:
+    virtual ~KateAbstractInputMode();
+
+    virtual KTextEditor::View::ViewMode viewMode() const = 0;
+    virtual QString viewModeHuman() const = 0;
+    virtual KTextEditor::View::InputMode viewInputMode() const = 0;
+    virtual QString viewInputModeHuman() const = 0;
+
+    virtual void activate() = 0;
+    virtual void deactivate() = 0;
+    virtual void reset() = 0;
+
+    virtual bool overwrite() const = 0;
+    virtual void overwrittenChar(const QChar &) = 0;
+    virtual void clearSelection() = 0;
+    virtual bool stealKey(const QKeyEvent *) const = 0;
+
+    virtual void gotFocus() = 0;
+    virtual void lostFocus() = 0;
+
+    virtual void readSessionConfig(const KConfigGroup &config) = 0;
+    virtual void writeSessionConfig(KConfigGroup &config) = 0;
+    virtual void updateRendererConfig() = 0;
+    virtual void updateConfig() = 0;
+    virtual void readWriteChanged(bool rw) = 0;
+
+    virtual void find() = 0;
+    virtual void findSelectedForwards() = 0;
+    virtual void findSelectedBackwards() = 0;
+    virtual void findReplace() = 0;
+    virtual void findNext() = 0;
+    virtual void findPrevious() = 0;
+
+    virtual void activateCommandLine() = 0;
+
+    virtual bool keyPress(QKeyEvent *) = 0;
+    virtual bool blinkCaret() const = 0;
+    virtual KateRenderer::caretStyles caretStyle() const = 0;
+
+    virtual void toggleInsert() = 0;
+    virtual void launchInteractiveCommand(const QString &command) = 0;
+
+    virtual QString bookmarkLabel(int line) const = 0;
+
+    /* functions that are currently view private, but vi-mode needs to access them */
+public:
+    void updateCursor(const KTextEditor::Cursor &newCursor);
+    KateLayoutCache *layoutCache() const;
+    int linesDisplayed() const;
+    void scrollViewLines(int offset);
+
+protected:
+    KateViewInternal *viewInternal() const { return m_viewInternal; }
+    KTextEditor::ViewPrivate *view() const { return m_view; }
+
+private:
+    KateViewInternal *m_viewInternal;
+    KTextEditor::ViewPrivate *m_view;
+};
+
+#endif
diff --git a/src/dialogs/kateconfigpage.h b/src/inputmode/kateabstractinputmodefactory.cpp
similarity index 60%
copy from src/dialogs/kateconfigpage.h
copy to src/inputmode/kateabstractinputmodefactory.cpp
index ddb0975..ea1f759 100644
--- a/src/dialogs/kateconfigpage.h
+++ b/src/inputmode/kateabstractinputmodefactory.cpp
@@ -1,4 +1,4 @@
-/* This file is part of the KDE libraries
+/*  This file is part of the KDE libraries and the Kate part.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -16,33 +16,14 @@
  *  Boston, MA 02110-1301, USA.
  */
 
-#ifndef __KATE_CONFIG_PAGE_H__
-#define __KATE_CONFIG_PAGE_H__
+#include "kateabstractinputmodefactory.h"
 
-#include <ktexteditor/configpage.h>
-
-class KateConfigPage : public KTextEditor::ConfigPage
+KateAbstractInputModeFactory::KateAbstractInputModeFactory()
 {
-    Q_OBJECT
-
-public:
-    explicit KateConfigPage(QWidget *parent = 0, const char *name = 0);
-    virtual ~KateConfigPage();
-
-public:
-    bool hasChanged()
-    {
-        return m_changed;
-    }
 
-protected Q_SLOTS:
-    void slotChanged();
+}
 
-private Q_SLOTS:
-    void somethingHasChanged();
-
-protected:
-    bool m_changed;
-};
+KateAbstractInputModeFactory::~KateAbstractInputModeFactory()
+{
 
-#endif
+}
diff --git a/src/dialogs/kateconfigpage.h b/src/inputmode/kateabstractinputmodefactory.h
similarity index 55%
copy from src/dialogs/kateconfigpage.h
copy to src/inputmode/kateabstractinputmodefactory.h
index ddb0975..03c4ca0 100644
--- a/src/dialogs/kateconfigpage.h
+++ b/src/inputmode/kateabstractinputmodefactory.h
@@ -1,4 +1,4 @@
-/* This file is part of the KDE libraries
+/*  This file is part of the KDE libraries and the Kate part.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -16,33 +16,31 @@
  *  Boston, MA 02110-1301, USA.
  */
 
-#ifndef __KATE_CONFIG_PAGE_H__
-#define __KATE_CONFIG_PAGE_H__
+#ifndef __KATE_ABSTRACT_INPUT_MODE_FACTORY_H__
+#define __KATE_ABSTRACT_INPUT_MODE_FACTORY_H__
 
-#include <ktexteditor/configpage.h>
+class KateAbstractInputMode;
+class KateViewInternal;
 
-class KateConfigPage : public KTextEditor::ConfigPage
-{
-    Q_OBJECT
+class KConfig;
+class KateConfigPage;
 
-public:
-    explicit KateConfigPage(QWidget *parent = 0, const char *name = 0);
-    virtual ~KateConfigPage();
+#include <QString>
+#include "ktexteditor/view.h"
+class QWidget;
 
+class KateAbstractInputModeFactory
+{
 public:
-    bool hasChanged()
-    {
-        return m_changed;
-    }
+    KateAbstractInputModeFactory();
 
-protected Q_SLOTS:
-    void slotChanged();
+    virtual ~KateAbstractInputModeFactory();
+    virtual KateAbstractInputMode *createInputMode(KateViewInternal *viewInternal) = 0;
 
-private Q_SLOTS:
-    void somethingHasChanged();
+    virtual QString name() = 0;
+    virtual KTextEditor::View::InputMode inputMode() = 0;
 
-protected:
-    bool m_changed;
+    virtual KateConfigPage *createConfigPage(QWidget *) = 0;
 };
 
 #endif
diff --git a/src/inputmode/katenormalinputmode.cpp b/src/inputmode/katenormalinputmode.cpp
new file mode 100644
index 0000000..4990892
--- /dev/null
+++ b/src/inputmode/katenormalinputmode.cpp
@@ -0,0 +1,254 @@
+/*  This file is part of the KDE libraries and the Kate part.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ */
+
+#include "katenormalinputmode.h"
+#include "kateviewinternal.h"
+#include "kateconfig.h"
+#include "katesearchbar.h"
+#include "katecompletionwidget.h"
+
+#include <KLocalizedString>
+
+KateNormalInputMode::KateNormalInputMode(KateViewInternal *viewInternal)
+    : KateAbstractInputMode(viewInternal)
+    , m_searchBar(0)
+    , m_cmdLine(0)
+{
+}
+
+KateNormalInputMode::~KateNormalInputMode()
+{
+    delete m_cmdLine;
+    delete m_searchBar;
+}
+
+void KateNormalInputMode::activate()
+{
+    view()->activateEditActions();
+}
+
+void KateNormalInputMode::deactivate()
+{
+    view()->deactivateEditActions();
+}
+
+void KateNormalInputMode::reset()
+{
+    // nothing todo
+}
+
+bool KateNormalInputMode::overwrite() const
+{
+    return view()->doc()->config()->ovr();
+}
+
+void KateNormalInputMode::overwrittenChar(const QChar &)
+{
+    // nothing todo
+}
+
+void KateNormalInputMode::clearSelection()
+{
+    view()->clearSelection();
+}
+
+bool KateNormalInputMode::stealKey(const QKeyEvent *) const
+{
+    return false;
+}
+
+KTextEditor::View::InputMode KateNormalInputMode::viewInputMode() const
+{
+    return KTextEditor::View::NormalInputMode;
+}
+
+QString KateNormalInputMode::viewInputModeHuman() const
+{
+    return i18n("Normal");
+}
+
+KTextEditor::View::ViewMode KateNormalInputMode::viewMode() const
+{
+    return view()->isOverwriteMode() ? KTextEditor::View::NormalModeOverwrite : KTextEditor::View::NormalModeInsert;
+}
+
+QString KateNormalInputMode::viewModeHuman() const
+{
+    return view()->isOverwriteMode() ? i18n("OVERWRITE") : i18n("INSERT");
+}
+
+void KateNormalInputMode::gotFocus()
+{
+    view()->activateEditActions();
+}
+
+void KateNormalInputMode::lostFocus()
+{
+    view()->deactivateEditActions();
+}
+
+void KateNormalInputMode::readSessionConfig(const KConfigGroup &)
+{
+    // do nothing
+}
+
+void KateNormalInputMode::writeSessionConfig(KConfigGroup &)
+{
+    // do nothing
+}
+
+void KateNormalInputMode::updateConfig()
+{
+    // do nothing
+}
+
+void KateNormalInputMode::readWriteChanged(bool)
+{
+    // inform search bar
+    if (m_searchBar) {
+        m_searchBar->slotReadWriteChanged();
+    }
+}
+
+
+void KateNormalInputMode::find()
+{
+    const bool INIT_HINT_AS_INCREMENTAL = false;
+    KateSearchBar *const bar = searchBar(INIT_HINT_AS_INCREMENTAL);
+    bar->enterIncrementalMode();
+    view()->bottomViewBar()->addBarWidget(bar);
+    view()->bottomViewBar()->showBarWidget(bar);
+    bar->setFocus();
+}
+
+void KateNormalInputMode::findSelectedForwards()
+{
+    KateSearchBar::nextMatchForSelection(view(), KateSearchBar::SearchForward);
+}
+
+void KateNormalInputMode::findSelectedBackwards()
+{
+    KateSearchBar::nextMatchForSelection(view(), KateSearchBar::SearchBackward);
+}
+
+void KateNormalInputMode::findReplace()
+{
+    const bool INIT_HINT_AS_POWER = true;
+    KateSearchBar *const bar = searchBar(INIT_HINT_AS_POWER);
+    bar->enterPowerMode();
+    view()->bottomViewBar()->addBarWidget(bar);
+    view()->bottomViewBar()->showBarWidget(bar);
+    bar->setFocus();
+}
+
+void KateNormalInputMode::findNext()
+{
+    searchBar()->findNext();
+}
+
+void KateNormalInputMode::findPrevious()
+{
+    searchBar()->findPrevious();
+}
+
+void KateNormalInputMode::activateCommandLine()
+{
+    const KTextEditor::Range selection = view()->selectionRange();
+
+    // if the user has selected text, insert the selection's range (start line to end line) in the
+    // command line when opened
+    if (selection.start().line() != -1 && selection.end().line() != -1) {
+        cmdLineBar()->setText(QString::number(selection.start().line() + 1) + QLatin1Char(',')
+        + QString::number(selection.end().line() + 1));
+    }
+    view()->bottomViewBar()->showBarWidget(cmdLineBar());
+    cmdLineBar()->setFocus();
+}
+
+KateSearchBar *KateNormalInputMode::searchBar(bool initHintAsPower)
+{
+    if (!m_searchBar) {
+        m_searchBar = new KateSearchBar(initHintAsPower, view(), KateViewConfig::global());
+    }
+    return m_searchBar;
+}
+
+KateCommandLineBar *KateNormalInputMode::cmdLineBar()
+{
+    if (!m_cmdLine) {
+        m_cmdLine = new KateCommandLineBar(view(), view()->bottomViewBar());
+        view()->bottomViewBar()->addBarWidget(m_cmdLine);
+    }
+
+    return m_cmdLine;
+}
+
+bool KateNormalInputMode::hasSearchBar() const
+{
+    return m_searchBar != 0;
+}
+
+void KateNormalInputMode::updateRendererConfig()
+{
+    if (m_searchBar) {
+        m_searchBar->updateHighlightColors();
+    }
+}
+
+bool KateNormalInputMode::keyPress(QKeyEvent *e)
+{
+    // Note: AND'ing with <Shift> is a quick hack to fix Key_Enter
+    const int key = e->key() | (e->modifiers() & Qt::ShiftModifier);
+
+    if (view()->isCompletionActive()) {
+        if (key == Qt::Key_Enter || key == Qt::Key_Return) {
+            view()->completionWidget()->execute();
+            e->accept();
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool KateNormalInputMode::blinkCaret() const
+{
+    return true;
+}
+
+KateRenderer::caretStyles KateNormalInputMode::caretStyle() const
+{
+    return view()->isOverwriteMode() ? KateRenderer::Block : KateRenderer::Line;
+}
+
+void KateNormalInputMode::toggleInsert()
+{
+    view()->toggleInsert();
+}
+
+void KateNormalInputMode::launchInteractiveCommand(const QString &command)
+{
+    KateCommandLineBar *cmdLine = cmdLineBar();
+    view()->bottomViewBar()->showBarWidget(cmdLine);
+    cmdLine->setText(command, false);
+}
+
+QString KateNormalInputMode::bookmarkLabel(int) const
+{
+    return QString();
+}
diff --git a/src/inputmode/katenormalinputmode.h b/src/inputmode/katenormalinputmode.h
new file mode 100644
index 0000000..ad72279
--- /dev/null
+++ b/src/inputmode/katenormalinputmode.h
@@ -0,0 +1,88 @@
+/*  This file is part of the KDE libraries and the Kate part.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __KATE_NORMAL_INPUT_MODE_H__
+#define __KATE_NORMAL_INPUT_MODE_H__
+
+#include "kateabstractinputmode.h"
+
+class KateNormalInputModeFactory;
+class KateSearchBar;
+class KateCommandLineBar;
+
+class KateNormalInputMode : public KateAbstractInputMode
+{
+    KateNormalInputMode(KateViewInternal *viewInternal);
+    friend KateNormalInputModeFactory;
+
+public:
+    virtual ~KateNormalInputMode();
+
+    virtual KTextEditor::View::ViewMode viewMode() const;
+    virtual QString viewModeHuman() const;
+    virtual KTextEditor::View::InputMode viewInputMode() const;
+    virtual QString viewInputModeHuman() const;
+
+    virtual void activate();
+    virtual void deactivate();
+    virtual void reset();
+
+    virtual bool overwrite() const;
+    virtual void overwrittenChar(const QChar &);
+
+    virtual void clearSelection();
+    virtual bool stealKey(const QKeyEvent *) const;
+
+    virtual void gotFocus();
+    virtual void lostFocus();
+
+    virtual void readSessionConfig(const KConfigGroup &config);
+    virtual void writeSessionConfig(KConfigGroup &config);
+    virtual void updateRendererConfig();
+    virtual void updateConfig();
+    virtual void readWriteChanged(bool rw);
+
+    virtual void find();
+    virtual void findSelectedForwards();
+    virtual void findSelectedBackwards();
+    virtual void findReplace();
+    virtual void findNext();
+    virtual void findPrevious();
+
+    virtual void activateCommandLine();
+
+    virtual bool keyPress(QKeyEvent *);
+    virtual bool blinkCaret() const;
+    virtual KateRenderer::caretStyles caretStyle() const;
+
+    virtual void toggleInsert();
+    virtual void launchInteractiveCommand(const QString &command);
+
+    virtual QString bookmarkLabel(int line) const;
+
+private:
+    KateSearchBar *searchBar(bool initHintAsPower = false);
+    bool hasSearchBar() const;
+    KateCommandLineBar *cmdLineBar();
+
+private:
+    KateSearchBar *m_searchBar;
+    KateCommandLineBar *m_cmdLine;
+};
+
+#endif
diff --git a/src/dialogs/kateconfigpage.h b/src/inputmode/katenormalinputmodefactory.cpp
similarity index 50%
copy from src/dialogs/kateconfigpage.h
copy to src/inputmode/katenormalinputmodefactory.cpp
index ddb0975..b8b086b 100644
--- a/src/dialogs/kateconfigpage.h
+++ b/src/inputmode/katenormalinputmodefactory.cpp
@@ -1,4 +1,4 @@
-/* This file is part of the KDE libraries
+/*  This file is part of the KDE libraries and the Kate part.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -16,33 +16,39 @@
  *  Boston, MA 02110-1301, USA.
  */
 
-#ifndef __KATE_CONFIG_PAGE_H__
-#define __KATE_CONFIG_PAGE_H__
+#include "katenormalinputmodefactory.h"
+#include "katenormalinputmode.h"
 
-#include <ktexteditor/configpage.h>
+#include <KLocalizedString>
 
-class KateConfigPage : public KTextEditor::ConfigPage
+KateNormalInputModeFactory::KateNormalInputModeFactory()
+    : KateAbstractInputModeFactory()
 {
-    Q_OBJECT
 
-public:
-    explicit KateConfigPage(QWidget *parent = 0, const char *name = 0);
-    virtual ~KateConfigPage();
+}
 
-public:
-    bool hasChanged()
-    {
-        return m_changed;
-    }
+KateNormalInputModeFactory::~KateNormalInputModeFactory()
+{
+
+}
 
-protected Q_SLOTS:
-    void slotChanged();
+KateAbstractInputMode *KateNormalInputModeFactory::createInputMode(KateViewInternal *viewInternal)
+{
+    return new KateNormalInputMode(viewInternal);
+}
 
-private Q_SLOTS:
-    void somethingHasChanged();
+KateConfigPage *KateNormalInputModeFactory::createConfigPage(QWidget *)
+{
+    return nullptr;
+}
 
-protected:
-    bool m_changed;
-};
+KTextEditor::View::InputMode KateNormalInputModeFactory::inputMode()
+{
+    return KTextEditor::View::NormalInputMode;
+}
+
+QString KateNormalInputModeFactory::name()
+{
+    return i18n("Normal Mode");
+}
 
-#endif
diff --git a/src/dialogs/kateconfigpage.h b/src/inputmode/katenormalinputmodefactory.h
similarity index 59%
copy from src/dialogs/kateconfigpage.h
copy to src/inputmode/katenormalinputmodefactory.h
index ddb0975..57e4902 100644
--- a/src/dialogs/kateconfigpage.h
+++ b/src/inputmode/katenormalinputmodefactory.h
@@ -1,4 +1,4 @@
-/* This file is part of the KDE libraries
+/*  This file is part of the KDE libraries and the Kate part.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -16,33 +16,23 @@
  *  Boston, MA 02110-1301, USA.
  */
 
-#ifndef __KATE_CONFIG_PAGE_H__
-#define __KATE_CONFIG_PAGE_H__
+#ifndef __KATE_NORMAL_INPUT_MODE_FACTORY_H__
+#define __KATE_NORMAL_INPUT_MODE_FACTORY_H__
 
-#include <ktexteditor/configpage.h>
+#include "kateabstractinputmodefactory.h"
 
-class KateConfigPage : public KTextEditor::ConfigPage
+class KateNormalInputModeFactory : public KateAbstractInputModeFactory
 {
-    Q_OBJECT
-
-public:
-    explicit KateConfigPage(QWidget *parent = 0, const char *name = 0);
-    virtual ~KateConfigPage();
-
 public:
-    bool hasChanged()
-    {
-        return m_changed;
-    }
+    KateNormalInputModeFactory();
 
-protected Q_SLOTS:
-    void slotChanged();
+    virtual ~KateNormalInputModeFactory();
+    virtual KateAbstractInputMode *createInputMode(KateViewInternal *viewInternal);
 
-private Q_SLOTS:
-    void somethingHasChanged();
+    virtual QString name();
+    virtual KTextEditor::View::InputMode inputMode();
 
-protected:
-    bool m_changed;
+    virtual KateConfigPage *createConfigPage(QWidget *);
 };
 
 #endif
diff --git a/src/inputmode/kateviinputmode.cpp b/src/inputmode/kateviinputmode.cpp
new file mode 100644
index 0000000..7fa1e91
--- /dev/null
+++ b/src/inputmode/kateviinputmode.cpp
@@ -0,0 +1,330 @@
+/*  This file is part of the KDE libraries and the Kate part.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ */
+
+#include "kateviinputmode.h"
+#include "kateviewinternal.h"
+#include "kateviinputmodemanager.h"
+#include "katevireplacemode.h"
+#include "kateviemulatedcommandbar.h"
+#include "kateconfig.h"
+#include "katevivisualmode.h"
+
+#include <KLocalizedString>
+
+#include <QCoreApplication>
+
+KateViInputMode::KateViInputMode(KateViewInternal *viewInternal, KateViGlobal *global)
+    : KateAbstractInputMode(viewInternal)
+    , m_viModeEmulatedCommandBar(0)
+    , m_viGlobal(global)
+    , m_activated(false)
+{
+    m_relLineNumbers = KateViewConfig::global()->viRelativeLineNumbers();
+
+    m_viModeManager = new KateViInputModeManager(this, view(), viewInternal);
+}
+
+KateViInputMode::~KateViInputMode()
+{
+    delete m_viModeManager;
+    delete m_viModeEmulatedCommandBar;
+}
+
+void KateViInputMode::activate()
+{
+    m_activated = true;
+    view()->setCaretStyle(KateRenderer::Block, true); // TODO: can we end up in insert mode?
+    reset(); // TODO: is this necessary? (well, not anymore I guess)
+
+    if (view()->selection()) {
+        m_viModeManager->changeViMode(VisualMode);
+        view()->setCursorPosition(Cursor(view()->selectionRange().end().line(), view()->selectionRange().end().column() - 1));
+        m_viModeManager->m_viVisualMode->updateSelection();
+    }
+}
+
+void KateViInputMode::deactivate()
+{
+    if (m_viModeEmulatedCommandBar) {
+        m_viModeEmulatedCommandBar->hideMe();
+    }
+
+    // make sure to turn off edits mergin when leaving vi input mode
+    view()->doc()->setUndoMergeAllEdits(false);
+    m_activated = false;
+}
+
+void KateViInputMode::reset()
+{
+    if (m_viModeEmulatedCommandBar) {
+        m_viModeEmulatedCommandBar->hideMe();
+    }
+
+    delete m_viModeManager;
+    m_viModeManager = new KateViInputModeManager(this, view(), viewInternal());
+
+    if (m_viModeEmulatedCommandBar) {
+        m_viModeEmulatedCommandBar->setViInputModeManager(m_viModeManager);
+    }
+}
+
+bool KateViInputMode::overwrite() const
+{
+    return  m_viModeManager->getCurrentViMode() == ReplaceMode;
+}
+
+void KateViInputMode::overwrittenChar(const QChar &c)
+{
+    m_viModeManager->getViReplaceMode()->overwrittenChar(c);
+}
+
+void KateViInputMode::clearSelection()
+{
+    // do nothing, handled elsewhere
+}
+
+bool KateViInputMode::stealKey(const QKeyEvent *k) const
+{
+    const bool steal = KateViewConfig::global()->viInputModeStealKeys();
+    return steal && (m_viModeManager->getCurrentViMode() != InsertMode || k->modifiers() == Qt::ControlModifier || k->key() == Qt::Key_Insert);
+}
+
+KTextEditor::View::InputMode KateViInputMode::viewInputMode() const
+{
+    return KTextEditor::View::ViInputMode;
+}
+
+QString KateViInputMode::viewInputModeHuman() const
+{
+    return i18n("vi-mode");
+}
+
+KTextEditor::View::ViewMode KateViInputMode::viewMode() const
+{
+    return m_viModeManager->getCurrentViewMode();
+}
+
+QString KateViInputMode::viewModeHuman() const
+{
+    QString currentMode = KateViInputModeManager::modeToString(m_viModeManager->getCurrentViMode());
+
+    if (m_viModeManager->isRecordingMacro()) {
+        currentMode.prepend (QLatin1String("(") + i18n("recording") + QLatin1String(") "));
+    }
+
+    /**
+     * perhaps append the current keys of a command not finalized
+     */
+    QString cmd = m_viModeManager->getVerbatimKeys();
+    if (!cmd.isEmpty()) {
+        currentMode.prepend(QString::fromLatin1("<em>%1</em> ").arg(cmd));
+    }
+
+    /**
+     * make it bold
+     */
+    return QString::fromLatin1("<b>%1</b>").arg(currentMode);
+}
+
+void KateViInputMode::gotFocus()
+{
+    // nothing to do
+}
+
+void KateViInputMode::lostFocus()
+{
+    // nothing to do
+}
+
+void KateViInputMode::readSessionConfig(const KConfigGroup &config)
+{
+    // restore vi registers and jump list
+    m_viModeManager->readSessionConfig(config);
+}
+
+void KateViInputMode::writeSessionConfig(KConfigGroup &config)
+{
+    // save vi registers and jump list
+    m_viModeManager->writeSessionConfig(config);
+}
+
+void KateViInputMode::updateConfig()
+{
+    KateViewConfig *cfg = view()->config();
+
+    // whether relative line numbers should be used or not.
+    m_relLineNumbers = cfg->viRelativeLineNumbers();
+}
+
+void KateViInputMode::readWriteChanged(bool)
+{
+    // nothing todo
+}
+
+void KateViInputMode::find()
+{
+    showViModeEmulatedCommandBar();
+    viModeEmulatedCommandBar()->init(KateViEmulatedCommandBar::SearchForward);
+}
+
+void KateViInputMode::findSelectedForwards()
+{
+    m_viModeManager->findNext();
+}
+
+void KateViInputMode::findSelectedBackwards()
+{
+    m_viModeManager->findPrevious();
+}
+
+void KateViInputMode::findReplace()
+{
+    showViModeEmulatedCommandBar();
+    viModeEmulatedCommandBar()->init(KateViEmulatedCommandBar::SearchForward);
+}
+
+void KateViInputMode::findNext()
+{
+    m_viModeManager->findNext();
+}
+
+void KateViInputMode::findPrevious()
+{
+    m_viModeManager->findPrevious();
+}
+
+void KateViInputMode::activateCommandLine()
+{
+    showViModeEmulatedCommandBar();
+    viModeEmulatedCommandBar()->init(KateViEmulatedCommandBar::Command);
+}
+
+void KateViInputMode::showViModeEmulatedCommandBar()
+{
+    view()->bottomViewBar()->addBarWidget(viModeEmulatedCommandBar());
+    view()->bottomViewBar()->showBarWidget(viModeEmulatedCommandBar());
+}
+
+KateViEmulatedCommandBar *KateViInputMode::viModeEmulatedCommandBar()
+{
+    if (!m_viModeEmulatedCommandBar) {
+        m_viModeEmulatedCommandBar = new KateViEmulatedCommandBar(m_viModeManager, view());
+        m_viModeEmulatedCommandBar->hide();
+    }
+
+    return m_viModeEmulatedCommandBar;
+}
+
+void KateViInputMode::updateRendererConfig()
+{
+    // do nothing
+}
+
+bool KateViInputMode::keyPress(QKeyEvent *e)
+{
+    if (m_viModeManager->getCurrentViMode() == InsertMode || m_viModeManager->getCurrentViMode() == ReplaceMode) {
+        if (m_viModeManager->handleKeypress(e)) {
+            return true;
+        } else if (e->modifiers() != Qt::NoModifier && e->modifiers() != Qt::ShiftModifier) {
+            // re-post key events not handled if they have a modifier other than shift
+            QEvent *copy = new QKeyEvent(e->type(), e->key(), e->modifiers(), e->text(),
+                                         e->isAutoRepeat(), e->count());
+            QCoreApplication::postEvent(viewInternal()->parent(), copy);
+        }
+    } else { // !InsertMode
+        if (!m_viModeManager->handleKeypress(e)) {
+            // we didn't need that keypress, un-steal it :-)
+            QEvent *copy = new QKeyEvent(e->type(), e->key(), e->modifiers(), e->text(),
+                                            e->isAutoRepeat(), e->count());
+            QCoreApplication::postEvent(viewInternal()->parent(), copy);
+        }
+        emit view()->viewModeChanged(view(), viewMode());
+        return true;
+    }
+
+    return false;
+}
+
+bool KateViInputMode::blinkCaret() const
+{
+    return false;
+}
+
+KateRenderer::caretStyles KateViInputMode::caretStyle() const
+{
+    switch (m_viModeManager->getCurrentViMode()) {
+        case InsertMode:
+            return KateRenderer::Line;
+        case ReplaceMode:
+            return KateRenderer::Underline;
+        case NormalMode:
+            if (!m_viModeManager->getViNormalMode()->m_awaitingMotionOrTextObject.isEmpty()) {
+                return KateRenderer::Half;
+            }
+        case VisualBlockMode:
+        case VisualLineMode:
+        case VisualMode:
+        default:
+            return KateRenderer::Block;
+    }
+}
+
+void KateViInputMode::toggleInsert()
+{
+    // do nothing
+}
+
+KateViGlobal *KateViInputMode::viGlobal()
+{
+    return m_viGlobal;
+}
+
+KateViInputModeManager *KateViInputMode::viInputModeManager()
+{
+    return m_viModeManager;
+}
+
+KateViInputModeManager *KateViInputMode::resetViInputModeManager()
+{
+    if (m_viModeEmulatedCommandBar) {
+        m_viModeEmulatedCommandBar->hideMe();
+    }
+
+    if (m_viModeManager) {
+        delete m_viModeManager;
+        m_viModeManager = nullptr;
+    }
+    m_viModeManager = new KateViInputModeManager(this, view(), viewInternal());
+
+
+    if (m_viModeEmulatedCommandBar) {
+        m_viModeEmulatedCommandBar->setViInputModeManager(m_viModeManager);
+    }
+
+    return m_viModeManager;
+}
+
+void KateViInputMode::launchInteractiveCommand(const QString &)
+{
+    // do nothing so far
+}
+
+QString KateViInputMode::bookmarkLabel(int line) const
+{
+    return m_viModeManager->getMarksOnTheLine(line);
+}
diff --git a/src/inputmode/kateviinputmode.h b/src/inputmode/kateviinputmode.h
new file mode 100644
index 0000000..374a87a
--- /dev/null
+++ b/src/inputmode/kateviinputmode.h
@@ -0,0 +1,97 @@
+/*  This file is part of the KDE libraries and the Kate part.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __KATE_VI_INPUT_MODE_H__
+#define __KATE_VI_INPUT_MODE_H__
+
+#include "kateabstractinputmode.h"
+
+class KateViGlobal;
+class KateViInputModeFactory;
+class KateViInputModeManager;
+class KateViEmulatedCommandBar;
+
+class KTEXTEDITOR_EXPORT KateViInputMode : public KateAbstractInputMode
+{
+    KateViInputMode(KateViewInternal *viewInternal, KateViGlobal *global);
+    friend KateViInputModeFactory;
+    friend KateViInputModeManager;
+
+public:
+    virtual ~KateViInputMode();
+
+    virtual KTextEditor::View::ViewMode viewMode() const;
+    virtual QString viewModeHuman() const;
+    virtual KTextEditor::View::InputMode viewInputMode() const;
+    virtual QString viewInputModeHuman() const;
+
+    virtual void activate();
+    virtual void deactivate();
+    virtual void reset();
+
+    virtual bool overwrite() const;
+    virtual void overwrittenChar(const QChar &);
+
+    virtual void clearSelection();
+    virtual bool stealKey(const QKeyEvent *) const;
+
+    virtual void gotFocus();
+    virtual void lostFocus();
+
+    virtual void readSessionConfig(const KConfigGroup &config);
+    virtual void writeSessionConfig(KConfigGroup &config);
+    virtual void updateRendererConfig();
+    virtual void updateConfig();
+    virtual void readWriteChanged(bool rw);
+
+    virtual void find();
+    virtual void findSelectedForwards();
+    virtual void findSelectedBackwards();
+    virtual void findReplace();
+    virtual void findNext();
+    virtual void findPrevious();
+
+    virtual void activateCommandLine();
+
+    virtual bool keyPress(QKeyEvent *);
+    virtual bool blinkCaret() const;
+    virtual KateRenderer::caretStyles caretStyle() const;
+
+    virtual void toggleInsert();
+    virtual void launchInteractiveCommand(const QString &command);
+
+    virtual QString bookmarkLabel(int line) const;
+public:
+    void showViModeEmulatedCommandBar();
+    KateViEmulatedCommandBar *viModeEmulatedCommandBar();
+    KateViGlobal *viGlobal();
+    KateViInputModeManager *viInputModeManager();
+    KateViInputModeManager *resetViInputModeManager();
+    bool isActive() { return m_activated; }
+
+private:
+    KateViInputModeManager *m_viModeManager;
+    KateViEmulatedCommandBar *m_viModeEmulatedCommandBar;
+    KateViGlobal *m_viGlobal;
+
+    // configs
+    bool m_relLineNumbers;
+    bool m_activated;
+};
+
+#endif
diff --git a/src/inputmode/kateviinputmodefactory.cpp b/src/inputmode/kateviinputmodefactory.cpp
new file mode 100644
index 0000000..5fca608
--- /dev/null
+++ b/src/inputmode/kateviinputmodefactory.cpp
@@ -0,0 +1,56 @@
+/*  This file is part of the KDE libraries and the Kate part.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ */
+
+#include "kateviinputmodefactory.h"
+#include "kateviinputmode.h"
+#include "kateviglobal.h"
+#include "kateviinputmodeconfigtab.h"
+
+#include <KLocalizedString>
+#include <KConfig>
+
+KateViInputModeFactory::KateViInputModeFactory()
+    : KateAbstractInputModeFactory()
+    , m_viGlobal(new KateViGlobal())
+{
+}
+
+KateViInputModeFactory::~KateViInputModeFactory()
+{
+}
+
+KateAbstractInputMode *KateViInputModeFactory::createInputMode(KateViewInternal *viewInternal)
+{
+    return new KateViInputMode(viewInternal, m_viGlobal);
+}
+
+KateConfigPage *KateViInputModeFactory::createConfigPage(QWidget *parent)
+{
+    return new KateViInputModeConfigTab(parent, m_viGlobal);
+}
+
+KTextEditor::View::InputMode KateViInputModeFactory::inputMode()
+{
+    return KTextEditor::View::ViInputMode;
+}
+
+QString KateViInputModeFactory::name()
+{
+    return i18n("Vi Input Mode");
+}
+
diff --git a/src/dialogs/kateconfigpage.h b/src/inputmode/kateviinputmodefactory.h
similarity index 55%
copy from src/dialogs/kateconfigpage.h
copy to src/inputmode/kateviinputmodefactory.h
index ddb0975..17bf8cc 100644
--- a/src/dialogs/kateconfigpage.h
+++ b/src/inputmode/kateviinputmodefactory.h
@@ -1,4 +1,4 @@
-/* This file is part of the KDE libraries
+/*  This file is part of the KDE libraries and the Kate part.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -16,33 +16,29 @@
  *  Boston, MA 02110-1301, USA.
  */
 
-#ifndef __KATE_CONFIG_PAGE_H__
-#define __KATE_CONFIG_PAGE_H__
+#ifndef __KATE_VI_INPUT_MODE_FACTORY_H__
+#define __KATE_VI_INPUT_MODE_FACTORY_H__
 
-#include <ktexteditor/configpage.h>
+#include "kateabstractinputmodefactory.h"
 
-class KateConfigPage : public KTextEditor::ConfigPage
-{
-    Q_OBJECT
-
-public:
-    explicit KateConfigPage(QWidget *parent = 0, const char *name = 0);
-    virtual ~KateConfigPage();
+class KateViGlobal;
+class KateViInputMode;
 
+class KateViInputModeFactory : public KateAbstractInputModeFactory
+{
+    friend KateViInputMode;
 public:
-    bool hasChanged()
-    {
-        return m_changed;
-    }
+    KateViInputModeFactory();
 
-protected Q_SLOTS:
-    void slotChanged();
+    virtual ~KateViInputModeFactory();
+    virtual KateAbstractInputMode *createInputMode(KateViewInternal *viewInternal);
 
-private Q_SLOTS:
-    void somethingHasChanged();
+    virtual QString name();
+    virtual KTextEditor::View::InputMode inputMode();
 
-protected:
-    bool m_changed;
+    virtual KateConfigPage *createConfigPage(QWidget *);
+private:
+    KateViGlobal *m_viGlobal;
 };
 
 #endif
diff --git a/src/script/katescriptaction.cpp b/src/script/katescriptaction.cpp
index f2d2099..c2490a9 100644
--- a/src/script/katescriptaction.cpp
+++ b/src/script/katescriptaction.cpp
@@ -26,6 +26,7 @@
 #include "kateviewhelpers.h"
 #include "katepartdebug.h"
 #include "katecmd.h"
+#include "kateabstractinputmode.h"
 
 #include <KXMLGUIFactory>
 #include <KActionCollection>
@@ -55,12 +56,7 @@ KateScriptAction::~KateScriptAction()
 void KateScriptAction::exec()
 {
     if (m_interactive) {
-        if (!m_view->viInputMode()) {
-            KateCommandLineBar *cmdLine = m_view->cmdLineBar();
-
-            m_view->bottomViewBar()->showBarWidget(cmdLine);
-            cmdLine->setText(m_command + QLatin1Char(' '), false);
-        }
+        m_view->currentInputMode()->launchInteractiveCommand(m_command + QLatin1Char(' '));
     } else {
         KTextEditor::Command *p = KateCmd::self()->queryCommand(m_command);
         if (p) {
diff --git a/src/utils/katebookmarks.cpp b/src/utils/katebookmarks.cpp
index ce338f0..e755dfd 100644
--- a/src/utils/katebookmarks.cpp
+++ b/src/utils/katebookmarks.cpp
@@ -21,6 +21,7 @@
 
 #include "katedocument.h"
 #include "kateview.h"
+#include "kateabstractinputmode.h"
 
 #include <KActionCollection>
 #include <KGuiItem>
@@ -172,7 +173,7 @@ void KateBookmarks::insertBookmarks(QMenu &menu)
         if (before) {
             QAction *a = new QAction(QString::fromLatin1("%1  %3  - \"%2\"")
                                      .arg(bookmarkLineArray.at(i) + 1).arg(bText)
-                                     .arg(m_view->getViInputModeManager()->getMarksOnTheLine(bookmarkLineArray.at(i))), &menu);
+                                     .arg(m_view->currentInputMode()->bookmarkLabel(bookmarkLineArray.at(i))), &menu);
             menu.insertAction(before, a);
             connect(a, SIGNAL(activated()), this, SLOT(gotoLine()));
             a->setData(bookmarkLineArray.at(i));
@@ -183,7 +184,7 @@ void KateBookmarks::insertBookmarks(QMenu &menu)
         } else {
             QAction *a = menu.addAction(QString::fromLatin1("%1  %3  - \"%2\"")
                                         .arg(bookmarkLineArray.at(i) + 1).arg(bText)
-                                        .arg(m_view->getViInputModeManager()->getMarksOnTheLine(bookmarkLineArray.at(i))),
+                                        .arg(m_view->currentInputMode()->bookmarkLabel(bookmarkLineArray.at(i))),
                                         this, SLOT(gotoLine()));
             a->setData(bookmarkLineArray.at(i));
         }
diff --git a/src/utils/kateconfig.cpp b/src/utils/kateconfig.cpp
index 1e7e000..1cd646f 100644
--- a/src/utils/kateconfig.cpp
+++ b/src/utils/kateconfig.cpp
@@ -1216,7 +1216,7 @@ KateViewConfig::KateViewConfig()
     m_searchFlagsSet(false),
     m_defaultMarkTypeSet(false),
     m_persistentSelectionSet(false),
-    m_viInputModeSet(false),
+    m_inputModeSet(false),
     m_viInputModeStealKeysSet(false),
     m_viRelativeLineNumbersSet(false),
     m_automaticCompletionInvocationSet(false),
@@ -1256,7 +1256,7 @@ KateViewConfig::KateViewConfig(KTextEditor::ViewPrivate *view)
     m_searchFlagsSet(false),
     m_defaultMarkTypeSet(false),
     m_persistentSelectionSet(false),
-    m_viInputModeSet(false),
+    m_inputModeSet(false),
     m_viInputModeStealKeysSet(false),
     m_viRelativeLineNumbersSet(false),
     m_automaticCompletionInvocationSet(false),
@@ -1297,7 +1297,7 @@ const char *const KEY_MAX_HISTORY_SIZE = "Maximum Search History Size";
 const char *const KEY_DEFAULT_MARK_TYPE = "Default Mark Type";
 const char *const KEY_ALLOW_MARK_MENU = "Allow Mark Menu";
 const char *const KEY_PERSISTENT_SELECTION = "Persistent Selection";
-const char *const KEY_VI_INPUT_MODE = "Vi Input Mode";
+const char *const KEY_INPUT_MODE = "Input Mode";
 const char *const KEY_VI_INPUT_MODE_STEAL_KEYS = "Vi Input Mode Steal Keys";
 const char *const KEY_VI_RELATIVE_LINE_NUMBERS = "Vi Relative Line Numbers";
 const char *const KEY_AUTOMATIC_COMPLETION_INVOCATION = "Auto Completion";
@@ -1349,7 +1349,7 @@ void KateViewConfig::readConfig(const KConfigGroup &config)
 
     setPersistentSelection(config.readEntry(KEY_PERSISTENT_SELECTION, false));
 
-    setViInputMode(config.readEntry(KEY_VI_INPUT_MODE, false));
+    setInputModeRaw(config.readEntry(KEY_INPUT_MODE, 0));
     setViInputModeStealKeys(config.readEntry(KEY_VI_INPUT_MODE_STEAL_KEYS, false));
     setViRelativeLineNumbers(config.readEntry(KEY_VI_RELATIVE_LINE_NUMBERS, false));
 
@@ -1419,7 +1419,7 @@ void KateViewConfig::writeConfig(KConfigGroup &config)
     config.writeEntry(KEY_SMART_COPY_CUT, smartCopyCut());
     config.writeEntry(KEY_SCROLL_PAST_END, scrollPastEnd());
 
-    config.writeEntry(KEY_VI_INPUT_MODE, viInputMode());
+    config.writeEntry(KEY_INPUT_MODE, static_cast<int>(inputMode()));
     config.writeEntry(KEY_VI_INPUT_MODE_STEAL_KEYS, viInputModeStealKeys());
     config.writeEntry(KEY_VI_RELATIVE_LINE_NUMBERS, viRelativeLineNumbers());
 
@@ -1881,34 +1881,34 @@ void KateViewConfig::setPersistentSelection(bool on)
     configEnd();
 }
 
-bool KateViewConfig::viInputMode() const
+KTextEditor::View::InputMode KateViewConfig::inputMode() const
 {
-    if (m_viInputModeSet || isGlobal()) {
-        return m_viInputMode;
+    if (m_inputModeSet || isGlobal()) {
+        return m_inputMode;
     }
 
-    return s_global->viInputMode();
+    return s_global->inputMode();
 }
 
-void KateViewConfig::setViInputMode(bool on)
+void KateViewConfig::setInputMode(KTextEditor::View::InputMode mode)
 {
-    if (m_viInputModeSet && m_viInputMode == on) {
+    if (m_inputModeSet && m_inputMode == mode) {
         return;
     }
 
     configStart();
 
-    m_viInputModeSet = true;
-    m_viInputMode = on;
-
-    // make sure to turn off edits mergin when leaving vi input mode
-    if (!on && m_view) {
-        m_view->doc()->setUndoMergeAllEdits(false);
-    }
+    m_inputModeSet = true;
+    m_inputMode = mode;
 
     configEnd();
 }
 
+void KateViewConfig::setInputModeRaw(int rawmode)
+{
+    setInputMode(static_cast<KTextEditor::View::InputMode>(rawmode));
+}
+
 bool KateViewConfig::viInputModeStealKeys() const
 {
     if (m_viInputModeStealKeysSet || isGlobal()) {
diff --git a/src/utils/kateconfig.h b/src/utils/kateconfig.h
index 07cfa07..2b69013 100644
--- a/src/utils/kateconfig.h
+++ b/src/utils/kateconfig.h
@@ -23,6 +23,7 @@
 #include <ktexteditor_export.h>
 
 #include <ktexteditor/markinterface.h>
+#include "ktexteditor/view.h"
 #include <KEncodingProber>
 
 #include <QBitRef>
@@ -515,8 +516,9 @@ public:
     bool persistentSelection() const;
     void setPersistentSelection(bool on);
 
-    bool viInputMode() const;
-    void setViInputMode(bool on);
+    KTextEditor::View::InputMode inputMode() const;
+    void setInputMode(KTextEditor::View::InputMode mode);
+    void setInputModeRaw(int rawmode);
 
     bool viInputModeStealKeys() const;
     void setViInputModeStealKeys(bool on);
@@ -572,7 +574,7 @@ private:
     QStringListModel m_replacementHistoryModel;
     uint m_defaultMarkType;
     bool m_persistentSelection;
-    bool m_viInputMode;
+    KTextEditor::View::InputMode m_inputMode;
     bool m_viInputModeStealKeys;
     bool m_viRelativeLineNumbers;
     bool m_automaticCompletionInvocation;
@@ -599,7 +601,7 @@ private:
     bool m_searchFlagsSet : 1;
     bool m_defaultMarkTypeSet : 1;
     bool m_persistentSelectionSet : 1;
-    bool m_viInputModeSet : 1;
+    bool m_inputModeSet : 1;
     bool m_viInputModeStealKeysSet : 1;
     bool m_viRelativeLineNumbersSet : 1;
     bool m_automaticCompletionInvocationSet : 1;
diff --git a/src/utils/kateglobal.cpp b/src/utils/kateglobal.cpp
index 1c54a78..4b93386 100644
--- a/src/utils/kateglobal.cpp
+++ b/src/utils/kateglobal.cpp
@@ -20,6 +20,7 @@
  */
 
 #include "kateglobal.h"
+#include "config.h"
 
 #include <ktexteditor_version.h>
 
@@ -35,11 +36,13 @@
 #include "kateconfig.h"
 #include "katescriptmanager.h"
 #include "katebuffer.h"
-#include "kateviglobal.h"
 #include "katewordcompletion.h"
 #include "spellcheck/spellcheck.h"
 #include "katepartdebug.h"
 
+#include "katenormalinputmodefactory.h"
+#include "kateviinputmodefactory.h"
+
 #include <KServiceTypeTrader>
 #include <kdirwatch.h>
 #include <KLocalizedString>
@@ -168,9 +171,16 @@ KTextEditor::EditorPrivate::EditorPrivate(QPointer<KTextEditor::EditorPrivate> &
     m_schemaManager = new KateSchemaManager();
 
     //
-    // vi input mode global
+    // input mode factories
     //
-    m_viInputModeGlobal = new KateViGlobal();
+    KateAbstractInputModeFactory *fact;
+    fact = new KateNormalInputModeFactory();
+    m_inputModeFactories.insert(KTextEditor::View::NormalInputMode, fact);
+
+#ifdef BUILD_VIMODE
+    fact = new KateViInputModeFactory();
+    m_inputModeFactories.insert(KTextEditor::View::ViInputMode, fact);
+#endif
 
     //
     // spell check manager
@@ -212,8 +222,6 @@ KTextEditor::EditorPrivate::~EditorPrivate()
     delete m_modeManager;
     delete m_schemaManager;
 
-    delete m_viInputModeGlobal;
-
     delete m_dirWatch;
 
     // cu managers
@@ -228,6 +236,8 @@ KTextEditor::EditorPrivate::~EditorPrivate()
     // delete the commands before we delete the cmd manager
     qDeleteAll(m_cmds);
     delete m_cmdManager;
+
+    qDeleteAll(m_inputModeFactories);
 }
 
 KTextEditor::Document *KTextEditor::EditorPrivate::createDocument(QObject *parent)
@@ -459,3 +469,7 @@ bool KTextEditor::EditorPrivate::eventFilter(QObject *obj, QEvent *event)
     return false; // always continue processing
 }
 
+QList< KateAbstractInputModeFactory *> KTextEditor::EditorPrivate::inputModeFactories()
+{
+    return m_inputModeFactories.values();
+}
diff --git a/src/utils/kateglobal.h b/src/utils/kateglobal.h
index 79f3b44..420845c 100644
--- a/src/utils/kateglobal.h
+++ b/src/utils/kateglobal.h
@@ -26,6 +26,7 @@
 #include "katescript.h"
 
 #include <ktexteditor/editor.h>
+#include "ktexteditor/view.h"
 
 #include <KService>
 #include <KAboutData>
@@ -37,6 +38,7 @@
 
 #include <QList>
 #include <QPointer>
+#include <QMap>
 
 class KateCmd;
 class KateModeManager;
@@ -51,8 +53,8 @@ class KateScriptManager;
 class KDirWatch;
 class KateHlManager;
 class KateSpellCheckManager;
-class KateViGlobal;
 class KateWordCompletionModel;
+class KateAbstractInputModeFactory;
 
 namespace KTextEditor
 {
@@ -311,15 +313,6 @@ public:
     }
 
     /**
-     * vi input mode global
-     * @return vi input mode global
-     */
-    KateViGlobal *viInputModeGlobal()
-    {
-        return m_viInputModeGlobal;
-    }
-
-    /**
      * spell check manager
      * @return spell check manager
      */
@@ -386,6 +379,11 @@ public:
         return m_documents.values();
     }
 
+    /**
+     * @return list of available input mode factories
+     */
+    QList<KateAbstractInputModeFactory *> inputModeFactories();
+
 Q_SIGNALS:
     /**
      * Emitted if the history of clipboard changes via copyToClipboard
@@ -470,11 +468,6 @@ private:
     KateCmd *m_cmdManager;
 
     /**
-     * vi input mode global
-     */
-    KateViGlobal *m_viInputModeGlobal;
-
-    /**
      * spell check manager
      */
     KateSpellCheckManager *m_spellCheckManager;
@@ -493,6 +486,11 @@ private:
      * access to application
      */
     QPointer<KTextEditor::Application> m_application;
+
+    /**
+     * input modes map
+     */
+    QMap<KTextEditor::View::InputMode, KateAbstractInputModeFactory *> m_inputModeFactories;
 };
 
 }
diff --git a/src/utils/katesedcmd.cpp b/src/utils/katesedcmd.cpp
index f252839..d799f9f 100644
--- a/src/utils/katesedcmd.cpp
+++ b/src/utils/katesedcmd.cpp
@@ -132,8 +132,6 @@ bool KateCommands::SedReplace::exec(class KTextEditor::View *view, const QString
         return interactiveSedReplace(kateView, interactiveSedReplacer);
     }
 
-    kateView->setSearchPattern(find);
-
     interactiveSedReplacer->replaceAllRemaining();
     msg = interactiveSedReplacer->finalStatusReportMessage();
 
diff --git a/src/view/katestatusbar.cpp b/src/view/katestatusbar.cpp
index 36a3479..125c295 100644
--- a/src/view/katestatusbar.cpp
+++ b/src/view/katestatusbar.cpp
@@ -25,6 +25,7 @@
 #include "katemodemanager.h"
 #include "katedocument.h"
 #include "kateconfig.h"
+#include "kateabstractinputmode.h"
 
 #include <KLocalizedString>
 #include <KIconLoader>
@@ -194,10 +195,8 @@ bool KateStatusBar::eventFilter(QObject *obj, QEvent *event)
 {
     if (obj == m_insertModeLabel) {
         if (event->type() == QEvent::MouseButtonDblClick) {
-            if (!m_view->viInputMode()) {
-                m_view->toggleInsert();
-                return true;
-            }
+            m_view->currentInputMode()->toggleInsert();
+            return true;
         }
     } else if (obj == m_lineColLabel) {
         if (event->type() == QEvent::MouseButtonDblClick) {
diff --git a/src/view/kateview.cpp b/src/view/kateview.cpp
index ee9f78d..a4fd561 100644
--- a/src/view/kateview.cpp
+++ b/src/view/kateview.cpp
@@ -31,7 +31,6 @@
 #include "katedocument.h"
 #include "kateundomanager.h"
 #include "kateglobal.h"
-#include "kateviglobal.h"
 #include "katehighlight.h"
 #include "katehighlightmenu.h"
 #include "katedialogs.h"
@@ -42,8 +41,6 @@
 #include "katemodemenu.h"
 #include "kateautoindent.h"
 #include "katecompletionwidget.h"
-#include "katesearchbar.h"
-#include "kateviemulatedcommandbar.h"
 #include "katewordcompletion.h"
 #include "katelayoutcache.h"
 #include "spellcheck/spellcheck.h"
@@ -58,6 +55,7 @@
 #include "katepartdebug.h"
 #include "printing/kateprinter.h"
 #include "katestatusbar.h"
+#include "kateabstractinputmode.h"
 
 #include <KTextEditor/Message>
 
@@ -115,9 +113,6 @@ KTextEditor::ViewPrivate::ViewPrivate(KTextEditor::DocumentPrivate *doc, QWidget
     , m_selection(m_doc->buffer(), KTextEditor::Range::invalid(), Kate::TextRange::ExpandLeft, Kate::TextRange::AllowEmpty)
     , blockSelect(false)
     , m_bottomViewBar(0)
-    , m_cmdLine(0)
-    , m_searchBar(0)
-    , m_viModeEmulatedCommandBar(0)
     , m_gotoBar(0)
     , m_dictionaryBar(NULL)
     , m_spellingMenu(new KateSpellingMenu(this))
@@ -238,10 +233,6 @@ KTextEditor::ViewPrivate::ViewPrivate(KTextEditor::DocumentPrivate *doc, QWidget
     slotHlChanged();
     KCursor::setAutoHideCursor(m_viewInternal, true);
 
-    if (viInputMode() /* && FIXME: HAEHH? !config()->viInputModeHideStatusBar() */) {
-        deactivateEditActions();
-    }
-
     // user interaction (scrollling) starts notification auto-hide timer
     connect(this, SIGNAL(displayRangeChanged(KTextEditor::ViewPrivate*)), m_topMessageWidget, SLOT(startAutoHideTimer()));
     connect(this, SIGNAL(displayRangeChanged(KTextEditor::ViewPrivate*)), m_bottomMessageWidget, SLOT(startAutoHideTimer()));
@@ -594,11 +585,17 @@ void KTextEditor::ViewPrivate::setupActions()
     a->setWhatsThis(i18n("Show/hide the command line on the bottom of the view."));
     connect(a, SIGNAL(triggered(bool)), SLOT(switchToCmdLine()));
 
-    a = m_viInputModeAction = new KToggleAction(i18n("&VI Input Mode"), this);
-    ac->addAction(QLatin1String("view_vi_input_mode"), a);
-    a->setShortcut(QKeySequence(Qt::CTRL + Qt::META + Qt::Key_V));
-    a->setWhatsThis(i18n("Activate/deactivate VI input mode"));
-    connect(a, SIGNAL(triggered(bool)), SLOT(toggleViInputMode()));
+    KActionMenu *am = new KActionMenu(i18n("Input Modes"), this);
+    ac->addAction(QLatin1String("view_input_modes"), am);
+
+    Q_FOREACH(KateAbstractInputMode *mode, m_viewInternal->m_inputModes) {
+        a = new KToggleAction(mode->viewInputModeHuman(), this);
+        am->addAction(a);
+        a->setWhatsThis(i18n("Activate/deactivate %1").arg(mode->viewInputModeHuman()));
+        a->setData(static_cast<int>(mode->viewInputMode()));
+        connect(a, SIGNAL(triggered(bool)), SLOT(toggleInputMode(bool)));
+        m_inputModeActions << a;
+    }
 
     a = m_setEndOfLine = new KSelectAction(i18n("&End of Line"), this);
     ac->addAction(QLatin1String("set_eol"), a);
@@ -1104,48 +1101,12 @@ void KTextEditor::ViewPrivate::unfoldLine(int startLine)
 
 KTextEditor::View::ViewMode KTextEditor::ViewPrivate::viewMode() const
 {
-    if (viInputMode()) {
-        return m_viewInternal->getViInputModeManager()->getCurrentViewMode();
-    } else {
-        return isOverwriteMode() ? KTextEditor::View::NormalModeOverwrite : KTextEditor::View::NormalModeInsert;
-    }
+    return currentInputMode()->viewMode();
 }
 
 QString KTextEditor::ViewPrivate::viewModeHuman() const
 {
-    /**
-     * normal two modes
-     */
-    QString currentMode = isOverwriteMode() ? i18n("OVERWRITE") : i18n("INSERT");
-
-    /**
-     * if we are in vi mode, this will be overwritten by current vi mode
-     */
-    if (viInputMode()) {
-        currentMode = KateViInputModeManager::modeToString(getCurrentViMode());
-
-        /**
-         * guard against calls during vi view input mode manager resets
-         */
-        if (m_viewInternal->getViInputModeManager()) {
-            if (m_viewInternal->getViInputModeManager()->isRecordingMacro()) {
-                currentMode.prepend (QLatin1String("(") + i18n("recording") + QLatin1String(") "));
-            }
-
-            /**
-            * perhaps append the current keys of a command not finalized
-            */
-            QString cmd = m_viewInternal->getViInputModeManager()->getVerbatimKeys();
-            if (!cmd.isEmpty()) {
-                currentMode.prepend(QString::fromLatin1("<em>%1</em> ").arg(cmd));
-            }
-        }
-
-        /**
-         * make it bold
-         */
-        currentMode = QString::fromLatin1("<b>%1</b>").arg(currentMode);
-    }
+    QString currentMode = currentInputMode()->viewModeHuman();
 
     /**
      * append read-only if needed
@@ -1162,33 +1123,52 @@ QString KTextEditor::ViewPrivate::viewModeHuman() const
 
 KTextEditor::View::InputMode KTextEditor::ViewPrivate::viewInputMode() const
 {
-    return viInputMode() ? KTextEditor::View::ViInputMode : KTextEditor::View::NormalInputMode;
+    return currentInputMode()->viewInputMode();
 }
 
 QString KTextEditor::ViewPrivate::viewInputModeHuman() const
 {
-    return viInputMode() ? i18n("vi-mode") : i18n("Normal");
+    return currentInputMode()->viewInputModeHuman();
 }
 
+void KTextEditor::ViewPrivate::setInputMode(KTextEditor::View::InputMode mode)
+{
+    if (currentInputMode()->viewInputMode() == mode) {
+        return;
+    }
+
+    if (!m_viewInternal->m_inputModes.contains(mode)) {
+        return;
+    }
+
+    m_viewInternal->m_currentInputMode->deactivate();
+    m_viewInternal->m_currentInputMode = m_viewInternal->m_inputModes[mode];
+    m_viewInternal->m_currentInputMode->activate();
+
+    config()->setInputMode(mode); // TODO: this could be called from read config procedure, so it's not a good idea to set a specific view mode here
+
+    /* small duplication, but need to do this; TODO: make it more sane */
+    Q_FOREACH(QAction *action, m_inputModeActions) {
+        bool checked = static_cast<InputMode>(action->data().toInt()) == mode;
+        action->setChecked(checked);
+    }
+
+    /* inform the rest of the system about the change */
+    emit viewInputModeChanged(this, mode);
+    emit viewModeChanged(this, viewMode());
+}
 
 void KTextEditor::ViewPrivate::slotGotFocus()
 {
     //qCDebug(LOG_PART) << "KTextEditor::ViewPrivate::slotGotFocus";
-
-    if (!viInputMode()) {
-        activateEditActions();
-    }
+    currentInputMode()->gotFocus();
     emit focusIn(this);
 }
 
 void KTextEditor::ViewPrivate::slotLostFocus()
 {
     //qCDebug(LOG_PART) << "KTextEditor::ViewPrivate::slotLostFocus";
-
-    if (!viInputMode()) {
-        deactivateEditActions();
-    }
-
+    currentInputMode()->lostFocus();
     emit focusOut(this);
 }
 
@@ -1245,10 +1225,7 @@ void KTextEditor::ViewPrivate::slotReadWriteChanged()
         }
     slotUpdateUndo();
 
-    // inform search bar
-    if (m_searchBar) {
-        m_searchBar->slotReadWriteChanged();
-    }
+    currentInputMode()->readWriteChanged(m_doc->isReadWrite());
 
     // => view mode changed
     emit viewModeChanged(this, viewMode());
@@ -1351,8 +1328,9 @@ void KTextEditor::ViewPrivate::readSessionConfig(const KConfigGroup &config, con
 //   m_savedFoldingState = config.readEntry("TextFolding", QVariantList());
 //   applyFoldingState ();
 
-    // save vi registers and jump list
-    getViInputModeManager()->readSessionConfig(config);
+    Q_FOREACH(KateAbstractInputMode *mode, m_viewInternal->m_inputModes) {
+        mode->readSessionConfig(config);
+    }
 }
 
 void KTextEditor::ViewPrivate::writeSessionConfig(KConfigGroup &config, const QSet<QString> &flags)
@@ -1368,8 +1346,9 @@ void KTextEditor::ViewPrivate::writeSessionConfig(KConfigGroup &config, const QS
 //   config.writeEntry("TextFolding", m_savedFoldingState);
 //   m_savedFoldingState.clear ();
 
-    // save vi registers and jump list
-    getViInputModeManager()->writeSessionConfig(config);
+    Q_FOREACH(KateAbstractInputMode *mode, m_viewInternal->m_inputModes) {
+        mode->writeSessionConfig(config);
+    }
 }
 
 int KTextEditor::ViewPrivate::getEol() const
@@ -1543,131 +1522,34 @@ int KTextEditor::ViewPrivate::textHintDelay() const
     return m_viewInternal->textHintDelay();
 }
 
-bool KTextEditor::ViewPrivate::viInputMode() const
-{
-    return m_viewInternal->m_viInputMode;
-}
-
-bool KTextEditor::ViewPrivate::viInputModeStealKeys() const
-{
-    return m_viewInternal->m_viInputModeStealKeys;
-}
-
-bool KTextEditor::ViewPrivate::viRelativeLineNumbers() const
-{
-    return m_viewInternal->m_viRelLineNumbers;
-}
-
-void KTextEditor::ViewPrivate::toggleViInputMode()
-{
-    config()->setViInputMode(!config()->viInputMode());
-
-    if (viInputMode()) {
-        m_viewInternal->getViInputModeManager()->viEnterNormalMode();
-        deactivateEditActions();
-    } else { // disabling the vi input mode
-        activateEditActions();
-    }
-
-    emit viewModeChanged(this, viewMode());
-    emit viewInputModeChanged(this, viewInputMode());
-}
-
-void KTextEditor::ViewPrivate::showViModeEmulatedCommandBar()
-{
-    bottomViewBar()->addBarWidget(viModeEmulatedCommandBar());
-    bottomViewBar()->showBarWidget(viModeEmulatedCommandBar());
-}
-
-ViMode KTextEditor::ViewPrivate::getCurrentViMode() const
-{
-    return m_viewInternal->getCurrentViMode();
-}
-
-KateViInputModeManager *KTextEditor::ViewPrivate::getViInputModeManager()
-{
-    return m_viewInternal->getViInputModeManager();
-}
-
-KateViInputModeManager *KTextEditor::ViewPrivate::resetViInputModeManager()
-{
-    if (m_viModeEmulatedCommandBar) {
-        m_viModeEmulatedCommandBar->hideMe();
-    }
-
-    KateViInputModeManager * manager = m_viewInternal->resetViInputModeManager();
-
-    if (m_viModeEmulatedCommandBar) {
-        m_viModeEmulatedCommandBar->setViInputModeManager(manager);
-    }
-
-    return manager;
-}
-
 void KTextEditor::ViewPrivate::find()
 {
-    if (viInputMode()) {
-        showViModeEmulatedCommandBar();
-        viModeEmulatedCommandBar()->init(KateViEmulatedCommandBar::SearchForward);
-    } else {
-        const bool INIT_HINT_AS_INCREMENTAL = false;
-        KateSearchBar *const bar = searchBar(INIT_HINT_AS_INCREMENTAL);
-        bar->enterIncrementalMode();
-        bottomViewBar()->addBarWidget(bar);
-        bottomViewBar()->showBarWidget(bar);
-        bar->setFocus();
-    }
+    currentInputMode()->find();
 }
 
 void KTextEditor::ViewPrivate::findSelectedForwards()
 {
-    if (viInputMode()) {
-        getViInputModeManager()->findNext();
-    } else {
-        KateSearchBar::nextMatchForSelection(this, KateSearchBar::SearchForward);
-    }
+    currentInputMode()->findSelectedForwards();
 }
 
 void KTextEditor::ViewPrivate::findSelectedBackwards()
 {
-    if (viInputMode()) {
-        getViInputModeManager()->findPrevious();
-    } else {
-        KateSearchBar::nextMatchForSelection(this, KateSearchBar::SearchBackward);
-    }
+    currentInputMode()->findSelectedBackwards();
 }
 
 void KTextEditor::ViewPrivate::replace()
 {
-    if (viInputMode()) {
-        showViModeEmulatedCommandBar();
-        viModeEmulatedCommandBar()->init(KateViEmulatedCommandBar::SearchForward);
-    } else {
-        const bool INIT_HINT_AS_POWER = true;
-        KateSearchBar *const bar = searchBar(INIT_HINT_AS_POWER);
-        bar->enterPowerMode();
-        bottomViewBar()->addBarWidget(bar);
-        bottomViewBar()->showBarWidget(bar);
-        bar->setFocus();
-    }
+    currentInputMode()->findReplace();
 }
 
 void KTextEditor::ViewPrivate::findNext()
 {
-    if (viInputMode()) {
-        getViInputModeManager()->findNext();
-    } else {
-        searchBar()->findNext();
-    }
+    currentInputMode()->findNext();
 }
 
 void KTextEditor::ViewPrivate::findPrevious()
 {
-    if (viInputMode()) {
-        getViInputModeManager()->findPrevious();
-    } else {
-        searchBar()->findPrevious();
-    }
+    currentInputMode()->findPrevious();
 }
 
 void KTextEditor::ViewPrivate::slotSelectionChanged()
@@ -1690,19 +1572,7 @@ void KTextEditor::ViewPrivate::slotSelectionChanged()
 
 void KTextEditor::ViewPrivate::switchToCmdLine()
 {
-    if (viInputMode()) {
-        showViModeEmulatedCommandBar();
-        viModeEmulatedCommandBar()->init(KateViEmulatedCommandBar::Command);
-    } else {
-        // if the user has selected text, insert the selection's range (start line to end line) in the
-        // command line when opened
-        if (selectionRange().start().line() != -1 && selectionRange().end().line() != -1) {
-            cmdLineBar()->setText(QString::number(selectionRange().start().line() + 1) + QLatin1Char(',')
-                                  + QString::number(selectionRange().end().line() + 1));
-        }
-        bottomViewBar()->showBarWidget(cmdLineBar());
-        cmdLineBar()->setFocus();
-    }
+    currentInputMode()->activateCommandLine();
 }
 
 KateRenderer *KTextEditor::ViewPrivate::renderer()
@@ -1758,9 +1628,6 @@ void KTextEditor::ViewPrivate::updateConfig()
     m_toggleBlockSelection->setChecked(blockSelection());
     m_toggleInsert->setChecked(isOverwriteMode());
 
-    // vi modes
-    m_viInputModeAction->setChecked(config()->viInputMode());
-
     updateFoldingConfig();
 
     // bookmark
@@ -1768,14 +1635,7 @@ void KTextEditor::ViewPrivate::updateConfig()
 
     m_viewInternal->setAutoCenterLines(config()->autoCenterLines());
 
-    // vi input mode
-    m_viewInternal->m_viInputMode = config()->viInputMode();
-
-    // whether vi input mode should override actions or not
-    m_viewInternal->m_viInputModeStealKeys = config()->viInputModeStealKeys();
-
-    // whether relative line numbers should be used or not.
-    m_viewInternal->m_leftBorder->setViRelLineNumbersOn(config()->viRelativeLineNumbers());
+    setInputMode(config()->inputMode());
 
     reflectOnTheFlySpellCheckStatus(m_doc->isOnTheFlySpellCheckingEnabled());
 
@@ -1834,10 +1694,6 @@ void KTextEditor::ViewPrivate::updateRendererConfig()
     m_viewInternal->updateBracketMarkAttributes();
     m_viewInternal->updateBracketMarks();
 
-    if (m_searchBar) {
-        m_searchBar->updateHighlightColors();
-    }
-
     // now redraw...
     m_viewInternal->cache()->clear();
     tagAll();
@@ -1849,6 +1705,8 @@ void KTextEditor::ViewPrivate::updateRendererConfig()
 
     m_viewInternal->m_lineScroll->queuePixmapUpdate();
 
+    currentInputMode()->updateRendererConfig();
+
 // @@ showIndentLines is not cached anymore.
 //  m_renderer->setShowIndentLines (m_renderer->config()->showIndentationLines());
     emit configChanged();
@@ -2493,34 +2351,6 @@ QString KTextEditor::ViewPrivate::currentTextLine()
     return m_doc->line(cursorPosition().line());
 }
 
-QString KTextEditor::ViewPrivate::searchPattern() const
-{
-    if (hasSearchBar()) {
-        return m_searchBar->searchPattern();
-    } else {
-        return QString();
-    }
-}
-
-QString KTextEditor::ViewPrivate::replacementPattern() const
-{
-    if (hasSearchBar()) {
-        return m_searchBar->replacementPattern();
-    } else {
-        return QString();
-    }
-}
-
-void KTextEditor::ViewPrivate::setSearchPattern(const QString &searchPattern)
-{
-    searchBar()->setSearchPattern(searchPattern);
-}
-
-void KTextEditor::ViewPrivate::setReplacementPattern(const QString &replacementPattern)
-{
-    searchBar()->setReplacementPattern(replacementPattern);
-}
-
 void KTextEditor::ViewPrivate::indent()
 {
     KTextEditor::Cursor c(cursorPosition().line(), 0);
@@ -3054,24 +2884,6 @@ KateViewBar *KTextEditor::ViewPrivate::bottomViewBar() const
     return m_bottomViewBar;
 }
 
-KateCommandLineBar *KTextEditor::ViewPrivate::cmdLineBar()
-{
-    if (!m_cmdLine) {
-        m_cmdLine = new KateCommandLineBar(this, bottomViewBar());
-        bottomViewBar()->addBarWidget(m_cmdLine);
-    }
-
-    return m_cmdLine;
-}
-
-KateSearchBar *KTextEditor::ViewPrivate::searchBar(bool initHintAsPower)
-{
-    if (!m_searchBar) {
-        m_searchBar = new KateSearchBar(initHintAsPower, this, KateViewConfig::global());
-    }
-    return m_searchBar;
-}
-
 KateGotoBar *KTextEditor::ViewPrivate::gotoBar()
 {
     if (!m_gotoBar) {
@@ -3092,16 +2904,6 @@ KateDictionaryBar *KTextEditor::ViewPrivate::dictionaryBar()
     return m_dictionaryBar;
 }
 
-KateViEmulatedCommandBar *KTextEditor::ViewPrivate::viModeEmulatedCommandBar()
-{
-    if (!m_viModeEmulatedCommandBar) {
-        m_viModeEmulatedCommandBar = new KateViEmulatedCommandBar(m_viewInternal->getViInputModeManager(), this);
-        m_viModeEmulatedCommandBar->hide();
-    }
-
-    return m_viModeEmulatedCommandBar;
-}
-
 void KTextEditor::ViewPrivate::setAnnotationModel(KTextEditor::AnnotationModel *model)
 {
     KTextEditor::AnnotationModel *oldmodel = m_annotationModel;
@@ -3426,6 +3228,37 @@ void KTextEditor::ViewPrivate::createHighlights()
     } while (matches.first().isValid());
 }
 
+KateAbstractInputMode *KTextEditor::ViewPrivate::currentInputMode() const
+{
+    return m_viewInternal->m_currentInputMode;
+}
+
+void KTextEditor::ViewPrivate::toggleInputMode(bool on)
+{
+    QAction *a = dynamic_cast<QAction *>(sender());
+    if (!a) {
+        return;
+    }
+
+    InputMode newmode = static_cast<KTextEditor::View::InputMode>(a->data().toInt());
+
+    if (currentInputMode()->viewInputMode() == newmode) {
+        if (!on) {
+            a->setChecked(true); // nasty
+        }
+
+        return;
+    }
+
+    Q_FOREACH(QAction *ac, m_inputModeActions) {
+        if (ac != a) {
+            ac->setChecked(false);
+        }
+    }
+
+    setInputMode(newmode);
+}
+
 //BEGIN KTextEditor::PrintInterface stuff
 bool KTextEditor::ViewPrivate::print()
 {
diff --git a/src/view/kateview.h b/src/view/kateview.h
index d4dd00f..b96e3a5 100644
--- a/src/view/kateview.h
+++ b/src/view/kateview.h
@@ -36,7 +36,6 @@
 #include <QModelIndex>
 #include <QMenu>
 
-#include "kateviinputmodemanager.h"
 #include "katetextrange.h"
 #include "katetextfolding.h"
 #include "katerenderer.h"
@@ -49,14 +48,11 @@ class Message;
 
 namespace KTextEditor { class DocumentPrivate; }
 class KateBookmarks;
-class KateCommandLineBar;
 class KateViewConfig;
 class KateRenderer;
 class KateSpellCheckDialog;
 class KateCompletionWidget;
 class KateViewInternal;
-class KateSearchBar;
-class KateViEmulatedCommandBar;
 class KateViewBar;
 class KateGotoBar;
 class KateDictionaryBar;
@@ -66,6 +62,7 @@ class KateIconBorder;
 class KateStatusBar;
 class KateViewEncodingAction;
 class KateModeMenu;
+class KateAbstractInputMode;
 
 class KToggleAction;
 class KSelectAction;
@@ -118,6 +115,8 @@ public:
     virtual InputMode viewInputMode() const;
     virtual QString viewInputModeHuman() const;
 
+    void setInputMode(InputMode mode);
+
     //
     // KTextEditor::ClipboardInterface
     //
@@ -406,32 +405,6 @@ public:
 
     QString currentTextLine();
 
-    /**
-     * The current search pattern.
-     * This is set by the last search.
-     * @return the search pattern or the empty string if not set
-     */
-    QString searchPattern() const;
-
-    /**
-     * The current replacement string.
-     * This is set by the last search and replace.
-     * @return the replacment string or the empty string if not set
-     */
-    QString replacementPattern() const;
-
-    /**
-     * Set the current search pattern.
-     * @param searchPattern the search pattern
-     */
-    void setSearchPattern(const QString &searchPattern);
-
-    /**
-     * Set the current replacement pattern.
-     * @param replacementPattern the replacement pattern
-     */
-    void setReplacementPattern(const QString &replacementPattern);
-
 public Q_SLOTS:
     void indent();
     void unIndent();
@@ -557,10 +530,6 @@ public Q_SLOTS:
     void toggleScrollBarMiniMap();
     void toggleScrollBarMiniMapAll();
     void toggleDynWordWrap();
-    void toggleViInputMode();
-
-    void showViModeEmulatedCommandBar();
-
     void setDynWrapIndicators(int mode);
 
 public:
@@ -583,6 +552,8 @@ private Q_SLOTS:
      */
     void slotSelectionChanged();
 
+    void toggleInputMode(bool);
+
 public:
     /**
      * accessor to katedocument pointer
@@ -672,6 +643,8 @@ private:
     QAction *m_selectAll;
     QAction *m_deSelect;
 
+    QList<QAction *> m_inputModeActions;
+
     KToggleAction *m_toggleBlockSelection;
     KToggleAction *m_toggleInsert;
     KToggleAction *m_toggleWriteLock;
@@ -730,16 +703,9 @@ public:
      */
 public:
     KateViewBar *bottomViewBar() const;
-    KateCommandLineBar *cmdLineBar();
     KateDictionaryBar *dictionaryBar();
-    KateViEmulatedCommandBar *viModeEmulatedCommandBar();
 
 private:
-    KateSearchBar *searchBar(bool initHintAsPower = false);
-    bool hasSearchBar() const
-    {
-        return m_searchBar != 0;
-    }
     KateGotoBar *gotoBar();
 
     /**
@@ -751,46 +717,12 @@ private:
     KateViewBar *m_bottomViewBar;
 
     // created on demand..., only access them through the above accessors....
-    KateCommandLineBar *m_cmdLine;
-    KateSearchBar *m_searchBar;
-    KateViEmulatedCommandBar *m_viModeEmulatedCommandBar;
     KateGotoBar *m_gotoBar;
     KateDictionaryBar *m_dictionaryBar;
 
-    // vi Mode
+    // input modes
 public:
-    /**
-     * @return boolean indicating whether vi mode is active or not
-     */
-    bool viInputMode() const;
-
-    /**
-     * @return the current vi mode
-     */
-    ViMode getCurrentViMode() const;
-
-    /**
-     * @return a pointer to the KateViInputModeManager belonging to the view
-     */
-    KateViInputModeManager *getViInputModeManager();
-
-    /**
-     * Replace ViInputModeManager by new one.
-     * @return a pointer to the new KateViInputModeManager.
-     */
-    KateViInputModeManager *resetViInputModeManager();
-
-    /**
-     * @return boolean indicating whether vi mode will override actions or not
-     */
-    bool viInputModeStealKeys() const;
-
-    /**
-     * @return boolean indicating whether relative line numbers should
-     * be used or not.
-     */
-    bool viRelativeLineNumbers() const;
-
+    KateAbstractInputMode *currentInputMode() const;
 public:
     KTextEditor::Range visibleRange();
 
diff --git a/src/view/kateviewhelpers.cpp b/src/view/kateviewhelpers.cpp
index 469d5c4..2528791 100644
--- a/src/view/kateviewhelpers.cpp
+++ b/src/view/kateviewhelpers.cpp
@@ -39,6 +39,7 @@
 #include "kateglobal.h"
 #include "katepartdebug.h"
 #include "katecommandrangeexpressionparser.h"
+#include "kateabstractinputmode.h"
 
 #include <KCharsets>
 #include <KColorScheme>
@@ -1041,9 +1042,6 @@ void KateCmdLineEdit::keyPressEvent(QKeyEvent *ev)
             (ev->key() == Qt::Key_BracketLeft && ev->modifiers() == Qt::ControlModifier)) {
         m_view->setFocus();
         hideLineEdit();
-        if (m_view->viInputMode()) {
-            m_view->getViInputModeManager()->reset();
-        }
         clear();
     } else if (ev->key() == Qt::Key_Up) {
         fromHistory(true);
@@ -1607,7 +1605,7 @@ void KateIconBorder::paintBorder(int /*x*/, int y, int /*width*/, int height)
 
             if (realLine > -1) {
                 if (m_viewInternal->cache()->viewLine(z).startCol() == 0) {
-                    if (m_viRelLineNumbersOn && m_view->viInputMode()) {
+                    if (m_viRelLineNumbersOn && m_view->currentInputMode()->viewInputMode() == KTextEditor::View::ViInputMode) { // FIXME: make it more general
                         int diff = abs(realLine - currentLine);
                         if (diff > 0) {
                             p.drawText(lnX + m_maxCharWidth / 2, y, lnWidth - m_maxCharWidth, h,
diff --git a/src/view/kateviewinternal.cpp b/src/view/kateviewinternal.cpp
index 3a8b416..d57eda7 100644
--- a/src/view/kateviewinternal.cpp
+++ b/src/view/kateviewinternal.cpp
@@ -36,17 +36,18 @@
 #include "kateconfig.h"
 #include "katelayoutcache.h"
 #include "katecompletionwidget.h"
-#include "kateviinputmodemanager.h"
-#include "katesearchbar.h"
 #include "spellcheck/spellingmenu.h"
 #include "kateviewaccessible.h"
 #include "katetextanimation.h"
 #include "katemessagewidget.h"
+#include "kateglobal.h"
+#include "kateabstractinputmodefactory.h"
+#include "kateabstractinputmode.h"
+#include "katepartdebug.h"
 
 #include <ktexteditor/movingrange.h>
 #include <ktexteditor/texthintinterface.h>
 #include <KCursor>
-#include "katepartdebug.h"
 
 #include <QMimeData>
 #include <QAccessible>
@@ -98,9 +99,14 @@ KateViewInternal::KateViewInternal(KTextEditor::ViewPrivate *view)
     , m_textHintDelay(500)
     , m_textHintPos(-1, -1)
     , m_imPreeditRange(0)
-    , m_viInputMode(false)
-    , m_viInputModeManager(0)
 {
+    QList<KateAbstractInputModeFactory *> factories = KTextEditor::EditorPrivate::self()->inputModeFactories();
+    Q_FOREACH(KateAbstractInputModeFactory *factory, factories) {
+        KateAbstractInputMode *m = factory->createInputMode(this);
+        m_inputModes.insert(m->viewInputMode(), m);
+    }
+    m_currentInputMode = m_inputModes[KTextEditor::View::NormalInputMode]; // TODO: twisted, but needed
+
     setMinimumSize(0, 0);
     setAttribute(Qt::WA_OpaquePaintEvent);
     setAttribute(Qt::WA_InputMethodEnabled);
@@ -235,7 +241,7 @@ KateViewInternal::~KateViewInternal()
     delete m_imPreeditRange;
     qDeleteAll(m_imPreeditRangeChildren);
 
-    delete m_viInputModeManager;
+    qDeleteAll(m_inputModes);
 
     // delete bracket markers
     delete m_bm;
@@ -2272,18 +2278,14 @@ bool KateViewInternal::eventFilter(QObject *obj, QEvent *e)
                 //qCDebug(LOG_PART) << obj << "shortcut override" << k->key() << "closing view bar";
                 return true;
             } else if (!m_view->config()->persistentSelection() && m_view->selection()) {
-                if (!m_view->viInputMode()) { // Vim mode handles clearing selections itself.
-                    m_view->clearSelection();
-                }
+                m_currentInputMode->clearSelection();
                 k->accept();
                 //qCDebug(LOG_PART) << obj << "shortcut override" << k->key() << "clearing selection";
                 return true;
             }
         }
 
-        // if vi input mode key stealing is on, override kate shortcuts
-        if (m_view->viInputMode() && m_view->viInputModeStealKeys() && (m_view->getCurrentViMode() != InsertMode ||
-                k->modifiers() == Qt::ControlModifier || k->key() == Qt::Key_Insert)) {
+        if (m_currentInputMode->stealKey(k)) {
             k->accept();
             return true;
         }
@@ -2383,37 +2385,10 @@ void KateViewInternal::keyPressEvent(QKeyEvent *e)
     // Note: AND'ing with <Shift> is a quick hack to fix Key_Enter
     const int key = e->key() | (e->modifiers() & Qt::ShiftModifier);
 
-    if (m_view->isCompletionActive()
-            && !m_view->viInputMode() /* Vi input mode needs to handle completion keypresses itself for e.g. mappings */) {
-        if (key == Qt::Key_Enter || key == Qt::Key_Return) {
-            m_view->completionWidget()->execute();
-            e->accept();
-            return;
-        }
+    if (m_currentInputMode->keyPress(e)) {
+        return;
     }
 
-    if (m_view->viInputMode()) {
-        if (getViInputModeManager()->getCurrentViMode() == InsertMode
-                || getViInputModeManager()->getCurrentViMode() == ReplaceMode) {
-            if (getViInputModeManager()->handleKeypress(e)) {
-                return;
-            } else if (e->modifiers() != Qt::NoModifier && e->modifiers() != Qt::ShiftModifier) {
-                // re-post key events not handled if they have a modifier other than shift
-                QEvent *copy = new QKeyEvent(e->type(), e->key(), e->modifiers(), e->text(),
-                                             e->isAutoRepeat(), e->count());
-                QCoreApplication::postEvent(parent(), copy);
-            }
-        } else { // !InsertMode
-            if (!getViInputModeManager()->handleKeypress(e)) {
-                // we didn't need that keypress, un-steal it :-)
-                QEvent *copy = new QKeyEvent(e->type(), e->key(), e->modifiers(), e->text(),
-                                             e->isAutoRepeat(), e->count());
-                QCoreApplication::postEvent(parent(), copy);
-            }
-            emit m_view->viewModeChanged(m_view, m_view->viewMode());
-            return;
-        }
-    }
 
     if (!doc()->isReadWrite()) {
         e->ignore();
@@ -2965,9 +2940,8 @@ void KateViewInternal::paintEvent(QPaintEvent *e)
     paint.save();
 
     // TODO put in the proper places
-    if (!m_view->viInputMode()) {
-        setCaretStyle(m_view->isOverwriteMode() ? KateRenderer::Block : KateRenderer::Line);
-    }
+    setCaretStyle(m_currentInputMode->caretStyle());
+
     renderer()->setShowTabs(doc()->config()->showTabs());
     renderer()->setShowTrailingSpaces(doc()->config()->showSpaces());
 
@@ -3105,7 +3079,7 @@ void KateViewInternal::scrollTimeout()
 
 void KateViewInternal::cursorTimeout()
 {
-    if (!debugPainting && !m_view->viInputMode()) {
+    if (!debugPainting && m_currentInputMode->blinkCaret()) {
         renderer()->setDrawCaret(!renderer()->drawCaret());
         paintCursor();
     }
@@ -3743,31 +3717,6 @@ void KateViewInternal::inputMethodEvent(QInputMethodEvent *e)
 
 //END IM INPUT STUFF
 
-ViMode KateViewInternal::getCurrentViMode()
-{
-    return getViInputModeManager()->getCurrentViMode();
-}
-
-KateViInputModeManager *KateViewInternal::getViInputModeManager()
-{
-    if (!m_viInputModeManager) {
-        m_viInputModeManager = new KateViInputModeManager(m_view, this);
-    }
-
-    return m_viInputModeManager;
-}
-
-KateViInputModeManager *KateViewInternal::resetViInputModeManager()
-{
-    if (m_viInputModeManager) {
-        delete m_viInputModeManager;
-        m_viInputModeManager = nullptr;
-    }
-    m_viInputModeManager = new KateViInputModeManager(m_view, this);
-
-    return m_viInputModeManager;
-}
-
 void KateViewInternal::flashChar(const KTextEditor::Cursor &pos, KTextEditor::Attribute::Ptr attribute)
 {
     Q_ASSERT(pos.isValid());
diff --git a/src/view/kateviewinternal.h b/src/view/kateviewinternal.h
index 2c286b2..d21e0a3 100644
--- a/src/view/kateviewinternal.h
+++ b/src/view/kateviewinternal.h
@@ -53,8 +53,7 @@ class KateIconBorder;
 class KateScrollBar;
 class KateTextLayout;
 class KateTextAnimation;
-
-class KateViInputModeManager;
+class KateAbstractInputMode;
 
 class QScrollBar;
 
@@ -68,7 +67,7 @@ class KateViewInternal : public QWidget
     friend class CalculatingCursor;
     friend class BoundedCursor;
     friend class WrappingCursor;
-    friend class KateViModeBase;
+    friend class KateAbstractInputMode;
 
 public:
     enum Bias {
@@ -458,32 +457,10 @@ private:
         return m_view->doc();
     }
 
-    // vi Mode
+    // input modes
 private:
-    bool m_viInputMode;
-    bool m_viInputModeStealKeys;
-    bool m_viRelLineNumbers;
-
-    /**
-     * returns the current vi mode
-     */
-    ViMode getCurrentViMode();
-
-    /**
-     * an instance of KateViInputModeManager. used for interacting with the vi input mode when
-     * enabled
-     */
-    KateViInputModeManager *m_viInputModeManager;
-
-    /**
-     * @return a pointer to a KateViInputModeManager
-     */
-    KateViInputModeManager *getViInputModeManager();
-
-    /**
-     * @return a pointer to a new KateViInputModeManager
-     */
-    KateViInputModeManager *resetViInputModeManager();
+    QMap<KTextEditor::View::InputMode, KateAbstractInputMode *> m_inputModes;
+    KateAbstractInputMode *m_currentInputMode;
 };
 
 #endif
diff --git a/src/vimode/katevicmds.cpp b/src/vimode/katevicmds.cpp
index cd9bfc0..eeb37d7 100644
--- a/src/vimode/katevicmds.cpp
+++ b/src/vimode/katevicmds.cpp
@@ -30,6 +30,7 @@
 #include "kateviemulatedcommandbar.h"
 #include "katecmd.h"
 #include "katepartdebug.h"
+#include "kateviinputmode.h"
 
 #include <KLocalizedString>
 
@@ -335,9 +336,9 @@ bool KateViCommands::AppCommands::help(KTextEditor::View *view, const QString &c
 //BEGIN SedReplace
 KateViCommands::SedReplace *KateViCommands::SedReplace::m_instance = 0;
 
-bool KateViCommands::SedReplace::interactiveSedReplace(KTextEditor::ViewPrivate *view, QSharedPointer<InteractiveSedReplacer> interactiveSedReplace)
+bool KateViCommands::SedReplace::interactiveSedReplace(KTextEditor::ViewPrivate *, QSharedPointer<InteractiveSedReplacer> interactiveSedReplace)
 {
-    KateViEmulatedCommandBar *emulatedCommandBar = view->viModeEmulatedCommandBar();
+    KateViEmulatedCommandBar *emulatedCommandBar = m_viInputModeManager->inputAdapter()->viModeEmulatedCommandBar();
     emulatedCommandBar->startInteractiveSearchAndReplace(interactiveSedReplace);
     return true;
 }
diff --git a/src/vimode/kateviglobal.cpp b/src/vimode/kateviglobal.cpp
index 6af796f..55757d9 100644
--- a/src/vimode/kateviglobal.cpp
+++ b/src/vimode/kateviglobal.cpp
@@ -25,9 +25,10 @@
 #include "kateviglobal.h"
 #include "katevikeyparser.h"
 #include "kateviemulatedcommandbar.h"
-
-#include "kconfiggroup.h"
 #include "katepartdebug.h"
+#include "kateviinputmode.h"
+
+#include <kconfiggroup.h>
 #include <ktexteditor/movingcursor.h>
 #include <QApplication>
 #include <QClipboard>
@@ -219,12 +220,12 @@ bool KateViGlobal::isMappingRecursive(MappingMode mode, const QString &from) con
     return m_mappingsForMode[mode][from].isRecursive;
 }
 
-KateViGlobal::MappingMode KateViGlobal::mappingModeForCurrentViMode(KTextEditor::ViewPrivate *view)
+KateViGlobal::MappingMode KateViGlobal::mappingModeForCurrentViMode(KateViInputMode *viInputMode)
 {
-    if (view->viModeEmulatedCommandBar()->isActive()) {
+    if (viInputMode->viModeEmulatedCommandBar()->isActive()) {
         return CommandModeMapping;
     }
-    const ViMode mode = view->getCurrentViMode();
+    const ViMode mode = viInputMode->viInputModeManager()->getCurrentViMode();
     switch (mode) {
     case NormalMode:
         return NormalModeMapping;
diff --git a/src/vimode/kateviglobal.h b/src/vimode/kateviglobal.h
index 31f30a3..38b4d3e 100644
--- a/src/vimode/kateviglobal.h
+++ b/src/vimode/kateviglobal.h
@@ -31,11 +31,13 @@
 #include <KSharedConfig>
 
 #include "katevimodebase.h"
+#include "kateviinputmodemanager.h"
 #include <ktexteditor_export.h>
 
 class QString;
 class QChar;
 class KConfigGroup;
+class KateViInputMode;
 
 namespace KateVi
 {
@@ -82,7 +84,7 @@ public:
      * Returns CommandModeMapping if the emulated command bar is active, else the mapping mode
      * corresponding to the current Vi mode.
      */
-    static MappingMode mappingModeForCurrentViMode(KTextEditor::ViewPrivate *view);
+    static MappingMode mappingModeForCurrentViMode(KateViInputMode *viInputMode);
 
     QStringList searchHistory();
     void clearSearchHistory();
diff --git a/src/vimode/kateviinputmodeconfigtab.cpp b/src/vimode/kateviinputmodeconfigtab.cpp
index a00305a..58ed74c 100644
--- a/src/vimode/kateviinputmodeconfigtab.cpp
+++ b/src/vimode/kateviinputmodeconfigtab.cpp
@@ -56,7 +56,6 @@ KateViInputModeConfigTab::KateViInputModeConfigTab(QWidget *parent, KateViGlobal
     // after initial reload, connect the stuff for the changed () signal
     //
 
-    connect(ui->chkViInputModeDefault, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
     connect(ui->chkViCommandsOverride, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
     connect(ui->chkViRelLineNumbers, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
     connect(ui->tblNormalModeMappings, SIGNAL(cellChanged(int,int)), this, SLOT(slotChanged()));
@@ -126,7 +125,6 @@ void KateViInputModeConfigTab::apply()
     KateViewConfig::global()->configStart();
 
     // General options.
-    KateViewConfig::global()->setViInputMode(ui->chkViInputModeDefault->isChecked());
     KateViewConfig::global()->setViRelativeLineNumbers(ui->chkViRelLineNumbers->isChecked());
     KateViewConfig::global()->setViInputModeStealKeys(ui->chkViCommandsOverride->isChecked());
 
@@ -142,10 +140,8 @@ void KateViInputModeConfigTab::apply()
 void KateViInputModeConfigTab::reload()
 {
     // General options.
-    ui->chkViInputModeDefault->setChecked(KateViewConfig::global()->viInputMode());
     ui->chkViRelLineNumbers->setChecked( KateViewConfig::global()->viRelativeLineNumbers () );
     ui->chkViCommandsOverride->setChecked(KateViewConfig::global()->viInputModeStealKeys());
-    ui->chkViCommandsOverride->setEnabled(ui->chkViInputModeDefault->isChecked());
 
     // Mappings.
     reloadTab(ui->tblNormalModeMappings, KateViGlobal::NormalModeMapping);
diff --git a/src/vimode/kateviinputmodemanager.cpp b/src/vimode/kateviinputmodemanager.cpp
index f3f5370..f8b19d6 100644
--- a/src/vimode/kateviinputmodemanager.cpp
+++ b/src/vimode/kateviinputmodemanager.cpp
@@ -43,6 +43,7 @@
 #include "katevikeymapper.h"
 #include "kateviemulatedcommandbar.h"
 #include "katepartdebug.h"
+#include "kateviinputmode.h"
 
 using KTextEditor::Cursor;
 using KTextEditor::Document;
@@ -50,7 +51,8 @@ using KTextEditor::Mark;
 using KTextEditor::MarkInterface;
 using KTextEditor::MovingCursor;
 
-KateViInputModeManager::KateViInputModeManager(KTextEditor::ViewPrivate *view, KateViewInternal *viewInternal)
+KateViInputModeManager::KateViInputModeManager(KateViInputMode *inputAdapter, KTextEditor::ViewPrivate *view, KateViewInternal *viewInternal)
+    : m_inputAdapter(inputAdapter)
 {
     m_viNormalMode = new KateViNormalMode(this, view, viewInternal);
     m_viInsertMode = new KateViInsertMode(this, view, viewInternal);
@@ -63,8 +65,6 @@ KateViInputModeManager::KateViInputModeManager(KTextEditor::ViewPrivate *view, K
     m_view = view;
     m_viewInternal = viewInternal;
 
-    m_view->setCaretStyle(KateRenderer::Block, true);
-
     m_insideHandlingKeyPressCount = 0;
 
     m_isReplayingLastChange = false;
@@ -95,12 +95,6 @@ KateViInputModeManager::KateViInputModeManager(KTextEditor::ViewPrivate *view, K
     // KateViVisualMode (which inherits from KateViNormalMode) to respond
     // to changes in the document as well.
     m_viNormalMode->beginMonitoringDocumentChanges();
-
-    if (view->selection()) {
-        changeViMode(VisualMode);
-        m_view->setCursorPosition(Cursor(view->selectionRange().end().line(), view->selectionRange().end().column() - 1));
-        m_viVisualMode->updateSelection();
-    }
 }
 
 KateViInputModeManager::~KateViInputModeManager()
@@ -117,7 +111,7 @@ bool KateViInputModeManager::handleKeypress(const QKeyEvent *e)
     m_insideHandlingKeyPressCount++;
     bool res = false;
     bool keyIsPartOfMapping = false;
-    const bool isSyntheticSearchCompletedKeyPress = m_view->viModeEmulatedCommandBar()->isSendingSyntheticSearchCompletedKeypress();
+    const bool isSyntheticSearchCompletedKeyPress = m_inputAdapter->viModeEmulatedCommandBar()->isSendingSyntheticSearchCompletedKeypress();
 
     // With macros, we want to record the keypresses *before* they are mapped, but if they end up *not* being part
     // of a mapping, we don't want to record them when they are played back by m_keyMapper, hence
@@ -150,8 +144,8 @@ bool KateViInputModeManager::handleKeypress(const QKeyEvent *e)
             appendKeyEventToLog(copy);
         }
 
-        if (m_view->viModeEmulatedCommandBar()->isActive()) {
-            res = m_view->viModeEmulatedCommandBar()->handleKeyPress(e);
+        if (m_inputAdapter->viModeEmulatedCommandBar()->isActive()) {
+            res = m_inputAdapter->viModeEmulatedCommandBar()->handleKeyPress(e);
         } else {
             res = getCurrentViModeHandler()->handleKeypress(e);
         }
@@ -322,7 +316,7 @@ void KateViInputModeManager::startRecordingMacro(QChar macroRegister)
     qCDebug(LOG_PART) << "Recording macro: " << macroRegister;
     m_isRecordingMacro = true;
     m_recordingMacroRegister = macroRegister;
-    KTextEditor::EditorPrivate::self()->viInputModeGlobal()->clearMacro(macroRegister);
+    m_inputAdapter->viGlobal()->clearMacro(macroRegister);
     m_currentMacroKeyEventsLog.clear();
     m_currentMacroCompletionsLog.clear();
 }
@@ -331,7 +325,7 @@ void KateViInputModeManager::finishRecordingMacro()
 {
     Q_ASSERT(m_isRecordingMacro);
     m_isRecordingMacro = false;
-    KTextEditor::EditorPrivate::self()->viInputModeGlobal()->storeMacro(m_recordingMacroRegister, m_currentMacroKeyEventsLog, m_currentMacroCompletionsLog);
+    m_inputAdapter->viGlobal()->storeMacro(m_recordingMacroRegister, m_currentMacroKeyEventsLog, m_currentMacroCompletionsLog);
 }
 
 bool KateViInputModeManager::isRecordingMacro()
@@ -346,12 +340,12 @@ void KateViInputModeManager::replayMacro(QChar macroRegister)
     }
     m_lastPlayedMacroRegister = macroRegister;
     qCDebug(LOG_PART) << "Replaying macro: " << macroRegister;
-    const QString macroAsFeedableKeypresses = KTextEditor::EditorPrivate::self()->viInputModeGlobal()->getMacro(macroRegister);
+    const QString macroAsFeedableKeypresses = m_inputAdapter->viGlobal()->getMacro(macroRegister);
     qCDebug(LOG_PART) << "macroAsFeedableKeypresses:  " << macroAsFeedableKeypresses;
 
     m_macrosBeingReplayedCount++;
     m_nextLoggedMacroCompletionIndex.push(0);
-    m_macroCompletionsToReplay.push(KTextEditor::EditorPrivate::self()->viInputModeGlobal()->getMacroCompletions(macroRegister));
+    m_macroCompletionsToReplay.push(m_inputAdapter->viGlobal()->getMacroCompletions(macroRegister));
     m_keyMapperStack.push(QSharedPointer<KateViKeyMapper>(new KateViKeyMapper(this, m_view->doc(), m_view)));
     feedKeyPresses(macroAsFeedableKeypresses);
     m_keyMapperStack.pop();
@@ -487,7 +481,7 @@ void KateViInputModeManager::viEnterNormalMode()
 
         if (r.isValid()) {
             QString insertedText = m_view->doc()->text(r);
-            KTextEditor::EditorPrivate::self()->viInputModeGlobal()->fillRegister(QLatin1Char('^'), insertedText);
+            m_inputAdapter->viGlobal()->fillRegister(QLatin1Char('^'), insertedText);
         }
 
         addMark(m_view->doc(), QLatin1Char('^'), Cursor(m_view->cursorPosition()), false, false);
@@ -580,7 +574,7 @@ const QString KateViInputModeManager::getVerbatimKeys() const
 void KateViInputModeManager::readSessionConfig(const KConfigGroup &config)
 {
 
-    if (KTextEditor::EditorPrivate::self()->viInputModeGlobal()->getRegisters()->size() > 0) {
+    if (m_inputAdapter->viGlobal()->getRegisters()->size() > 0) {
         QStringList names = config.readEntry("ViRegisterNames", QStringList());
         QStringList contents = config.readEntry("ViRegisterContents", QStringList());
         QList<int> flags = config.readEntry("ViRegisterFlags", QList<int>());
@@ -589,7 +583,7 @@ void KateViInputModeManager::readSessionConfig(const KConfigGroup &config)
         if (names.size() == contents.size() && contents.size() == flags.size()) {
             for (int i = 0; i < names.size(); i++) {
                 if (!names.at(i).isEmpty()) {
-                    KTextEditor::EditorPrivate::self()->viInputModeGlobal()->fillRegister(names.at(i).at(0), contents.at(i), (OperationMode)(flags.at(i)));
+                    m_inputAdapter->viGlobal()->fillRegister(names.at(i).at(0), contents.at(i), (OperationMode)(flags.at(i)));
                 }
             }
         }
@@ -616,8 +610,8 @@ void KateViInputModeManager::readSessionConfig(const KConfigGroup &config)
 
 void KateViInputModeManager::writeSessionConfig(KConfigGroup &config)
 {
-    if (KTextEditor::EditorPrivate::self()->viInputModeGlobal()->getRegisters()->size() > 0) {
-        const QMap<QChar, KateViRegister> *regs = KTextEditor::EditorPrivate::self()->viInputModeGlobal()->getRegisters();
+    if (m_inputAdapter->viGlobal()->getRegisters()->size() > 0) {
+        const QMap<QChar, KateViRegister> *regs = m_inputAdapter->viGlobal()->getRegisters();
         QStringList names, contents;
         QList<int> flags;
         QMap<QChar, KateViRegister>::const_iterator i;
@@ -869,11 +863,9 @@ QString KateViInputModeManager::getMarksOnTheLine(int line)
 {
     QString res;
 
-    if (m_view->viInputMode()) {
-        foreach (QChar markerChar, m_marks.keys()) {
-            if (m_marks.value(markerChar)->line() == line) {
-                res += markerChar + QLatin1String(":") + QString::number(m_marks.value(markerChar)->column()) + QLatin1String(" ");
-            }
+    foreach (QChar markerChar, m_marks.keys()) {
+        if (m_marks.value(markerChar)->line() == line) {
+            res += markerChar + QLatin1String(":") + QString::number(m_marks.value(markerChar)->column()) + QLatin1String(" ");
         }
     }
 
@@ -935,9 +927,14 @@ KateViInputModeManager::Completion::CompletionType KateViInputModeManager::Compl
     return m_completionType;
 }
 
+void KateViInputModeManager::updateCursor(const Cursor &c)
+{
+    m_inputAdapter->updateCursor(c);
+}
+
 KateViGlobal *KateViInputModeManager::viGlobal() const
 {
-    return KTextEditor::EditorPrivate::self()->viInputModeGlobal();
+    return m_inputAdapter->viGlobal();
 }
 
 KTextEditor::ViewPrivate *KateViInputModeManager::view() const
diff --git a/src/vimode/kateviinputmodemanager.h b/src/vimode/kateviinputmodemanager.h
index 871458c..f3771ba 100644
--- a/src/vimode/kateviinputmodemanager.h
+++ b/src/vimode/kateviinputmodemanager.h
@@ -69,12 +69,16 @@ class Mark;
 class MarkInterface;
 }
 
+class KateViInputMode;
+
 class KTEXTEDITOR_EXPORT KateViInputModeManager : public QObject
 {
     Q_OBJECT
 
+    friend KateViInputMode;
+
 public:
-    KateViInputModeManager(KTextEditor::ViewPrivate *view, KateViewInternal *viewInternal);
+    KateViInputModeManager(KateViInputMode *inputAdapter, KTextEditor::ViewPrivate *view, KateViewInternal *viewInternal);
     ~KateViInputModeManager();
 
     /**
@@ -332,6 +336,9 @@ public:
     KateViGlobal *viGlobal() const;
     KTextEditor::ViewPrivate *view() const;
 
+    KateViInputMode *inputAdapter() { return m_inputAdapter; }
+    void updateCursor(const KTextEditor::Cursor &c);
+
 private Q_SLOTS:
     void markChanged(KTextEditor::Document *doc,
                      KTextEditor::Mark mark,
@@ -346,6 +353,7 @@ private:
     ViMode m_currentViMode;
     ViMode m_previousViMode;
 
+    KateViInputMode *m_inputAdapter;
     KTextEditor::ViewPrivate *m_view;
     KateViewInternal *m_viewInternal;
     KateViKeyParser *m_keyParser;
diff --git a/src/vimode/katevikeymapper.cpp b/src/vimode/katevikeymapper.cpp
index 786b27a..a6a4d0f 100644
--- a/src/vimode/katevikeymapper.cpp
+++ b/src/vimode/katevikeymapper.cpp
@@ -45,8 +45,8 @@ void KateViKeyMapper::executeMapping()
     m_mappingKeys.clear();
     m_mappingTimer->stop();
     m_numMappingsBeingExecuted++;
-    const QString mappedKeypresses = m_viInputModeManager->viGlobal()->getMapping(KateViGlobal::mappingModeForCurrentViMode(m_viInputModeManager->view()), m_fullMappingMatch);
-    if (!m_viInputModeManager->viGlobal()->isMappingRecursive(KateViGlobal::mappingModeForCurrentViMode(m_viInputModeManager->view()), m_fullMappingMatch)) {
+    const QString mappedKeypresses = m_viInputModeManager->viGlobal()->getMapping(KateViGlobal::mappingModeForCurrentViMode(m_viInputModeManager->inputAdapter()), m_fullMappingMatch);
+    if (!m_viInputModeManager->viGlobal()->isMappingRecursive(KateViGlobal::mappingModeForCurrentViMode(m_viInputModeManager->inputAdapter()), m_fullMappingMatch)) {
         qCDebug(LOG_PART) << "Non-recursive: " << mappedKeypresses;
         m_doNotExpandFurtherMappings = true;
     }
@@ -90,7 +90,7 @@ bool KateViKeyMapper::handleKeypress(QChar key)
         bool isPartialMapping = false;
         bool isFullMapping = false;
         m_fullMappingMatch.clear();
-        foreach (const QString &mapping, m_viInputModeManager->viGlobal()->getMappings(KateViGlobal::mappingModeForCurrentViMode(m_viInputModeManager->view()))) {
+        foreach (const QString &mapping, m_viInputModeManager->viGlobal()->getMappings(KateViGlobal::mappingModeForCurrentViMode(m_viInputModeManager->inputAdapter()))) {
             if (mapping.startsWith(m_mappingKeys)) {
                 if (mapping == m_mappingKeys) {
                     isFullMapping = true;
diff --git a/src/vimode/katevimodebase.cpp b/src/vimode/katevimodebase.cpp
index 427daaa..77952d8 100644
--- a/src/vimode/katevimodebase.cpp
+++ b/src/vimode/katevimodebase.cpp
@@ -24,23 +24,23 @@
 #include "katevimodebase.h"
 #include "katevirange.h"
 #include "kateglobal.h"
+#include "kateviinputmode.h"
 #include "kateviglobal.h"
 #include "katevivisualmode.h"
 #include "katevinormalmode.h"
 #include "katevireplacemode.h"
 #include "kateviinputmodemanager.h"
 #include "katelayoutcache.h"
-
-#include <QString>
-#include <KLocalizedString>
-#include <QRegExp>
 #include "kateconfig.h"
 #include "katedocument.h"
 #include "kateviewinternal.h"
-#include <ktexteditor/view.h>
 #include "katerenderer.h"
 #include "katepartdebug.h"
 
+#include <QString>
+#include <KLocalizedString>
+#include <QRegExp>
+
 using KTextEditor::Cursor;
 using KTextEditor::Range;
 
@@ -916,7 +916,7 @@ int KateViModeBase::findLineStartingWitchChar(const QChar &c, unsigned int count
 
 void KateViModeBase::updateCursor(const Cursor &c) const
 {
-    m_viewInternal->updateCursor(c);
+    m_viInputModeManager->updateCursor(c);
 }
 
 /**
@@ -1045,7 +1045,7 @@ KateViRange KateViModeBase::goVisualLineUpDown(int lines)
         return r;
     }
 
-    KateLayoutCache *cache = m_viewInternal->cache();
+    KateLayoutCache *cache = m_viInputModeManager->inputAdapter()->layoutCache();
 
     // Work out the real and visual line pair of the beginning of the visual line we'd end up
     // on by moving lines visual lines.  We ignore the column, for now.
@@ -1224,11 +1224,6 @@ void KateViModeBase::error(const QString &errorMsg)
 {
     delete m_infoMessage;
 
-    // nop if no vi mode around
-    if (!m_view->viInputMode()) {
-        return;
-    }
-
     m_infoMessage = new KTextEditor::Message(errorMsg, KTextEditor::Message::Error);
     m_infoMessage->setPosition(KTextEditor::Message::BottomInView);
     m_infoMessage->setAutoHide(2000); // 2 seconds
@@ -1241,11 +1236,6 @@ void KateViModeBase::message(const QString &msg)
 {
     delete m_infoMessage;
 
-    // nop if no vi mode around
-    if (!m_view->viInputMode()) {
-        return;
-    }
-
     m_infoMessage = new KTextEditor::Message(msg, KTextEditor::Message::Positive);
     m_infoMessage->setPosition(KTextEditor::Message::BottomInView);
     m_infoMessage->setAutoHide(2000); // 2 seconds
@@ -1467,7 +1457,7 @@ void KateViModeBase::switchView(Direction direction)
     }
     if (bestview != NULL) {
         bestview->setFocus();
-        KateViewConfig::global()->setViInputMode(true);
+        bestview->setInputMode(KTextEditor::View::ViInputMode);
     }
 }
 
@@ -1539,10 +1529,10 @@ void KateViModeBase::findPrev()
 
 unsigned int KateViModeBase::linesDisplayed() const
 {
-    return m_viewInternal->linesDisplayed();
+    return m_viInputModeManager->inputAdapter()->linesDisplayed();
 }
 
 void KateViModeBase::scrollViewLines(int l)
 {
-    m_viewInternal->scrollViewLines(l);
+    m_viInputModeManager->inputAdapter()->scrollViewLines(l);
 }
diff --git a/src/vimode/katevinormalmode.cpp b/src/vimode/katevinormalmode.cpp
index c6e1f06..935876f 100644
--- a/src/vimode/katevinormalmode.cpp
+++ b/src/vimode/katevinormalmode.cpp
@@ -42,6 +42,7 @@
 #include "katevivisualmode.h"
 #include "katecmd.h"
 #include <ktexteditor/attribute.h>
+#include "kateviinputmode.h"
 
 #include <QApplication>
 #include <QList>
@@ -1442,8 +1443,8 @@ bool KateViNormalMode::commandSwitchToCmdLine()
         initialText = QLatin1String(".,.+") + QString::number(getCount() - 1);
     }
 
-    m_view->showViModeEmulatedCommandBar();
-    m_view->viModeEmulatedCommandBar()->init(KateViEmulatedCommandBar::Command, initialText);
+    m_viInputModeManager->inputAdapter()->showViModeEmulatedCommandBar();
+    m_viInputModeManager->inputAdapter()->viModeEmulatedCommandBar()->init(KateViEmulatedCommandBar::Command, initialText);
 
     m_commandShouldKeepSelection = true;
 
@@ -1452,15 +1453,15 @@ bool KateViNormalMode::commandSwitchToCmdLine()
 
 bool KateViNormalMode::commandSearchBackward()
 {
-    m_view->showViModeEmulatedCommandBar();
-    m_view->viModeEmulatedCommandBar()->init(KateViEmulatedCommandBar::SearchBackward);
+    m_viInputModeManager->inputAdapter()->showViModeEmulatedCommandBar();
+    m_viInputModeManager->inputAdapter()->viModeEmulatedCommandBar()->init(KateViEmulatedCommandBar::SearchBackward);
     return true;
 }
 
 bool KateViNormalMode::commandSearchForward()
 {
-    m_view->showViModeEmulatedCommandBar();
-    m_view->viModeEmulatedCommandBar()->init(KateViEmulatedCommandBar::SearchForward);
+    m_viInputModeManager->inputAdapter()->showViModeEmulatedCommandBar();
+    m_viInputModeManager->inputAdapter()->viModeEmulatedCommandBar()->init(KateViEmulatedCommandBar::SearchForward);
     m_viInputModeManager->setLastSearchBackwards(false);
     return true;
 }
diff --git a/src/vimode/katevinormalmode.h b/src/vimode/katevinormalmode.h
index aad0981..571c308 100644
--- a/src/vimode/katevinormalmode.h
+++ b/src/vimode/katevinormalmode.h
@@ -40,6 +40,7 @@ class KateViCommand;
 class KateViMotion;
 class KateViKeyParser;
 class KateViInputModeManager;
+class KateViInputMode;
 
 /**
  * Commands for the vi normal mode
@@ -48,6 +49,8 @@ class KTEXTEDITOR_EXPORT KateViNormalMode : public KateViModeBase
 {
     Q_OBJECT
 
+    friend KateViInputMode;
+
 public:
     KateViNormalMode(KateViInputModeManager *viInputModeManager, KTextEditor::ViewPrivate *view, KateViewInternal *viewInternal);
     virtual ~KateViNormalMode();
diff --git a/src/vimode/katevivisualmode.cpp b/src/vimode/katevivisualmode.cpp
index 8fcdea2..e381539 100644
--- a/src/vimode/katevivisualmode.cpp
+++ b/src/vimode/katevivisualmode.cpp
@@ -27,6 +27,7 @@
 #include "katevimotion.h"
 #include "katevirange.h"
 #include "katedocument.h"
+#include "kateviinputmode.h"
 
 using KTextEditor::Cursor;
 using KTextEditor::Range;
@@ -238,7 +239,11 @@ void KateViVisualMode::goToPos(const Cursor &c)
 
 void KateViVisualMode::updateSelection()
 {
-    if (!m_view->viInputMode() || (m_viInputModeManager->isHandlingKeypress() && !m_isUndo)) {
+    if (!m_viInputModeManager->inputAdapter()->isActive()) {
+        return;
+    }
+
+    if (m_viInputModeManager->isHandlingKeypress() && !m_isUndo) {
         return;
     }
 
diff --git a/src/vimode/viinputmodeconfigwidget.ui b/src/vimode/viinputmodeconfigwidget.ui
index 3c8da22..b01ac61 100644
--- a/src/vimode/viinputmodeconfigwidget.ui
+++ b/src/vimode/viinputmodeconfigwidget.ui
@@ -30,16 +30,6 @@
      </property>
      <layout class="QVBoxLayout">
       <item>
-       <widget class="QCheckBox" name="chkViInputModeDefault">
-        <property name="whatsThis">
-         <string>When selected, the vi input mode will be enabled when opening a new view. You can still toggle the vi input mode on/off for a particular view in the Edit menu.</string>
-        </property>
-        <property name="text">
-         <string>Use Vi input mode</string>
-        </property>
-       </widget>
-      </item>
-      <item>
        <widget class="QCheckBox" name="chkViCommandsOverride">
         <property name="whatsThis">
          <string>When selected, vi commands will override Kate's built-in commands. For example: Ctrl+R will redo, and override the standard action (showing the search and replace dialog).</string>


More information about the kde-doc-english mailing list