diff options
| -rw-r--r-- | include/keymap/KeySeqParser.hpp | 20 | ||||
| -rw-r--r-- | spec/KeySeqParserSpec.cpp | 52 | ||||
| -rw-r--r-- | src/keymap/KeySeqParser.cpp | 79 |
3 files changed, 151 insertions, 0 deletions
diff --git a/include/keymap/KeySeqParser.hpp b/include/keymap/KeySeqParser.hpp new file mode 100644 index 0000000..aefcb62 --- /dev/null +++ b/include/keymap/KeySeqParser.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include <QtCore/qnamespace.h> +#include <QtCore> + +struct KeyChord { + Qt::KeyboardModifiers mod; + Qt::Key key; +}; +bool operator==(const KeyChord a, const KeyChord b); + +class KeySeqParser { +public: + KeySeqParser(); + + QList<KeyChord> parse(QString keySequence); + +private: + Qt::Key parseKey(QString keyName); +}; diff --git a/spec/KeySeqParserSpec.cpp b/spec/KeySeqParserSpec.cpp new file mode 100644 index 0000000..a29c97e --- /dev/null +++ b/spec/KeySeqParserSpec.cpp @@ -0,0 +1,52 @@ +#include "testUtils.h" +#include <QtCore/qnamespace.h> +#include <QtCore> + +#include "keymap/KeySeqParser.hpp" + +class KeySeqParserSpec : public QObject { + Q_OBJECT + +private slots: + void testThings() { + context("when mix of upper/lower cases"); + it("parses keys ignoring the casing") { + KeySeqParser parser; + + QList<KeyChord> keys = parser.parse("<C-tab><c-tAb><c-Tab>"); + + QList<KeyChord> expectedKeys = { + {.mod = Qt::ControlModifier, .key = Qt::Key_Tab}, + {.mod = Qt::ControlModifier, .key = Qt::Key_Tab}, + {.mod = Qt::ControlModifier, .key = Qt::Key_Tab}, + }; + QCOMPARE(keys, expectedKeys); + } + + context("when input contains individual keys"); + it("parses the characters") { + KeySeqParser parser; + + QList<KeyChord> keys = parser.parse("ab<c><s><sPace><tab><esC>z"); + + for (auto &k : keys) { + qDebug() << k.key << k.mod; + } + + QList<KeyChord> expectedKeys = { + {.mod = Qt::NoModifier, .key = Qt::Key_A}, + {.mod = Qt::NoModifier, .key = Qt::Key_B}, + {.mod = Qt::NoModifier, .key = Qt::Key_C}, + {.mod = Qt::NoModifier, .key = Qt::Key_S}, + {.mod = Qt::NoModifier, .key = Qt::Key_Space}, + {.mod = Qt::NoModifier, .key = Qt::Key_Tab}, + {.mod = Qt::NoModifier, .key = Qt::Key_Escape}, + {.mod = Qt::NoModifier, .key = Qt::Key_Z}, + }; + QCOMPARE(keys, expectedKeys); + } + } +}; + +QTEST_REGISTER(KeySeqParserSpec) +#include "KeySeqParserSpec.moc" diff --git a/src/keymap/KeySeqParser.cpp b/src/keymap/KeySeqParser.cpp new file mode 100644 index 0000000..c5534eb --- /dev/null +++ b/src/keymap/KeySeqParser.cpp @@ -0,0 +1,79 @@ +#include <QWidget> +#include <QtCore> +#include <algorithm> + +#include "keymap/KeySeqParser.hpp" + +bool operator==(const KeyChord a, const KeyChord b) { + return a.mod == b.mod && a.key == b.key; +} + +KeySeqParser::KeySeqParser() {} + +QList<KeyChord> KeySeqParser::parse(QString keySequence) { + QList<KeyChord> keyChords; + KeyChord lastKey; + + // TODO: Refactor + // TODO: Support <C-S-t> + keySequence = keySequence.toLower(); + while (!keySequence.isEmpty()) { + int skipCount = 1; + if (keySequence.startsWith("<c-")) { + int nextClosing = keySequence.indexOf('>'); + auto keyName = keySequence.sliced(3, nextClosing - 3); + lastKey.mod = lastKey.mod | Qt::KeyboardModifier::ControlModifier; + lastKey.key = parseKey(keyName); + skipCount = nextClosing + 1; + } else if (keySequence.startsWith("<s-")) { + int nextClosing = keySequence.indexOf('>'); + auto keyName = keySequence.sliced(3, nextClosing - 3); + lastKey.mod = lastKey.mod | Qt::KeyboardModifier::ShiftModifier; + lastKey.key = parseKey(keyName); + skipCount = nextClosing + 1; + } else if (keySequence.startsWith("<")) { + int nextClosing = keySequence.indexOf('>'); + auto keyName = keySequence.sliced(1, nextClosing - 1); + lastKey.mod = Qt::KeyboardModifier::NoModifier; + lastKey.key = parseKey(keyName); + skipCount = nextClosing + 1; + } else { + auto keyName = keySequence.first(1); + lastKey.mod = Qt::KeyboardModifier::NoModifier; + lastKey.key = parseKey(keyName); + } + + keySequence.slice(std::max(1, skipCount)); + keyChords.push_back(lastKey); + lastKey = KeyChord(); + } + + return keyChords; +} + +Qt::Key KeySeqParser::parseKey(QString keyName) { + if (keyName.length() == 0) + return Qt::Key_T; // TODO: tmp + + if (keyName.length() == 1) { + char c = keyName.toStdString().at(0); + return Qt::Key(Qt::Key_A + (c - 'a')); + } + + if (keyName == "space") + return Qt::Key_Space; + + if (keyName == "cr") + return Qt::Key_Return; + + if (keyName == "esc") + return Qt::Key_Escape; + + if (keyName == "bs") + return Qt::Key_Backspace; + + if (keyName == "tab") + return Qt::Key_Tab; + + return Qt::Key_T; +} |
