diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp index 67d984f1d8a..e160247b560 100644 --- a/src/plugins/fakevim/fakevimhandler.cpp +++ b/src/plugins/fakevim/fakevimhandler.cpp @@ -326,7 +326,7 @@ public: explicit Input(QChar x) : m_key(x.unicode()), m_xkey(x.unicode()), m_modifiers(0), m_text(x) {} - Input(int k, int m, QString t) + Input(int k, int m, const QString &t) : m_key(k), m_modifiers(m), m_text(t) { // m_xkey is only a cache. @@ -360,13 +360,21 @@ public: bool operator==(const Input &a) const { - return a.m_key == m_key && m_text == a.m_text; + return a.m_key == m_key && a.m_modifiers == m_modifiers + && m_text == a.m_text; } + bool operator!=(const Input &a) const { return !operator==(a); } + QString text() const { return m_text; } int key() const { return m_key; } + QDebug dump(QDebug ts) const + { + return ts << m_key << '-' << m_modifiers << '-' + << quoteUnprintable(m_text); + } private: int m_key; int m_xkey; @@ -374,15 +382,48 @@ private: QString m_text; }; -QDebug &operator<<(QDebug &ts, const Input &input) +QDebug operator<<(QDebug ts, const Input &input) { return input.dump(ts); } + +class Inputs : public QVector { - return ts << input.text() << input.key(); +public: + Inputs() {} + explicit Inputs(const QString &str) { parseFrom(str); } + void parseFrom(const QString &str); +}; + + +void Inputs::parseFrom(const QString &str) +{ + const int n = str.size(); + for (int i = 0; i < n; ++i) { + uint c0 = str.at(i).unicode(), c1 = 0, c2 = 0, c3 = 0, c4 = 0, c5 = 0; + if (i + 1 < n) + c1 = str.at(i + 1).unicode(); + if (i + 2 < n) + c2 = str.at(i + 2).unicode(); + if (i + 3 < n) + c3 = str.at(i + 3).unicode(); + if (i + 4 < n) + c4 = str.at(i + 4).unicode(); + if (i + 5 < n) + c5 = str.at(i + 5).unicode(); + if (c0 == '<') { + if ((c1 == 'C' || c1 == 'c') && c2 == '-' && c4 == '>') { + uint c = (c3 < 90 ? c3 : c3 - 32); + append(Input(c, Qt::ControlModifier, QString(QChar(c - 64)))); + i += 4; + } else { + append(Input(QLatin1Char(c0))); + } + } else { + append(Input(QLatin1Char(c0))); + } + } } -typedef QVector Inputs; - // Mappings for a specific mode. -class ModeMapping : private QList > +class ModeMapping : public QList > { public: ModeMapping() { test(); } @@ -412,24 +453,24 @@ public: } } - // Returns 'false' if more input input is needed to decide whether a - // mapping needs to be applied. If a decision can be made, return 'true', + // Returns 'false' if more input is needed to decide whether a mapping + // needs to be applied. If a decision can be made, return 'true', // and replace *input with the mapped data. - bool mappingDone(Inputs *input) const + bool mappingDone(Inputs *inputs) const { - Q_UNUSED(input); // FIXME: inefficient. for (int i = 0; i != size(); ++i) { + const Inputs &haystack = at(i).first; // A mapping - if (startsWith(at(i).first, *input)) { - if (at(i).first.size() != input->size()) + if (startsWith(haystack, *inputs)) { + if (haystack.size() != inputs->size()) return false; // This can be extended. // Actual mapping. - *input = at(i).second; + *inputs = at(i).second; return true; } } - // No extensible mapping found. Use input as-is. + // No extensible mapping found. Use inputs as-is. return true; } @@ -440,7 +481,7 @@ private: if (needle.size() > haystack.size()) return false; for (int i = 0; i != needle.size(); ++i) { - if (needle.at(i).text() != haystack.at(i).text()) + if (needle.at(i) != haystack.at(i)) return false; } return true; @@ -764,7 +805,7 @@ public: } // Input. - QVector pendingInput; + Inputs pendingInput; int inputTimer; // Repetition. @@ -1017,6 +1058,7 @@ void FakeVimHandler::Private::restoreWidget(int tabSize) EventResult FakeVimHandler::Private::handleKey(const Input &input) { + KEY_DEBUG("HANDLE INPUT: " << input); if (m_mode == ExMode) return handleExMode(input); if (m_subsubmode == SearchSubSubMode) @@ -2821,12 +2863,13 @@ bool FakeVimHandler::Private::handleExSubstituteCommand(const QString &line) bool FakeVimHandler::Private::handleExMapCommand(const QString &line) // :map { - int pos1 = line.indexOf(QLatin1Char(' ')); - if (pos1 == -1) - return false; - int pos2 = line.indexOf(QLatin1Char(' '), pos1 + 1); - if (pos2 == -1) - return false; + const int pos1 = line.indexOf(QLatin1Char(' ')); + const int pos2 = line.indexOf(QLatin1Char(' '), pos1 + 1); + if (pos1 == -1 || pos2 == -1) { + // FIXME: Dump mappings here. + qDebug() << g.mappings; + return true;; + } QByteArray modes; enum Type { Map, Noremap, Unmap } type; @@ -2872,8 +2915,7 @@ bool FakeVimHandler::Private::handleExMapCommand(const QString &line) // :map QString lhs = line.mid(pos1 + 1, pos2 - pos1 - 1); QString rhs = line.mid(pos2 + 1); Inputs key; - foreach (QChar c, lhs) - key.append(Input(c)); + key.parseFrom(lhs); //qDebug() << "MAPPING: " << modes << lhs << rhs; switch (type) { case Unmap: @@ -2885,9 +2927,7 @@ bool FakeVimHandler::Private::handleExMapCommand(const QString &line) // :map rhs = rhs; // FIXME: expand rhs. // Fall through. case Noremap: { - Inputs inputs; - foreach (QChar c, rhs) - inputs.append(Input(c)); + Inputs inputs(rhs); foreach (char c, modes) g.mappings[c].insert(key, inputs); break;