Enable a set of flags if one specific flag is enabled
Hello,
Assume I have flags -a, -b, -c, -d.
Now let's say that I want to create a flag -Z. When provided, this flag should also enable flags -b and -c. This is similar for example to the -a flag in rsync, which automatically enables certain other flags. From the rsync man page:
-a, --archive archive mode; equals -rlptgoD (no -H,-A,-X)
Is there any functionality in CLI11 to facilitate this?
If I am reading your question correctly you want to define a flag -Z which essentially acts like you specified -b -c.
If that is what you mean there is no prebuilt functionality for it but you can add it using a preparse_callback. For example
auto b=app.add_flag("-b",bflag,"b flag");
auto c=app.add_flag("-c",cflag,"c flag");
auto triggerGroup=app.add_option_group("Zgroup");
triggerGroup->add_flag("-Z");
triggerGroup->preparse_callback([a,b](std::size_t){b->add_result("true"); c->add_result("true");});
The preparse callback gets executed immediately after the -Z flag is specified in this case. I have never tried it but I don't know why it wouldn't work.
I might add a test case for this soon, and maybe consider making a function like TriggerOn or deprecate
Hi Philip,
The method you proposed works. However, I would like the -Z flag to appear like a regular flag in the help menu and not show the "[Option Group: Zgroup]" above it.
How can this be done?
I would like to treat it as a regular flag and assign it to visual groups etc. If there was a preparse_callback function for regular flags that would make this trivial without having to use option groups.
Thank you.
I might look at this a little more later on to see if there are things that can be done to make this simpler in the future. In the mean time
CLI::Option *b;
CLI::Option *c;
app.add_flag_callback("-Z", [&b, &c]() {b->add_result("true"); c->add_result("true"); }, "equivalent to -b -c");
bool bval{ false };
bool cval{ false };
b = app.add_flag("-b", bval, "set b to true");
c = app.add_flag("-c", cval, "set c to true");
args = { "-Z"};
run();
EXPECT_TRUE(bval);
EXPECT_TRUE(cval);
I tried out this test, It relies on ordering of the options. So the callback for the Z flag would have to come before the callbacks for the others. So this does work, not the most elegant of solutions but I am not sure a general facility to order option callbacks would be all that wise either since option groups can already do that to some extent. But perhaps a means of making the option group options in the help show up like other options is in order.
Here is an alternative using the app callback
bool bval{false};
bool cval{false};
auto b = app.add_flag("-b", bval, "set b to true");
auto c = app.add_flag("-c", cval, "set c to true");
app.add_flag("-Z", "equivalent to -b -c");
auto tapp = &app;
app.final_callback([b, c, tapp]() {
if((*tapp)["-Z"]) {
b->add_result("true")->run_callback();
c->add_result("true")->run_callback();
}
});
args = {"-Z"};
run();
EXPECT_TRUE(bval);
EXPECT_TRUE(cval);
Thank you for writing these solutions.
The last solution does not seem to work if there is an option that needs one of the options enabled by flag -Z. So if there is a flag -k that needs flag -b, if I provide flag -Z, flag -k will cause an error because it requires -b, even though it is enabled by flag -Z.
I assume this is because final_callback() executes in the end, after the phase where needs, excludes, etc are processed.
You might try to use the parse_complete_callback that executes a bit earlier in the process.
Maybe there is a use case for a fourth callback that executes after the arguments have been parsed but before the the options are actually processed and checked, or maybe parse_complete should be there and a new one where parse complete actually is now.
I am guessing that is not going to work either, since I am pretty sure that still runs after the option callbacks.
Yes, parse_complete_callback does not work either.
I think it would be great to have a callback that occurs after parsing but before option processing or checking. It could also allow for custom, more advanced option validation logic if a user wishes to provide some (for example check if two different float options when divided have a result less than 0.5 and provide custom error messages etc).
4 callbacks 1). pre_parse - After the first argument is called in the app/subcommand 2). [NEW] post_parse (maybe pre_processing)- After parsing, but before option callbacks and checks are processed 3). parse_complete - After option_processing before subcommand callbacks 4). final_callback - Last thing done before exiting
That would allow some new and interesting possibilities.
It will probably be a little while before I get to that though, there is a bit of a backlog until @henryiii is able to devote some time again.