diff --git a/src/libs/utils/synchronousprocess.cpp b/src/libs/utils/synchronousprocess.cpp index 52033ff0bd3e4bbd77c56cb0e86527d8dd8d1b29..ba68b0871005db62c53939f7858b8950c7d57fc6 100644 --- a/src/libs/utils/synchronousprocess.cpp +++ b/src/libs/utils/synchronousprocess.cpp @@ -476,8 +476,8 @@ void SynchronousProcess::stdErrReady() QString SynchronousProcess::convertOutput(const QByteArray &ba) const { - QString output = d->m_codec ? d->m_codec->toUnicode(ba) : QString::fromLocal8Bit(ba.constData(), ba.size()); - return output.remove(QLatin1Char('\r')); + return normalizeNewlines(d->m_codec ? d->m_codec->toUnicode(ba) + : QString::fromLocal8Bit(ba.constData(), ba.size())); } void SynchronousProcess::processStdOut(bool emitSignals) @@ -676,6 +676,25 @@ QString SynchronousProcess::locateBinary(const QString &path, const QString &bin return QString(); } +QString SynchronousProcess::normalizeNewlines(const QString &text) +{ + const QChar cr(QLatin1Char('\r')); + const QChar lf(QLatin1Char('\n')); + QString res; + res.reserve(text.size()); + for (int i = 0, count = text.size(); i < count; ++i) { + const QChar c = text.at(i); + if (c == cr) { + res += lf; + if (i + 1 < count && text.at(i + 1) == lf) + ++i; + } else { + res += c; + } + } + return res; +} + QString SynchronousProcess::locateBinary(const QString &binary) { const QByteArray path = qgetenv("PATH"); diff --git a/src/libs/utils/synchronousprocess.h b/src/libs/utils/synchronousprocess.h index 6db6e86841d346f20c156b27a858c00d862436b6..9172d8be58b59a0c23ae7dfa4263bc2caa27c5b0 100644 --- a/src/libs/utils/synchronousprocess.h +++ b/src/libs/utils/synchronousprocess.h @@ -138,6 +138,8 @@ public: static QString locateBinary(const QString &binary); static QString locateBinary(const QString &path, const QString &binary); + static QString normalizeNewlines(const QString &text); + signals: void stdOut(const QByteArray &data, bool firstTime); void stdErr(const QByteArray &data, bool firstTime); diff --git a/src/plugins/coreplugin/outputwindow.cpp b/src/plugins/coreplugin/outputwindow.cpp index 2c5499571efce3dc3a68ff4712ba74acae7a31ff..8e70dea29b41e45ac34a634982cc570c728d5a0c 100644 --- a/src/plugins/coreplugin/outputwindow.cpp +++ b/src/plugins/coreplugin/outputwindow.cpp @@ -33,6 +33,8 @@ #include "coreconstants.h" #include "icore.h" +#include <utils/synchronousprocess.h> + #include <QAction> #include <QScrollBar> @@ -200,8 +202,7 @@ void OutputWindow::setMaxLineCount(int count) void OutputWindow::appendMessage(const QString &output, OutputFormat format) { - QString out = output; - out.remove(QLatin1Char('\r')); + const QString out = Utils::SynchronousProcess::normalizeNewlines(output); setMaximumBlockCount(m_maxLineCount); const bool atBottom = isScrollbarAtBottom(); @@ -251,8 +252,7 @@ void OutputWindow::appendMessage(const QString &output, OutputFormat format) // TODO rename void OutputWindow::appendText(const QString &textIn, const QTextCharFormat &format) { - QString text = textIn; - text.remove(QLatin1Char('\r')); + const QString text = Utils::SynchronousProcess::normalizeNewlines(textIn); if (m_maxLineCount > 0 && document()->blockCount() >= m_maxLineCount) return; const bool atBottom = isScrollbarAtBottom(); diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 7dab68eba60b16e3b392e380970ca25c3693d263..c7fe23bc01a99f68099ad32c620f769c4527b567 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -744,9 +744,7 @@ Core::IEditor *locateEditor(const char *property, const QString &entry) // Return converted command output, remove '\r' read on Windows static inline QString commandOutputFromLocal8Bit(const QByteArray &a) { - QString output = QString::fromLocal8Bit(a); - output.remove(QLatin1Char('\r')); - return output; + return Utils::SynchronousProcess::normalizeNewlines(QString::fromLocal8Bit(a)); } // Return converted command output split into lines @@ -3398,7 +3396,7 @@ QString GitClient::readConfig(const QString &workingDirectory, const QStringList VcsBasePlugin::SuppressCommandLogging)) return QString(); if (Utils::HostOsInfo::isWindowsHost()) - return QString::fromUtf8(outputText).remove(QLatin1Char('\r')); + return Utils::SynchronousProcess::normalizeNewlines(QString::fromUtf8(outputText)); return commandOutputFromLocal8Bit(outputText); } diff --git a/src/plugins/mercurial/mercurialclient.cpp b/src/plugins/mercurial/mercurialclient.cpp index 3bb4ea9e55d0730e294482585958c1a32bd594ec..274cd57a651f6ac44121871e0c176722fcd4abd5 100644 --- a/src/plugins/mercurial/mercurialclient.cpp +++ b/src/plugins/mercurial/mercurialclient.cpp @@ -187,8 +187,8 @@ QStringList MercurialClient::parentRevisionsSync(const QString &workingDirectory QByteArray outputData; if (!vcsFullySynchronousExec(workingDirectory, args, &outputData)) return QStringList(); - QString output = QString::fromLocal8Bit(outputData); - output.remove(QLatin1Char('\r')); + const QString output = Utils::SynchronousProcess::normalizeNewlines( + QString::fromLocal8Bit(outputData)); /* Looks like: \code changeset: 0:031a48610fba user: ... @@ -230,8 +230,7 @@ QString MercurialClient::shortDescriptionSync(const QString &workingDirectory, QByteArray outputData; if (!vcsFullySynchronousExec(workingDirectory, args, &outputData)) return revision; - description = QString::fromLocal8Bit(outputData); - description.remove(QLatin1Char('\r')); + description = Utils::SynchronousProcess::normalizeNewlines(QString::fromLocal8Bit(outputData)); if (description.endsWith(QLatin1Char('\n'))) description.truncate(description.size() - 1); return description; diff --git a/src/plugins/vcsbase/command.cpp b/src/plugins/vcsbase/command.cpp index 55eb8b9f5ce3b8a529b2315443cb6b036d5d9e55..ed0291075b9522f33a13c5a7120c8322e8daa20b 100644 --- a/src/plugins/vcsbase/command.cpp +++ b/src/plugins/vcsbase/command.cpp @@ -253,15 +253,14 @@ void Command::run() exitCode = process->exitCode(); } - QString stdOutS = d->m_codec ? d->m_codec->toUnicode(stdOut) - : QString::fromLocal8Bit(stdOut.constData(), stdOut.size()); - stdOutS.remove(QLatin1Char('\r')); - d->m_lastExecSuccess = ok; d->m_lastExecExitCode = exitCode; - if (ok) - emit output(stdOutS); + if (ok) { + emit output(Utils::SynchronousProcess::normalizeNewlines( + d->m_codec ? d->m_codec->toUnicode(stdOut) + : QString::fromLocal8Bit(stdOut.constData(), stdOut.size()))); + } if (!error.isEmpty()) emit errorText(error); diff --git a/src/plugins/vcsbase/vcsbaseclient.cpp b/src/plugins/vcsbase/vcsbaseclient.cpp index 32030abb5e6e5f6349f7669ecaebe7812e4e72f0..99002213031759a66640edc448de638f9bfcfbe3 100644 --- a/src/plugins/vcsbase/vcsbaseclient.cpp +++ b/src/plugins/vcsbase/vcsbaseclient.cpp @@ -189,9 +189,8 @@ bool VcsBaseClient::synchronousCreateRepository(const QString &workingDirectory, QByteArray outputData; if (!vcsFullySynchronousExec(workingDirectory, args, &outputData)) return false; - QString output = QString::fromLocal8Bit(outputData); - output.remove(QLatin1Char('\r')); - ::vcsOutputWindow()->append(output); + ::vcsOutputWindow()->append( + Utils::SynchronousProcess::normalizeNewlines(QString::fromLocal8Bit(outputData))); resetCachedVcsInfo(workingDirectory); diff --git a/src/plugins/vcsbase/vcsbaseplugin.cpp b/src/plugins/vcsbase/vcsbaseplugin.cpp index 703b79f5bbd541842f75ac4ab73a17342ab51c94..9d1905ccc7cf85d418730bc8fa4bca2f775d2c48 100644 --- a/src/plugins/vcsbase/vcsbaseplugin.cpp +++ b/src/plugins/vcsbase/vcsbaseplugin.cpp @@ -863,15 +863,15 @@ static SynchronousProcessResponse runVcsFullySynchronously(const QString &workin &stdOut, &stdErr, true); if (!stdErr.isEmpty()) { - response.stdErr = (outputCodec ? outputCodec->toUnicode(stdErr) : QString::fromLocal8Bit(stdErr)); - response.stdErr.remove(QLatin1Char('\r')); + response.stdErr = Utils::SynchronousProcess::normalizeNewlines( + outputCodec ? outputCodec->toUnicode(stdErr) : QString::fromLocal8Bit(stdErr)); if (!(flags & VcsBasePlugin::SuppressStdErrInLogWindow)) outputWindow->append(response.stdErr); } if (!stdOut.isEmpty()) { - response.stdOut = (outputCodec ? outputCodec->toUnicode(stdOut) : QString::fromLocal8Bit(stdOut)); - response.stdOut.remove(QLatin1Char('\r')); + response.stdOut = Utils::SynchronousProcess::normalizeNewlines( + outputCodec ? outputCodec->toUnicode(stdOut) : QString::fromLocal8Bit(stdOut)); if (flags & VcsBasePlugin::ShowStdOutInLogWindow) { if (flags & VcsBasePlugin::SilentOutput) outputWindow->appendSilently(response.stdOut);