forked from qt-creator/qt-creator
famevim: make <C-.> etc work in mappings
This commit is contained in:
@@ -326,7 +326,7 @@ public:
|
|||||||
explicit Input(QChar x)
|
explicit Input(QChar x)
|
||||||
: m_key(x.unicode()), m_xkey(x.unicode()), m_modifiers(0), m_text(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_key(k), m_modifiers(m), m_text(t)
|
||||||
{
|
{
|
||||||
// m_xkey is only a cache.
|
// m_xkey is only a cache.
|
||||||
@@ -360,13 +360,21 @@ public:
|
|||||||
|
|
||||||
bool operator==(const Input &a) const
|
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; }
|
QString text() const { return m_text; }
|
||||||
|
|
||||||
int key() const { return m_key; }
|
int key() const { return m_key; }
|
||||||
|
|
||||||
|
QDebug dump(QDebug ts) const
|
||||||
|
{
|
||||||
|
return ts << m_key << '-' << m_modifiers << '-'
|
||||||
|
<< quoteUnprintable(m_text);
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
int m_key;
|
int m_key;
|
||||||
int m_xkey;
|
int m_xkey;
|
||||||
@@ -374,15 +382,48 @@ private:
|
|||||||
QString m_text;
|
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<Input>
|
||||||
{
|
{
|
||||||
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<Input> Inputs;
|
|
||||||
|
|
||||||
// Mappings for a specific mode.
|
// Mappings for a specific mode.
|
||||||
class ModeMapping : private QList<QPair<Inputs, Inputs> >
|
class ModeMapping : public QList<QPair<Inputs, Inputs> >
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ModeMapping() { test(); }
|
ModeMapping() { test(); }
|
||||||
@@ -412,24 +453,24 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns 'false' if more input input is needed to decide whether a
|
// Returns 'false' if more input is needed to decide whether a mapping
|
||||||
// mapping needs to be applied. If a decision can be made, return 'true',
|
// needs to be applied. If a decision can be made, return 'true',
|
||||||
// and replace *input with the mapped data.
|
// and replace *input with the mapped data.
|
||||||
bool mappingDone(Inputs *input) const
|
bool mappingDone(Inputs *inputs) const
|
||||||
{
|
{
|
||||||
Q_UNUSED(input);
|
|
||||||
// FIXME: inefficient.
|
// FIXME: inefficient.
|
||||||
for (int i = 0; i != size(); ++i) {
|
for (int i = 0; i != size(); ++i) {
|
||||||
|
const Inputs &haystack = at(i).first;
|
||||||
// A mapping
|
// A mapping
|
||||||
if (startsWith(at(i).first, *input)) {
|
if (startsWith(haystack, *inputs)) {
|
||||||
if (at(i).first.size() != input->size())
|
if (haystack.size() != inputs->size())
|
||||||
return false; // This can be extended.
|
return false; // This can be extended.
|
||||||
// Actual mapping.
|
// Actual mapping.
|
||||||
*input = at(i).second;
|
*inputs = at(i).second;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// No extensible mapping found. Use input as-is.
|
// No extensible mapping found. Use inputs as-is.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -440,7 +481,7 @@ private:
|
|||||||
if (needle.size() > haystack.size())
|
if (needle.size() > haystack.size())
|
||||||
return false;
|
return false;
|
||||||
for (int i = 0; i != needle.size(); ++i) {
|
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 false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -764,7 +805,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Input.
|
// Input.
|
||||||
QVector<Input> pendingInput;
|
Inputs pendingInput;
|
||||||
int inputTimer;
|
int inputTimer;
|
||||||
|
|
||||||
// Repetition.
|
// Repetition.
|
||||||
@@ -1017,6 +1058,7 @@ void FakeVimHandler::Private::restoreWidget(int tabSize)
|
|||||||
|
|
||||||
EventResult FakeVimHandler::Private::handleKey(const Input &input)
|
EventResult FakeVimHandler::Private::handleKey(const Input &input)
|
||||||
{
|
{
|
||||||
|
KEY_DEBUG("HANDLE INPUT: " << input);
|
||||||
if (m_mode == ExMode)
|
if (m_mode == ExMode)
|
||||||
return handleExMode(input);
|
return handleExMode(input);
|
||||||
if (m_subsubmode == SearchSubSubMode)
|
if (m_subsubmode == SearchSubSubMode)
|
||||||
@@ -2821,12 +2863,13 @@ bool FakeVimHandler::Private::handleExSubstituteCommand(const QString &line)
|
|||||||
|
|
||||||
bool FakeVimHandler::Private::handleExMapCommand(const QString &line) // :map
|
bool FakeVimHandler::Private::handleExMapCommand(const QString &line) // :map
|
||||||
{
|
{
|
||||||
int pos1 = line.indexOf(QLatin1Char(' '));
|
const int pos1 = line.indexOf(QLatin1Char(' '));
|
||||||
if (pos1 == -1)
|
const int pos2 = line.indexOf(QLatin1Char(' '), pos1 + 1);
|
||||||
return false;
|
if (pos1 == -1 || pos2 == -1) {
|
||||||
int pos2 = line.indexOf(QLatin1Char(' '), pos1 + 1);
|
// FIXME: Dump mappings here.
|
||||||
if (pos2 == -1)
|
qDebug() << g.mappings;
|
||||||
return false;
|
return true;;
|
||||||
|
}
|
||||||
|
|
||||||
QByteArray modes;
|
QByteArray modes;
|
||||||
enum Type { Map, Noremap, Unmap } type;
|
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 lhs = line.mid(pos1 + 1, pos2 - pos1 - 1);
|
||||||
QString rhs = line.mid(pos2 + 1);
|
QString rhs = line.mid(pos2 + 1);
|
||||||
Inputs key;
|
Inputs key;
|
||||||
foreach (QChar c, lhs)
|
key.parseFrom(lhs);
|
||||||
key.append(Input(c));
|
|
||||||
//qDebug() << "MAPPING: " << modes << lhs << rhs;
|
//qDebug() << "MAPPING: " << modes << lhs << rhs;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Unmap:
|
case Unmap:
|
||||||
@@ -2885,9 +2927,7 @@ bool FakeVimHandler::Private::handleExMapCommand(const QString &line) // :map
|
|||||||
rhs = rhs; // FIXME: expand rhs.
|
rhs = rhs; // FIXME: expand rhs.
|
||||||
// Fall through.
|
// Fall through.
|
||||||
case Noremap: {
|
case Noremap: {
|
||||||
Inputs inputs;
|
Inputs inputs(rhs);
|
||||||
foreach (QChar c, rhs)
|
|
||||||
inputs.append(Input(c));
|
|
||||||
foreach (char c, modes)
|
foreach (char c, modes)
|
||||||
g.mappings[c].insert(key, inputs);
|
g.mappings[c].insert(key, inputs);
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user