cxxopts icon indicating copy to clipboard operation
cxxopts copied to clipboard

short option ignores an argument

Open crusader-mike opened this issue 5 years ago • 6 comments

I have code (simplified):

    cxxopts::Options opts("jobsrv", "Job Server");
    opts.add_options()
        ("w,dump-data", "write data to <filename>.json", cxxopts::value<string>()->implicit_value("default_filename"), "filename")
        ("f,file", "file to process (e.g. /dir1/a.txt)", cxxopts::value<vector<string>>())
        ;
    opts.parse_positional(vector<string>{ "f" });
    opts.positional_help("[<file>...]");
    auto cmdline = opts.parse(argc, argv);

    ...

    if (cmdline.count("w"))
    {
        string job_name = cmdline["w"].as<string>();
    ...

... now if I run my binary like this: <binary> --dump-job=newfile then job_name contains newfile and all is dandy.

... but if I run it like this: <binary> --dump-job newfile or <binary> -w newfile then job_name contains default_filename (and newfile ends up in positional arguments).

... and if I run it like this: <binary> -w=newfile it complains with Argument '-w=newfile' starts with a - but has incorrect syntax.

Did I miss something when definition my options?

crusader-mike avatar Nov 05 '19 20:11 crusader-mike

The reason that newfile ends up in positional arguments is because --dump-job has an implicit parameter. There were a few issues previously with confusion about implicit parameters and assumptions about where the arguments should go, and that seemed like the clearest way to solve it.

For the short option, I think if you write -wnewfile you will get what you want.

jarro2783 avatar Nov 05 '19 20:11 jarro2783

Hmm... What is the best way to deal with this situation? get rid of implicit parameter?

For the short option, I think if you write -wnewfile you will get what you want.

Nope, fails with same exception

crusader-mike avatar Nov 05 '19 21:11 crusader-mike

Ok I remember now, you have to use the long option with =.

jarro2783 avatar Nov 06 '19 06:11 jarro2783

OK. So it is a bug. But it has a work-around. I would like to try to fix it.

formidable01 avatar Nov 06 '19 06:11 formidable01

The problem is that with an implicit value, when you write --option by itself, you get the option set with its implicit value. So the parser can't tell whether to consume the next argument as the option value or to make it a positional argument. There was a previous bug where someone was writing --option value and expecting value to be a positional parameter.

jarro2783 avatar Nov 06 '19 07:11 jarro2783

So, this is design-level problem -- I guess you need to provide stricter definition of implicit value and how it gets handled in presence of positional options.

May be it makes sense to provide strict definition of command line (BNF grammar?) and build your object model based on it? Will probably lead to significant overhaul of the library as well as usage of some parser framework (smth like Boost Spirit only without boost dependency?)

As for workaround -- it seems for me it is the best to remove implicit value. Am I right?

crusader-mike avatar Nov 06 '19 14:11 crusader-mike