Commit 47a7c3b89f5cc2b100f1143b2eb05321fc19606e

Authored by Henry Fredrick Schreiner
1 parent c36c913a

Add vectors, fix bad bug

include/CLI.hpp
@@ -87,7 +87,7 @@ struct Combiner { @@ -87,7 +87,7 @@ struct Combiner {
87 Combiner operator() (int n) const { 87 Combiner operator() (int n) const {
88 Combiner self = *this; 88 Combiner self = *this;
89 self.num = n; 89 self.num = n;
90 - return *this; 90 + return self;
91 } 91 }
92 /// Call to give a validator 92 /// Call to give a validator
93 Combiner operator() (std::function<bool(std::string)> func) const { 93 Combiner operator() (std::function<bool(std::string)> func) const {
@@ -182,8 +182,7 @@ const Combiner NOTHING {0, false,false,false, {}}; @@ -182,8 +182,7 @@ const Combiner NOTHING {0, false,false,false, {}};
182 const Combiner REQUIRED {1, false,true, false, {}}; 182 const Combiner REQUIRED {1, false,true, false, {}};
183 const Combiner DEFAULT {1, false,false,true, {}}; 183 const Combiner DEFAULT {1, false,false,true, {}};
184 const Combiner POSITIONAL {1, true, false,false, {}}; 184 const Combiner POSITIONAL {1, true, false,false, {}};
185 -const Combiner ARGS {1, false,false,false, {}};  
186 -const Combiner UNLIMITED {-1,false,false,false, {}}; 185 +const Combiner ARGS {-1, false,false,false, {}};
187 const Combiner VALIDATORS {1, false, false, false, {}}; 186 const Combiner VALIDATORS {1, false, false, false, {}};
188 187
189 // Warning about using these validators: 188 // Warning about using these validators:
@@ -196,6 +195,8 @@ const Combiner NonexistentPath {1, false, false, false, {_NonexistentPath}}; @@ -196,6 +195,8 @@ const Combiner NonexistentPath {1, false, false, false, {_NonexistentPath}};
196 typedef std::vector<std::vector<std::string>> results_t; 195 typedef std::vector<std::vector<std::string>> results_t;
197 typedef std::function<bool(results_t)> callback_t; 196 typedef std::function<bool(results_t)> callback_t;
198 197
  198 +
  199 +
199 class Option { 200 class Option {
200 public: 201 public:
201 protected: 202 protected:
@@ -433,27 +434,28 @@ public: @@ -433,27 +434,28 @@ public:
433 * std::string filename 434 * std::string filename
434 * program.add_option("filename", filename, "discription of filename"); 435 * program.add_option("filename", filename, "discription of filename");
435 */ 436 */
436 - void add_option( 437 + Option* add_option(
437 std::string name, ///< The name, long,short 438 std::string name, ///< The name, long,short
438 callback_t callback, ///< The callback 439 callback_t callback, ///< The callback
439 std::string discription="", ///< Discription string 440 std::string discription="", ///< Discription string
440 - Combiner opts=ARGS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS()) 441 + Combiner opts=VALIDATORS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS())
441 ) { 442 ) {
442 Option myopt{name, discription, opts, callback}; 443 Option myopt{name, discription, opts, callback};
443 if(std::find(std::begin(options), std::end(options), myopt) == std::end(options)) 444 if(std::find(std::begin(options), std::end(options), myopt) == std::end(options))
444 options.push_back(myopt); 445 options.push_back(myopt);
445 else 446 else
446 throw OptionAlreadyAdded(myopt.get_name()); 447 throw OptionAlreadyAdded(myopt.get_name());
  448 + return &options.back();
447 449
448 } 450 }
449 451
450 /// Add option for string 452 /// Add option for string
451 template<typename T, enable_if_t<!std::is_array<T>::value, detail::enabler> = dummy> 453 template<typename T, enable_if_t<!std::is_array<T>::value, detail::enabler> = dummy>
452 - void add_option( 454 + Option* add_option(
453 std::string name, ///< The name, long,short 455 std::string name, ///< The name, long,short
454 T &variable, ///< The variable to set 456 T &variable, ///< The variable to set
455 std::string discription="", ///< Discription string 457 std::string discription="", ///< Discription string
456 - Combiner opts=ARGS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS()) 458 + Combiner opts=VALIDATORS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS())
457 ) { 459 ) {
458 460
459 461
@@ -469,38 +471,37 @@ public: @@ -469,38 +471,37 @@ public:
469 return lexical_cast(res[0][0], variable); 471 return lexical_cast(res[0][0], variable);
470 }; 472 };
471 473
472 - add_option(name, fun, discription, opts); 474 + return add_option(name, fun, discription, opts);
473 } 475 }
474 476
475 /// Add option for vector of results 477 /// Add option for vector of results
476 template<typename T> 478 template<typename T>
477 - void add_option( 479 + Option* add_option(
478 std::string name, ///< The name, long,short 480 std::string name, ///< The name, long,short
479 std::vector<T> &variable, ///< The variable to set 481 std::vector<T> &variable, ///< The variable to set
480 std::string discription="", ///< Discription string 482 std::string discription="", ///< Discription string
481 - Combiner opts=ARGS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS()) 483 + Combiner opts=VALIDATORS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS())
482 ) { 484 ) {
483 485
484 if(opts.num==0) 486 if(opts.num==0)
485 - throw IncorrectConstruction("Must have ARGS(1) or be a vector."); 487 + throw IncorrectConstruction("Must have ARGS or be a vector.");
486 CLI::callback_t fun = [&variable](CLI::results_t res){ 488 CLI::callback_t fun = [&variable](CLI::results_t res){
487 bool retval = true; 489 bool retval = true;
488 - int count = 0;  
489 variable.clear(); 490 variable.clear();
490 for(const auto &a : res) 491 for(const auto &a : res)
491 for(const auto &b : a) { 492 for(const auto &b : a) {
492 variable.emplace_back(); 493 variable.emplace_back();
493 retval &= lexical_cast(b, variable.back()); 494 retval &= lexical_cast(b, variable.back());
494 } 495 }
495 - return count != 0 && retval; 496 + return variable.size() > 0 && retval;
496 }; 497 };
497 498
498 - add_option(name, fun, discription, opts); 499 + return add_option(name, fun, discription, opts);
499 } 500 }
500 501
501 502
502 /// Add option for flag 503 /// Add option for flag
503 - void add_flag( 504 + Option* add_flag(
504 std::string name, ///< The name, short,long 505 std::string name, ///< The name, short,long
505 std::string discription="" ///< Discription string 506 std::string discription="" ///< Discription string
506 ) { 507 ) {
@@ -508,12 +509,12 @@ public: @@ -508,12 +509,12 @@ public:
508 return true; 509 return true;
509 }; 510 };
510 511
511 - add_option(name, fun, discription, NOTHING); 512 + return add_option(name, fun, discription, NOTHING);
512 } 513 }
513 514
514 /// Add option for flag 515 /// Add option for flag
515 template<typename T, enable_if_t<std::is_integral<T>::value, detail::enabler> = dummy> 516 template<typename T, enable_if_t<std::is_integral<T>::value, detail::enabler> = dummy>
516 - void add_flag( 517 + Option* add_flag(
517 std::string name, ///< The name, short,long 518 std::string name, ///< The name, short,long
518 T &count, ///< A varaible holding the count 519 T &count, ///< A varaible holding the count
519 std::string discription="" ///< Discription string 520 std::string discription="" ///< Discription string
@@ -525,19 +526,22 @@ public: @@ -525,19 +526,22 @@ public:
525 return true; 526 return true;
526 }; 527 };
527 528
528 - add_option(name, fun, discription, NOTHING); 529 + return add_option(name, fun, discription, NOTHING);
529 } 530 }
530 531
531 /// Add set of options 532 /// Add set of options
532 template<typename T> 533 template<typename T>
533 - void add_set( 534 + Option* add_set(
534 std::string name, ///< The name, short,long 535 std::string name, ///< The name, short,long
535 T &member, ///< The selected member of the set 536 T &member, ///< The selected member of the set
536 std::unordered_set<T> options, ///< The set of posibilities 537 std::unordered_set<T> options, ///< The set of posibilities
537 std::string discription="", ///< Discription string 538 std::string discription="", ///< Discription string
538 - Combiner opts=ARGS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS()) 539 + Combiner opts=VALIDATORS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS())
539 ) { 540 ) {
540 541
  542 + if(opts.num!=1)
  543 + throw IncorrectConstruction("Must have ARGS(1).");
  544 +
541 CLI::callback_t fun = [&member, options](CLI::results_t res){ 545 CLI::callback_t fun = [&member, options](CLI::results_t res){
542 if(res.size()!=1) { 546 if(res.size()!=1) {
543 return false; 547 return false;
@@ -551,7 +555,7 @@ public: @@ -551,7 +555,7 @@ public:
551 return std::find(std::begin(options), std::end(options), retval) != std::end(options); 555 return std::find(std::begin(options), std::end(options), retval) != std::end(options);
552 }; 556 };
553 557
554 - add_option(name, fun, discription, opts); 558 + return add_option(name, fun, discription, opts);
555 } 559 }
556 560
557 561
tests/CLITest.cpp
@@ -249,10 +249,37 @@ TEST_F(TApp, FileExists) { @@ -249,10 +249,37 @@ TEST_F(TApp, FileExists) {
249 EXPECT_FALSE(CLI::_ExistingFile(myfile)); 249 EXPECT_FALSE(CLI::_ExistingFile(myfile));
250 } 250 }
251 251
  252 +TEST_F(TApp, VectorFixedString) {
  253 + std::vector<std::string> strvec;
  254 + std::vector<std::string> answer{"mystring", "mystring2", "mystring3"};
  255 +
  256 + CLI::Option* opt = app.add_option("s,string", strvec, "", CLI::ARGS(3));
  257 + EXPECT_EQ(3, opt->expected());
  258 +
  259 + args = {"--string", "mystring", "mystring2", "mystring3"};
  260 + run();
  261 + EXPECT_EQ(3, app.count("string"));
  262 + EXPECT_EQ(answer, strvec);
  263 +}
252 264
253 -// TODO: Add directory test  
254 265
255 -TEST_F(TApp, Basic) { 266 +
  267 +TEST_F(TApp, VectorUnlimString) {
  268 + std::vector<std::string> strvec;
  269 + std::vector<std::string> answer{"mystring", "mystring2", "mystring3"};
  270 +
  271 + CLI::Option* opt = app.add_option("s,string", strvec, "", CLI::ARGS);
  272 + EXPECT_EQ(-1, opt->expected());
  273 +
  274 + args = {"--string", "mystring", "mystring2", "mystring3"};
  275 + EXPECT_NO_THROW(run());
  276 + EXPECT_EQ(3, app.count("string"));
  277 + EXPECT_EQ(answer, strvec);
  278 +}
  279 +
  280 +
  281 +
  282 +TEST_F(TApp, BasicSubcommands) {
256 auto sub1 = app.add_subcommand("sub1"); 283 auto sub1 = app.add_subcommand("sub1");
257 auto sub2 = app.add_subcommand("sub2"); 284 auto sub2 = app.add_subcommand("sub2");
258 285
@@ -272,6 +299,9 @@ TEST_F(TApp, Basic) { @@ -272,6 +299,9 @@ TEST_F(TApp, Basic) {
272 EXPECT_EQ(sub2, app.get_subcommand()); 299 EXPECT_EQ(sub2, app.get_subcommand());
273 } 300 }
274 301
  302 +// TODO: Add directory test
  303 +
  304 +
275 305
276 struct SubcommandProgram : public TApp { 306 struct SubcommandProgram : public TApp {
277 307
@@ -316,7 +346,7 @@ TEST_F(SubcommandProgram, SpareSub) { @@ -316,7 +346,7 @@ TEST_F(SubcommandProgram, SpareSub) {
316 } 346 }
317 347
318 // TODO: Add vector arguments 348 // TODO: Add vector arguments
319 -// TODO: Maybe add function to call on subcommand parse? 349 +// TODO: Maybe add function to call on subcommand parse? Stashed.
320 // TODO: Check help output 350 // TODO: Check help output
321 // TODO: Add default/type info to help 351 // TODO: Add default/type info to help
322 // TODO: Add set checking 352 // TODO: Add set checking