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,6 +80,9 @@ class App {
80 /// 80 ///
81 /// This is faster and cleaner than storing just a list of strings and reparsing. This may contain the -- separator. 81 /// This is faster and cleaner than storing just a list of strings and reparsing. This may contain the -- separator.
82 missing_t missing_; 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 /// @name Subcommands 88 /// @name Subcommands
@@ -710,6 +713,11 @@ class App { @@ -710,6 +713,11 @@ class App {
710 713
711 return local_name == name_to_check; 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,6 +957,7 @@ class App {
949 (static_cast<int>(opt->count()) < opt->get_expected() || opt->get_expected() < 0)) { 957 (static_cast<int>(opt->count()) < opt->get_expected() || opt->get_expected() < 0)) {
950 958
951 opt->add_result(positional); 959 opt->add_result(positional);
  960 + parse_order_.push_back(opt.get());
952 args.pop_back(); 961 args.pop_back();
953 return; 962 return;
954 } 963 }
@@ -1011,18 +1020,21 @@ class App { @@ -1011,18 +1020,21 @@ class App {
1011 1020
1012 int num = op->get_expected(); 1021 int num = op->get_expected();
1013 1022
1014 - if(num == 0) 1023 + if(num == 0) {
1015 op->add_result(""); 1024 op->add_result("");
1016 - else if(rest != "") { 1025 + parse_order_.push_back(op.get());
  1026 + } else if(rest != "") {
1017 if(num > 0) 1027 if(num > 0)
1018 num--; 1028 num--;
1019 op->add_result(rest); 1029 op->add_result(rest);
  1030 + parse_order_.push_back(op.get());
1020 rest = ""; 1031 rest = "";
1021 } 1032 }
1022 1033
1023 if(num == -1) { 1034 if(num == -1) {
1024 while(!args.empty() && _recognize(args.back()) == detail::Classifer::NONE) { 1035 while(!args.empty() && _recognize(args.back()) == detail::Classifer::NONE) {
1025 op->add_result(args.back()); 1036 op->add_result(args.back());
  1037 + parse_order_.push_back(op.get());
1026 args.pop_back(); 1038 args.pop_back();
1027 } 1039 }
1028 } else 1040 } else
@@ -1031,6 +1043,7 @@ class App { @@ -1031,6 +1043,7 @@ class App {
1031 std::string current_ = args.back(); 1043 std::string current_ = args.back();
1032 args.pop_back(); 1044 args.pop_back();
1033 op->add_result(current_); 1045 op->add_result(current_);
  1046 + parse_order_.push_back(op.get());
1034 } 1047 }
1035 1048
1036 if(rest != "") { 1049 if(rest != "") {
@@ -1075,19 +1088,23 @@ class App { @@ -1075,19 +1088,23 @@ class App {
1075 if(num != -1) 1088 if(num != -1)
1076 num--; 1089 num--;
1077 op->add_result(value); 1090 op->add_result(value);
  1091 + parse_order_.push_back(op.get());
1078 } else if(num == 0) { 1092 } else if(num == 0) {
1079 op->add_result(""); 1093 op->add_result("");
  1094 + parse_order_.push_back(op.get());
1080 } 1095 }
1081 1096
1082 if(num == -1) { 1097 if(num == -1) {
1083 while(!args.empty() && _recognize(args.back()) == detail::Classifer::NONE) { 1098 while(!args.empty() && _recognize(args.back()) == detail::Classifer::NONE) {
1084 op->add_result(args.back()); 1099 op->add_result(args.back());
  1100 + parse_order_.push_back(op.get());
1085 args.pop_back(); 1101 args.pop_back();
1086 } 1102 }
1087 } else 1103 } else
1088 while(num > 0 && !args.empty()) { 1104 while(num > 0 && !args.empty()) {
1089 num--; 1105 num--;
1090 op->add_result(args.back()); 1106 op->add_result(args.back());
  1107 + parse_order_.push_back(op.get());
1091 args.pop_back(); 1108 args.pop_back();
1092 } 1109 }
1093 return; 1110 return;
tests/AppTest.cpp
@@ -501,6 +501,23 @@ TEST_F(TApp, VectorFancyOpts) { @@ -501,6 +501,23 @@ TEST_F(TApp, VectorFancyOpts) {
501 EXPECT_THROW(run(), CLI::ParseError); 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 TEST_F(TApp, RequiresFlags) { 521 TEST_F(TApp, RequiresFlags) {
505 CLI::Option *opt = app.add_flag("-s,--string"); 522 CLI::Option *opt = app.add_flag("-s,--string");
506 app.add_flag("--both")->requires(opt); 523 app.add_flag("--both")->requires(opt);