From 63274c95a3d78fbed8f511690cf7b248a6231273 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Thu, 17 Mar 2016 12:48:38 +0100 Subject: [PATCH] Add QCommandLineOption::Flags containing HiddenFromHelp and ShortOptionStyle This patch adds a new option, QCommandLineOption::ShortOptionStyle, which helps applications (such as compilers, so moc and now qdoc) which need to mix long-style and short flags. [ChangeLog][QtCore][QCommandLineOption] Added flags() and setFlags() methods. Added ShortOptionStyle and HiddenFromHelp flags. Change-Id: I944ce56aff2b28ecd6bb9d2d23c4e726e9d06647 Reviewed-by: Marc Mutz --- src/corelib/tools/qcommandlineoption.cpp | 58 ++++++++++++++++--- src/corelib/tools/qcommandlineoption.h | 16 +++++ src/corelib/tools/qcommandlineparser.cpp | 20 ++++++- .../qcommandlineparser_test_helper.cpp | 6 +- .../tst_qcommandlineparser.cpp | 11 ++++ 5 files changed, 98 insertions(+), 13 deletions(-) diff --git a/src/corelib/tools/qcommandlineoption.cpp b/src/corelib/tools/qcommandlineoption.cpp index 64cabcc304..1f7f9cc33b 100644 --- a/src/corelib/tools/qcommandlineoption.cpp +++ b/src/corelib/tools/qcommandlineoption.cpp @@ -49,14 +49,12 @@ class QCommandLineOptionPrivate : public QSharedData public: Q_NEVER_INLINE explicit QCommandLineOptionPrivate(const QString &name) - : names(removeInvalidNames(QStringList(name))), - hidden(false) + : names(removeInvalidNames(QStringList(name))) { } Q_NEVER_INLINE explicit QCommandLineOptionPrivate(const QStringList &names) - : names(removeInvalidNames(names)), - hidden(false) + : names(removeInvalidNames(names)) { } static QStringList removeInvalidNames(QStringList nameList); @@ -74,8 +72,7 @@ public: //! The list of default values used for this option. QStringList defaultValues; - //! Show or hide in --help - bool hidden; + QCommandLineOption::Flags flags; }; /*! @@ -394,6 +391,7 @@ QStringList QCommandLineOption::defaultValues() const return d->defaultValues; } +#if QT_DEPRECATED_SINCE(5, 8) /*! Sets whether to hide this option in the user-visible help output. @@ -401,11 +399,12 @@ QStringList QCommandLineOption::defaultValues() const a particular option makes it internal, i.e. not listed in the help output. \since 5.6 + \obsolete Use setFlags(QCommandLineOption::HiddenFromHelp), QCommandLineOption::HiddenFromHelp \sa isHidden */ void QCommandLineOption::setHidden(bool hide) { - d->hidden = hide; + d->flags.setFlag(HiddenFromHelp, hide); } /*! @@ -413,11 +412,52 @@ void QCommandLineOption::setHidden(bool hide) false if the option is listed. \since 5.6 - \sa setHidden() + \obsolete Use flags() & QCommandLineOption::HiddenFromHelp + \sa setHidden(), QCommandLineOption::HiddenFromHelp */ bool QCommandLineOption::isHidden() const { - return d->hidden; + return d->flags & HiddenFromHelp; +} +#endif + +/*! + Returns a set of flags that affect this command-line option. + + \since 5.8 + \sa setFlags(), QCommandLineOption::Flags + */ +QCommandLineOption::Flags QCommandLineOption::flags() const +{ + return d->flags; } +/*! + Set the set of flags that affect this command-line option. + + \since 5.8 + \sa flags(), QCommandLineOption::Flags + */ +void QCommandLineOption::setFlags(Flags flags) +{ + d->flags = flags; +} + +/*! + \enum QCommandLineOption::Flag + + \value HiddenFromHelp Hide this option in the user-visible help output. All + options are visible by default. Setting this flag for a particular + option makes it internal, i.e. not listed in the help output. + + \value ShortOptionStyle The option will always be understood as a short + option, regardless of what was set by + QCommandLineParser::setSingleDashWordOptionMode. + This allows flags such as \c{-DDEFINE=VALUE} or \c{-I/include/path} to be + interpreted as short flags even when the parser is in + QCommandLineParser::ParseAsLongOptions mode. + + \sa QCommandLineOption::setFlags(), QCommandLineOption::flags() +*/ + QT_END_NAMESPACE diff --git a/src/corelib/tools/qcommandlineoption.h b/src/corelib/tools/qcommandlineoption.h index a7747f9fb2..6ebaab3d48 100644 --- a/src/corelib/tools/qcommandlineoption.h +++ b/src/corelib/tools/qcommandlineoption.h @@ -50,6 +50,12 @@ class QCommandLineOptionPrivate; class Q_CORE_EXPORT QCommandLineOption { public: + enum Flag { + HiddenFromHelp = 0x1, + ShortOptionStyle = 0x2 + }; + Q_DECLARE_FLAGS(Flags, Flag) + explicit QCommandLineOption(const QString &name); explicit QCommandLineOption(const QStringList &names); /*implicit*/ QCommandLineOption(const QString &name, const QString &description, @@ -82,14 +88,24 @@ public: void setDefaultValues(const QStringList &defaultValues); QStringList defaultValues() const; + Flags flags() const; + void setFlags(Flags aflags); + +#if QT_DEPRECATED_SINCE(5, 8) + QT_DEPRECATED_X("Use setFlags() with HiddenFromHelp)") void setHidden(bool hidden); + QT_DEPRECATED_X("Use flags() and HiddenFromHelp") bool isHidden() const; +#endif + private: QSharedDataPointer d; }; Q_DECLARE_SHARED(QCommandLineOption) +Q_DECLARE_OPERATORS_FOR_FLAGS(QCommandLineOption::Flags) + QT_END_NAMESPACE diff --git a/src/corelib/tools/qcommandlineparser.cpp b/src/corelib/tools/qcommandlineparser.cpp index 6587d900d2..81568681d8 100644 --- a/src/corelib/tools/qcommandlineparser.cpp +++ b/src/corelib/tools/qcommandlineparser.cpp @@ -295,7 +295,9 @@ QCommandLineParser::~QCommandLineParser() i.e. as the long option named \c{abc}. This is how Qt's own tools (uic, rcc...) have always been parsing arguments. This mode should be used for preserving compatibility in applications that were parsing - arguments in such a way. + arguments in such a way. There is an exception if the \c{a} option has the + QCommandLineOption::ShortOptionStyle flag set, in which case it is still + interpreted as \c{-a bc}. \sa setSingleDashWordOptionMode() */ @@ -762,6 +764,18 @@ bool QCommandLineParserPrivate::parse(const QStringList &args) } case QCommandLineParser::ParseAsLongOptions: { + if (argument.size() > 2) { + const QString possibleShortOptionStyleName = argument.mid(1, 1); + const auto shortOptionIt = nameHash.constFind(possibleShortOptionStyleName); + if (shortOptionIt != nameHash.constEnd()) { + const auto &arg = commandLineOptionList.at(*shortOptionIt); + if (arg.flags() & QCommandLineOption::ShortOptionStyle) { + registerFoundOption(possibleShortOptionStyleName); + optionValuesHash[*shortOptionIt].append(argument.mid(2)); + break; + } + } + } const QString optionName = argument.mid(1).section(assignChar, 0, 0); if (registerFoundOption(optionName)) { if (!parseOptionValue(optionName, argument, &argumentIterator, args.end())) @@ -1097,7 +1111,7 @@ QString QCommandLineParserPrivate::helpText() const optionNameList.reserve(commandLineOptionList.size()); int longestOptionNameString = 0; for (const QCommandLineOption &option : commandLineOptionList) { - if (option.isHidden()) + if (option.flags() & QCommandLineOption::HiddenFromHelp) continue; const QStringList optionNames = option.names(); QString optionNamesString; @@ -1116,7 +1130,7 @@ QString QCommandLineParserPrivate::helpText() const ++longestOptionNameString; auto optionNameIterator = optionNameList.cbegin(); for (const QCommandLineOption &option : commandLineOptionList) { - if (option.isHidden()) + if (option.flags() & QCommandLineOption::HiddenFromHelp) continue; text += wrapText(*optionNameIterator, longestOptionNameString, option.description()); ++optionNameIterator; 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 36bc8621d2..30c7b1bf69 100644 --- a/tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.cpp +++ b/tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.cpp @@ -71,8 +71,12 @@ int main(int argc, char *argv[]) // A hidden option QCommandLineOption hiddenOption(QStringList() << QStringLiteral("hidden")); hiddenOption.setDescription(QStringLiteral("THIS SHOULD NEVER APPEAR")); - hiddenOption.setHidden(true); + hiddenOption.setFlags(QCommandLineOption::HiddenFromHelp); parser.addOption(hiddenOption); + QCommandLineOption hiddenOption2(QStringList() << QStringLiteral("hidden2")); + hiddenOption2.setDescription(QStringLiteral("NEITHER SHOULD THIS")); + hiddenOption2.setHidden(true); + parser.addOption(hiddenOption2); // This program supports different options depending on the "command" (first argument). // Call parse() to find out the positional arguments. diff --git a/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp b/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp index f3f335cb92..fd835daa3a 100644 --- a/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp +++ b/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp @@ -450,6 +450,13 @@ void tst_QCommandLineParser::testSingleDashWordOptionModes_data() << QStringList("abc") << QStringList("val"); QTest::newRow("implicitlylong_with_space") << QCommandLineParser::ParseAsCompactedShortOptions << (QStringList() << "-c" << "val") << QStringList("c") << QStringList("val"); + + QTest::newRow("forceshort_detached") << QCommandLineParser::ParseAsLongOptions << (QStringList() << "-I" << "45") + << QStringList("I") << QStringList("45"); + QTest::newRow("forceshort_attached") << QCommandLineParser::ParseAsLongOptions << (QStringList() << "-I46") + << QStringList("I") << QStringList("46"); + QTest::newRow("forceshort_mixed") << QCommandLineParser::ParseAsLongOptions << (QStringList() << "-I45" << "-nn") + << (QStringList() << "I" << "nn") << QStringList("45"); } void tst_QCommandLineParser::testSingleDashWordOptionModes() @@ -468,6 +475,10 @@ void tst_QCommandLineParser::testSingleDashWordOptionModes() parser.addOption(QCommandLineOption("b", QStringLiteral("b option."))); parser.addOption(QCommandLineOption(QStringList() << "c" << "abc", QStringLiteral("c option."), QStringLiteral("value"))); parser.addOption(QCommandLineOption("nn", QStringLiteral("nn option."))); + QCommandLineOption forceShort(QStringLiteral("I"), QStringLiteral("always short option"), + QStringLiteral("path"), QStringLiteral("default")); + forceShort.setFlags(QCommandLineOption::ShortOptionStyle); + parser.addOption(forceShort); QVERIFY(parser.parse(commandLine)); QCOMPARE(parser.optionNames(), expectedOptionNames); for (int i = 0; i < expectedOptionValues.count(); ++i)