Commit ca433d9b authored by Lorenz Haas's avatar Lorenz Haas Committed by David Schulz

Beautifier: Add new class Command and option to format text via piping

The tool's formatting command is now enclosed in Command. For the
formatting itself it can be defined whether to use a temporary file or
the pipe.
Additionally, settings can return the current tool's version - if
needed.

Change-Id: I0e242c3e8016ed77cad92cc97a19fe3384dda858
Reviewed-by: default avatarDavid Schulz <david.schulz@digia.com>
parent af5b3246
......@@ -44,7 +44,8 @@ namespace Beautifier {
namespace Internal {
AbstractSettings::AbstractSettings(const QString &name, const QString &ending)
: m_name(name)
: m_version(0)
, m_name(name)
, m_ending(ending)
, m_styleDir(Core::ICore::userResourcePath() + QLatin1Char('/')
+ QLatin1String(Beautifier::Constants::SETTINGS_DIRNAME) + QLatin1Char('/')
......@@ -135,6 +136,18 @@ void AbstractSettings::setCommand(const QString &command)
return;
m_command = command;
updateVersion();
}
int AbstractSettings::version() const
{
return m_version;
}
void AbstractSettings::updateVersion()
{
// If a beautifier needs to know the current tool's version, reimplement and store the version
// in m_version.
}
QStringList AbstractSettings::options()
......
......@@ -67,6 +67,8 @@ public:
QString command() const;
void setCommand(const QString &command);
int version() const;
virtual void updateVersion();
QStringList options();
QString documentation(const QString &option) const;
......@@ -74,6 +76,7 @@ public:
protected:
QMap<QString, QString> m_styles;
QMap<QString, QVariant> m_settings;
int m_version;
void readDocumentation();
......
......@@ -27,6 +27,8 @@
**
****************************************************************************/
// Tested with version 2.01, 2.02, 2.02.1, 2.03 and 2.04
#include "artisticstyle.h"
#include "artisticstyleconstants.h"
......@@ -35,6 +37,7 @@
#include "../beautifierconstants.h"
#include "../beautifierplugin.h"
#include "../command.h"
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
......@@ -136,11 +139,19 @@ void ArtisticStyle::formatFile()
BeautifierPlugin::showError(BeautifierPlugin::msgCannotGetConfigurationFile(
QLatin1String(Constants::ArtisticStyle::DISPLAY_NAME)));
} else {
BeautifierPlugin::formatCurrentFile(QStringList()
<< m_settings->command()
<< QLatin1String("-q")
<< QLatin1String("--options=") + cfgFileName
<< QLatin1String("%file"));
Command command;
command.setExecutable(m_settings->command());
command.addOption(QLatin1String("-q"));
command.addOption(QLatin1String("--options=") + cfgFileName);
if (m_settings->version() > ArtisticStyleSettings::Version_2_03) {
command.setProcessing(Command::PipeProcessing);
command.setPipeAddsNewline(true);
} else {
command.addOption(QLatin1String("%file"));
}
BeautifierPlugin::formatCurrentFile(command);
}
}
......
......@@ -39,6 +39,7 @@
#include <QFile>
#include <QFileInfo>
#include <QProcess>
#include <QtConcurrent>
#include <QTextDocument> // Qt::escape() in Qt 4
#include <QXmlStreamWriter>
......@@ -57,6 +58,8 @@ ArtisticStyleSettings::ArtisticStyleSettings() :
AbstractSettings(QLatin1String(Constants::ArtisticStyle::SETTINGS_NAME),
QLatin1String(".astyle"))
{
connect(&m_versionWatcher, SIGNAL(finished()), this, SLOT(helperSetVersion()));
setCommand(QLatin1String("astyle"));
m_settings.insert(QLatin1String(kUseOtherFiles), QVariant(true));
m_settings.insert(QLatin1String(kUseHomeFile), QVariant(false));
......@@ -65,6 +68,40 @@ ArtisticStyleSettings::ArtisticStyleSettings() :
read();
}
void ArtisticStyleSettings::updateVersion()
{
if (m_versionFuture.isRunning())
m_versionFuture.cancel();
m_versionFuture = QtConcurrent::run(this, &ArtisticStyleSettings::helperUpdateVersion);
m_versionWatcher.setFuture(m_versionFuture);
}
int ArtisticStyleSettings::helperUpdateVersion() const
{
QProcess process;
process.start(command(), QStringList() << QLatin1String("--version"));
if (!process.waitForFinished()) {
process.kill();
return 0;
}
// The version in Artistic Style is printed like "Artistic Style Version 2.04"
const QString version = QString::fromUtf8(process.readAllStandardError()).trimmed();
const QRegExp rx(QLatin1String("([2-9]{1})\\.([0-9]{2})(\\.[1-9]{1})?$"));
if (rx.indexIn(version) != -1) {
const int major = rx.cap(1).toInt() * 100;
const int minor = rx.cap(2).toInt();
return major + minor;
}
return 0;
}
void ArtisticStyleSettings::helperSetVersion()
{
m_version = m_versionWatcher.result();
}
bool ArtisticStyleSettings::useOtherFiles() const
{
return m_settings.value(QLatin1String(kUseOtherFiles)).toBool();
......
......@@ -34,15 +34,26 @@
#include <utils/qtcoverride.h>
#include <QFuture>
#include <QFutureWatcher>
namespace Beautifier {
namespace Internal {
namespace ArtisticStyle {
class ArtisticStyleSettings : public AbstractSettings
class ArtisticStyleSettings : public QObject, public AbstractSettings
{
Q_OBJECT
public:
enum ArtisticStyleVersion {
Version_2_03 = 203
};
ArtisticStyleSettings();
void updateVersion() QTC_OVERRIDE;
bool useOtherFiles() const;
void setUseOtherFiles(bool useOtherFiles);
......@@ -57,6 +68,14 @@ public:
QString documentationFilePath() const QTC_OVERRIDE;
void createDocumentationFile() const QTC_OVERRIDE;
private slots:
void helperSetVersion();
private:
QFuture<int> m_versionFuture;
QFutureWatcher<int> m_versionWatcher;
int helperUpdateVersion() const;
};
} // namespace ArtisticStyle
......
......@@ -7,6 +7,7 @@ HEADERS += \
beautifierabstracttool.h \
beautifierconstants.h \
beautifierplugin.h \
command.h \
configurationdialog.h \
configurationeditor.h \
configurationpanel.h \
......@@ -26,6 +27,7 @@ HEADERS += \
SOURCES += \
abstractsettings.cpp \
beautifierplugin.cpp \
command.cpp \
configurationdialog.cpp \
configurationeditor.cpp \
configurationpanel.cpp \
......
......@@ -22,6 +22,8 @@ QtcPlugin {
"beautifierconstants.h",
"beautifierplugin.cpp",
"beautifierplugin.h",
"command.cpp",
"command.h",
"configurationdialog.cpp",
"configurationdialog.h",
"configurationdialog.ui",
......
......@@ -30,6 +30,8 @@
#include "beautifierplugin.h"
#include "beautifierconstants.h"
#include "command.h"
#include "artisticstyle/artisticstyle.h"
#include "clangformat/clangformat.h"
#include "uncrustify/uncrustify.h"
......@@ -116,47 +118,83 @@ void BeautifierPlugin::updateActions(Core::IEditor *editor)
m_tools.at(i)->updateActions(editor);
}
QString BeautifierPlugin::format(const QString &text, QStringList command, const QString &fileName)
QString BeautifierPlugin::format(const QString &text, const Command &command, const QString &fileName)
{
if (command.isEmpty())
const QString executable = command.executable();
if (executable.isEmpty())
return QString();
// Save text to temporary file
QFileInfo fi(fileName);
Utils::TempFileSaver sourceFile(fi.absolutePath() + QLatin1String("/qtc_beautifier_XXXXXXXX.")
+ fi.suffix());
sourceFile.setAutoRemove(true);
sourceFile.write(text.toUtf8());
if (!sourceFile.finalize()) {
showError(tr("Cannot create temporary file \"%1\": %2.")
.arg(sourceFile.fileName()).arg(sourceFile.errorString()));
return QString();
}
switch (command.processing()) {
case Command::FileProcessing: {
// Save text to temporary file
QFileInfo fi(fileName);
Utils::TempFileSaver sourceFile(QDir::tempPath() + QLatin1String("/qtc_beautifier_XXXXXXXX.")
+ fi.suffix());
sourceFile.setAutoRemove(true);
sourceFile.write(text.toUtf8());
if (!sourceFile.finalize()) {
showError(tr("Cannot create temporary file \"%1\": %2.")
.arg(sourceFile.fileName()).arg(sourceFile.errorString()));
return QString();
}
// Format temporary file
QProcess process;
command.replaceInStrings(QLatin1String("%file"), sourceFile.fileName());
const QString processProgram = command.takeFirst();
process.start(processProgram, command);
if (!process.waitForFinished()) {
showError(tr("Cannot call %1 or some other error occurred.").arg(processProgram));
return QString();
// Format temporary file
QProcess process;
QStringList options = command.options();
options.replaceInStrings(QLatin1String("%file"), sourceFile.fileName());
process.start(executable, options);
if (!process.waitForFinished()) {
showError(tr("Cannot call %1 or some other error occurred.").arg(executable));
return QString();
}
const QByteArray output = process.readAllStandardError();
if (!output.isEmpty())
showError(executable + QLatin1String(": ") + QString::fromUtf8(output));
// Read text back
Utils::FileReader reader;
if (!reader.fetch(sourceFile.fileName(), QIODevice::Text)) {
showError(tr("Cannot read file \"%1\": %2.")
.arg(sourceFile.fileName()).arg(reader.errorString()));
return QString();
}
return QString::fromUtf8(reader.data());
} break;
case Command::PipeProcessing: {
QProcess process;
QStringList options = command.options();
options.replaceInStrings(QLatin1String("%file"), fileName);
process.start(executable, options);
if (!process.waitForStarted()) {
showError(tr("Cannot call %1 or some other error occurred.").arg(executable));
return QString();
}
process.write(text.toUtf8());
process.closeWriteChannel();
if (!process.waitForFinished()) {
showError(tr("Cannot call %1 or some other error occurred.").arg(executable));
return QString();
}
const QByteArray error = process.readAllStandardError();
if (!error.isEmpty()) {
showError(executable + QLatin1String(": ") + QString::fromUtf8(error));
return QString();
}
if (command.pipeAddsNewline()) {
QString formatted = QString::fromUtf8(process.readAllStandardOutput());
formatted.remove(QRegExp(QLatin1String("(\\r\\n|\\n)$")));
return formatted;
}
return QString::fromUtf8(process.readAllStandardOutput());
}
const QByteArray output = process.readAllStandardError();
if (!output.isEmpty())
showError(processProgram + QLatin1String(": ") + QString::fromLocal8Bit(output));
// Read text back
Utils::FileReader reader;
if (!reader.fetch(sourceFile.fileName(), QIODevice::Text)) {
showError(tr("Cannot read file \"%1\": %2.")
.arg(sourceFile.fileName()).arg(reader.errorString()));
return QString();
}
return QString::fromUtf8(reader.data());
return QString();
}
void BeautifierPlugin::formatCurrentFile(QStringList command)
void BeautifierPlugin::formatCurrentFile(const Command &command)
{
QPlainTextEdit *textEditor = 0;
if (TextEditor::BaseTextEditor *editor
......
......@@ -39,6 +39,7 @@ namespace Beautifier {
namespace Internal {
class BeautifierAbstractTool;
class Command;
class BeautifierPlugin : public ExtensionSystem::IPlugin
{
......@@ -52,8 +53,8 @@ public:
void extensionsInitialized() QTC_OVERRIDE;
ShutdownFlag aboutToShutdown() QTC_OVERRIDE;
static QString format(const QString &text, QStringList command, const QString &fileName);
static void formatCurrentFile(QStringList command);
static QString format(const QString &text, const Command &command, const QString &fileName);
static void formatCurrentFile(const Command &command);
static void showError(const QString &error);
static QString msgCannotGetConfigurationFile(const QString &command);
......
......@@ -27,6 +27,8 @@
**
****************************************************************************/
// Tested with version 3.3, 3.4 and 3.4.1
#include "clangformat.h"
#include "clangformatconstants.h"
......@@ -125,22 +127,24 @@ void ClangFormat::formatSelectedText()
}
}
QStringList ClangFormat::command(int offset, int length) const
Command ClangFormat::command(int offset, int length) const
{
QStringList command;
command << m_settings->command();
command << QLatin1String("-i");
Command command;
command.setExecutable(m_settings->command());
command.setProcessing(Command::PipeProcessing);
if (m_settings->usePredefinedStyle()) {
command << QLatin1String("-style=") + m_settings->predefinedStyle();
command.addOption(QLatin1String("-style=") + m_settings->predefinedStyle());
} else {
command << QLatin1String("-style={") + m_settings->style(
m_settings->customStyle()).remove(QLatin1Char('\n')) + QLatin1String("}");
command.addOption(QLatin1String("-style={")
+ m_settings->style(m_settings->customStyle()).remove(QLatin1Char('\n'))
+ QLatin1String("}"));
}
if (offset != -1) {
command << QLatin1String("-offset=") + QString::number(offset);
command << QLatin1String("-length=") + QString::number(length);
command.addOption(QLatin1String("-offset=") + QString::number(offset));
command.addOption(QLatin1String("-length=") + QString::number(length));
}
command << QLatin1String("%file");
return command;
}
......
......@@ -31,6 +31,7 @@
#define BEAUTIFIER_CLANGFORMAT_H
#include "../beautifierabstracttool.h"
#include "../command.h"
#include <utils/qtcoverride.h>
......@@ -61,7 +62,7 @@ private:
QAction *m_formatFile;
QAction *m_formatRange;
ClangFormatSettings *m_settings;
QStringList command(int offset = -1, int length = -1) const;
Command command(int offset = -1, int length = -1) const;
};
} // namespace ClangFormat
......
/**************************************************************************
**
** Copyright (c) 2014 Lorenz Haas
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "command.h"
namespace Beautifier {
namespace Internal {
Command::Command()
: m_processing(FileProcessing)
, m_pipeAddsNewline(false)
{
}
QString Command::executable() const
{
return m_executable;
}
void Command::setExecutable(const QString &executable)
{
m_executable = executable;
}
QStringList Command::options() const
{
return m_options;
}
void Command::addOption(const QString &option)
{
m_options << option;
}
Command::Processing Command::processing() const
{
return m_processing;
}
void Command::setProcessing(const Processing &processing)
{
m_processing = processing;
}
bool Command::pipeAddsNewline() const
{
return m_pipeAddsNewline;
}
void Command::setPipeAddsNewline(bool pipeAddsNewline)
{
m_pipeAddsNewline = pipeAddsNewline;
}
} // namespace Internal
} // namespace Beautifier
/**************************************************************************
**
** Copyright (c) 2014 Lorenz Haas
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef BEAUTIFIER_COMMAND_H
#define BEAUTIFIER_COMMAND_H
#include <QString>
#include <QStringList>
namespace Beautifier {
namespace Internal {
class Command
{
public:
enum Processing {
FileProcessing,
PipeProcessing
};
Command();
QString executable() const;
void setExecutable(const QString &executable);
QStringList options() const;
void addOption(const QString &option);
Processing processing() const;
void setProcessing(const Processing &processing);
bool pipeAddsNewline() const;
void setPipeAddsNewline(bool pipeAddsNewline);
private:
QString m_executable;
QStringList m_options;
Processing m_processing;
bool m_pipeAddsNewline;
};
} // namespace Internal
} // namespace Beautifier
#endif // BEAUTIFIER_COMMAND_H
......@@ -27,6 +27,8 @@
**
****************************************************************************/
// Tested with version 0.59 and 0.60
#include "uncrustify.h"
#include "uncrustifyconstants.h"
......@@ -35,6 +37,7 @@
#include "../beautifierconstants.h"
#include "../beautifierplugin.h"
#include "../command.h"
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
......@@ -130,16 +133,16 @@ void Uncrustify::formatFile()
BeautifierPlugin::showError(BeautifierPlugin::msgCannotGetConfigurationFile(
QLatin1String(Constants::Uncrustify::DISPLAY_NAME)));
} else {
BeautifierPlugin::formatCurrentFile(QStringList()
<< m_settings->command()
<< QLatin1String("-l")
<< QLatin1String("cpp")
<< QLatin1String("-L")
<< QLatin1String("1-2")
<< QLatin1String("--no-backup")
<< QLatin1String("-c")
<< cfgFileName
<< QLatin1String("%file"));
Command command;
command.setExecutable(m_settings->command());
command.setProcessing(Command::PipeProcessing);
command.addOption(QLatin1String("-l"));
command.addOption(QLatin1String("cpp"));
command.addOption(QLatin1String("-L"));
command.addOption(QLatin1String("1-2"));
command.addOption(QLatin1String("-c"));
command.addOption(cfgFileName);
BeautifierPlugin::formatCurrentFile(command);
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment