diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index efa11e8769202745ad5f31b12de14e7e0c6317f8..9807f867132614f3b7b856a3401a3f07d595ffda 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -134,7 +134,7 @@ public: int columnsOnScreen() const; int cursorLineInDocument() const; int cursorColumnInDocument() const; - int linesInDocument() const { return m_tc.document()->blockCount(); } + int linesInDocument() const; void scrollToLineInDocument(int line); void moveToFirstNonBlankOnLine(); @@ -143,6 +143,9 @@ public: void handleFfTt(int key); void handleCommand(const QString &cmd); + // helper function for handleCommand. return 1 based line index. + int readLineCode(QString &cmd); + FakeVimHandler *q; Mode m_mode; SubMode m_submode; @@ -663,14 +666,70 @@ void FakeVimHandler::Private::handleExMode(int key, const QString &text) } } -void FakeVimHandler::Private::handleCommand(const QString &cmd) +// 1 based. +int FakeVimHandler::Private::readLineCode(QString &cmd) +{ + //qDebug() << "CMD: " << cmd; + if (cmd.isEmpty()) + return -1; + QChar c = cmd.at(0); + cmd = cmd.mid(1); + if (c == '.') + return cursorLineInDocument() + 1; + if (c == '$') + return linesInDocument(); + if (c == '-') { + int n = readLineCode(cmd); + return cursorLineInDocument() + 1 - (n == -1 ? 1 : n); + } + if (c == '+') { + int n = readLineCode(cmd); + return cursorLineInDocument() + 1 + (n == -1 ? 1 : n); + } + if (c.isDigit()) { + int n = c.unicode() - '0'; + while (!cmd.isEmpty()) { + c = cmd.at(0); + if (!c.isDigit()) + break; + cmd = cmd.mid(1); + n = n * 10 + (c.unicode() - '0'); + } + //qDebug() << "N: " << n; + return n; + } + // not parsed + cmd = c + cmd; + return -1; +} + +void FakeVimHandler::Private::handleCommand(const QString &cmd0) { - static QRegExp reGoto("^(\\d+)$"); + QString cmd = cmd0; + if (cmd.startsWith("%")) + cmd = "1,$" + cmd.mid(1); + + int beginLine = 0; + int endLine = linesInDocument(); + + int line = readLineCode(cmd); + if (line != -1) + beginLine = line; + + if (cmd.startsWith(',')) { + cmd = cmd.mid(1); + line = readLineCode(cmd); + if (line != -1) + endLine = line; + } + + //qDebug() << "RANGE: " << beginLine << endLine << cmd << cmd0; + static QRegExp reWrite("^w!?( (.*))?$"); - if (reGoto.indexIn(cmd) != -1) { - int n = reGoto.cap(1).toInt(); + + if (cmd.isEmpty()) { m_tc.setPosition(m_tc.block().document() - ->findBlockByNumber(n - 1).position()); + ->findBlockByNumber(beginLine - 1).position()); showMessage(QString()); } else if (cmd == "q!" || cmd == "q") { if (m_textedit) @@ -705,6 +764,8 @@ void FakeVimHandler::Private::handleCommand(const QString &cmd) QTextStream ts(&file); EDITOR(setPlainText(ts.readAll())); showMessage(QString()); + } else { + showMessage("E492: Not an editor command: " + cmd0); } } @@ -878,6 +939,11 @@ int FakeVimHandler::Private::cursorColumnInDocument() const return m_tc.position() - m_tc.block().position(); } +int FakeVimHandler::Private::linesInDocument() const +{ + return m_tc.isNull() ? 0 : m_tc.document()->blockCount(); +} + void FakeVimHandler::Private::scrollToLineInDocument(int line) { // FIXME: works only for QPlainTextEdit