Command-line option "--help-all"
-
Using Qt version 6.9.2 on Linux Ubuntu 24.04.3 LTS...
When I call my app with the "-h" or "--help" option, Qt "helpfully" adds the "--help-all" option to the ones I define myself.
For example:
MyApp -h ---- results in... ---- Usage: /home/bob/code/build/6.9.2/Debug/MyApp [options] Description: MyApp description Options: -h, --help Displays help on commandline options. --help-all Displays help, including generic Qt options. <-- Qt puts this here... -v, --version Displays version information. -c, --codec <CODEC> Codec to use for de-/encoding -m, --mib <MIB enum> Codec represented by its MIB enum value -l, --list-all List all available encodings -o, --output < - | FILENAME> Name of output file, or STDOUT if '-'
But if I call MyApp with the "--help-all" option, I get this:
Found options in command line: "help-all" An error occurred while parsing command line arguments: Unknown option name: help-all
I seem to remember reading about a bug two or three years ago, but I am a bit surprised that this is still the default behavior.
Since Qt is passing the "help-all" option back to my application, what am I supposed to do with it? I would imagine that Qt would show the "generic Qt options" itself instead of relying on the application to do this.
-
Using Qt version 6.9.2 on Linux Ubuntu 24.04.3 LTS...
When I call my app with the "-h" or "--help" option, Qt "helpfully" adds the "--help-all" option to the ones I define myself.
For example:
MyApp -h ---- results in... ---- Usage: /home/bob/code/build/6.9.2/Debug/MyApp [options] Description: MyApp description Options: -h, --help Displays help on commandline options. --help-all Displays help, including generic Qt options. <-- Qt puts this here... -v, --version Displays version information. -c, --codec <CODEC> Codec to use for de-/encoding -m, --mib <MIB enum> Codec represented by its MIB enum value -l, --list-all List all available encodings -o, --output < - | FILENAME> Name of output file, or STDOUT if '-'
But if I call MyApp with the "--help-all" option, I get this:
Found options in command line: "help-all" An error occurred while parsing command line arguments: Unknown option name: help-all
I seem to remember reading about a bug two or three years ago, but I am a bit surprised that this is still the default behavior.
Since Qt is passing the "help-all" option back to my application, what am I supposed to do with it? I would imagine that Qt would show the "generic Qt options" itself instead of relying on the application to do this.
@Robert-Hairgrove said in Command-line option "--help-all":
Since Qt is passing the "help-all" option back to my application, what am I supposed to do with it?
It is not meant to be passed to your code. It (and all other flags It documents) are intercepted in the
QCoreApplication
constructor. Make sure that the QApplication object is created before yourQCommandLineParser
, and you pass argc and argv to it. -
@Robert-Hairgrove said in Command-line option "--help-all":
Since Qt is passing the "help-all" option back to my application, what am I supposed to do with it?
It is not meant to be passed to your code. It (and all other flags It documents) are intercepted in the
QCoreApplication
constructor. Make sure that the QApplication object is created before yourQCommandLineParser
, and you pass argc and argv to it.@IgKh said in Command-line option "--help-all":
It is not meant to be passed to your code. It (and all other flags It documents) are intercepted in the QCoreApplication constructor. Make sure that the QApplication object is created before your QCommandLineParser, and you pass argc and argv to it.
It seems like Qt doesn't want anything to do with this option, either.
QCommandLineParser
's constructor takes no arguments. TheQCoreApplication
object is created as the first line inside themain()
function, and there I passargc
andargv
to the constructor. I am calling theparse()
function like this:// --- QCommandLineParser parser(); if (parser.parse(QCoreApplication::arguments())) { // etc.
Up to now, I have dealt with this problem by not calling
QCommandLineParser::showHelp()
directly, but by fetchingQCommandLineParser::helpText()
and removing the line beginning with--help-all
, then sending the altered string tostdout
. -
@IgKh said in Command-line option "--help-all":
It is not meant to be passed to your code. It (and all other flags It documents) are intercepted in the QCoreApplication constructor. Make sure that the QApplication object is created before your QCommandLineParser, and you pass argc and argv to it.
It seems like Qt doesn't want anything to do with this option, either.
QCommandLineParser
's constructor takes no arguments. TheQCoreApplication
object is created as the first line inside themain()
function, and there I passargc
andargv
to the constructor. I am calling theparse()
function like this:// --- QCommandLineParser parser(); if (parser.parse(QCoreApplication::arguments())) { // etc.
Up to now, I have dealt with this problem by not calling
QCommandLineParser::showHelp()
directly, but by fetchingQCommandLineParser::helpText()
and removing the line beginning with--help-all
, then sending the altered string tostdout
.@Robert-Hairgrove
About to have a look at this FWIW (never used this before so I don't know how it works). Do you or do you not explicitly callQCommandLineParser::addHelpOption()
? You do not mention it but I am assuming you do? I am comparing against https://forum.qt.io/topic/135533/how-to-remove-help-all-option-from-the-command-line-help-text/2. -
@Robert-Hairgrove
About to have a look at this FWIW (never used this before so I don't know how it works). Do you or do you not explicitly callQCommandLineParser::addHelpOption()
? You do not mention it but I am assuming you do? I am comparing against https://forum.qt.io/topic/135533/how-to-remove-help-all-option-from-the-command-line-help-text/2.@JonB Yes, I call
addHelpOption()
andaddVersionOption()
.I will take a look at the topic you linked and see if it does what I want.
-
The topic does not really "solve" your issue, it just does it in a different way. You call
addHelpOption()
and then remove--help-all ...
, they do not call it and instead add-h, --help ...
, I think? But you want Qt to parse a-h / --help
so I think you needaddHelpOption()
?You keep telling us about extra stuff you have/call. I am supposed to try yours out. That is why you really should post a minimal, complete example, not randomly tell us about things in your code at various stages in the conversation. And btw your
// --- QCommandLineParser parser(); if (parser.parse(QCoreApplication::arguments())) { // etc.
does not even compile...
-
Using Qt version 6.9.2 on Linux Ubuntu 24.04.3 LTS...
When I call my app with the "-h" or "--help" option, Qt "helpfully" adds the "--help-all" option to the ones I define myself.
For example:
MyApp -h ---- results in... ---- Usage: /home/bob/code/build/6.9.2/Debug/MyApp [options] Description: MyApp description Options: -h, --help Displays help on commandline options. --help-all Displays help, including generic Qt options. <-- Qt puts this here... -v, --version Displays version information. -c, --codec <CODEC> Codec to use for de-/encoding -m, --mib <MIB enum> Codec represented by its MIB enum value -l, --list-all List all available encodings -o, --output < - | FILENAME> Name of output file, or STDOUT if '-'
But if I call MyApp with the "--help-all" option, I get this:
Found options in command line: "help-all" An error occurred while parsing command line arguments: Unknown option name: help-all
I seem to remember reading about a bug two or three years ago, but I am a bit surprised that this is still the default behavior.
Since Qt is passing the "help-all" option back to my application, what am I supposed to do with it? I would imagine that Qt would show the "generic Qt options" itself instead of relying on the application to do this.
@Robert-Hairgrove said in Command-line option "--help-all":
But if I call MyApp with the "--help-all" option, I get this:
Works fine for me. Output:
jon@ubuntu-22:~/QtTests/C++$ cmdlinehelp/build/Desktop-Debug/cmdlinehelp --help-all parser.parse(QCoreApplication::arguments()) true Usage: cmdlinehelp/build/Desktop-Debug/cmdlinehelp [options] Options: -h, --help Displays help on commandline options. --help-all Displays help including Qt specific options. -v, --version Displays version information.
None of your
Unknown option name: help-all
. Code:#include <QCommandLineParser> #include <QCoreApplication> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QCommandLineParser parser; parser.addHelpOption(); parser.addVersionOption(); qDebug() << "parser.parse(QCoreApplication::arguments())" << parser.parse(QCoreApplication::arguments()); parser.showHelp(); return a.exec(); }
Ubuntu 24.04, Qt 6.4.2.
-
@Robert-Hairgrove said in Command-line option "--help-all":
But if I call MyApp with the "--help-all" option, I get this:
Works fine for me. Output:
jon@ubuntu-22:~/QtTests/C++$ cmdlinehelp/build/Desktop-Debug/cmdlinehelp --help-all parser.parse(QCoreApplication::arguments()) true Usage: cmdlinehelp/build/Desktop-Debug/cmdlinehelp [options] Options: -h, --help Displays help on commandline options. --help-all Displays help including Qt specific options. -v, --version Displays version information.
None of your
Unknown option name: help-all
. Code:#include <QCommandLineParser> #include <QCoreApplication> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QCommandLineParser parser; parser.addHelpOption(); parser.addVersionOption(); qDebug() << "parser.parse(QCoreApplication::arguments())" << parser.parse(QCoreApplication::arguments()); parser.showHelp(); return a.exec(); }
Ubuntu 24.04, Qt 6.4.2.
@JonB Here is my minimal(?) example:
#include <QCoreApplication> #include <QCommandLineOption> #include <QCommandLineParser> #include <QtCore> #include <QtDebug> #include <iostream> enum opt_info { opt_error = -1, opt_no_opt = 0x0, opt_codec = 0x1, opt_mib = 0x2, opt_list = 0x3, opt_help = 0x4, opt_version = 0x5, opt_filename = 0x10 }; int parseCommandLine(QCommandLineParser &parser, QString * pValue); int main(int argc, char *argv[]) { using namespace std; QCoreApplication a(argc, argv); QCoreApplication::setApplicationName("MyApp"); QCoreApplication::setApplicationVersion("1.0"); QCommandLineParser parser; parser.setApplicationDescription("Description: describes MyApp"); parser.addHelpOption(); parser.addVersionOption(); parser.addOptions({ {{"c", "codec"}, "Codec to use for de-/encoding", "CODEC"}, {{"m", "mib"}, "Codec represented by its MIB enum value", "MIB enum"}, {{"l", "list-all"}, "List all available encodings"}, {{"o", "output"}, "Name of output file, or STDOUT if '-'", " - | FILENAME"} }); QString opttext; QString filename; int res = parseCommandLine(parser, &opttext); if (res > opt_filename) { res -= opt_filename; int sep = opttext.indexOf("|"); if ((sep >= 0) && (sep < opttext.size()-1)) { filename = opttext.mid(sep+1); opttext.chop(opttext.size() - sep); } else { filename = opttext; } } switch (res) { case opt_error: cout << "An error occurred while parsing command line arguments:\n" << opttext.toStdString() << endl; break; case opt_help: cout << opttext.toStdString() << endl; break; case opt_version: parser.showVersion(); break; case opt_codec: cout << "A codec name was supplied:\n" << opttext.toStdString() << endl; break; case opt_mib: cout << "A MIB enum was supplied:\n" << opttext.toStdString() << endl; break; case opt_list: cout << "A list was requested." << endl; break; case opt_no_opt: default: cout << "No options were supplied (this should not happen)" << endl; break; } if (!filename.isEmpty()) { cout << "Output to a file was specified:\n" << filename.toStdString() << endl; } return 0; } int parseCommandLine(QCommandLineParser &parser, QString * pValue) { Q_ASSERT_X(pValue, __func__, "Argument 'pValue' was 'nullptr' (must be set)!"); int retval = opt_no_opt; pValue->clear(); if (!parser.parse(QCoreApplication::arguments())) { *pValue = parser.errorText(); return opt_error; } if (parser.isSet("h") || parser.isSet("help")) { *pValue = parser.helpText(); return opt_help; } if (parser.isSet("v") || parser.isSet("version")) { return opt_version; } QStringList opts = parser.optionNames(); QString fn; if (!opts.isEmpty()) { qDebug() << "Found options in command line:"; for (const QString &o : opts) { qDebug() << o; if (o.at(0) == 'c') { retval = opt_codec; *pValue = parser.value(o); } else if (o.at(0) == 'm') { retval = opt_mib; *pValue = parser.value(o); } else if (o.at(0) == 'l') { retval = opt_list; } else if (o.at(0) == 'o') { fn = parser.value(o); } else { retval = opt_error; *pValue = QString("Unknown option name: %1").arg(o); } } if ((retval != opt_error) && !fn.isEmpty()) { retval |= opt_filename; if (!pValue->isEmpty()) { pValue->append("|"); } pValue->append(fn); } } else { retval = opt_error; *pValue = "The parser returned no options."; } return retval; }
-
@JonB Here is my minimal(?) example:
#include <QCoreApplication> #include <QCommandLineOption> #include <QCommandLineParser> #include <QtCore> #include <QtDebug> #include <iostream> enum opt_info { opt_error = -1, opt_no_opt = 0x0, opt_codec = 0x1, opt_mib = 0x2, opt_list = 0x3, opt_help = 0x4, opt_version = 0x5, opt_filename = 0x10 }; int parseCommandLine(QCommandLineParser &parser, QString * pValue); int main(int argc, char *argv[]) { using namespace std; QCoreApplication a(argc, argv); QCoreApplication::setApplicationName("MyApp"); QCoreApplication::setApplicationVersion("1.0"); QCommandLineParser parser; parser.setApplicationDescription("Description: describes MyApp"); parser.addHelpOption(); parser.addVersionOption(); parser.addOptions({ {{"c", "codec"}, "Codec to use for de-/encoding", "CODEC"}, {{"m", "mib"}, "Codec represented by its MIB enum value", "MIB enum"}, {{"l", "list-all"}, "List all available encodings"}, {{"o", "output"}, "Name of output file, or STDOUT if '-'", " - | FILENAME"} }); QString opttext; QString filename; int res = parseCommandLine(parser, &opttext); if (res > opt_filename) { res -= opt_filename; int sep = opttext.indexOf("|"); if ((sep >= 0) && (sep < opttext.size()-1)) { filename = opttext.mid(sep+1); opttext.chop(opttext.size() - sep); } else { filename = opttext; } } switch (res) { case opt_error: cout << "An error occurred while parsing command line arguments:\n" << opttext.toStdString() << endl; break; case opt_help: cout << opttext.toStdString() << endl; break; case opt_version: parser.showVersion(); break; case opt_codec: cout << "A codec name was supplied:\n" << opttext.toStdString() << endl; break; case opt_mib: cout << "A MIB enum was supplied:\n" << opttext.toStdString() << endl; break; case opt_list: cout << "A list was requested." << endl; break; case opt_no_opt: default: cout << "No options were supplied (this should not happen)" << endl; break; } if (!filename.isEmpty()) { cout << "Output to a file was specified:\n" << filename.toStdString() << endl; } return 0; } int parseCommandLine(QCommandLineParser &parser, QString * pValue) { Q_ASSERT_X(pValue, __func__, "Argument 'pValue' was 'nullptr' (must be set)!"); int retval = opt_no_opt; pValue->clear(); if (!parser.parse(QCoreApplication::arguments())) { *pValue = parser.errorText(); return opt_error; } if (parser.isSet("h") || parser.isSet("help")) { *pValue = parser.helpText(); return opt_help; } if (parser.isSet("v") || parser.isSet("version")) { return opt_version; } QStringList opts = parser.optionNames(); QString fn; if (!opts.isEmpty()) { qDebug() << "Found options in command line:"; for (const QString &o : opts) { qDebug() << o; if (o.at(0) == 'c') { retval = opt_codec; *pValue = parser.value(o); } else if (o.at(0) == 'm') { retval = opt_mib; *pValue = parser.value(o); } else if (o.at(0) == 'l') { retval = opt_list; } else if (o.at(0) == 'o') { fn = parser.value(o); } else { retval = opt_error; *pValue = QString("Unknown option name: %1").arg(o); } } if ((retval != opt_error) && !fn.isEmpty()) { retval |= opt_filename; if (!pValue->isEmpty()) { pValue->append("|"); } pValue->append(fn); } } else { retval = opt_error; *pValue = "The parser returned no options."; } return retval; }
@Robert-Hairgrove
This is nowhere near minimal!!Your whole code, and your own error message, relies on
int res = parseCommandLine(parser, &opttext);
and the result that returns causing you to print the error message. (I assumed you meant Qt output it, you didn't say anything about this.) That function seems to me to allow for
-h
and--help
(if (parser.isSet("h") || parser.isSet("help"))
) but not--help-all
, so what do you expect?! If you are not going to allow--help-all
you cannot afford to useaddHelpOption()
:QCommandLineOption QCommandLineParser::addHelpOption()
Adds help options to the command-line parser.
The options specified for this command-line are described by -h or --help. On Windows, the alternative -? is also supported. The option --help-all extends that to include generic Qt options, not defined by this command, in the output.
-
@JonB Here is my minimal(?) example:
#include <QCoreApplication> #include <QCommandLineOption> #include <QCommandLineParser> #include <QtCore> #include <QtDebug> #include <iostream> enum opt_info { opt_error = -1, opt_no_opt = 0x0, opt_codec = 0x1, opt_mib = 0x2, opt_list = 0x3, opt_help = 0x4, opt_version = 0x5, opt_filename = 0x10 }; int parseCommandLine(QCommandLineParser &parser, QString * pValue); int main(int argc, char *argv[]) { using namespace std; QCoreApplication a(argc, argv); QCoreApplication::setApplicationName("MyApp"); QCoreApplication::setApplicationVersion("1.0"); QCommandLineParser parser; parser.setApplicationDescription("Description: describes MyApp"); parser.addHelpOption(); parser.addVersionOption(); parser.addOptions({ {{"c", "codec"}, "Codec to use for de-/encoding", "CODEC"}, {{"m", "mib"}, "Codec represented by its MIB enum value", "MIB enum"}, {{"l", "list-all"}, "List all available encodings"}, {{"o", "output"}, "Name of output file, or STDOUT if '-'", " - | FILENAME"} }); QString opttext; QString filename; int res = parseCommandLine(parser, &opttext); if (res > opt_filename) { res -= opt_filename; int sep = opttext.indexOf("|"); if ((sep >= 0) && (sep < opttext.size()-1)) { filename = opttext.mid(sep+1); opttext.chop(opttext.size() - sep); } else { filename = opttext; } } switch (res) { case opt_error: cout << "An error occurred while parsing command line arguments:\n" << opttext.toStdString() << endl; break; case opt_help: cout << opttext.toStdString() << endl; break; case opt_version: parser.showVersion(); break; case opt_codec: cout << "A codec name was supplied:\n" << opttext.toStdString() << endl; break; case opt_mib: cout << "A MIB enum was supplied:\n" << opttext.toStdString() << endl; break; case opt_list: cout << "A list was requested." << endl; break; case opt_no_opt: default: cout << "No options were supplied (this should not happen)" << endl; break; } if (!filename.isEmpty()) { cout << "Output to a file was specified:\n" << filename.toStdString() << endl; } return 0; } int parseCommandLine(QCommandLineParser &parser, QString * pValue) { Q_ASSERT_X(pValue, __func__, "Argument 'pValue' was 'nullptr' (must be set)!"); int retval = opt_no_opt; pValue->clear(); if (!parser.parse(QCoreApplication::arguments())) { *pValue = parser.errorText(); return opt_error; } if (parser.isSet("h") || parser.isSet("help")) { *pValue = parser.helpText(); return opt_help; } if (parser.isSet("v") || parser.isSet("version")) { return opt_version; } QStringList opts = parser.optionNames(); QString fn; if (!opts.isEmpty()) { qDebug() << "Found options in command line:"; for (const QString &o : opts) { qDebug() << o; if (o.at(0) == 'c') { retval = opt_codec; *pValue = parser.value(o); } else if (o.at(0) == 'm') { retval = opt_mib; *pValue = parser.value(o); } else if (o.at(0) == 'l') { retval = opt_list; } else if (o.at(0) == 'o') { fn = parser.value(o); } else { retval = opt_error; *pValue = QString("Unknown option name: %1").arg(o); } } if ((retval != opt_error) && !fn.isEmpty()) { retval |= opt_filename; if (!pValue->isEmpty()) { pValue->append("|"); } pValue->append(fn); } } else { retval = opt_error; *pValue = "The parser returned no options."; } return retval; }
@Robert-Hairgrove
Quite separately, just a couple of observations on yourint parseCommandLine(QCommandLineParser &parser, QString * pValue)
-
You could avoid the nasty "accept a pointer and assert if it's null" by defining it to take a
QString &
instead ofQString *
. -
You could avoid having a "free C function" (we don't much like those these days!) and taking
QCommandLineParser &parser
as a parameter if you chose either to subclassQCommandLineParser
for your own purpose and adding yourparseCommandLine()
as a member method or maybe a class which encapsulates aQCommandLineParser
and has theparseCommandLine()
member.
Both stylistic, just they seem neater to me, but no difference to your issue so as you please.
-
-
@Robert-Hairgrove
Quite separately, just a couple of observations on yourint parseCommandLine(QCommandLineParser &parser, QString * pValue)
-
You could avoid the nasty "accept a pointer and assert if it's null" by defining it to take a
QString &
instead ofQString *
. -
You could avoid having a "free C function" (we don't much like those these days!) and taking
QCommandLineParser &parser
as a parameter if you chose either to subclassQCommandLineParser
for your own purpose and adding yourparseCommandLine()
as a member method or maybe a class which encapsulates aQCommandLineParser
and has theparseCommandLine()
member.
Both stylistic, just they seem neater to me, but no difference to your issue so as you please.
@JonB Thanks, I realize that passing by reference is better. But it doesn't really have anything to do with the topic.
Here is a quote from the documentation of
QCommandLineParser
:Known limitation: The parsing of Qt options inside QCoreApplication and subclasses
happens before QCommandLineParser exists, so it can't take it into
account. This means any option value that looks like a builtin
Qt option will be treated by QCoreApplication as a builtin Qt option.Example: --profile -reverse will lead to QGuiApplication seeing
the -reverse option set, and removing it from
QCoreApplication::arguments() before QCommandLineParser defines the
profile option and parses the command line.This is why I didn't expect the
"--help-all"
option to be passed back to my application. -
-
I am marking this as "solved" because I can work around it, now that I know that
"--help-all"
will be passed back to my application. I should call"QCommandLineParser::showHelp()"
if either the simple help option or the help-all option was passed.However, in this particular case, Qt doesn't add any other options to my own except for "help-all" because with both options, the exact same help text is shown. One might think that if Qt doesn't have any options of its own to add, that it wouldn't need to add the "help-all" option to the help output...
-