diff --git a/src/plugins/coreplugin/actionmanager/actionmanager.cpp b/src/plugins/coreplugin/actionmanager/actionmanager.cpp
index 3b5f4dffb93a033cbe1c092639b580d1b1d6fc4e..6e4f34133e2a5fe932618323d39142ef28d13289 100644
--- a/src/plugins/coreplugin/actionmanager/actionmanager.cpp
+++ b/src/plugins/coreplugin/actionmanager/actionmanager.cpp
@@ -246,9 +246,13 @@ QList<int> ActionManagerPrivate::defaultGroups() const
     return m_defaultGroups;
 }
 
-QList<CommandPrivate *> ActionManagerPrivate::commands() const
+QList<Command *> ActionManagerPrivate::commands() const
 {
-    return m_idCmdMap.values();
+    // transform list of CommandPrivate into list of Command
+    QList<Command *> result;
+    foreach(Command *cmd, m_idCmdMap.values())
+        result << cmd;
+    return result;
 }
 
 QList<ActionContainerPrivate *> ActionManagerPrivate::containers() const
diff --git a/src/plugins/coreplugin/actionmanager/actionmanager.h b/src/plugins/coreplugin/actionmanager/actionmanager.h
index a418321198444adc098edece2257e040a93665e8..9746d37bc46f43b021994742b567ed2318d60754 100644
--- a/src/plugins/coreplugin/actionmanager/actionmanager.h
+++ b/src/plugins/coreplugin/actionmanager/actionmanager.h
@@ -61,6 +61,8 @@ public:
 
     virtual Command *command(const QString &id) const = 0;
     virtual ActionContainer *actionContainer(const QString &id) const = 0;
+
+    virtual QList<Command *> commands() const = 0;
 };
 
 } // namespace Core
diff --git a/src/plugins/coreplugin/actionmanager/actionmanager_p.h b/src/plugins/coreplugin/actionmanager/actionmanager_p.h
index 62da0d8f19b6bf0b901f139ef0889fe01b27d513..0929130c66fedfd3e3ecbc152be93fb22a66d9e9 100644
--- a/src/plugins/coreplugin/actionmanager/actionmanager_p.h
+++ b/src/plugins/coreplugin/actionmanager/actionmanager_p.h
@@ -56,7 +56,7 @@ class ActionContainerPrivate;
 class MainWindow;
 class CommandPrivate;
 
-class ActionManagerPrivate : public Core::ActionManager
+class CORE_EXPORT ActionManagerPrivate : public Core::ActionManager
 {
     Q_OBJECT
 
@@ -70,7 +70,7 @@ public:
     void saveSettings(QSettings *settings);
     QList<int> defaultGroups() const;
 
-    QList<CommandPrivate *> commands() const;
+    QList<Command *> commands() const;
     QList<ActionContainerPrivate *> containers() const;
 
     bool hasContext(int context) const;
diff --git a/src/plugins/fakevim/fakevim.pro b/src/plugins/fakevim/fakevim.pro
index 3d7195412a642892a7ab43f76e7e845b455c945d..71a94b06d78d9027879b8c7ea6830021407e264e 100644
--- a/src/plugins/fakevim/fakevim.pro
+++ b/src/plugins/fakevim/fakevim.pro
@@ -13,18 +13,12 @@ include(../../shared/indenter/indenter.pri)
 
 # DEFINES += QT_NO_CAST_FROM_ASCII QT_NO_CAST_TO_ASCII
 QT += gui
-
-SOURCES += \
-    fakevimactions.cpp \
+SOURCES += fakevimactions.cpp \
     fakevimhandler.cpp \
     fakevimplugin.cpp
-
-HEADERS += \
-    fakevimactions.h \
+HEADERS += fakevimactions.h \
     fakevimhandler.h \
     fakevimplugin.h
-
-FORMS += \
-    fakevimoptions.ui
-
+FORMS += fakevimoptions.ui \
+    fakevimexcommands.ui
 OTHER_FILES += FakeVim.pluginspec
diff --git a/src/plugins/fakevim/fakevimexcommands.ui b/src/plugins/fakevim/fakevimexcommands.ui
new file mode 100644
index 0000000000000000000000000000000000000000..98e30b7c07223d9d2200820e970999c6c4c20929
--- /dev/null
+++ b/src/plugins/fakevim/fakevimexcommands.ui
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>FakeVimExCommandsPage</class>
+ <widget class="QWidget" name="FakeVimExCommandsPage">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>568</width>
+    <height>451</height>
+   </rect>
+  </property>
+  <layout class="QVBoxLayout">
+   <item>
+    <widget class="QGroupBox" name="groupBox">
+     <property name="title">
+      <string>Ex Command Mapping</string>
+     </property>
+     <layout class="QVBoxLayout">
+      <item>
+       <layout class="QHBoxLayout">
+        <item>
+         <widget class="QLabel" name="filterLabel">
+          <property name="text">
+           <string>Filter:</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLineEdit" name="filterEdit"/>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <widget class="QTreeWidget" name="commandList">
+        <property name="rootIsDecorated">
+         <bool>false</bool>
+        </property>
+        <property name="uniformRowHeights">
+         <bool>true</bool>
+        </property>
+        <property name="sortingEnabled">
+         <bool>true</bool>
+        </property>
+        <property name="columnCount">
+         <number>3</number>
+        </property>
+        <column>
+         <property name="text">
+          <string>Command</string>
+         </property>
+        </column>
+        <column>
+         <property name="text">
+          <string>Label</string>
+         </property>
+        </column>
+        <column>
+         <property name="text">
+          <string>Ex Trigger Expression</string>
+         </property>
+        </column>
+       </widget>
+      </item>
+      <item>
+       <layout class="QHBoxLayout">
+        <item>
+         <widget class="QPushButton" name="defaultButton">
+          <property name="text">
+           <string>Defaults</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <spacer>
+          <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>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="seqGrp">
+     <property name="title">
+      <string>Ex Command</string>
+     </property>
+     <layout class="QVBoxLayout">
+      <item>
+       <layout class="QHBoxLayout">
+        <item>
+         <widget class="QLabel" name="regexLabel">
+          <property name="text">
+           <string>Regular Expression:</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLineEdit" name="regexEdit"/>
+        </item>
+        <item>
+         <widget class="QToolButton" name="resetButton">
+          <property name="toolTip">
+           <string>Reset</string>
+          </property>
+          <property name="text">
+           <string/>
+          </property>
+          <property name="icon">
+           <iconset resource="../coreplugin/core.qrc">
+            <normaloff>:/core/images/reset.png</normaloff>:/core/images/reset.png</iconset>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QToolButton" name="removeButton">
+          <property name="toolTip">
+           <string>Remove</string>
+          </property>
+          <property name="text">
+           <string/>
+          </property>
+          <property name="icon">
+           <iconset resource="../coreplugin/core.qrc">
+            <normaloff>:/core/images/clear.png</normaloff>:/core/images/clear.png</iconset>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <widget class="QLabel" name="infoLabel">
+        <property name="textFormat">
+         <enum>Qt::RichText</enum>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources>
+  <include location="../coreplugin/core.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/src/plugins/fakevim/fakevimplugin.cpp b/src/plugins/fakevim/fakevimplugin.cpp
index 1f5ca6c0ce5a7bbc92e655e74cfb134fedb4aad5..97e9d5db4c5a5c66fca9e8c3a7745d28a03ec42c 100644
--- a/src/plugins/fakevim/fakevimplugin.cpp
+++ b/src/plugins/fakevim/fakevimplugin.cpp
@@ -31,6 +31,7 @@
 
 #include "fakevimhandler.h"
 #include "ui_fakevimoptions.h"
+#include "ui_fakevimexcommands.h"
 
 
 #include <coreplugin/actionmanager/actionmanager.h>
@@ -62,6 +63,8 @@
 #include <utils/qtcassert.h>
 #include <utils/savedaction.h>
 
+#include <cpptools/cpptoolsconstants.h>
+
 #include <indenter.h>
 
 #include <QtCore/QDebug>
@@ -73,6 +76,7 @@
 
 #include <QtGui/QMessageBox>
 #include <QtGui/QPlainTextEdit>
+#include <QtGui/QShortcut>
 #include <QtGui/QTextBlock>
 #include <QtGui/QTextCursor>
 #include <QtGui/QTextEdit>
@@ -92,6 +96,7 @@ const char * const MINI_BUFFER            = "TextEditor.FakeVimMiniBuffer";
 const char * const INSTALL_KEY            = "Alt+V,Alt+V";
 const char * const SETTINGS_CATEGORY      = "D.FakeVim";
 const char * const SETTINGS_ID            = "General";
+const char * const SETTINGS_EX_CMDS_ID    = "ExCommands";
 
 } // namespace Constants
 } // namespace FakeVim
@@ -242,6 +247,239 @@ bool FakeVimOptionPage::matches(const QString &s) const
 } // namespace FakeVim
 
 
+///////////////////////////////////////////////////////////////////////
+//
+// FakeVimExCommandsPage
+//
+///////////////////////////////////////////////////////////////////////
+
+struct CommandItem
+{
+    Command *m_cmd;
+    QString m_regex;
+    QTreeWidgetItem *m_item;
+};
+
+Q_DECLARE_METATYPE(CommandItem*);
+
+namespace FakeVim {
+namespace Internal {
+
+static QMap<QString, QRegExp> s_exCommandMap;
+static QMap<QString, QRegExp> s_defaultExCommandMap;
+
+
+class FakeVimExCommandsPage : public Core::IOptionsPage
+{
+    Q_OBJECT
+
+public:
+    FakeVimExCommandsPage() {}
+
+    // IOptionsPage
+    QString id() const { return QLatin1String(Constants::SETTINGS_EX_CMDS_ID); }
+    QString displayName() const { return tr("Ex Command Mapping"); }
+    QString category() const { return QLatin1String(Constants::SETTINGS_CATEGORY); }
+    QString displayCategory() const { return tr("FakeVim"); }
+
+    QWidget *createPage(QWidget *parent);
+    void initialize();
+    void apply() {}
+    void finish() {}
+    virtual bool matches(const QString &) const;
+    bool filter(const QString &f, const QTreeWidgetItem *item);
+
+public slots:
+    void filterChanged(const QString &f);
+    void commandChanged(QTreeWidgetItem *current);
+    void regexChanged();
+    void resetRegex();
+    void removeRegex();
+    void defaultAction();
+
+private:
+    Ui::FakeVimExCommandsPage m_ui;
+    QString m_searchKeywords;
+    void setRegex(const QString &regex);
+    QList<CommandItem *> m_citems;
+};
+
+QWidget *FakeVimExCommandsPage::createPage(QWidget *parent)
+{
+    QWidget *w = new QWidget(parent);
+    m_ui.setupUi(w);
+
+    connect(m_ui.resetButton, SIGNAL(clicked()),
+        this, SLOT(resetRegex()));
+    connect(m_ui.removeButton, SIGNAL(clicked()),
+        this, SLOT(removeRegex()));
+    connect(m_ui.defaultButton, SIGNAL(clicked()),
+        this, SLOT(defaultAction()));
+
+    initialize();
+
+    m_ui.commandList->sortByColumn(0, Qt::AscendingOrder);
+
+    connect(m_ui.filterEdit, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(QString)));
+    connect(m_ui.commandList, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
+        this, SLOT(commandChanged(QTreeWidgetItem *)));
+    connect(m_ui.regexEdit, SIGNAL(textChanged(QString)), this, SLOT(regexChanged()));
+
+    if (m_searchKeywords.isEmpty()) {
+        QTextStream(&m_searchKeywords)
+            << ' ' << m_ui.groupBox->title();
+        m_searchKeywords.remove(QLatin1Char('&'));
+    }
+
+    return w;
+}
+
+void FakeVimExCommandsPage::initialize()
+{
+    Core::ActionManager *am = Core::ICore::instance()->actionManager();
+    QTC_ASSERT(am, return);
+    UniqueIDManager *uidm = UniqueIDManager::instance();
+    QTC_ASSERT(uidm, return);
+
+    foreach (Command *c, am->commands()) {
+        if (c->action() && c->action()->isSeparator())
+            continue;
+
+        CommandItem *ci = new CommandItem;
+        QTreeWidgetItem *item = new QTreeWidgetItem(m_ui.commandList);
+        ci->m_cmd = c;
+        ci->m_item = item;
+        m_citems << ci;
+
+        const QString name = uidm->stringForUniqueIdentifier(c->id());
+        item->setText(0, name);
+
+        if (c->action()) {
+            QString text = c->hasAttribute(Command::CA_UpdateText) && !c->defaultText().isNull() ? c->defaultText() : c->action()->text();
+            text.remove(QRegExp("&(?!&)"));
+            item->setText(1, text);
+        } else {
+            item->setText(1, c->shortcut()->whatsThis());
+        }
+        if (s_exCommandMap.contains(name)) {
+            ci->m_regex = s_exCommandMap[name].pattern();
+        } else {
+            ci->m_regex = "";
+        }
+
+        item->setText(2, ci->m_regex);
+        item->setData(0, Qt::UserRole, qVariantFromValue(ci));
+    }
+
+    commandChanged(0);
+}
+
+void FakeVimExCommandsPage::commandChanged(QTreeWidgetItem *current)
+{
+    if (!current || !current->data(0, Qt::UserRole).isValid()) {
+        m_ui.regexEdit->setText("");
+        m_ui.seqGrp->setEnabled(false);
+        return;
+    }
+    m_ui.seqGrp->setEnabled(true);
+    CommandItem *citem = qVariantValue<CommandItem *>(current->data(0, Qt::UserRole));
+    m_ui.regexEdit->setText(citem->m_regex);
+}
+
+void FakeVimExCommandsPage::filterChanged(const QString &f)
+{
+    for (int i=0; i<m_ui.commandList->topLevelItemCount(); ++i) {
+        QTreeWidgetItem *item = m_ui.commandList->topLevelItem(i);
+        item->setHidden(filter(f, item));
+    }
+}
+
+void FakeVimExCommandsPage::regexChanged()
+{
+    UniqueIDManager *uidm = UniqueIDManager::instance();
+    QTreeWidgetItem *current = m_ui.commandList->currentItem();
+    if (current && current->data(0, Qt::UserRole).isValid()) {
+        CommandItem *citem = qVariantValue<CommandItem *>(current->data(0, Qt::UserRole));
+        citem->m_regex = m_ui.regexEdit->text();
+        current->setText(2, citem->m_regex);
+        s_exCommandMap[uidm->stringForUniqueIdentifier(citem->m_cmd->id())] = QRegExp(citem->m_regex);
+    }
+}
+
+void FakeVimExCommandsPage::setRegex(const QString &regex)
+{
+    m_ui.regexEdit->setText(regex);
+}
+
+bool FakeVimExCommandsPage::filter(const QString &f, const QTreeWidgetItem *item)
+{
+    if (item->childCount() == 0) {
+        if (f.isEmpty())
+            return false;
+        for (int i = 0; i < item->columnCount(); ++i) {
+            if (item->text(i).contains(f, Qt::CaseInsensitive))
+                return false;
+        }
+        return true;
+    }
+
+    bool found = false;
+    for (int i = 0; i < item->childCount(); ++i) {
+        QTreeWidgetItem *citem = item->child(i);
+        if (filter(f, citem)) {
+            citem->setHidden(true);
+        } else {
+            citem->setHidden(false);
+            found = true;
+        }
+    }
+    return !found;
+}
+
+void FakeVimExCommandsPage::resetRegex()
+{
+    UniqueIDManager *uidm = UniqueIDManager::instance();
+    QTreeWidgetItem *current = m_ui.commandList->currentItem();
+    if (current && current->data(0, Qt::UserRole).isValid()) {
+        CommandItem *citem = qVariantValue<CommandItem *>(current->data(0, Qt::UserRole));
+        const QString &name = uidm->stringForUniqueIdentifier(citem->m_cmd->id());
+        if (s_defaultExCommandMap.contains(name))
+            setRegex(s_defaultExCommandMap[name].pattern());
+        else
+            setRegex("");
+    }
+}
+
+void FakeVimExCommandsPage::removeRegex()
+{
+    m_ui.regexEdit->clear();
+}
+
+void FakeVimExCommandsPage::defaultAction()
+{
+    UniqueIDManager *uidm = UniqueIDManager::instance();
+    foreach (CommandItem *item, m_citems) {
+        const QString &name = uidm->stringForUniqueIdentifier(item->m_cmd->id());
+        if (s_defaultExCommandMap.contains(name)) {
+            item->m_regex = s_defaultExCommandMap[name].pattern();
+        } else {
+            item->m_regex = "";
+        }
+        item->m_item->setText(2, item->m_regex);
+        if (item->m_item == m_ui.commandList->currentItem())
+            commandChanged(item->m_item);
+    }
+}
+
+bool FakeVimExCommandsPage::matches(const QString &s) const
+{
+    return m_searchKeywords.contains(s, Qt::CaseInsensitive);
+}
+
+} // namespace Internal
+} // namespace FakeVim
+
+
 ///////////////////////////////////////////////////////////////////////
 //
 // FakeVimPluginPrivate
@@ -295,10 +533,14 @@ signals:
 private:
     FakeVimPlugin *q;
     FakeVimOptionPage *m_fakeVimOptionsPage;
+    FakeVimExCommandsPage *m_fakeVimExCommandsPage;
     QHash<Core::IEditor *, FakeVimHandler *> m_editorToHandler;
 
     void triggerAction(const QString& code);
     void setActionChecked(const QString& code, bool check);
+
+    void readSettings(QSettings *settings);
+    void writeSettings(QSettings *settings);
 };
 
 } // namespace Internal
@@ -308,6 +550,12 @@ FakeVimPluginPrivate::FakeVimPluginPrivate(FakeVimPlugin *plugin)
 {       
     q = plugin;
     m_fakeVimOptionsPage = 0;
+    m_fakeVimExCommandsPage = 0;
+
+    s_defaultExCommandMap[CppTools::Constants::SWITCH_HEADER_SOURCE] = QRegExp("^A$");
+    s_defaultExCommandMap[ProjectExplorer::Constants::BUILD] = QRegExp("^make$");
+    s_defaultExCommandMap["Coreplugin.OutputPane.previtem"] = QRegExp("^(cN(ext)?|cp(revious)?)!?( (.*))?$");
+    s_defaultExCommandMap["Coreplugin.OutputPane.nextitem"] = QRegExp("^cn(ext)?!?( (.*))?$");
 }
 
 FakeVimPluginPrivate::~FakeVimPluginPrivate()
@@ -321,6 +569,11 @@ void FakeVimPluginPrivate::shutdown()
     m_fakeVimOptionsPage = 0;
     theFakeVimSettings()->writeSettings(Core::ICore::instance()->settings());
     delete theFakeVimSettings();
+
+    q->removeObject(m_fakeVimExCommandsPage);
+    delete m_fakeVimExCommandsPage;
+    m_fakeVimExCommandsPage = 0;
+    writeSettings(Core::ICore::instance()->settings());
 }
 
 bool FakeVimPluginPrivate::initialize()
@@ -334,6 +587,10 @@ bool FakeVimPluginPrivate::initialize()
     m_fakeVimOptionsPage = new FakeVimOptionPage;
     q->addObject(m_fakeVimOptionsPage);
     theFakeVimSettings()->readSettings(Core::ICore::instance()->settings());
+
+    m_fakeVimExCommandsPage = new FakeVimExCommandsPage;
+    q->addObject(m_fakeVimExCommandsPage);
+    readSettings(Core::ICore::instance()->settings());
     
     Core::Command *cmd = 0;
     cmd = actionManager->registerAction(theFakeVimSetting(ConfigUseFakeVim),
@@ -365,6 +622,46 @@ bool FakeVimPluginPrivate::initialize()
     return true;
 }
 
+static const char *exCommandMapGroup = "FakeVimExCommand";
+static const char *reKey = "RegEx";
+static const char *idKey = "Command";
+
+void FakeVimPluginPrivate::writeSettings(QSettings *settings)
+{
+    settings->beginWriteArray(QLatin1String(exCommandMapGroup));
+
+    int count = 0;
+    const QMap<QString, QRegExp>::const_iterator end = s_exCommandMap.constEnd();
+    for (QMap<QString, QRegExp>::const_iterator it = s_exCommandMap.constBegin(); it != end; ++it) {
+        const QString &id = it.key();
+        const QRegExp &re = it.value();
+
+        if ((s_defaultExCommandMap.contains(id) && s_defaultExCommandMap[id] != re)
+            || (!s_defaultExCommandMap.contains(id) && !re.pattern().isEmpty())) {
+            settings->setArrayIndex(count);
+            settings->setValue(QLatin1String(idKey), id);
+            settings->setValue(QLatin1String(reKey), re.pattern());
+            ++count;
+        }
+    }
+
+    settings->endArray();
+}
+
+void FakeVimPluginPrivate::readSettings(QSettings *settings)
+{
+    s_exCommandMap = s_defaultExCommandMap;
+
+    int size = settings->beginReadArray(QLatin1String(exCommandMapGroup));
+    for (int i=0; i<size; ++i) {
+        settings->setArrayIndex(i);
+        const QString id = settings->value(QLatin1String(idKey)).toString();
+        const QString re = settings->value(QLatin1String(reKey)).toString();
+        s_exCommandMap[id] = QRegExp(re);
+    }
+    settings->endArray();
+}
+
 void FakeVimPluginPrivate::showSettingsDialog()
 {
     Core::ICore::instance()->showOptionsDialog(QLatin1String(Constants::SETTINGS_CATEGORY),
@@ -610,6 +907,17 @@ void FakeVimPluginPrivate::handleExCommand(const QString &cmd)
         bool forced = cmd.contains(QChar('!'));
         emit delayedQuitAllRequested(forced);
     } else {
+        const QMap<QString, QRegExp>::const_iterator end = s_exCommandMap.constEnd();
+        for (QMap<QString, QRegExp>::const_iterator it = s_exCommandMap.constBegin(); it != end; ++it) {
+            const QString &id = it.key();
+            const QRegExp &re = it.value();
+
+            if (re.indexIn(cmd) != -1) {
+                triggerAction(id);
+                return;
+            }
+        }
+
         handler->showRedMessage(tr("Not an editor command: %1").arg(cmd));
     }
 }