forked from qt-creator/qt-creator
183 lines
5.4 KiB
C++
183 lines
5.4 KiB
C++
/***************************************************************************
|
|
**
|
|
** This file is part of Qt Creator
|
|
**
|
|
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
|
**
|
|
** Contact: Qt Software Information (qt-info@nokia.com)
|
|
**
|
|
**
|
|
** Non-Open Source Usage
|
|
**
|
|
** Licensees may use this file in accordance with the Qt Beta Version
|
|
** License Agreement, Agreement version 2.2 provided with the Software or,
|
|
** alternatively, in accordance with the terms contained in a written
|
|
** agreement between you and Nokia.
|
|
**
|
|
** GNU General Public License Usage
|
|
**
|
|
** Alternatively, this file may be used under the terms of the GNU General
|
|
** Public License versions 2.0 or 3.0 as published by the Free Software
|
|
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
|
** of this file. Please review the following information to ensure GNU
|
|
** General Public Licensing requirements will be met:
|
|
**
|
|
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
|
** http://www.gnu.org/copyleft/gpl.html.
|
|
**
|
|
** In addition, as a special exception, Nokia gives you certain additional
|
|
** rights. These rights are described in the Nokia Qt GPL Exception version
|
|
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
|
**
|
|
***************************************************************************/
|
|
|
|
#include "indenter.h"
|
|
|
|
#include <QtCore/QFile>
|
|
#include <QtCore/QStringList>
|
|
#include <QtCore/QDebug>
|
|
#include <QtCore/QTextStream>
|
|
#include <QtCore/QFileInfo>
|
|
|
|
#include <stdio.h>
|
|
|
|
typedef SharedTools::Indenter<QStringList::const_iterator> Indenter;
|
|
|
|
static QString fileContents(const QString &fileName)
|
|
{
|
|
QFile f(fileName);
|
|
if (!f.open(QIODevice::ReadOnly)) {
|
|
const QString msg = QString(QLatin1String("error: Cannot open file '%1' for reading: %2")).
|
|
arg(fileName).arg(f.errorString());
|
|
qWarning(msg.toLatin1().constData());
|
|
return QString::null;
|
|
}
|
|
|
|
const QString contents = QString::fromUtf8(f.readAll());
|
|
f.close();
|
|
if ( contents.isEmpty() ) {
|
|
const QString msg = QString(QLatin1String("error: File '%1' is empty")).arg(fileName);
|
|
qWarning(msg.toLatin1().constData());
|
|
return QString::null;
|
|
}
|
|
return contents;
|
|
}
|
|
|
|
static void printUsage(char *a0)
|
|
{
|
|
const QFileInfo fi(QString::fromUtf8(a0));
|
|
const QString usage = QString(QLatin1String("Usage: %1 [-i indent-size] [-t tab-size] file.cpp")).
|
|
arg(fi.fileName());
|
|
qWarning(usage.toUtf8().constData());
|
|
}
|
|
|
|
static int integerOptionArgument(char ** &aptr, char **end)
|
|
{
|
|
if (++aptr == end)
|
|
return -1;
|
|
const QString arg = QString::fromUtf8(*aptr);
|
|
bool ok;
|
|
const int rc = arg.toInt (&ok);
|
|
if (!ok)
|
|
return -1;
|
|
return rc;
|
|
}
|
|
|
|
static QStringList parseCommandLine(char **begin, char **end)
|
|
{
|
|
char **aptr = begin;
|
|
if (++aptr == end)
|
|
return QStringList();
|
|
|
|
QStringList fileNames;
|
|
for ( ; aptr != end; ++aptr) {
|
|
const char *arg = *aptr;
|
|
if (arg[0] == '-') {
|
|
switch (arg[1]) {
|
|
case 't': {
|
|
const int tabSize = integerOptionArgument(aptr, end);
|
|
if ( tabSize == -1)
|
|
return QStringList();
|
|
Indenter::instance().setTabSize(tabSize);
|
|
}
|
|
break;
|
|
case 'i': {
|
|
const int indentSize = integerOptionArgument(aptr, end);
|
|
if (indentSize == -1)
|
|
return QStringList();
|
|
Indenter::instance().setIndentSize(indentSize);
|
|
}
|
|
break;
|
|
default:
|
|
return QStringList();
|
|
}
|
|
} else {
|
|
fileNames.push_back(QString::fromUtf8(arg));
|
|
}
|
|
}
|
|
return fileNames;
|
|
}
|
|
|
|
int format(const QString &fileName)
|
|
{
|
|
const QString code = fileContents(fileName);
|
|
if (code == QString::null)
|
|
return 1;
|
|
|
|
QStringList program = code.split(QLatin1Char('\n'), QString::KeepEmptyParts);
|
|
while (!program.isEmpty()) {
|
|
if (!program.back().trimmed().isEmpty())
|
|
break;
|
|
program.pop_back();
|
|
}
|
|
|
|
QStringList p;
|
|
QString out;
|
|
|
|
const QChar colon = QLatin1Char(':');
|
|
const QChar blank = QLatin1Char(' ');
|
|
const QChar newLine = QLatin1Char('\n');
|
|
|
|
QStringList::const_iterator cend = program.constEnd();
|
|
for (QStringList::const_iterator it = program.constBegin(); it != cend; ++it) {
|
|
p.push_back(*it);
|
|
QString &line = p.back();
|
|
|
|
QChar typedIn = Indenter::instance().firstNonWhiteSpace(line);
|
|
if (p.last().endsWith(colon))
|
|
typedIn = colon;
|
|
|
|
const int indent = Indenter::instance().indentForBottomLine(p.constBegin(), p.constEnd(), typedIn);
|
|
|
|
const QString trimmed = line.trimmed();
|
|
// Indent the line in the list so that the formatter code sees the indented line.
|
|
if (!trimmed.isEmpty()) {
|
|
line = QString(indent, blank);
|
|
line += trimmed;
|
|
}
|
|
out += line;
|
|
out += newLine ;
|
|
}
|
|
|
|
while (out.endsWith(newLine))
|
|
out.truncate(out.length() - 1 );
|
|
|
|
fputs(out.toUtf8().constData(), stdout);
|
|
return 0;
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
const QStringList fileNames = parseCommandLine(argv, argv + argc);
|
|
if (fileNames.empty()) {
|
|
printUsage(argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
foreach(QString fileName, fileNames)
|
|
if (const int rc = format(fileName))
|
|
return rc;
|
|
|
|
return 0;
|
|
}
|