Commit a3522c1ddf972722f6a91973de22e5ef95d8ba33
1 parent
17564cec
Fix and add cov for subcom ini parser
Showing
4 changed files
with
50 additions
and
5 deletions
CHANGELOG.md
| ... | ... | @@ -6,6 +6,7 @@ |
| 6 | 6 | * Added CodeCov code coverage reports |
| 7 | 7 | * Lots of small bugfixes related to adding tests to increase coverage |
| 8 | 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 | 11 | ## Version 0.6 |
| 11 | 12 | ... | ... |
include/CLI/App.hpp
| ... | ... | @@ -758,7 +758,7 @@ protected: |
| 758 | 758 | std::vector<detail::ini_ret_t> values = detail::parse_ini(config_name_); |
| 759 | 759 | while(values.size() > 0) { |
| 760 | 760 | if(!_parse_ini(values)) { |
| 761 | - throw ExtrasError(values.back().name()); | |
| 761 | + throw ExtrasINIError(values.back().fullname); | |
| 762 | 762 | } |
| 763 | 763 | } |
| 764 | 764 | } catch (const FileError &) { |
| ... | ... | @@ -780,7 +780,7 @@ protected: |
| 780 | 780 | |
| 781 | 781 | // Process callbacks |
| 782 | 782 | for(const Option_p& opt : options_) { |
| 783 | - if (opt->count() > 0) { | |
| 783 | + if (opt->count() > 0 && !opt->get_callback_run()) { | |
| 784 | 784 | opt->run_callback(); |
| 785 | 785 | } |
| 786 | 786 | } |
| ... | ... | @@ -827,15 +827,17 @@ protected: |
| 827 | 827 | /// Returns true if it managed to find the option, if false you'll need to remove the arg manully. |
| 828 | 828 | bool _parse_ini(std::vector<detail::ini_ret_t> &args) { |
| 829 | 829 | detail::ini_ret_t& current = args.back(); |
| 830 | - std::string parent = current.parent(); | |
| 830 | + std::string parent = current.parent(); // respects curent.level | |
| 831 | 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 | 835 | if(parent != "") { |
| 833 | 836 | current.level++; |
| 834 | 837 | for(const App_p &com : subcommands_) |
| 835 | 838 | if(com->check_name(parent)) |
| 836 | 839 | return com->_parse_ini(args); |
| 837 | 840 | return false; |
| 838 | - //throw CLI::ExtraINIError(current.fullname); | |
| 839 | 841 | } |
| 840 | 842 | |
| 841 | 843 | auto op_ptr = std::find_if(std::begin(options_), std::end(options_), |
| ... | ... | @@ -868,8 +870,10 @@ protected: |
| 868 | 870 | } |
| 869 | 871 | } else |
| 870 | 872 | throw ConversionError(current.fullname + ": too many inputs for a flag"); |
| 871 | - } else | |
| 873 | + } else { | |
| 872 | 874 | op->results_ = current.inputs; |
| 875 | + op->run_callback(); | |
| 876 | + } | |
| 873 | 877 | } |
| 874 | 878 | |
| 875 | 879 | args.pop_back(); | ... | ... |
include/CLI/Option.hpp
| ... | ... | @@ -106,6 +106,9 @@ protected: |
| 106 | 106 | /// Results of parsing |
| 107 | 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 | 114 | /// Making an option by hand is not defined, it must be made by the App class |
| ... | ... | @@ -442,6 +445,7 @@ public: |
| 442 | 445 | /// Puts a result at position r |
| 443 | 446 | void add_result(std::string s) { |
| 444 | 447 | results_.push_back(s); |
| 448 | + callback_run_ = false; | |
| 445 | 449 | } |
| 446 | 450 | |
| 447 | 451 | |
| ... | ... | @@ -450,6 +454,11 @@ public: |
| 450 | 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 | 464 | protected: | ... | ... |
tests/IniTest.cpp
| ... | ... | @@ -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 | 328 | TEST_F(TApp, IniFlags) { |
| 298 | 329 | TempFile tmpini{"TestIniTmp.ini"}; |
| 299 | 330 | app.add_config("--config", tmpini); | ... | ... |