bfgroup / Lyra

A simple to use, composable, command line parser for C++ 11 and beyond
https://bfgroup.github.io/Lyra/
Boost Software License 1.0
483 stars 58 forks source link

Unknown options are silently ignored and mixed with positional arguments #58

Closed lahwaacz closed 2 years ago

lahwaacz commented 2 years ago

When there are options as well as positional arguments, some of which may be optional, there is a problem with unknown options. Consider this repro case:

int foo = 0;
std::string positional;
std::string optional = "default";

auto cli = lyra::cli();
cli |= lyra::opt(foo, "foo")["--foo"];
cli |= lyra::arg(positional, "positional");
cli |= lyra::arg(optional, "optional").optional();

auto result = cli.parse(lyra::args({ argv[0], "--foo", "1", "--bar", "a" }));
if (!result) {
    std::cerr << "Error in command line: " << result.errorMessage() << std::endl;
    std::cerr << cli << std::endl;
    return EXIT_FAILURE;
}

std::cout << "foo = " << foo << std::endl;
std::cout << "positional = " << positional << std::endl;
std::cout << "optional = " << optional << std::endl;

which leads to this output:

foo = 1
positional = --bar
optional = a

This is a problem, because --bar as is not reported as unknown/invalid option, but passed to the next positional argument. It is pretty unlikely that the user intended to use --bar as a positional argument -- most likely they made a typo or another mistake and need to read the help page.

grafikrobot commented 2 years ago

This is related to https://github.com/bfgroup/Lyra/issues/24

lahwaacz commented 2 years ago

GNU tools and many others use the -- argument as separator indicating that all following arguments are positionals rather than options. See e.g. grep example.

grafikrobot commented 2 years ago

GNU tools and many others use the -- argument as separator indicating that all following arguments are positionals rather than options. See e.g. grep example.

Right. There are two choices.. You do not treat "--xxx" as a special prefix that only means an option. Which is what Lyra does currently. Or you do make "--xxx" special and then need the special token, i.e. "--"by itself, to turn off the restriction. The only way for a CLI to support that would be have two different, mutually exclusive, parsing modes.