summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Faure <david.faure@kdab.com>2013-09-02 10:26:21 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-11-17 00:45:03 +0100
commit2026e502596cf6d447caf9545ffed8d3f73fe597 (patch)
tree34a1b9181221c6da45d0f0edaeabe46ffccafbca
parentafe8e368721b6cac34d3b8de7689b53200f8c6fb (diff)
QCommandLineParser: add word-wrapping algorithm
Rather than breaking at column 79 precisely, break entire words, to improve readability. Change-Id: Ie30db00f0e6ed95cce87480c3b91804826c6076b Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@digia.com>
-rw-r--r--src/corelib/tools/qcommandlineparser.cpp49
-rw-r--r--tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.cpp11
-rw-r--r--tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp49
3 files changed, 82 insertions, 27 deletions
diff --git a/src/corelib/tools/qcommandlineparser.cpp b/src/corelib/tools/qcommandlineparser.cpp
index 8054542333..5463e4f0c1 100644
--- a/src/corelib/tools/qcommandlineparser.cpp
+++ b/src/corelib/tools/qcommandlineparser.cpp
@@ -845,11 +845,50 @@ static QString wrapText(const QString &names, int longestOptionNameString, const
{
const QLatin1Char nl('\n');
QString text = QStringLiteral(" ") + names.leftJustified(longestOptionNameString) + QLatin1Char(' ');
- const int leftColumnWidth = text.length();
- const int rightColumnWidth = 79 - leftColumnWidth;
- text += description.left(rightColumnWidth) + nl;
- for (int n = rightColumnWidth; n < description.length(); n += rightColumnWidth)
- text += QStringLiteral(" ").repeated(leftColumnWidth) + description.mid(n, rightColumnWidth) + nl;
+ const int indent = text.length();
+ int lineStart = 0;
+ int lastBreakable = -1;
+ const int max = 79 - indent;
+ int x = 0;
+ const int len = description.length();
+
+ for (int i = 0; i < len; ++i) {
+ ++x;
+ const QChar c = description.at(i);
+ if (c.isSpace())
+ lastBreakable = i;
+
+ int breakAt = -1;
+ int nextLineStart = -1;
+ if (x > max && lastBreakable != -1) {
+ // time to break and we know where
+ breakAt = lastBreakable;
+ nextLineStart = lastBreakable + 1;
+ } else if ((x > max - 1 && lastBreakable == -1) || i == len - 1) {
+ // time to break but found nowhere [-> break here], or end of last line
+ breakAt = i + 1;
+ nextLineStart = breakAt;
+ } else if (c == nl) {
+ // forced break
+ breakAt = i;
+ nextLineStart = i + 1;
+ }
+
+ if (breakAt != -1) {
+ const int numChars = breakAt - lineStart;
+ //qDebug() << "breakAt=" << description.at(breakAt) << "breakAtSpace=" << breakAtSpace << lineStart << "to" << breakAt << description.mid(lineStart, numChars);
+ if (lineStart > 0)
+ text += QString(indent, QLatin1Char(' '));
+ text += description.midRef(lineStart, numChars) + nl;
+ x = 0;
+ lastBreakable = -1;
+ lineStart = nextLineStart;
+ if (lineStart < len && description.at(lineStart).isSpace())
+ ++lineStart; // don't start a line with a space
+ i = lineStart;
+ }
+ }
+
return text;
}
diff --git a/tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.cpp b/tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.cpp
index 07f8ddfc8e..2b30b0486b 100644
--- a/tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.cpp
+++ b/tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.cpp
@@ -69,9 +69,18 @@ int main(int argc, char *argv[])
// An option with a longer description, to test wrapping
QCommandLineOption noImplicitIncludesOption(QStringList() << QStringLiteral("n") << QStringLiteral("no-implicit-includes"));
- noImplicitIncludesOption.setDescription(QStringLiteral("Disable automatic generation of implicit #include-directives."));
+ noImplicitIncludesOption.setDescription(QStringLiteral("Disable magic generation of implicit #include-directives."));
parser.addOption(noImplicitIncludesOption);
+ QCommandLineOption newlineOption(QStringList() << QStringLiteral("newline"));
+ newlineOption.setDescription(QString::fromLatin1("This is an option with a rather long\n"
+ "description using explicit newline characters "
+ "(but testing automatic wrapping too). In addition, "
+ "here, we test breaking after a comma. Testing -option. "
+ "Long URL: http://qt-project.org/wiki/How_to_create_a_library_with_Qt_and_use_it_in_an_application "
+ "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"));
+ parser.addOption(newlineOption);
+
// This program supports different options depending on the "command" (first argument).
// Call parse() to find out the positional arguments.
parser.parse(QCoreApplication::arguments());
diff --git a/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp b/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp
index d8965dee5d..f37e192ad3 100644
--- a/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp
+++ b/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp
@@ -459,27 +459,40 @@ void tst_QCommandLineParser::testVersionOption()
#endif // !QT_NO_PROCESS
}
+static const char expectedOptionsHelp[] =
+ "Options:\n"
+ " -h, --help Displays this help.\n"
+ " -v, --version Displays version information.\n"
+ " --load <url> Load file from URL.\n"
+ " -o, --output <file> Set output file.\n"
+ " -D <key=value> Define macro.\n"
+ " -n, --no-implicit-includes Disable magic generation of implicit\n"
+ " #include-directives.\n"
+ " --newline This is an option with a rather long\n"
+ " description using explicit newline characters (but\n"
+ " testing automatic wrapping too). In addition,\n"
+ " here, we test breaking after a comma. Testing\n"
+ " -option. Long URL:\n"
+ " http://qt-project.org/wiki/How_to_create_a_library\n"
+ " _with_Qt_and_use_it_in_an_application\n"
+ " abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx\n"
+ " yzabcdefghijklmnopqrstuvwxyz\n";
+
void tst_QCommandLineParser::testHelpOption_data()
{
QTest::addColumn<QCommandLineParser::SingleDashWordOptionMode>("parsingMode");
QTest::addColumn<QString>("expectedHelpOutput");
- QString expectedOutput =
+ QString expectedOutput = QString::fromLatin1(
"Usage: testhelper/qcommandlineparser_test_helper [options] parsingMode command\n"
"Test helper\n"
- "\n"
- "Options:\n"
- " -h, --help Displays this help.\n"
- " -v, --version Displays version information.\n"
- " --load <url> Load file from URL.\n"
- " -o, --output <file> Set output file.\n"
- " -D <key=value> Define macro.\n"
- " -n, --no-implicit-includes Disable automatic generation of implicit #include\n"
- " -directives.\n"
+ "\n")
+ + QString::fromLatin1(expectedOptionsHelp) +
+ QString::fromLatin1(
"\n"
"Arguments:\n"
" parsingMode The parsing mode to test.\n"
- " command The command to execute.\n";
+ " command The command to execute.\n");
#ifdef Q_OS_WIN
expectedOutput.replace(" -h, --help Displays this help.\n",
" -?, -h, --help Displays this help.\n");
@@ -510,6 +523,7 @@ void tst_QCommandLineParser::testHelpOption()
#ifdef Q_OS_WIN
output.replace(QStringLiteral("\r\n"), QStringLiteral("\n"));
#endif
+ QCOMPARE(output.split('\n'), expectedHelpOutput.split('\n')); // easier to debug than the next line, on failure
QCOMPARE(output, expectedHelpOutput);
process.start("testhelper/qcommandlineparser_test_helper", QStringList() << "0" << "resize" << "--help");
@@ -519,18 +533,11 @@ void tst_QCommandLineParser::testHelpOption()
#ifdef Q_OS_WIN
output.replace(QStringLiteral("\r\n"), QStringLiteral("\n"));
#endif
- QByteArray expectedResizeHelp =
+ QByteArray expectedResizeHelp = QByteArrayLiteral(
"Usage: testhelper/qcommandlineparser_test_helper [options] resize [resize_options]\n"
"Test helper\n"
- "\n"
- "Options:\n"
- " -h, --help Displays this help.\n"
- " -v, --version Displays version information.\n"
- " --load <url> Load file from URL.\n"
- " -o, --output <file> Set output file.\n"
- " -D <key=value> Define macro.\n"
- " -n, --no-implicit-includes Disable automatic generation of implicit #include\n"
- " -directives.\n"
+ "\n")
+ + expectedOptionsHelp +
" --size <size> New size.\n"
"\n"
"Arguments:\n"