/*************************************************************************** ** ** 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 #include #include #include #include #include typedef SharedTools::Indenter 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; }