Commit 3b04cd62af5ff2b29c65e561e0c51511ac390aa3

Authored by Henry Fredrick Schreiner
1 parent 05867beb

Adding parse order capture

include/CLI/App.hpp
... ... @@ -80,6 +80,9 @@ class App {
80 80 ///
81 81 /// This is faster and cleaner than storing just a list of strings and reparsing. This may contain the -- separator.
82 82 missing_t missing_;
  83 +
  84 + /// This is a list of pointers to options with the orignal parse order
  85 + std::vector<Option*> parse_order_;
83 86  
84 87 ///@}
85 88 /// @name Subcommands
... ... @@ -710,6 +713,11 @@ class App {
710 713  
711 714 return local_name == name_to_check;
712 715 }
  716 +
  717 + /// This gets a vector of pointers with the original parse order
  718 + const std::vector<Option*> &parse_order() const {
  719 + return parse_order_;
  720 + }
713 721  
714 722 ///@}
715 723  
... ... @@ -949,6 +957,7 @@ class App {
949 957 (static_cast<int>(opt->count()) < opt->get_expected() || opt->get_expected() < 0)) {
950 958  
951 959 opt->add_result(positional);
  960 + parse_order_.push_back(opt.get());
952 961 args.pop_back();
953 962 return;
954 963 }
... ... @@ -1011,18 +1020,21 @@ class App {
1011 1020  
1012 1021 int num = op->get_expected();
1013 1022  
1014   - if(num == 0)
  1023 + if(num == 0) {
1015 1024 op->add_result("");
1016   - else if(rest != "") {
  1025 + parse_order_.push_back(op.get());
  1026 + } else if(rest != "") {
1017 1027 if(num > 0)
1018 1028 num--;
1019 1029 op->add_result(rest);
  1030 + parse_order_.push_back(op.get());
1020 1031 rest = "";
1021 1032 }
1022 1033  
1023 1034 if(num == -1) {
1024 1035 while(!args.empty() && _recognize(args.back()) == detail::Classifer::NONE) {
1025 1036 op->add_result(args.back());
  1037 + parse_order_.push_back(op.get());
1026 1038 args.pop_back();
1027 1039 }
1028 1040 } else
... ... @@ -1031,6 +1043,7 @@ class App {
1031 1043 std::string current_ = args.back();
1032 1044 args.pop_back();
1033 1045 op->add_result(current_);
  1046 + parse_order_.push_back(op.get());
1034 1047 }
1035 1048  
1036 1049 if(rest != "") {
... ... @@ -1075,19 +1088,23 @@ class App {
1075 1088 if(num != -1)
1076 1089 num--;
1077 1090 op->add_result(value);
  1091 + parse_order_.push_back(op.get());
1078 1092 } else if(num == 0) {
1079 1093 op->add_result("");
  1094 + parse_order_.push_back(op.get());
1080 1095 }
1081 1096  
1082 1097 if(num == -1) {
1083 1098 while(!args.empty() && _recognize(args.back()) == detail::Classifer::NONE) {
1084 1099 op->add_result(args.back());
  1100 + parse_order_.push_back(op.get());
1085 1101 args.pop_back();
1086 1102 }
1087 1103 } else
1088 1104 while(num > 0 && !args.empty()) {
1089 1105 num--;
1090 1106 op->add_result(args.back());
  1107 + parse_order_.push_back(op.get());
1091 1108 args.pop_back();
1092 1109 }
1093 1110 return;
... ...
tests/AppTest.cpp
... ... @@ -501,6 +501,23 @@ TEST_F(TApp, VectorFancyOpts) {
501 501 EXPECT_THROW(run(), CLI::ParseError);
502 502 }
503 503  
  504 +TEST_F(TApp, OriginalOrder) {
  505 + std::vector<int> st1;
  506 + CLI::Option* op1 = app.add_option("-a", st1);
  507 + std::vector<int> st2;
  508 + CLI::Option* op2 = app.add_option("-b", st2);
  509 +
  510 + args = {"-a", "1", "-b", "2", "-a3", "-a", "4"};
  511 +
  512 + run();
  513 +
  514 + EXPECT_EQ(st1, std::vector<int>({1,3,4}));
  515 + EXPECT_EQ(st2, std::vector<int>({2}));
  516 +
  517 + EXPECT_EQ(app.parse_order(), std::vector<CLI::Option*>({op1, op2, op1, op1}));
  518 +
  519 +}
  520 +
504 521 TEST_F(TApp, RequiresFlags) {
505 522 CLI::Option *opt = app.add_flag("-s,--string");
506 523 app.add_flag("--both")->requires(opt);
... ...