1
0
mirror of https://github.com/CLIUtils/CLI11.git synced 2025-05-03 05:53:52 +00:00

Adding a number to required_subcommand

This commit is contained in:
Henry Fredrick Schreiner 2017-02-24 12:54:37 -05:00
parent 1884108578
commit ade78c5842
4 changed files with 30 additions and 5 deletions

View File

@ -1,3 +1,7 @@
## Version 0.6
* Added the ability to add a number to `.require_subcommand()`.
## Version 0.5
* Allow `Hidden` options.

View File

@ -157,7 +157,9 @@ everything after that is positional only.
## Subcommands
Subcommands are naturally supported, with an infinite depth. To add a subcommand, call the `add_subcommand` method with a name and an optional description. This gives a pointer to an `App` that behaves just like the main app, and can take options or further subcommands. Add `->ignore_case()` to a subcommand to allow any variation of caps to also be accepted. Children inherit the current setting from the parent. You cannot add multiple matching subcommand names at the same level (including ignore case).
Subcommands are naturally supported, with an infinite depth. To add a subcommand, call the `add_subcommand` method with a name and an optional description. This gives a pointer to an `App` that behaves just like the main app, and can take options or further subcommands. Add `->ignore_case()` to a subcommand to allow any variation of caps to also be accepted. Children inherit the current setting from the parent. You cannot add multiple matching subcommand names at the same level (including ignore
case).
If you want to require at least one subcommand is given, use `.require_subcommand()` on the parent app. You can optionally give an exact number of subcommands to require, as well.
All `App`s have a `get_subcommands()` method, which returns a list of pointers to the subcommand passed on the command line. A simple compare of these pointers to each subcommand allows choosing based on subcommand, facilitated by a `got_subcommand(App_or_name) method that will check the list for you. For many cases, however, using an app's callback may be easier. Every app executes a callback function after it parses; just use a lambda function (with capture to get parsed values) to `.add_callback`. If you throw `CLI::Success`, you can
even exit the program through the callback. The main `App` has a callback slot, as well, but it is generally not as useful.

View File

@ -52,7 +52,7 @@ protected:
std::vector<App_p> subcommands;
bool parsed {false};
std::vector<App*> selected_subcommands;
bool required_subcommand = false;
int required_subcommand = 0; ///< -1 for 1 or more, 0 for not required, # for exact number required
std::string progname {"program"};
Option* help_flag {nullptr};
@ -476,7 +476,7 @@ public:
}
if(subcommands.size() > 0) {
if(required_subcommand)
if(required_subcommand != 0)
out << " SUBCOMMAND";
else
out << " [SUBCOMMAND]";
@ -571,7 +571,7 @@ public:
/// Require a subcommand to be given (does not affect help call)
/// Does not return a pointer since it is supposed to be called on the main App.
void require_subcommand(bool value = true) {
void require_subcommand(int value = -1) {
required_subcommand = value;
}
@ -729,8 +729,10 @@ protected:
throw ExcludesError(opt->get_name(), opt_ex->get_name());
}
if(required_subcommand && selected_subcommands.size() == 0)
if(required_subcommand < 0 && selected_subcommands.size() == 0)
throw RequiredError("Subcommand required");
else if(required_subcommand > 0 && selected_subcommands.size() != required_subcommand)
throw RequiredError(std::to_string(required_subcommand) + " subcommand(s) required");
// Convert missing (pairs) to extras (string only)
args.resize(missing.size());

View File

@ -60,6 +60,23 @@ TEST_F(TApp, RequiredSubCom) {
}
TEST_F(TApp, Required1SubCom) {
app.require_subcommand(1);
app.add_subcommand("sub1");
app.add_subcommand("sub2");
app.add_subcommand("sub3");
EXPECT_THROW(run(), CLI::RequiredError);
app.reset();
args = {"sub1"};
EXPECT_NO_THROW(run());
app.reset();
args = {"sub1", "sub2"};
EXPECT_THROW(run(), CLI::RequiredError);
}
struct SubcommandProgram : public TApp {
CLI::App* start;