New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Wrong text when no arguments supplied #234
Comments
A short-term fix would be to use a different pattern. // confusing errors
program.add_argument("first name");
program.add_argument("middle name");
program.add_argument("last name");
// versus
// gives correct count of missing arguments
program.add_argument("names").nargs(3); This should give a more meaningful error to your users. But, yes, it may not semantically fit with your use. Please leave this Issue open. This has come up before and we should address it. |
@rnwhitehead I looked at this again and I'm now not sure it's as bad as I first believed. The "confusing errors" pattern gives Can you give a simplified example of how you are using positional arguments? |
I don't see why it's right: it needs 3 positional parameters, why does it say "1 argument(s) expected"? It should say "3 positional arguments expected" or if that can't be done, "Insufficient positional arguments provided", or simply don't say anything - which is what most commands and apps do on Linux:
|
It says If the program specified program.add_argument("first name").nargs(3); then you'd see |
That is confusing from a user perspective, though. IMO the "N arguments expected" should be the sum of all nargs for all positional arguments, because anything else is ambiguous. The way it is specified in code shouldn't really matter here; it's about what makes sense to the user trying to interpret the error message. |
How do you think it should it be presented for Consider this example: #include "argparse.hpp"
#include <iostream>
int main(int argc, char *argv[])
{
argparse::ArgumentParser program("program_name");
program.add_argument("first_name");
program.add_argument("middle_name");
program.add_argument("last_name").nargs(1, 3);
try
{
program.parse_args(argc, argv);
}
catch (const std::exception &err)
{
std::cerr << err.what() << "\n";
std::cerr << program;
return 1;
}
std::cout << program.get("first_name") << "\n";
std::cout << program.get("middle_name") << "\n";
std::cout << program.get("last_name") << "\n";
return 0;
} with usage: foo:bar$ ./program Foo Bar
foo:bar$ ./main Foo Bar
last_name: 1 to 3 argument(s) expected. 0 provided.
Usage: program_name [-h] first_name middle_name last_name
Positional arguments:
first_name
middle_name
last_name [nargs=1..3]
Optional arguments:
-h, --help shows help message and exits
-v, --version prints version information and exits Should it instead sum all the nargs and say That's sounds more ambiguous than simply reporting that for the current positional argument |
Yea, I think so. It seems clearer to me, though of course that's a matter of taste. More fundamentally you could argue that an application with multiple positional arguments with varying amounts of |
Honestly, the rest of the help output is so clear, you could simply not output this line, it isn't really helping. |
@rnwhitehead It sounds like the default error message is not appropriate for your users. So catch the exception and throw your own error message. try {
program.parse_args(arguments);
} catch ( const std::runtime_error &e ) {
if ( e.what() == std::string{"first name: 1 argument(s) expected. 0 provided."} ) {
throw std::runtime_error("a full name (at least three words) is required");
}
if ( e.what() == std::string{"middle name: 1 argument(s) expected. 0 provided."} ) {
throw std::runtime_error("only a first name was given, a full name is required");
}
if ( e.what() == std::string{"last name: 1 argument(s) expected. 0 provided."} ) {
throw std::runtime_error("almost there, three names are required");
}
} Rather than viewing the argparse error message as the mandatory user message, think of it as a starting point for your custom messages. In my own projects, I've used a similar pattern to replace the generic missing positional argument error with a reminder that a configuration file path is required. |
If I require 3 positional arguments, but none are supplied, it always says "1 argument(s) expected. 0 provided.", rather than "3 arguments(s) expected..."
It doesn't matter if you add ".required()" or not.
This is confusing for the user. It would be better to simply not print this line, in fact - the help output is sufficient; prefixing it with this incorrect information is just confusing..
The text was updated successfully, but these errors were encountered: