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 +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); |