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 87 Combiner operator() (int n) const {
88 88 Combiner self = *this;
89 89 self.num = n;
90   - return *this;
  90 + return self;
91 91 }
92 92 /// Call to give a validator
93 93 Combiner operator() (std::function<bool(std::string)> func) const {
... ... @@ -182,8 +182,7 @@ const Combiner NOTHING {0, false,false,false, {}};
182 182 const Combiner REQUIRED {1, false,true, false, {}};
183 183 const Combiner DEFAULT {1, false,false,true, {}};
184 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 186 const Combiner VALIDATORS {1, false, false, false, {}};
188 187  
189 188 // Warning about using these validators:
... ... @@ -196,6 +195,8 @@ const Combiner NonexistentPath {1, false, false, false, {_NonexistentPath}};
196 195 typedef std::vector<std::vector<std::string>> results_t;
197 196 typedef std::function<bool(results_t)> callback_t;
198 197  
  198 +
  199 +
199 200 class Option {
200 201 public:
201 202 protected:
... ... @@ -433,27 +434,28 @@ public:
433 434 * std::string filename
434 435 * program.add_option("filename", filename, "discription of filename");
435 436 */
436   - void add_option(
  437 + Option* add_option(
437 438 std::string name, ///< The name, long,short
438 439 callback_t callback, ///< The callback
439 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 443 Option myopt{name, discription, opts, callback};
443 444 if(std::find(std::begin(options), std::end(options), myopt) == std::end(options))
444 445 options.push_back(myopt);
445 446 else
446 447 throw OptionAlreadyAdded(myopt.get_name());
  448 + return &options.back();
447 449  
448 450 }
449 451  
450 452 /// Add option for string
451 453 template<typename T, enable_if_t<!std::is_array<T>::value, detail::enabler> = dummy>
452   - void add_option(
  454 + Option* add_option(
453 455 std::string name, ///< The name, long,short
454 456 T &variable, ///< The variable to set
455 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 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 477 /// Add option for vector of results
476 478 template<typename T>
477   - void add_option(
  479 + Option* add_option(
478 480 std::string name, ///< The name, long,short
479 481 std::vector<T> &variable, ///< The variable to set
480 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 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 488 CLI::callback_t fun = [&variable](CLI::results_t res){
487 489 bool retval = true;
488   - int count = 0;
489 490 variable.clear();
490 491 for(const auto &a : res)
491 492 for(const auto &b : a) {
492 493 variable.emplace_back();
493 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 503 /// Add option for flag
503   - void add_flag(
  504 + Option* add_flag(
504 505 std::string name, ///< The name, short,long
505 506 std::string discription="" ///< Discription string
506 507 ) {
... ... @@ -508,12 +509,12 @@ public:
508 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 515 /// Add option for flag
515 516 template<typename T, enable_if_t<std::is_integral<T>::value, detail::enabler> = dummy>
516   - void add_flag(
  517 + Option* add_flag(
517 518 std::string name, ///< The name, short,long
518 519 T &count, ///< A varaible holding the count
519 520 std::string discription="" ///< Discription string
... ... @@ -525,19 +526,22 @@ public:
525 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 532 /// Add set of options
532 533 template<typename T>
533   - void add_set(
  534 + Option* add_set(
534 535 std::string name, ///< The name, short,long
535 536 T &member, ///< The selected member of the set
536 537 std::unordered_set<T> options, ///< The set of posibilities
537 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 545 CLI::callback_t fun = [&member, options](CLI::results_t res){
542 546 if(res.size()!=1) {
543 547 return false;
... ... @@ -551,7 +555,7 @@ public:
551 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 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 283 auto sub1 = app.add_subcommand("sub1");
257 284 auto sub2 = app.add_subcommand("sub2");
258 285  
... ... @@ -272,6 +299,9 @@ TEST_F(TApp, Basic) {
272 299 EXPECT_EQ(sub2, app.get_subcommand());
273 300 }
274 301  
  302 +// TODO: Add directory test
  303 +
  304 +
275 305  
276 306 struct SubcommandProgram : public TApp {
277 307  
... ... @@ -316,7 +346,7 @@ TEST_F(SubcommandProgram, SpareSub) {
316 346 }
317 347  
318 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 350 // TODO: Check help output
321 351 // TODO: Add default/type info to help
322 352 // TODO: Add set checking
... ...