diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp index 0612b73fce7..0e8af01c256 100644 --- a/src/plugins/fakevim/fakevimhandler.cpp +++ b/src/plugins/fakevim/fakevimhandler.cpp @@ -693,6 +693,33 @@ static void setClipboardData(const QString &content, RangeMode mode, clipboard->setMimeData(data, clipboardMode); } +static QByteArray toLocalEncoding(const QString &text) +{ + return HostOsInfo::isWindowsHost() ? QString(text).replace(_("\n"), _("\r\n")).toLocal8Bit() + : text.toLocal8Bit(); +} + +static QString fromLocalEncoding(const QByteArray &data) +{ + return HostOsInfo::isWindowsHost() ? QString::fromLocal8Bit(data).replace(_("\n"), _("\r\n")) + : QString::fromLocal8Bit(data); +} + +static QString getProcessOutput(const QString &command, const QString &input) +{ + QProcess proc; + proc.start(command); + proc.waitForStarted(); + proc.write(toLocalEncoding(input)); + proc.closeWriteChannel(); + + // FIXME: Process should be interruptable by user. + // Solution is to create a QObject for each process and emit finished state. + proc.waitForFinished(); + + return fromLocalEncoding(proc.readAllStandardOutput()); +} + static const QMap &vimKeyNames() { static QMap k; @@ -804,6 +831,11 @@ QString Range::toString() const .arg(rangemode); } +bool Range::isValid() const +{ + return beginPos >= 0 && endPos >= 0; +} + QDebug operator<<(QDebug ts, const Range &range) { return ts << '[' << range.beginPos << ',' << range.endPos << ']'; @@ -5038,9 +5070,6 @@ bool FakeVimHandler::Private::parseExCommmand(QString *line, ExCommand *cmd) if (line->isEmpty()) return false; - // remove leading colons and spaces - line->remove(QRegExp(_("^\\s*(:+\\s*)*"))); - // parse range first if (!parseLineRange(line, cmd)) return false; @@ -5093,6 +5122,15 @@ bool FakeVimHandler::Private::parseExCommmand(QString *line, ExCommand *cmd) bool FakeVimHandler::Private::parseLineRange(QString *line, ExCommand *cmd) { + // remove leading colons and spaces + line->remove(QRegExp(_("^\\s*(:+\\s*)*"))); + + // special case ':!...' (use invalid range) + if (line->startsWith(QLatin1Char('!'))) { + cmd->range = Range(); + return true; + } + // FIXME: that seems to be different for %w and %s if (line->startsWith(QLatin1Char('%'))) line->replace(0, 1, _("1,$")); @@ -5655,22 +5693,15 @@ bool FakeVimHandler::Private::handleExBangCommand(const ExCommand &cmd) // :! if (!cmd.cmd.isEmpty() || !cmd.hasBang) return false; - setCurrentRange(cmd.range); - int targetPosition = firstPositionInLine(lineForPosition(cmd.range.beginPos)); - QString command = QString(cmd.cmd.mid(1) + QLatin1Char(' ') + cmd.args).trimmed(); - QString text = selectText(cmd.range); - QProcess proc; - proc.start(command); - proc.waitForStarted(); - if (HostOsInfo::isWindowsHost()) - text.replace(_("\n"), _("\r\n")); - proc.write(text.toUtf8()); - proc.closeWriteChannel(); - proc.waitForFinished(); - QString result = QString::fromUtf8(proc.readAllStandardOutput()); - if (text.isEmpty()) { - emit q->extraInformationChanged(result); - } else { + bool replaceText = cmd.range.isValid(); + const QString command = QString(cmd.cmd.mid(1) + QLatin1Char(' ') + cmd.args).trimmed(); + const QString input = replaceText ? selectText(cmd.range) : QString(); + + const QString result = getProcessOutput(command, input); + + if (replaceText) { + setCurrentRange(cmd.range); + int targetPosition = firstPositionInLine(lineForPosition(cmd.range.beginPos)); beginEditBlock(); removeText(currentRange()); insertText(result); @@ -5679,8 +5710,11 @@ bool FakeVimHandler::Private::handleExBangCommand(const ExCommand &cmd) // :! leaveVisualMode(); //qDebug() << "FILTER: " << command; showMessage(MessageInfo, FakeVimHandler::tr("%n lines filtered.", 0, - text.count(QLatin1Char('\n')))); + input.count(QLatin1Char('\n')))); + } else if (!result.isEmpty()) { + emit q->extraInformationChanged(result); } + return true; } diff --git a/src/plugins/fakevim/fakevimhandler.h b/src/plugins/fakevim/fakevimhandler.h index 3af38bd8b76..e6a1320b5ac 100644 --- a/src/plugins/fakevim/fakevimhandler.h +++ b/src/plugins/fakevim/fakevimhandler.h @@ -52,6 +52,7 @@ struct Range Range(); Range(int b, int e, RangeMode m = RangeCharMode); QString toString() const; + bool isValid() const; int beginPos; int endPos;