Commit 59b6de2550e66716dbad95a1db3325a702132361
Committed by
Henry Schreiner
1 parent
cb7c3ff8
Dropping missing(), now implemented correctly
Showing
4 changed files
with
41 additions
and
38 deletions
examples/prefix_command.cpp
| @@ -15,7 +15,7 @@ int main(int argc, char **argv) { | @@ -15,7 +15,7 @@ int main(int argc, char **argv) { | ||
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | std::vector<std::string> more_comms = app.remaining(); | 17 | std::vector<std::string> more_comms = app.remaining(); |
| 18 | - | 18 | + |
| 19 | std::cout << "Prefix:"; | 19 | std::cout << "Prefix:"; |
| 20 | for(int v : vals) | 20 | for(int v : vals) |
| 21 | std::cout << v << ":"; | 21 | std::cout << v << ":"; |
include/CLI/App.hpp
| @@ -584,7 +584,8 @@ class App { | @@ -584,7 +584,8 @@ class App { | ||
| 584 | App *add_subcommand(std::string name, std::string description = "", bool help = true) { | 584 | App *add_subcommand(std::string name, std::string description = "", bool help = true) { |
| 585 | subcommands_.emplace_back(new App(description, help, detail::dummy)); | 585 | subcommands_.emplace_back(new App(description, help, detail::dummy)); |
| 586 | subcommands_.back()->name_ = name; | 586 | subcommands_.back()->name_ = name; |
| 587 | - subcommands_.back()->allow_extras(); | 587 | + subcommands_.back()->allow_extras_ = allow_extras_; |
| 588 | + subcommands_.back()->prefix_command_ = prefix_command_; | ||
| 588 | subcommands_.back()->parent_ = this; | 589 | subcommands_.back()->parent_ = this; |
| 589 | subcommands_.back()->ignore_case_ = ignore_case_; | 590 | subcommands_.back()->ignore_case_ = ignore_case_; |
| 590 | subcommands_.back()->fallthrough_ = fallthrough_; | 591 | subcommands_.back()->fallthrough_ = fallthrough_; |
| @@ -863,23 +864,34 @@ class App { | @@ -863,23 +864,34 @@ class App { | ||
| 863 | const std::vector<Option *> &parse_order() const { return parse_order_; } | 864 | const std::vector<Option *> &parse_order() const { return parse_order_; } |
| 864 | 865 | ||
| 865 | /// This retuns the missing options from the current subcommand | 866 | /// This retuns the missing options from the current subcommand |
| 866 | - std::vector<std::string> remaining() const { | 867 | + std::vector<std::string> remaining(bool recurse = false) const { |
| 867 | std::vector<std::string> miss_list; | 868 | std::vector<std::string> miss_list; |
| 868 | - for(const std::pair<detail::Classifer, std::string>& miss : missing_) { | 869 | + for(const std::pair<detail::Classifer, std::string> &miss : missing_) { |
| 869 | miss_list.push_back(std::get<1>(miss)); | 870 | miss_list.push_back(std::get<1>(miss)); |
| 870 | } | 871 | } |
| 872 | + if(recurse) { | ||
| 873 | + for(const App_p &sub : subcommands_) { | ||
| 874 | + std::vector<std::string> output = sub->remaining(recurse); | ||
| 875 | + miss_list.assign(std::begin(output), std::end(output)); | ||
| 876 | + } | ||
| 877 | + } | ||
| 871 | return miss_list; | 878 | return miss_list; |
| 872 | } | 879 | } |
| 873 | - | 880 | + |
| 874 | /// This returns the number of remaining options, minus the -- seperator | 881 | /// This returns the number of remaining options, minus the -- seperator |
| 875 | - size_t remaining_size() const { | ||
| 876 | - return std::count_if( | ||
| 877 | - std::begin(missing_), std::end(missing_), | ||
| 878 | - [](const std::pair<detail::Classifer, std::string> &val) { | ||
| 879 | - return val.first != detail::Classifer::POSITIONAL_MARK; | ||
| 880 | - }); | 882 | + size_t remaining_size(bool recurse = false) const { |
| 883 | + size_t count = std::count_if( | ||
| 884 | + std::begin(missing_), std::end(missing_), [](const std::pair<detail::Classifer, std::string> &val) { | ||
| 885 | + return val.first != detail::Classifer::POSITIONAL_MARK; | ||
| 886 | + }); | ||
| 887 | + if(recurse) { | ||
| 888 | + for(const App_p &sub : subcommands_) { | ||
| 889 | + count += sub->remaining_size(recurse); | ||
| 890 | + } | ||
| 891 | + } | ||
| 892 | + return count; | ||
| 881 | } | 893 | } |
| 882 | - | 894 | + |
| 883 | ///@} | 895 | ///@} |
| 884 | 896 | ||
| 885 | protected: | 897 | protected: |
| @@ -896,13 +908,6 @@ class App { | @@ -896,13 +908,6 @@ class App { | ||
| 896 | app->_validate(); | 908 | app->_validate(); |
| 897 | } | 909 | } |
| 898 | 910 | ||
| 899 | - /// Return missing from the master | ||
| 900 | - missing_t *missing() { | ||
| 901 | - if(parent_ != nullptr) | ||
| 902 | - return parent_->missing(); | ||
| 903 | - return &missing_; | ||
| 904 | - } | ||
| 905 | - | ||
| 906 | /// Internal function to run (App) callback, top down | 911 | /// Internal function to run (App) callback, top down |
| 907 | void run_callback() { | 912 | void run_callback() { |
| 908 | pre_callback(); | 913 | pre_callback(); |
| @@ -1028,14 +1033,14 @@ class App { | @@ -1028,14 +1033,14 @@ class App { | ||
| 1028 | 1033 | ||
| 1029 | // Convert missing (pairs) to extras (string only) | 1034 | // Convert missing (pairs) to extras (string only) |
| 1030 | if(parent_ == nullptr) { | 1035 | if(parent_ == nullptr) { |
| 1031 | - args = remaining(); | 1036 | + args = remaining(true); |
| 1032 | std::reverse(std::begin(args), std::end(args)); | 1037 | std::reverse(std::begin(args), std::end(args)); |
| 1038 | + } | ||
| 1033 | 1039 | ||
| 1034 | - size_t num_left_over = remaining_size(); | 1040 | + size_t num_left_over = remaining_size(); |
| 1035 | 1041 | ||
| 1036 | - if(num_left_over > 0 && !(allow_extras_ || prefix_command_)) | ||
| 1037 | - throw ExtrasError("[" + detail::rjoin(args, " ") + "]"); | ||
| 1038 | - } | 1042 | + if(num_left_over > 0 && !(allow_extras_ || prefix_command_)) |
| 1043 | + throw ExtrasError("[" + detail::rjoin(args, " ") + "]"); | ||
| 1039 | } | 1044 | } |
| 1040 | 1045 | ||
| 1041 | /// Parse one ini param, return false if not found in any subcommand, remove if it is | 1046 | /// Parse one ini param, return false if not found in any subcommand, remove if it is |
| @@ -1102,7 +1107,7 @@ class App { | @@ -1102,7 +1107,7 @@ class App { | ||
| 1102 | detail::Classifer classifer = positional_only ? detail::Classifer::NONE : _recognize(args.back()); | 1107 | detail::Classifer classifer = positional_only ? detail::Classifer::NONE : _recognize(args.back()); |
| 1103 | switch(classifer) { | 1108 | switch(classifer) { |
| 1104 | case detail::Classifer::POSITIONAL_MARK: | 1109 | case detail::Classifer::POSITIONAL_MARK: |
| 1105 | - missing()->emplace_back(classifer, args.back()); | 1110 | + missing_.emplace_back(classifer, args.back()); |
| 1106 | args.pop_back(); | 1111 | args.pop_back(); |
| 1107 | positional_only = true; | 1112 | positional_only = true; |
| 1108 | break; | 1113 | break; |
| @@ -1154,11 +1159,11 @@ class App { | @@ -1154,11 +1159,11 @@ class App { | ||
| 1154 | return parent_->_parse_positional(args); | 1159 | return parent_->_parse_positional(args); |
| 1155 | else { | 1160 | else { |
| 1156 | args.pop_back(); | 1161 | args.pop_back(); |
| 1157 | - missing()->emplace_back(detail::Classifer::NONE, positional); | 1162 | + missing_.emplace_back(detail::Classifer::NONE, positional); |
| 1158 | 1163 | ||
| 1159 | if(prefix_command_) { | 1164 | if(prefix_command_) { |
| 1160 | while(!args.empty()) { | 1165 | while(!args.empty()) { |
| 1161 | - missing()->emplace_back(detail::Classifer::NONE, args.back()); | 1166 | + missing_.emplace_back(detail::Classifer::NONE, args.back()); |
| 1162 | args.pop_back(); | 1167 | args.pop_back(); |
| 1163 | } | 1168 | } |
| 1164 | } | 1169 | } |
| @@ -1204,7 +1209,7 @@ class App { | @@ -1204,7 +1209,7 @@ class App { | ||
| 1204 | // Otherwise, add to missing | 1209 | // Otherwise, add to missing |
| 1205 | else { | 1210 | else { |
| 1206 | args.pop_back(); | 1211 | args.pop_back(); |
| 1207 | - missing()->emplace_back(detail::Classifer::SHORT, current); | 1212 | + missing_.emplace_back(detail::Classifer::SHORT, current); |
| 1208 | return; | 1213 | return; |
| 1209 | } | 1214 | } |
| 1210 | } | 1215 | } |
| @@ -1268,7 +1273,7 @@ class App { | @@ -1268,7 +1273,7 @@ class App { | ||
| 1268 | // Otherwise, add to missing | 1273 | // Otherwise, add to missing |
| 1269 | else { | 1274 | else { |
| 1270 | args.pop_back(); | 1275 | args.pop_back(); |
| 1271 | - missing()->emplace_back(detail::Classifer::LONG, current); | 1276 | + missing_.emplace_back(detail::Classifer::LONG, current); |
| 1272 | return; | 1277 | return; |
| 1273 | } | 1278 | } |
| 1274 | } | 1279 | } |
tests/AppTest.cpp
| @@ -917,7 +917,7 @@ TEST_F(TApp, AllowExtras) { | @@ -917,7 +917,7 @@ TEST_F(TApp, AllowExtras) { | ||
| 917 | EXPECT_FALSE(val); | 917 | EXPECT_FALSE(val); |
| 918 | 918 | ||
| 919 | args = {"-x", "-f"}; | 919 | args = {"-x", "-f"}; |
| 920 | - | 920 | + |
| 921 | EXPECT_NO_THROW(run()); | 921 | EXPECT_NO_THROW(run()); |
| 922 | EXPECT_TRUE(val); | 922 | EXPECT_TRUE(val); |
| 923 | EXPECT_EQ(app.remaining(), std::vector<std::string>({"-x"})); | 923 | EXPECT_EQ(app.remaining(), std::vector<std::string>({"-x"})); |
tests/SubcommandTest.cpp
| @@ -291,20 +291,18 @@ TEST_F(TApp, SubComExtras) { | @@ -291,20 +291,18 @@ TEST_F(TApp, SubComExtras) { | ||
| 291 | EXPECT_EQ(sub->remaining(), std::vector<std::string>()); | 291 | EXPECT_EQ(sub->remaining(), std::vector<std::string>()); |
| 292 | 292 | ||
| 293 | app.reset(); | 293 | app.reset(); |
| 294 | - | 294 | + |
| 295 | args = {"extra1", "extra2", "sub"}; | 295 | args = {"extra1", "extra2", "sub"}; |
| 296 | run(); | 296 | run(); |
| 297 | EXPECT_EQ(app.remaining(), std::vector<std::string>({"extra1", "extra2"})); | 297 | EXPECT_EQ(app.remaining(), std::vector<std::string>({"extra1", "extra2"})); |
| 298 | EXPECT_EQ(sub->remaining(), std::vector<std::string>()); | 298 | EXPECT_EQ(sub->remaining(), std::vector<std::string>()); |
| 299 | - | ||
| 300 | - app.reset(); | ||
| 301 | - | ||
| 302 | - //args = {"sub", "extra"}; | ||
| 303 | - //run(); | ||
| 304 | - //EXPECT_EQ(app.remaining(), std::vector<std::string>()); | ||
| 305 | - //EXPECT_EQ(sub->remaining(), std::vector<std::string>({"extra"})); | ||
| 306 | 299 | ||
| 300 | + app.reset(); | ||
| 307 | 301 | ||
| 302 | + // args = {"sub", "extra"}; | ||
| 303 | + // run(); | ||
| 304 | + // EXPECT_EQ(app.remaining(), std::vector<std::string>()); | ||
| 305 | + // EXPECT_EQ(sub->remaining(), std::vector<std::string>({"extra"})); | ||
| 308 | } | 306 | } |
| 309 | 307 | ||
| 310 | TEST_F(TApp, Required1SubCom) { | 308 | TEST_F(TApp, Required1SubCom) { |