Utils: Support \r handling in OutputFormatter

Change-Id: Iae7ddc376cff86eef9d6873bdb6a6ed3f5f7022f
Reviewed-by: Tobias Hunger <tobias.hunger@digia.com>
This commit is contained in:
Orgad Shaneh
2014-03-18 20:23:08 +02:00
committed by Orgad Shaneh
parent 1c953f0ac0
commit 0960127ece
5 changed files with 39 additions and 30 deletions

View File

@@ -100,12 +100,18 @@ QList<FormattedText> AnsiEscapeCodeHandler::parseText(const FormattedText &input
const QChar semicolon = QLatin1Char(';'); const QChar semicolon = QLatin1Char(';');
const QChar colorTerminator = QLatin1Char('m'); const QChar colorTerminator = QLatin1Char('m');
const QChar eraseToEol = QLatin1Char('K');
// strippedText always starts with "\e[" // strippedText always starts with "\e["
QString strippedText = input.text.mid(escapePos); QString strippedText = input.text.mid(escapePos);
while (!strippedText.isEmpty()) { while (!strippedText.isEmpty()) {
while (strippedText.startsWith(escape)) { while (strippedText.startsWith(escape)) {
strippedText.remove(0, 2); strippedText.remove(0, 2);
// \e[K is not supported. Just strip it.
if (strippedText.startsWith(eraseToEol)) {
strippedText.remove(0, 1);
continue;
}
// get the number // get the number
QString strNumber; QString strNumber;
QStringList numbers; QStringList numbers;

View File

@@ -39,6 +39,7 @@ OutputFormatter::OutputFormatter()
, m_plainTextEdit(0) , m_plainTextEdit(0)
, m_formats(0) , m_formats(0)
, m_escapeCodeHandler(new AnsiEscapeCodeHandler) , m_escapeCodeHandler(new AnsiEscapeCodeHandler)
, m_overwriteOutput(false)
{ {
} }
@@ -67,7 +68,15 @@ void OutputFormatter::appendMessage(const QString &text, OutputFormat format)
foreach (const FormattedText &output, foreach (const FormattedText &output,
m_escapeCodeHandler->parseText(FormattedText(text, m_formats[format]))) { m_escapeCodeHandler->parseText(FormattedText(text, m_formats[format]))) {
cursor.insertText(output.text, output.format); int startPos = 0;
int crPos = -1;
while ((crPos = output.text.indexOf(QLatin1Char('\r'), startPos)) >= 0) {
append(cursor, output.text.mid(startPos, crPos - startPos), output.format);
startPos = crPos + 1;
m_overwriteOutput = true;
}
if (startPos < output.text.count())
append(cursor, output.text.mid(startPos), output.format);
} }
} }
@@ -76,6 +85,17 @@ QTextCharFormat OutputFormatter::charFormat(OutputFormat format) const
return m_formats[format]; return m_formats[format];
} }
void OutputFormatter::append(QTextCursor &cursor, const QString &text,
const QTextCharFormat &format)
{
if (m_overwriteOutput) {
cursor.clearSelection();
cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::KeepAnchor);
m_overwriteOutput = false;
}
cursor.insertText(text, format);
}
void OutputFormatter::clearLastLine() void OutputFormatter::clearLastLine()
{ {
QTextCursor cursor(m_plainTextEdit->document()); QTextCursor cursor(m_plainTextEdit->document());

View File

@@ -37,9 +37,10 @@
#include <QFont> #include <QFont>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QColor;
class QPlainTextEdit; class QPlainTextEdit;
class QTextCharFormat; class QTextCharFormat;
class QColor; class QTextCursor;
QT_END_NAMESPACE QT_END_NAMESPACE
namespace Utils { namespace Utils {
@@ -68,6 +69,7 @@ protected:
void initFormats(); void initFormats();
virtual void clearLastLine(); virtual void clearLastLine();
QTextCharFormat charFormat(OutputFormat format) const; QTextCharFormat charFormat(OutputFormat format) const;
void append(QTextCursor &cursor, const QString &text, const QTextCharFormat &format);
static QColor mixColors(const QColor &a, const QColor &b); static QColor mixColors(const QColor &a, const QColor &b);
@@ -76,6 +78,7 @@ private:
QTextCharFormat *m_formats; QTextCharFormat *m_formats;
QFont m_font; QFont m_font;
AnsiEscapeCodeHandler *m_escapeCodeHandler; AnsiEscapeCodeHandler *m_escapeCodeHandler;
bool m_overwriteOutput;
}; };
} // namespace Utils } // namespace Utils

View File

@@ -31,6 +31,7 @@
#include "command.h" #include "command.h"
#include "vcsbaseplugin.h" #include "vcsbaseplugin.h"
#include <utils/outputformatter.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <QApplication> #include <QApplication>
@@ -61,7 +62,9 @@ CheckoutProgressWizardPage::CheckoutProgressWizardPage(QWidget *parent) :
resize(264, 200); resize(264, 200);
QVBoxLayout *verticalLayout = new QVBoxLayout(this); QVBoxLayout *verticalLayout = new QVBoxLayout(this);
m_logPlainTextEdit = new QPlainTextEdit; m_logPlainTextEdit = new QPlainTextEdit;
m_formatter = new Utils::OutputFormatter;
m_logPlainTextEdit->setReadOnly(true); m_logPlainTextEdit->setReadOnly(true);
m_formatter->setPlainTextEdit(m_logPlainTextEdit);
verticalLayout->addWidget(m_logPlainTextEdit); verticalLayout->addWidget(m_logPlainTextEdit);
@@ -74,6 +77,7 @@ CheckoutProgressWizardPage::~CheckoutProgressWizardPage()
{ {
if (m_state == Running) // Paranoia! if (m_state == Running) // Paranoia!
QApplication::restoreOverrideCursor(); QApplication::restoreOverrideCursor();
delete m_formatter;
} }
void CheckoutProgressWizardPage::setStartedStatus(const QString &startedStatus) void CheckoutProgressWizardPage::setStartedStatus(const QString &startedStatus)
@@ -131,20 +135,7 @@ void CheckoutProgressWizardPage::slotFinished(bool ok, int exitCode, const QVari
void CheckoutProgressWizardPage::slotOutput(const QString &text) void CheckoutProgressWizardPage::slotOutput(const QString &text)
{ {
int startPos = 0; m_formatter->appendMessage(text, Utils::StdOutFormat);
int crPos = -1;
const QString ansiEraseToEol = QLatin1String("\x1b[K");
while ((crPos = text.indexOf(QLatin1Char('\r'), startPos)) >= 0) {
QString part = text.mid(startPos, crPos - startPos);
// Discard ANSI erase-to-eol
if (part.endsWith(ansiEraseToEol))
part.chop(ansiEraseToEol.length());
outputText(part);
startPos = crPos + 1;
m_overwriteOutput = true;
}
if (startPos < text.count())
outputText(text.mid(startPos));
} }
void CheckoutProgressWizardPage::slotError(const QString &text) void CheckoutProgressWizardPage::slotError(const QString &text)
@@ -152,18 +143,6 @@ void CheckoutProgressWizardPage::slotError(const QString &text)
m_error.append(text); m_error.append(text);
} }
void CheckoutProgressWizardPage::outputText(const QString &text)
{
if (m_overwriteOutput) {
QTextCursor cursor = m_logPlainTextEdit->textCursor();
cursor.clearSelection();
cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::KeepAnchor);
m_logPlainTextEdit->setTextCursor(cursor);
m_overwriteOutput = false;
}
m_logPlainTextEdit->insertPlainText(text);
}
void CheckoutProgressWizardPage::terminate() void CheckoutProgressWizardPage::terminate()
{ {
if (m_command) if (m_command)

View File

@@ -38,6 +38,8 @@ class QPlainTextEdit;
class QLabel; class QLabel;
QT_END_NAMESPACE QT_END_NAMESPACE
namespace Utils { class OutputFormatter; }
namespace VcsBase { namespace VcsBase {
class Command; class Command;
@@ -70,9 +72,8 @@ private slots:
void slotError(const QString &text); void slotError(const QString &text);
private: private:
void outputText(const QString &text);
QPlainTextEdit *m_logPlainTextEdit; QPlainTextEdit *m_logPlainTextEdit;
Utils::OutputFormatter *m_formatter;
QLabel *m_statusLabel; QLabel *m_statusLabel;
Command *m_command; Command *m_command;