CLI11 icon indicating copy to clipboard operation
CLI11 copied to clipboard

Cannot choose group based on flag

Open BMBurstein opened this issue 3 years ago • 4 comments

#include <CLI/CLI.hpp>
int main(int argc, char **argv) {
    CLI::App app{"App"};

    int a, b;
    bool other;

    auto ogroup_a = app.add_option_group("a_group", "do a");
    ogroup_a->add_option("a", a, "option a")->required();

    auto ogroup_b = app.add_option_group("b_group", "do other");
    ogroup_b->add_option("-o", other, "do other thing")->required();
    ogroup_b->add_option("b", b, "option b")->required();
  
    app.require_option(1);
    CLI11_PARSE(app, argc, argv);
}

I want to be able to run either this: a.out 1 or this: a.out -o 2

But if I try to run the second one I get

b is required
Run with --help for more information.

BMBurstein avatar Jun 01 '22 11:06 BMBurstein

#include <CLI/CLI.hpp>
int main(int argc, char **argv) {
    CLI::App app{"App"};

    int a, b;

    auto ogroup = app.add_option_group("subgroup", "do a");
    ogroup->add_option("a", a, "option a");
    ogroup->add_option("-o", b, "do other thing");
  
    ogroup->require_option(1,1);  // specify exactly one option from the group must be selected
    CLI11_PARSE(app, argc, argv);
}

I think this will do what you want

phlptp avatar Jun 06 '22 01:06 phlptp

The way you had it before was just grouping so both were required as if they were members of the app directly.

phlptp avatar Jun 06 '22 01:06 phlptp

That doesn't do the same thing. I realize I made a mistake in the example. It should have been

#include <CLI/CLI.hpp>
int main(int argc, char **argv) {
    CLI::App app{"App"};

    int a, b;
    bool other;

    auto ogroup_a = app.add_option_group("a_group", "do a");
    ogroup_a->add_option("a", a, "option a")->required();

    auto ogroup_b = app.add_option_group("b_group", "do other");
    ogroup_b->add_flag("-o", other, "do other thing")->required();
    ogroup_b->add_option("b", b, "option b")->required();
  
    app.require_option(1);
    CLI11_PARSE(app, argc, argv);
}

And the error is:

> ./a.out -o 2
Exactly 1 option from [,[Option Group: a_group],[Option Group: b_group]] is required and 2 were given
Run with --help for more information.

BMBurstein avatar Jun 06 '22 06:06 BMBurstein

Ok so

int main(int argc, const char *argv[]) {

    CLI::App app{"App"};

    int a{0}, b{0};
    bool other{false};

    auto ogroup_a = app.add_option_group("a_group", "do a");
    ogroup_a->enabled_by_default();
    ogroup_a->add_option("a", a, "option a")->required();

    auto triggerGroup = app.add_option_group("trigger", "trigger for group b");
    auto oflag = triggerGroup->add_flag("-o", other, "do other thing");

    auto ogroup_b = app.add_option_group("b_group", "do other");
    ogroup_b->add_option("b", b, "option b")->required();
    ogroup_b->disabled_by_default();

    triggerGroup->preparse_callback([ogroup_a, ogroup_b](std::size_t) {
        ogroup_b->disabled(false);
        ogroup_a->disabled();
    });

    CLI11_PARSE(app, argc, argv);
    if(other) {
        std::cout << "selected other b=" << b << std::endl;
    } else {
        std::cout << "selected a =" << a << std::endl;
    }
}

will produce

> ./a.out -o 2
selected other b=2
> ./a.out 1
selected a =1

if you want to disallow something like

> ./a.out 1 -o 2
selected other b=2

Then you need to add this line

ogroup_a->preparse_callback([triggerGroup](std::size_t) {
        triggerGroup->disabled();
    });

Then

> ./a.out 1 -o 2
The following arguments were not expected: 2 -o
Run with --help for more information.

phlptp avatar Jun 07 '22 13:06 phlptp