Commit 324a9c738decace7446bbae52c46a25d7a8c689a

Authored by Henry Fredrick Schreiner
1 parent 074d0339

Adding make_* options

include/CLI.hpp
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 #include <algorithm> 11 #include <algorithm>
12 #include <sstream> 12 #include <sstream>
13 #include <type_traits> 13 #include <type_traits>
14 -#include <unordered_set> 14 +#include <set>
15 #include <iomanip> 15 #include <iomanip>
16 #include <numeric> 16 #include <numeric>
17 17
@@ -450,6 +450,10 @@ public: @@ -450,6 +450,10 @@ public:
450 logit(subcommands.back()->name); 450 logit(subcommands.back()->name);
451 return subcommands.back().get(); 451 return subcommands.back().get();
452 } 452 }
  453 +
  454 +
  455 + //------------ ADD STYLE ---------//
  456 +
453 /// Add an option, will automatically understand the type for common types. 457 /// Add an option, will automatically understand the type for common types.
454 /** To use, create a variable with the expected type, and pass it in after the name. 458 /** To use, create a variable with the expected type, and pass it in after the name.
455 * After start is called, you can use count to see if the value was passed, and 459 * After start is called, you can use count to see if the value was passed, and
@@ -563,7 +567,7 @@ public: @@ -563,7 +567,7 @@ public:
563 Option* add_set( 567 Option* add_set(
564 std::string name, ///< The name, short,long 568 std::string name, ///< The name, short,long
565 T &member, ///< The selected member of the set 569 T &member, ///< The selected member of the set
566 - std::unordered_set<T> options, ///< The set of posibilities 570 + std::set<T> options, ///< The set of posibilities
567 std::string discription="", ///< Discription string 571 std::string discription="", ///< Discription string
568 Combiner opts=VALIDATORS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS()) 572 Combiner opts=VALIDATORS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS())
569 ) { 573 ) {
@@ -581,14 +585,20 @@ public: @@ -581,14 +585,20 @@ public:
581 bool retval = lexical_cast(res[0][0], member); 585 bool retval = lexical_cast(res[0][0], member);
582 if(!retval) 586 if(!retval)
583 return false; 587 return false;
584 - return std::find(std::begin(options), std::end(options), retval) != std::end(options); 588 + return std::find(std::begin(options), std::end(options), member) != std::end(options);
585 }; 589 };
586 590
587 return add_option(name, fun, discription, opts); 591 return add_option(name, fun, discription, opts);
588 } 592 }
589 593
  594 +
  595 +
  596 +
  597 + //------------ MAKE STYLE ---------//
  598 +
590 /// Prototype for new output style 599 /// Prototype for new output style
591 - template<typename T = std::string> 600 + template<typename T = std::string,
  601 + enable_if_t<!std::is_array<T>::value, detail::enabler> = dummy>
592 Value<T> make_option( 602 Value<T> make_option(
593 std::string name, ///< The name, short,long 603 std::string name, ///< The name, short,long
594 std::string discription="", 604 std::string discription="",
@@ -611,7 +621,117 @@ public: @@ -611,7 +621,117 @@ public:
611 add_option(name, fun, discription, opts); 621 add_option(name, fun, discription, opts);
612 return out; 622 return out;
613 } 623 }
  624 +
  625 + /// Prototype for new output style with default
  626 + template<typename T = std::string,
  627 + enable_if_t<!std::is_array<T>::value, detail::enabler> = dummy>
  628 + Value<T> make_option(
  629 + std::string name, ///< The name, short,long
  630 + const T& default_value,
  631 + std::string discription="",
  632 + Combiner opts=VALIDATORS
  633 + ) {
  634 +
  635 + Value<T> out(name);
  636 + std::shared_ptr<std::unique_ptr<T>> ptr = out.value;
  637 + ptr->reset(new T(default_value)); // resets the internal ptr
  638 +
  639 + CLI::callback_t fun = [ptr](CLI::results_t res){
  640 + if(res.size()!=1) {
  641 + return false;
  642 + }
  643 + if(res[0].size()!=1) {
  644 + return false;
  645 + }
  646 + ptr->reset(new T()); // resets the internal ptr
  647 + return lexical_cast(res[0][0], **ptr);
  648 + };
  649 + add_option(name, fun, discription, opts);
  650 + return out;
  651 + }
614 652
  653 + /// Prototype for new output style
  654 + template<typename T>
  655 + Value<std::vector<T>> make_option(
  656 + std::string name, ///< The name, short,long
  657 + std::string discription="",
  658 + Combiner opts=VALIDATORS
  659 + ) {
  660 +
  661 + if(opts.num==0)
  662 + throw IncorrectConstruction("Must have ARGS or be a vector.");
  663 +
  664 + Value<std::vector<T>> out(name);
  665 + std::shared_ptr<std::unique_ptr<std::vector<T> >> ptr = out.value;
  666 +
  667 + CLI::callback_t fun = [ptr](CLI::results_t res){
  668 + ptr->reset(new std::vector<T>()); // resets the internal ptr
  669 + bool retval = true;
  670 + for(const auto &a : res)
  671 + for(const auto &b : a) {
  672 + (*ptr)->emplace_back();
  673 + retval &= lexical_cast(b, (*ptr)->back());
  674 + }
  675 + return (*ptr)->size() > 0 && retval;
  676 + };
  677 + add_option(name, fun, discription, opts);
  678 + return out;
  679 + }
  680 +
  681 +
  682 + /// Prototype for new output style: flag
  683 + Value<int> make_flag(
  684 + std::string name, ///< The name, short,long
  685 + std::string discription=""
  686 + ) {
  687 +
  688 + Value<int> out(name);
  689 + std::shared_ptr<std::unique_ptr<int>> ptr = out.value;
  690 + ptr->reset(new int()); // resets the internal ptr
  691 + **ptr = 0;
  692 +
  693 + CLI::callback_t fun = [ptr](CLI::results_t res){
  694 + **ptr = (int) res.size();
  695 + return true;
  696 + };
  697 + add_option(name, fun, discription, NOTHING);
  698 + return out;
  699 + }
  700 +
  701 + /// Add set of options
  702 + template<typename T>
  703 + Value<T> make_set(
  704 + std::string name, ///< The name, short,long
  705 + std::set<T> options, ///< The set of posibilities
  706 + std::string discription="", ///< Discription string
  707 + Combiner opts=VALIDATORS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS())
  708 + ) {
  709 +
  710 + Value<T> out(name);
  711 + std::shared_ptr<std::unique_ptr<T>> ptr = out.value;
  712 +
  713 + if(opts.num!=1)
  714 + throw IncorrectConstruction("Must have ARGS(1).");
  715 +
  716 + CLI::callback_t fun = [ptr, options](CLI::results_t res){
  717 + if(res.size()!=1) {
  718 + return false;
  719 + }
  720 + if(res[0].size()!=1) {
  721 + return false;
  722 + }
  723 + ptr->reset(new T());
  724 + bool retval = lexical_cast(res[0][0], **ptr);
  725 + if(!retval)
  726 + return false;
  727 + return std::find(std::begin(options), std::end(options), **ptr) != std::end(options);
  728 + };
  729 +
  730 + add_option(name, fun, discription, opts);
  731 + return out;
  732 + }
  733 +
  734 +
615 735
616 /// Parses the command line - throws errors 736 /// Parses the command line - throws errors
617 void parse(int argc, char **argv) { 737 void parse(int argc, char **argv) {
tests/CLITest.cpp
@@ -249,6 +249,22 @@ TEST_F(TApp, FileExists) { @@ -249,6 +249,22 @@ TEST_F(TApp, FileExists) {
249 EXPECT_FALSE(CLI::_ExistingFile(myfile)); 249 EXPECT_FALSE(CLI::_ExistingFile(myfile));
250 } 250 }
251 251
  252 +TEST_F(TApp, InSet) {
  253 +
  254 + std::string choice;
  255 + app.add_set("q,quick", choice, {"one", "two", "three"});
  256 +
  257 + args = {"--quick", "two"};
  258 +
  259 + EXPECT_NO_THROW(run());
  260 + EXPECT_EQ("two", choice);
  261 +
  262 + app.reset();
  263 +
  264 + args = {"--quick", "four"};
  265 + EXPECT_THROW(run(), CLI::ParseError);
  266 +}
  267 +
252 TEST_F(TApp, VectorFixedString) { 268 TEST_F(TApp, VectorFixedString) {
253 std::vector<std::string> strvec; 269 std::vector<std::string> strvec;
254 std::vector<std::string> answer{"mystring", "mystring2", "mystring3"}; 270 std::vector<std::string> answer{"mystring", "mystring2", "mystring3"};
@@ -366,7 +382,6 @@ TEST_F(TAppValue, OneString) { @@ -366,7 +382,6 @@ TEST_F(TAppValue, OneString) {
366 382
367 } 383 }
368 384
369 -// TODO: Add vector arguments  
370 // TODO: Maybe add function to call on subcommand parse? Stashed. 385 // TODO: Maybe add function to call on subcommand parse? Stashed.
371 // TODO: Check help output 386 // TODO: Check help output
372 // TODO: Add default/type info to help 387 // TODO: Add default/type info to help