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
include/CLI/App.hpp
| ... | ... | @@ -584,7 +584,8 @@ class App { |
| 584 | 584 | App *add_subcommand(std::string name, std::string description = "", bool help = true) { |
| 585 | 585 | subcommands_.emplace_back(new App(description, help, detail::dummy)); |
| 586 | 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 | 589 | subcommands_.back()->parent_ = this; |
| 589 | 590 | subcommands_.back()->ignore_case_ = ignore_case_; |
| 590 | 591 | subcommands_.back()->fallthrough_ = fallthrough_; |
| ... | ... | @@ -863,23 +864,34 @@ class App { |
| 863 | 864 | const std::vector<Option *> &parse_order() const { return parse_order_; } |
| 864 | 865 | |
| 865 | 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 | 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 | 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 | 878 | return miss_list; |
| 872 | 879 | } |
| 873 | - | |
| 880 | + | |
| 874 | 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 | 897 | protected: |
| ... | ... | @@ -896,13 +908,6 @@ class App { |
| 896 | 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 | 911 | /// Internal function to run (App) callback, top down |
| 907 | 912 | void run_callback() { |
| 908 | 913 | pre_callback(); |
| ... | ... | @@ -1028,14 +1033,14 @@ class App { |
| 1028 | 1033 | |
| 1029 | 1034 | // Convert missing (pairs) to extras (string only) |
| 1030 | 1035 | if(parent_ == nullptr) { |
| 1031 | - args = remaining(); | |
| 1036 | + args = remaining(true); | |
| 1032 | 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 | 1046 | /// Parse one ini param, return false if not found in any subcommand, remove if it is |
| ... | ... | @@ -1102,7 +1107,7 @@ class App { |
| 1102 | 1107 | detail::Classifer classifer = positional_only ? detail::Classifer::NONE : _recognize(args.back()); |
| 1103 | 1108 | switch(classifer) { |
| 1104 | 1109 | case detail::Classifer::POSITIONAL_MARK: |
| 1105 | - missing()->emplace_back(classifer, args.back()); | |
| 1110 | + missing_.emplace_back(classifer, args.back()); | |
| 1106 | 1111 | args.pop_back(); |
| 1107 | 1112 | positional_only = true; |
| 1108 | 1113 | break; |
| ... | ... | @@ -1154,11 +1159,11 @@ class App { |
| 1154 | 1159 | return parent_->_parse_positional(args); |
| 1155 | 1160 | else { |
| 1156 | 1161 | args.pop_back(); |
| 1157 | - missing()->emplace_back(detail::Classifer::NONE, positional); | |
| 1162 | + missing_.emplace_back(detail::Classifer::NONE, positional); | |
| 1158 | 1163 | |
| 1159 | 1164 | if(prefix_command_) { |
| 1160 | 1165 | while(!args.empty()) { |
| 1161 | - missing()->emplace_back(detail::Classifer::NONE, args.back()); | |
| 1166 | + missing_.emplace_back(detail::Classifer::NONE, args.back()); | |
| 1162 | 1167 | args.pop_back(); |
| 1163 | 1168 | } |
| 1164 | 1169 | } |
| ... | ... | @@ -1204,7 +1209,7 @@ class App { |
| 1204 | 1209 | // Otherwise, add to missing |
| 1205 | 1210 | else { |
| 1206 | 1211 | args.pop_back(); |
| 1207 | - missing()->emplace_back(detail::Classifer::SHORT, current); | |
| 1212 | + missing_.emplace_back(detail::Classifer::SHORT, current); | |
| 1208 | 1213 | return; |
| 1209 | 1214 | } |
| 1210 | 1215 | } |
| ... | ... | @@ -1268,7 +1273,7 @@ class App { |
| 1268 | 1273 | // Otherwise, add to missing |
| 1269 | 1274 | else { |
| 1270 | 1275 | args.pop_back(); |
| 1271 | - missing()->emplace_back(detail::Classifer::LONG, current); | |
| 1276 | + missing_.emplace_back(detail::Classifer::LONG, current); | |
| 1272 | 1277 | return; |
| 1273 | 1278 | } |
| 1274 | 1279 | } | ... | ... |
tests/AppTest.cpp
tests/SubcommandTest.cpp
| ... | ... | @@ -291,20 +291,18 @@ TEST_F(TApp, SubComExtras) { |
| 291 | 291 | EXPECT_EQ(sub->remaining(), std::vector<std::string>()); |
| 292 | 292 | |
| 293 | 293 | app.reset(); |
| 294 | - | |
| 294 | + | |
| 295 | 295 | args = {"extra1", "extra2", "sub"}; |
| 296 | 296 | run(); |
| 297 | 297 | EXPECT_EQ(app.remaining(), std::vector<std::string>({"extra1", "extra2"})); |
| 298 | 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 | 308 | TEST_F(TApp, Required1SubCom) { | ... | ... |