diff --git a/src/resources/vnote.ini b/src/resources/vnote.ini index 27d96791..00555dd1 100644 --- a/src/resources/vnote.ini +++ b/src/resources/vnote.ini @@ -262,6 +262,10 @@ key_mode=0 ; Enable smart input method in Vim mode (disable IM in non-Insert modes) enable_smart_im_in_vim_mode=true +; Leader key in Vim mode +; Should be one character long +vim_leader_key=" " + [export] ; Path of the wkhtmltopdf tool wkhtmltopdf=wkhtmltopdf diff --git a/src/utils/vvim.cpp b/src/utils/vvim.cpp index 32ed8001..0551791f 100644 --- a/src/utils/vvim.cpp +++ b/src/utils/vvim.cpp @@ -83,6 +83,68 @@ static QChar keyToChar(int p_key, int p_modifiers) return ch; } +#define ADDCHAR(x, y) case (x): {p_key = (y); break;} +#define ADDCHAR_SHIFT(x, y) case (x): {p_key = (y); p_modifiers = Qt::ShiftModifier; break;} + +static void charToKey(const QChar &p_char, int &p_key, int &p_modifiers) +{ + p_modifiers = Qt::NoModifier; + + ushort ucode = p_char.unicode(); + if (ucode >= '0' && ucode <= '9') { + p_key = Qt::Key_0 + ucode - '0'; + return; + } else if (ucode >= 'a' && ucode <= 'z') { + p_key = Qt::Key_A + ucode - 'a'; + return; + } else if (ucode >= 'A' && ucode <= 'Z') { + p_key = Qt::Key_A + ucode - 'A'; + p_modifiers = Qt::ShiftModifier; + return; + } + + switch (p_char.unicode()) { + ADDCHAR('\t', Qt::Key_Tab); + ADDCHAR(' ', Qt::Key_Space); + ADDCHAR_SHIFT('!', Qt::Key_Exclam); + ADDCHAR_SHIFT('"', Qt::Key_QuoteDbl); + ADDCHAR_SHIFT('#', Qt::Key_NumberSign); + ADDCHAR_SHIFT('$', Qt::Key_Dollar); + ADDCHAR_SHIFT('%', Qt::Key_Percent); + ADDCHAR_SHIFT('&', Qt::Key_Ampersand); + ADDCHAR('\'', Qt::Key_Apostrophe); + ADDCHAR_SHIFT('(', Qt::Key_ParenLeft); + ADDCHAR_SHIFT(')', Qt::Key_ParenRight); + ADDCHAR_SHIFT('*', Qt::Key_Asterisk); + ADDCHAR_SHIFT('+', Qt::Key_Plus); + ADDCHAR(',', Qt::Key_Comma); + ADDCHAR('-', Qt::Key_Minus); + ADDCHAR('.', Qt::Key_Period); + ADDCHAR('/', Qt::Key_Slash); + ADDCHAR_SHIFT(':', Qt::Key_Colon); + ADDCHAR(';', Qt::Key_Semicolon); + ADDCHAR_SHIFT('<', Qt::Key_Less); + ADDCHAR('=', Qt::Key_Equal); + ADDCHAR_SHIFT('>', Qt::Key_Greater); + ADDCHAR_SHIFT('?', Qt::Key_Question); + ADDCHAR_SHIFT('@', Qt::Key_At); + ADDCHAR('[', Qt::Key_BracketLeft); + ADDCHAR('\\', Qt::Key_Backslash); + ADDCHAR(']', Qt::Key_BracketRight); + ADDCHAR_SHIFT('^', Qt::Key_AsciiCircum); + ADDCHAR_SHIFT('_', Qt::Key_Underscore); + ADDCHAR('`', Qt::Key_QuoteLeft); + ADDCHAR_SHIFT('{', Qt::Key_BraceLeft); + ADDCHAR_SHIFT('|', Qt::Key_Bar); + ADDCHAR_SHIFT('}', Qt::Key_BraceRight); + ADDCHAR_SHIFT('~', Qt::Key_AsciiTilde); + + default: + p_key = -1; + break; + } +} + static QString keyToString(int p_key, int p_modifiers) { QChar ch = keyToChar(p_key, p_modifiers); @@ -114,6 +176,8 @@ VVim::VVim(VEditor *p_editor) setMode(VimMode::Normal); + initLeaderKey(); + initRegisters(); connect(m_editor->object(), &VEditorObject::mousePressed, @@ -124,6 +188,17 @@ VVim::VVim(VEditor *p_editor) this, &VVim::handleMouseReleased); } +void VVim::initLeaderKey() +{ + QChar ch = g_config->getVimLeaderKey(); + Q_ASSERT(!ch.isNull()); + + int key, modifiers; + charToKey(ch, key, modifiers); + m_leaderKey = Key(key, modifiers); + qDebug() << "Vim leader key" << ch << key << modifiers; +} + // Set @p_cursor's position specified by @p_positionInBlock. // If @p_positionInBlock is bigger than the block's length, move to the end of block. // Need to setTextCursor() after calling this. diff --git a/src/utils/vvim.h b/src/utils/vvim.h index ae649475..978ac711 100644 --- a/src/utils/vvim.h +++ b/src/utils/vvim.h @@ -678,6 +678,9 @@ private: // of @p_cursor. void expandSelectionToWholeLines(QTextCursor &p_cursor); + // Init leader key from config. + void initLeaderKey(); + // Init m_registers. // Currently supported registers: // a-z, A-Z (append to a-z), ", +, _ diff --git a/src/vconfigmanager.cpp b/src/vconfigmanager.cpp index a049fceb..a5e40a53 100644 --- a/src/vconfigmanager.cpp +++ b/src/vconfigmanager.cpp @@ -330,6 +330,17 @@ void VConfigManager::initEditorConfigs() m_enableSmartImInVimMode = getConfigFromSettings("editor", "enable_smart_im_in_vim_mode").toBool(); + + QString tmpLeader = getConfigFromSettings("editor", + "vim_leader_key").toString(); + if (tmpLeader.isEmpty()) { + m_vimLeaderKey = QChar(' '); + } else { + m_vimLeaderKey = tmpLeader[0]; + if (m_vimLeaderKey.isNull()) { + m_vimLeaderKey = QChar(' '); + } + } } void VConfigManager::initSettings() diff --git a/src/vconfigmanager.h b/src/vconfigmanager.h index a30dcd4e..9689f717 100644 --- a/src/vconfigmanager.h +++ b/src/vconfigmanager.h @@ -545,6 +545,8 @@ public: const QString &getImageNamePrefix() const; + QChar getVimLeaderKey() const; + private: // Look up a config from user and default settings. QVariant getConfigFromSettings(const QString §ion, const QString &key) const; @@ -979,6 +981,9 @@ private: // Max number of tag labels to display. int m_maxNumOfTagLabels; + // Vim leader key. + QChar m_vimLeaderKey; + // The name of the config file in each directory. static const QString c_dirConfigFile; @@ -2529,4 +2534,9 @@ inline int VConfigManager::getMaxNumOfTagLabels() const { return m_maxNumOfTagLabels; } + +inline QChar VConfigManager::getVimLeaderKey() const +{ + return m_vimLeaderKey; +} #endif // VCONFIGMANAGER_H