Commit a3522c1ddf972722f6a91973de22e5ef95d8ba33

Authored by Henry Fredrick Schreiner
1 parent 17564cec

Fix and add cov for subcom ini parser

CHANGELOG.md
@@ -6,6 +6,7 @@ @@ -6,6 +6,7 @@
6 * Added CodeCov code coverage reports 6 * Added CodeCov code coverage reports
7 * Lots of small bugfixes related to adding tests to increase coverage 7 * Lots of small bugfixes related to adding tests to increase coverage
8 * Error handling now uses scoped enum in errors 8 * Error handling now uses scoped enum in errors
  9 +* Reparsing rules changed a little to accommodate Ini files. Callbacks are now called when parsing INI, and reset any time results are added.
9 10
10 ## Version 0.6 11 ## Version 0.6
11 12
include/CLI/App.hpp
@@ -758,7 +758,7 @@ protected: @@ -758,7 +758,7 @@ protected:
758 std::vector<detail::ini_ret_t> values = detail::parse_ini(config_name_); 758 std::vector<detail::ini_ret_t> values = detail::parse_ini(config_name_);
759 while(values.size() > 0) { 759 while(values.size() > 0) {
760 if(!_parse_ini(values)) { 760 if(!_parse_ini(values)) {
761 - throw ExtrasError(values.back().name()); 761 + throw ExtrasINIError(values.back().fullname);
762 } 762 }
763 } 763 }
764 } catch (const FileError &) { 764 } catch (const FileError &) {
@@ -780,7 +780,7 @@ protected: @@ -780,7 +780,7 @@ protected:
780 780
781 // Process callbacks 781 // Process callbacks
782 for(const Option_p& opt : options_) { 782 for(const Option_p& opt : options_) {
783 - if (opt->count() > 0) { 783 + if (opt->count() > 0 && !opt->get_callback_run()) {
784 opt->run_callback(); 784 opt->run_callback();
785 } 785 }
786 } 786 }
@@ -827,15 +827,17 @@ protected: @@ -827,15 +827,17 @@ protected:
827 /// Returns true if it managed to find the option, if false you'll need to remove the arg manully. 827 /// Returns true if it managed to find the option, if false you'll need to remove the arg manully.
828 bool _parse_ini(std::vector<detail::ini_ret_t> &args) { 828 bool _parse_ini(std::vector<detail::ini_ret_t> &args) {
829 detail::ini_ret_t& current = args.back(); 829 detail::ini_ret_t& current = args.back();
830 - std::string parent = current.parent(); 830 + std::string parent = current.parent(); // respects curent.level
831 std::string name = current.name(); 831 std::string name = current.name();
  832 + std::cout << current.fullname << " " << parent << " " << name << std::endl;
  833 +
  834 + // If a parent is listed, go to a subcommand
832 if(parent != "") { 835 if(parent != "") {
833 current.level++; 836 current.level++;
834 for(const App_p &com : subcommands_) 837 for(const App_p &com : subcommands_)
835 if(com->check_name(parent)) 838 if(com->check_name(parent))
836 return com->_parse_ini(args); 839 return com->_parse_ini(args);
837 return false; 840 return false;
838 - //throw CLI::ExtraINIError(current.fullname);  
839 } 841 }
840 842
841 auto op_ptr = std::find_if(std::begin(options_), std::end(options_), 843 auto op_ptr = std::find_if(std::begin(options_), std::end(options_),
@@ -868,8 +870,10 @@ protected: @@ -868,8 +870,10 @@ protected:
868 } 870 }
869 } else 871 } else
870 throw ConversionError(current.fullname + ": too many inputs for a flag"); 872 throw ConversionError(current.fullname + ": too many inputs for a flag");
871 - } else 873 + } else {
872 op->results_ = current.inputs; 874 op->results_ = current.inputs;
  875 + op->run_callback();
  876 + }
873 } 877 }
874 878
875 args.pop_back(); 879 args.pop_back();
include/CLI/Option.hpp
@@ -106,6 +106,9 @@ protected: @@ -106,6 +106,9 @@ protected:
106 /// Results of parsing 106 /// Results of parsing
107 results_t results_; 107 results_t results_;
108 108
  109 + /// Whether the callback has run (needed for INI parsing)
  110 + bool callback_run_ {false};
  111 +
109 ///@} 112 ///@}
110 113
111 /// Making an option by hand is not defined, it must be made by the App class 114 /// Making an option by hand is not defined, it must be made by the App class
@@ -442,6 +445,7 @@ public: @@ -442,6 +445,7 @@ public:
442 /// Puts a result at position r 445 /// Puts a result at position r
443 void add_result(std::string s) { 446 void add_result(std::string s) {
444 results_.push_back(s); 447 results_.push_back(s);
  448 + callback_run_ = false;
445 } 449 }
446 450
447 451
@@ -450,6 +454,11 @@ public: @@ -450,6 +454,11 @@ public:
450 return results_; 454 return results_;
451 } 455 }
452 456
  457 + /// See if the callback has been run already
  458 + bool get_callback_run() const {
  459 + return callback_run_;
  460 + }
  461 +
453 ///@} 462 ///@}
454 463
455 protected: 464 protected:
tests/IniTest.cpp
@@ -294,6 +294,37 @@ TEST_F(TApp, IniVector) { @@ -294,6 +294,37 @@ TEST_F(TApp, IniVector) {
294 294
295 } 295 }
296 296
  297 +
  298 +TEST_F(TApp, IniLayered) {
  299 +
  300 + TempFile tmpini{"TestIniTmp.ini"};
  301 +
  302 + app.add_config("--config", tmpini);
  303 +
  304 + {
  305 + std::ofstream out{tmpini};
  306 + out << "[default]" << std::endl;
  307 + out << "val=1" << std::endl;
  308 + out << "[subcom]" << std::endl;
  309 + out << "val=2" << std::endl;
  310 + out << "subsubcom.val=3" << std::endl;
  311 + }
  312 +
  313 + int one=0, two=0, three=0;
  314 + app.add_option("--val", one);
  315 + auto subcom = app.add_subcommand("subcom");
  316 + subcom->add_option("--val", two);
  317 + auto subsubcom = subcom->add_subcommand("subsubcom");
  318 + subsubcom->add_option("--val", three);
  319 +
  320 + ASSERT_NO_THROW(run());
  321 +
  322 + EXPECT_EQ(1, one);
  323 + EXPECT_EQ(2, two);
  324 + EXPECT_EQ(3, three);
  325 +
  326 +}
  327 +
297 TEST_F(TApp, IniFlags) { 328 TEST_F(TApp, IniFlags) {
298 TempFile tmpini{"TestIniTmp.ini"}; 329 TempFile tmpini{"TestIniTmp.ini"};
299 app.add_config("--config", tmpini); 330 app.add_config("--config", tmpini);