From 61e91cb2812a2ba63354dbfb7a1fb4debcfcbe9e Mon Sep 17 00:00:00 2001 From: Kaloyan Chehlarski Date: Fri, 23 Aug 2024 14:24:24 +0200 Subject: [PATCH] QCommandLineParser: Support ignoring input past a certain option This change adds a new flag to QCommandLineOption to indicate that any command line options that follow are to be ignored by QCommandLineParser. When an option with that flag is parsed, any subsequent options are immediately skipped, and the parser will return true, indicating success. This is motivated by Qt WebEngine's need for being able to pass through command line options from the host application to the underlying Chromium. This is done by using the --webEngineArgs option, which separates the Qt application options (on the left), and the Chromium ones (on the right). With this change, this mechanism will no longer clash with QCommandLineParser's behavior of shutting the app down when encountering an unknown option. Change-Id: I31aedb7a18e551def742891623604513a329d7ca Reviewed-by: David Faure --- src/corelib/tools/qcommandlineoption.cpp | 4 ++++ src/corelib/tools/qcommandlineoption.h | 3 ++- src/corelib/tools/qcommandlineparser.cpp | 7 ++++++- .../tst_qcommandlineparser.cpp | 18 +++++++++++++++++- 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/corelib/tools/qcommandlineoption.cpp b/src/corelib/tools/qcommandlineoption.cpp index 6b990cecf17..5d8f089d5b9 100644 --- a/src/corelib/tools/qcommandlineoption.cpp +++ b/src/corelib/tools/qcommandlineoption.cpp @@ -389,6 +389,10 @@ void QCommandLineOption::setFlags(Flags flags) interpreted as short flags even when the parser is in QCommandLineParser::ParseAsLongOptions mode. + \value IgnoreOptionsAfter [since 6.9] No options beyond this one will be parsed. Useful + for cases where you need to send extra command line arguments to a secondary + application. If a value is provided for this option, it will be ignored. + \sa QCommandLineOption::setFlags(), QCommandLineOption::flags() */ diff --git a/src/corelib/tools/qcommandlineoption.h b/src/corelib/tools/qcommandlineoption.h index 63c90a4005a..f2e89509fd8 100644 --- a/src/corelib/tools/qcommandlineoption.h +++ b/src/corelib/tools/qcommandlineoption.h @@ -19,7 +19,8 @@ class Q_CORE_EXPORT QCommandLineOption public: enum Flag { HiddenFromHelp = 0x1, - ShortOptionStyle = 0x2 + ShortOptionStyle = 0x2, + IgnoreOptionsAfter = 0x4, }; Q_DECLARE_FLAGS(Flags, Flag) diff --git a/src/corelib/tools/qcommandlineparser.cpp b/src/corelib/tools/qcommandlineparser.cpp index ffe1193fc34..5aa1cc9d697 100644 --- a/src/corelib/tools/qcommandlineparser.cpp +++ b/src/corelib/tools/qcommandlineparser.cpp @@ -653,7 +653,12 @@ bool QCommandLineParserPrivate::parseOptionValue(const QString &optionName, cons if (nameHashIt != nameHash.constEnd()) { const qsizetype assignPos = argument.indexOf(assignChar); const NameHash_t::mapped_type optionOffset = *nameHashIt; - const bool withValue = !commandLineOptionList.at(optionOffset).valueName().isEmpty(); + const QCommandLineOption &option = commandLineOptionList.at(optionOffset); + if (option.flags() & QCommandLineOption::IgnoreOptionsAfter) { + *argumentIterator = argsEnd; + return true; + } + const bool withValue = !option.valueName().isEmpty(); if (withValue) { if (assignPos == -1) { ++(*argumentIterator); diff --git a/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp b/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp index 812cf2d1b3d..374c397f9b1 100644 --- a/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp +++ b/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp @@ -59,6 +59,7 @@ private slots: void testHelpAll_data(); void testHelpAll(); void testVeryLongOptionNames(); + void testIgnoringOptions(); }; static char *empty_argv[] = { 0 }; @@ -784,6 +785,21 @@ void tst_QCommandLineParser::testVeryLongOptionNames() #endif // QT_CONFIG(process) } +void tst_QCommandLineParser::testIgnoringOptions() +{ + QCommandLineParser parser; + QCommandLineOption ignoreAfterOption(QStringLiteral("ignoreAfterOption")); + ignoreAfterOption.setFlags(QCommandLineOption::IgnoreOptionsAfter); + ignoreAfterOption.setValueName(QStringLiteral("ignoreAfterValue")); + parser.addOption(ignoreAfterOption); + QCommandLineOption normalOption(QStringLiteral("normalOption")); + parser.addOption(QCommandLineOption(QStringLiteral("normalOption"))); + QVERIFY(parser.parse({"executableName", "--normalOption", "--ignoreAfterOption=value", "--badOption", "notAnOption"})); + QVERIFY(parser.isSet(normalOption)); + QVERIFY(parser.isSet(ignoreAfterOption)); // The ignore option is not ignored itself + QVERIFY(parser.value(ignoreAfterOption).isEmpty()); // Values passed to the ignore option should be ignored + QVERIFY(!parser.isSet("badOption")); +} + QTEST_APPLESS_MAIN(tst_QCommandLineParser) #include "tst_qcommandlineparser.moc" -