mirror of
https://github.com/CLIUtils/CLI11.git
synced 2025-04-29 12:13:52 +00:00
Subcommand parse order corrected and preserved
This commit is contained in:
parent
512b3604e2
commit
9acaeebd1e
@ -102,6 +102,9 @@ class App {
|
||||
/// This is a list of pointers to options with the original parse order
|
||||
std::vector<Option *> parse_order_;
|
||||
|
||||
/// This is a list of the subcommands collected, in order
|
||||
std::vector<App *> parsed_subcommands_;
|
||||
|
||||
///@}
|
||||
/// @name Subcommands
|
||||
///@{
|
||||
@ -732,6 +735,7 @@ class App {
|
||||
|
||||
parsed_ = false;
|
||||
missing_.clear();
|
||||
parsed_subcommands_.clear();
|
||||
|
||||
for(const Option_p &opt : options_) {
|
||||
opt->clear();
|
||||
@ -755,13 +759,18 @@ class App {
|
||||
throw OptionNotFound(name);
|
||||
}
|
||||
|
||||
/// Get a subcommand pointer list to the currently selected subcommands (after parsing)
|
||||
std::vector<App *> get_subcommands() const {
|
||||
std::vector<App *> subcomms;
|
||||
for(const App_p &subcomptr : subcommands_)
|
||||
if(subcomptr->parsed_)
|
||||
subcomms.push_back(subcomptr.get());
|
||||
return subcomms;
|
||||
/// Get a subcommand pointer list to the currently selected subcommands (after parsing by default, in command line
|
||||
/// order)
|
||||
std::vector<App *> get_subcommands(bool parsed = true) const {
|
||||
if(parsed) {
|
||||
return parsed_subcommands_;
|
||||
} else {
|
||||
std::vector<App *> subcomms(subcommands_.size());
|
||||
std::transform(std::begin(subcommands_), std::end(subcommands_), std::begin(subcomms), [](const App_p &v) {
|
||||
return v.get();
|
||||
});
|
||||
return subcomms;
|
||||
}
|
||||
}
|
||||
|
||||
/// Check to see if given subcommand was selected
|
||||
@ -952,7 +961,7 @@ class App {
|
||||
miss_list.push_back(std::get<1>(miss));
|
||||
}
|
||||
if(recurse) {
|
||||
for(const App_p &sub : subcommands_) {
|
||||
for(const App *sub : parsed_subcommands_) {
|
||||
std::vector<std::string> output = sub->remaining(recurse);
|
||||
std::copy(std::begin(output), std::end(output), std::back_inserter(miss_list));
|
||||
}
|
||||
@ -1260,6 +1269,9 @@ class App {
|
||||
for(const App_p &com : subcommands_) {
|
||||
if(com->check_name(args.back())) {
|
||||
args.pop_back();
|
||||
if(std::find(std::begin(parsed_subcommands_), std::end(parsed_subcommands_), com.get()) ==
|
||||
std::end(parsed_subcommands_))
|
||||
parsed_subcommands_.push_back(com.get());
|
||||
com->_parse(args);
|
||||
return;
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ TEST_F(TApp, BasicSubcommands) {
|
||||
|
||||
args = {"sub2"};
|
||||
run();
|
||||
EXPECT_EQ((size_t)1, app.get_subcommands().size());
|
||||
EXPECT_EQ(sub2, app.get_subcommands().at(0));
|
||||
|
||||
app.reset();
|
||||
@ -560,3 +561,84 @@ TEST_F(SubcommandProgram, Groups) {
|
||||
EXPECT_THAT(help, HasSubstr("More Commands:"));
|
||||
EXPECT_THAT(help, Not(HasSubstr("Subcommands:")));
|
||||
}
|
||||
|
||||
TEST_F(SubcommandProgram, ExtrasErrors) {
|
||||
|
||||
args = {"one", "two", "start", "three", "four"};
|
||||
EXPECT_THROW(run(), CLI::ExtrasError);
|
||||
app.reset();
|
||||
|
||||
args = {"start", "three", "four"};
|
||||
EXPECT_THROW(run(), CLI::ExtrasError);
|
||||
app.reset();
|
||||
|
||||
args = {"one", "two"};
|
||||
EXPECT_THROW(run(), CLI::ExtrasError);
|
||||
app.reset();
|
||||
}
|
||||
|
||||
TEST_F(SubcommandProgram, OrderedExtras) {
|
||||
|
||||
app.allow_extras();
|
||||
args = {"one", "two", "start", "three", "four"};
|
||||
EXPECT_THROW(run(), CLI::ExtrasError);
|
||||
app.reset();
|
||||
|
||||
start->allow_extras();
|
||||
|
||||
run();
|
||||
|
||||
EXPECT_EQ(app.remaining(), std::vector<std::string>({"one", "two"}));
|
||||
EXPECT_EQ(start->remaining(), std::vector<std::string>({"three", "four"}));
|
||||
EXPECT_EQ(app.remaining(true), std::vector<std::string>({"one", "two", "three", "four"}));
|
||||
|
||||
app.reset();
|
||||
args = {"one", "two", "start", "three", "--", "four"};
|
||||
|
||||
run();
|
||||
|
||||
EXPECT_EQ(app.remaining(), std::vector<std::string>({"one", "two"}));
|
||||
EXPECT_EQ(start->remaining(), std::vector<std::string>({"three", "--", "four"}));
|
||||
EXPECT_EQ(app.remaining(true), std::vector<std::string>({"one", "two", "three", "--", "four"}));
|
||||
}
|
||||
|
||||
TEST_F(SubcommandProgram, MixedOrderExtras) {
|
||||
|
||||
app.allow_extras();
|
||||
start->allow_extras();
|
||||
stop->allow_extras();
|
||||
|
||||
args = {"one", "two", "start", "three", "four", "stop", "five", "six"};
|
||||
run();
|
||||
|
||||
EXPECT_EQ(app.remaining(), std::vector<std::string>({"one", "two"}));
|
||||
EXPECT_EQ(start->remaining(), std::vector<std::string>({"three", "four"}));
|
||||
EXPECT_EQ(stop->remaining(), std::vector<std::string>({"five", "six"}));
|
||||
EXPECT_EQ(app.remaining(true), std::vector<std::string>({"one", "two", "three", "four", "five", "six"}));
|
||||
|
||||
app.reset();
|
||||
args = {"one", "two", "stop", "three", "four", "start", "five", "six"};
|
||||
run();
|
||||
|
||||
EXPECT_EQ(app.remaining(), std::vector<std::string>({"one", "two"}));
|
||||
EXPECT_EQ(stop->remaining(), std::vector<std::string>({"three", "four"}));
|
||||
EXPECT_EQ(start->remaining(), std::vector<std::string>({"five", "six"}));
|
||||
EXPECT_EQ(app.remaining(true), std::vector<std::string>({"one", "two", "three", "four", "five", "six"}));
|
||||
}
|
||||
|
||||
TEST_F(SubcommandProgram, CallbackOrder) {
|
||||
std::vector<int> callback_order;
|
||||
start->set_callback([&callback_order]() { callback_order.push_back(1); });
|
||||
stop->set_callback([&callback_order]() { callback_order.push_back(2); });
|
||||
|
||||
args = {"start", "stop"};
|
||||
run();
|
||||
EXPECT_EQ(callback_order, std::vector<int>({1, 2}));
|
||||
|
||||
app.reset();
|
||||
callback_order.clear();
|
||||
|
||||
args = {"stop", "start"};
|
||||
run();
|
||||
EXPECT_EQ(callback_order, std::vector<int>({2, 1}));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user