diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp
index 25f0b7032f9078688a7b7c7c90d3be543d91741e..4ad0abb42605d47424c361659824e85db455f7d4 100644
--- a/src/plugins/fakevim/fakevimhandler.cpp
+++ b/src/plugins/fakevim/fakevimhandler.cpp
@@ -439,7 +439,6 @@ public:
     SubMode m_submode;
     SubSubMode m_subsubmode;
     int m_subsubdata;
-    QString m_input;
     QTextCursor m_tc;
     int m_oldPosition; // copy from last event to check for external changes
     int m_anchor;
@@ -561,6 +560,13 @@ public:
     QVector<CursorPosition> m_jumpListRedo;
 
     QList<QTextEdit::ExtraSelection> m_searchSelections;
+
+    bool handleMapping(const QString &line);
+    // Mappings for a specific mode.
+    typedef QHash<QByteArray, QByteArray> ModeMappings;
+    // All mappings.
+    typedef QHash<char, ModeMappings> Mappings;
+    Mappings m_mappings;
 };
 
 QStringList FakeVimHandler::Private::m_searchHistory;
@@ -751,7 +757,6 @@ void FakeVimHandler::Private::setupWidget()
         updateSelection();
     }
 
-    //showBlackMessage("vi emulation mode. Type :q to leave. Use , Ctrl-R to trigger run.");
     updateMiniBuffer();
 }
 
@@ -2408,6 +2413,78 @@ static bool isSubstitution(const QString &cmd0, QStringList *result)
     return true;
 }
 
+bool FakeVimHandler::Private::handleMapping(const QString &cmd0)
+{
+    QByteArray line = cmd0.toLatin1();
+    int pos1 = line.indexOf(' ');
+    if (pos1 == -1)
+        return false;
+    int pos2 = line.indexOf(' ', pos1 + 1);
+    if (pos2 == -1)
+        return false;
+
+    QByteArray modes;
+    enum Type { Map, Noremap, Unmap } type;
+
+    QByteArray cmd = line.left(pos1);
+
+    // Strange formatting. But everything else is even uglier.
+    if (cmd == "map") { modes = "nvo"; type = Map; } else
+    if (cmd == "nm" || cmd == "nmap") { modes = "n"; type = Map; } else
+    if (cmd == "vm" || cmd == "vmap") { modes = "v"; type = Map; } else
+    if (cmd == "xm" || cmd == "xmap") { modes = "x"; type = Map; } else
+    if (cmd == "smap") { modes = "s"; type = Map; } else
+    if (cmd == "map!") { modes = "ic"; type = Map; } else
+    if (cmd == "im" || cmd == "imap") { modes = "i"; type = Map; } else
+    if (cmd == "lm" || cmd == "lmap") { modes = "l"; type = Map; } else
+    if (cmd == "cm" || cmd == "cmap") { modes = "c"; type = Map; } else
+
+    if (cmd == "no" || cmd == "noremap") { modes = "nvo"; type = Noremap; } else
+    if (cmd == "nn" || cmd == "nnoremap") { modes = "n"; type = Noremap; } else
+    if (cmd == "vn" || cmd == "vnoremap") { modes = "v"; type = Noremap; } else
+    if (cmd == "xn" || cmd == "xnoremap") { modes = "x"; type = Noremap; } else
+    if (cmd == "snor" || cmd == "snoremap") { modes = "s"; type = Noremap; } else
+    if (cmd == "ono" || cmd == "onoremap") { modes = "o"; type = Noremap; } else
+    if (cmd == "no!" || cmd == "noremap!") { modes = "ic"; type = Noremap; } else
+    if (cmd == "ino" || cmd == "inoremap") { modes = "i"; type = Noremap; } else
+    if (cmd == "ln" || cmd == "lnoremap") { modes = "l"; type = Noremap; } else
+    if (cmd == "cno" || cmd == "cnoremap") { modes = "c"; type = Noremap; } else
+
+    if (cmd == "unm" || cmd == "unmap") { modes = "nvo"; type = Unmap; } else
+    if (cmd == "nun" || cmd == "nunmap") { modes = "n"; type = Unmap; } else
+    if (cmd == "vu" || cmd == "vunmap") { modes = "v"; type = Unmap; } else
+    if (cmd == "xu" || cmd == "xunmap") { modes = "x"; type = Unmap; } else
+    if (cmd == "sunm" || cmd == "sunmap") { modes = "s"; type = Unmap; } else
+    if (cmd == "ou" || cmd == "ounmap") { modes = "o"; type = Unmap; } else
+    if (cmd == "unm!" || cmd == "unmap!") { modes = "ic"; type = Unmap; } else
+    if (cmd == "iu" || cmd == "iunmap") { modes = "i"; type = Unmap; } else
+    if (cmd == "lu" || cmd == "lunmap") { modes = "l"; type = Unmap; } else
+    if (cmd == "cu" || cmd == "cunmap") { modes = "c"; type = Unmap; }
+
+    else
+        return false;
+
+    QByteArray lhs = line.mid(pos1 + 1, pos2 - pos1 - 1);
+    QByteArray rhs = line.mid(pos2 + 1);
+    qDebug() << "MAPPING: " << modes << lhs << rhs;
+    switch (type) {
+        case Unmap:
+            foreach (char c, modes)
+                if (m_mappings.contains(c))
+                    m_mappings[c].remove(lhs);
+            break;
+        case Map:
+            rhs = rhs; // FIXME: expand rhs.
+            // Fall through.
+        case Noremap:
+            foreach (char c, modes)
+                m_mappings[c][lhs] = rhs;
+            break;
+    }
+    qDebug() << "CURRENT: " << m_mappings;
+    return true;
+}
+
 void FakeVimHandler::Private::handleExCommand(const QString &cmd0)
 {
     QString cmd = cmd0;
@@ -2653,6 +2730,8 @@ void FakeVimHandler::Private::handleExCommand(const QString &cmd0)
             notImplementedYet();
         }
         updateMiniBuffer();
+    } else if (handleMapping(cmd)) {
+        /* done */
     } else {
         passUnknownExCommand(cmd);
     }
@@ -3797,7 +3876,6 @@ void FakeVimHandler::showRedMessage(const QString &msg)
    d->showRedMessage(msg);
 }
 
-
 QWidget *FakeVimHandler::widget()
 {
     return d->editor();