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>
This commit is contained in:
parent
afe8e36872
commit
2026e50259
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
|
@ -459,27 +459,40 @@ void tst_QCommandLineParser::testVersionOption()
|
||||
#endif // !QT_NO_PROCESS
|
||||
}
|
||||
|
||||
void tst_QCommandLineParser::testHelpOption_data()
|
||||
{
|
||||
QTest::addColumn<QCommandLineParser::SingleDashWordOptionMode>("parsingMode");
|
||||
QTest::addColumn<QString>("expectedHelpOutput");
|
||||
|
||||
QString expectedOutput =
|
||||
"Usage: testhelper/qcommandlineparser_test_helper [options] parsingMode command\n"
|
||||
"Test helper\n"
|
||||
"\n"
|
||||
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 automatic generation of implicit #include\n"
|
||||
" -directives.\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::fromLatin1(
|
||||
"Usage: testhelper/qcommandlineparser_test_helper [options] parsingMode command\n"
|
||||
"Test helper\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"
|
||||
|
Loading…
Reference in New Issue
Block a user