Commit c02130b7db98f2389fe45a823cb189265c47c075

Authored by Henry Fredrick Schreiner
1 parent 1dfe8dce

Nicer docs

Showing 1 changed file with 133 additions and 96 deletions
include/CLI/App.hpp
@@ -109,10 +109,13 @@ protected: @@ -109,10 +109,13 @@ protected:
109 /// Pointer to the config option 109 /// Pointer to the config option
110 Option* config_ptr_ {nullptr}; 110 Option* config_ptr_ {nullptr};
111 111
112 - ///@} 112 + yy///@}
113 113
114 114
115 public: 115 public:
  116 + /// @name Basic
  117 + ///@{
  118 +
116 /// Create a new program. Pass in the same arguments as main(), along with a help string. 119 /// Create a new program. Pass in the same arguments as main(), along with a help string.
117 App(std::string description_="", bool help=true) 120 App(std::string description_="", bool help=true)
118 : description_(description_) { 121 : description_(description_) {
@@ -133,67 +136,49 @@ public: @@ -133,67 +136,49 @@ public:
133 callback_ = callback; 136 callback_ = callback;
134 } 137 }
135 138
136 - /// Reset the parsed data  
137 - void reset() {  
138 -  
139 - selected_subcommands_.clear();  
140 - missing_.clear(); 139 + /// Remove the error when extras are left over on the command line.
  140 + void allow_extras (bool allow=true) {
  141 + allow_extras_ = allow;
  142 + }
141 143
142 - for(const Option_p &opt : options_) {  
143 - opt->clear();  
144 - }  
145 - for(const App_p &app : subcommands_) {  
146 - app->reset(); 144 + /// Ignore case
  145 + App* ignore_case(bool value = true) {
  146 + ignore_case_ = value;
  147 + if(parent_ != nullptr) {
  148 + for(const auto &subc : parent_->subcommands_) {
  149 + if(subc.get() != this && (this->check_name(subc->name_) || subc->check_name(this->name_)))
  150 + throw OptionAlreadyAdded(subc->name_);
  151 + }
147 } 152 }
  153 + return this;
148 } 154 }
149 155
150 - /// Get a pointer to the help flag.  
151 - Option* get_help_ptr() {  
152 - return help_ptr_; 156 + /// Require a subcommand to be given (does not affect help call)
  157 + /// Does not return a pointer since it is supposed to be called on the main App.
  158 + void require_subcommand(int value = -1) {
  159 + require_subcommand_ = value;
153 } 160 }
154 161
155 - /// Get a pointer to the config option.  
156 - Option* get_config_ptr() {  
157 - return config_ptr_;  
158 - }  
159 162
160 - /// Produce a string that could be read in as a config of the current values of the App  
161 - std::string config_to_str() const {  
162 - std::stringstream out;  
163 - for(const Option_p &opt : options_) {  
164 - if(opt->lnames.size() > 0 && opt->count() > 0 && opt->get_expected() > 0)  
165 - out << opt->lnames[0] << "=" << detail::join(opt->flatten_results()) << std::endl;  
166 - }  
167 - return out.str();  
168 - }  
169 -  
170 - /// Add a subcommand. Like the constructor, you can override the help message addition by setting help=false  
171 - App* add_subcommand(std::string name, std::string description="", bool help=true) {  
172 - subcommands_.emplace_back(new App(description, help));  
173 - subcommands_.back()->name_ = name;  
174 - subcommands_.back()->allow_extras();  
175 - subcommands_.back()->parent_ = this;  
176 - subcommands_.back()->ignore_case_ = ignore_case_;  
177 - for(const auto& subc : subcommands_)  
178 - if(subc.get() != subcommands_.back().get())  
179 - if(subc->check_name(subcommands_.back()->name_) || subcommands_.back()->check_name(subc->name_))  
180 - throw OptionAlreadyAdded(subc->name_);  
181 - return subcommands_.back().get();  
182 - }  
183 163
  164 + ///@}
  165 + /// @name Adding options
  166 + ///@{
  167 +
184 /// Add an option, will automatically understand the type for common types. 168 /// Add an option, will automatically understand the type for common types.
185 - /** To use, create a variable with the expected type, and pass it in after the name.  
186 - * After start is called, you can use count to see if the value was passed, and  
187 - * the value will be initialized properly.  
188 - *  
189 - * ->required(), ->default, and the validators are options_,  
190 - * The positional options take an optional number of arguments.  
191 - *  
192 - * For example,  
193 - *  
194 - * std::string filename  
195 - * program.add_option("filename", filename, "description of filename");  
196 - */ 169 + ///
  170 + /// To use, create a variable with the expected type, and pass it in after the name.
  171 + /// After start is called, you can use count to see if the value was passed, and
  172 + /// the value will be initialized properly. Numbers, vectors, and strings are supported.
  173 + ///
  174 + /// ->required(), ->default, and the validators are options,
  175 + /// The positional options take an optional number of arguments.
  176 + ///
  177 + /// For example,
  178 + ///
  179 + /// std::string filename
  180 + /// program.add_option("filename", filename, "description of filename");
  181 +
197 Option* add_option( 182 Option* add_option(
198 std::string name, 183 std::string name,
199 callback_t callback, 184 callback_t callback,
@@ -213,7 +198,7 @@ public: @@ -213,7 +198,7 @@ public:
213 198
214 } 199 }
215 200
216 - /// Add option for string 201 + /// Add option for non-vectors
217 template<typename T, enable_if_t<!is_vector<T>::value, detail::enabler> = detail::dummy> 202 template<typename T, enable_if_t<!is_vector<T>::value, detail::enabler> = detail::dummy>
218 Option* add_option( 203 Option* add_option(
219 std::string name, 204 std::string name,
@@ -243,7 +228,7 @@ public: @@ -243,7 +228,7 @@ public:
243 return retval; 228 return retval;
244 } 229 }
245 230
246 - /// Add option for vector of results 231 + /// Add option for vectors
247 template<typename T> 232 template<typename T>
248 Option* add_option( 233 Option* add_option(
249 std::string name, 234 std::string name,
@@ -272,7 +257,6 @@ public: @@ -272,7 +257,6 @@ public:
272 return retval; 257 return retval;
273 } 258 }
274 259
275 -  
276 /// Add option for flag 260 /// Add option for flag
277 Option* add_flag( 261 Option* add_flag(
278 std::string name, 262 std::string name,
@@ -430,11 +414,39 @@ public: @@ -430,11 +414,39 @@ public:
430 } 414 }
431 return false; 415 return false;
432 } 416 }
  417 +
  418 + ///@}
  419 + /// @name Subcommmands
  420 + ///@{
  421 +
  422 + /// Add a subcommand. Like the constructor, you can override the help message addition by setting help=false
  423 + App* add_subcommand(std::string name, std::string description="", bool help=true) {
  424 + subcommands_.emplace_back(new App(description, help));
  425 + subcommands_.back()->name_ = name;
  426 + subcommands_.back()->allow_extras();
  427 + subcommands_.back()->parent_ = this;
  428 + subcommands_.back()->ignore_case_ = ignore_case_;
  429 + for(const auto& subc : subcommands_)
  430 + if(subc.get() != subcommands_.back().get())
  431 + if(subc->check_name(subcommands_.back()->name_) || subcommands_.back()->check_name(subc->name_))
  432 + throw OptionAlreadyAdded(subc->name_);
  433 + return subcommands_.back().get();
  434 + }
  435 +
  436 +
  437 +
  438 + ///@}
  439 + /// @name Extras for subclassing
  440 + ///@{
433 441
434 /// This allows subclasses to inject code before callbacks but after parse 442 /// This allows subclasses to inject code before callbacks but after parse
435 /// This does not run if any errors or help is thrown. 443 /// This does not run if any errors or help is thrown.
436 virtual void pre_callback() {} 444 virtual void pre_callback() {}
437 445
  446 + ///@}
  447 + /// @name Parsing
  448 + ///@{
  449 +
438 /// Parses the command line - throws errors 450 /// Parses the command line - throws errors
439 /// This must be called after the options are in but before the rest of the program. 451 /// This must be called after the options are in but before the rest of the program.
440 std::vector<std::string> parse(int argc, char **argv) { 452 std::vector<std::string> parse(int argc, char **argv) {
@@ -452,12 +464,6 @@ public: @@ -452,12 +464,6 @@ public:
452 return _parse(args); 464 return _parse(args);
453 } 465 }
454 466
455 - /// Remove the error when extras are left over on the command line.  
456 - void allow_extras (bool allow=true) {  
457 - allow_extras_ = allow;  
458 - }  
459 -  
460 -  
461 /// Print a nice error message and return the exit code 467 /// Print a nice error message and return the exit code
462 int exit(const Error& e) const { 468 int exit(const Error& e) const {
463 if(e.exit_code != 0) { 469 if(e.exit_code != 0) {
@@ -472,6 +478,24 @@ public: @@ -472,6 +478,24 @@ public:
472 return e.exit_code; 478 return e.exit_code;
473 } 479 }
474 480
  481 + /// Reset the parsed data
  482 + void reset() {
  483 +
  484 + selected_subcommands_.clear();
  485 + missing_.clear();
  486 +
  487 + for(const Option_p &opt : options_) {
  488 + opt->clear();
  489 + }
  490 + for(const App_p &app : subcommands_) {
  491 + app->reset();
  492 + }
  493 + }
  494 +
  495 + ///@}
  496 + /// @name Post parsing
  497 + ///@{
  498 +
475 /// Counts the number of times the given option was passed. 499 /// Counts the number of times the given option was passed.
476 int count(std::string name) const { 500 int count(std::string name) const {
477 for(const Option_p &opt : options_) { 501 for(const Option_p &opt : options_) {
@@ -482,6 +506,41 @@ public: @@ -482,6 +506,41 @@ public:
482 throw OptionNotFound(name); 506 throw OptionNotFound(name);
483 } 507 }
484 508
  509 + /// Get a subcommand pointer list to the currently selected subcommands (after parsing)
  510 + std::vector<App*> get_subcommands() {
  511 + return selected_subcommands_;
  512 + }
  513 +
  514 +
  515 + /// Check to see if selected subcommand in list
  516 + bool got_subcommand(App* subcom) const {
  517 + return std::find(std::begin(selected_subcommands_),
  518 + std::end(selected_subcommands_), subcom)
  519 + != std::end(selected_subcommands_);
  520 + }
  521 +
  522 + /// Check with name instead of pointer
  523 + bool got_subcommand(std::string name) const {
  524 + for(const auto subcomptr : selected_subcommands_)
  525 + if(subcomptr->check_name(name))
  526 + return true;
  527 + return false;
  528 + }
  529 +
  530 + ///@}
  531 + /// @name Help
  532 + ///@{
  533 +
  534 + /// Produce a string that could be read in as a config of the current values of the App
  535 + std::string config_to_str() const {
  536 + std::stringstream out;
  537 + for(const Option_p &opt : options_) {
  538 + if(opt->lnames.size() > 0 && opt->count() > 0 && opt->get_expected() > 0)
  539 + out << opt->lnames[0] << "=" << detail::join(opt->flatten_results()) << std::endl;
  540 + }
  541 + return out.str();
  542 + }
  543 +
485 /// Makes a help message, with a column wid for column 1 544 /// Makes a help message, with a column wid for column 1
486 std::string help(size_t wid=30, std::string prev="") const { 545 std::string help(size_t wid=30, std::string prev="") const {
487 // Delegate to subcommand if needed 546 // Delegate to subcommand if needed
@@ -568,34 +627,27 @@ public: @@ -568,34 +627,27 @@ public:
568 } 627 }
569 return out.str(); 628 return out.str();
570 } 629 }
571 -  
572 - /// Get a subcommand pointer list to the currently selected subcommands (after parsing)  
573 - std::vector<App*> get_subcommands() {  
574 - return selected_subcommands_;  
575 - }  
576 630
  631 + ///@}
  632 + /// @name Getters
  633 + ///@{
577 634
578 - /// Check to see if selected subcommand in list  
579 - bool got_subcommand(App* subcom) const {  
580 - return std::find(std::begin(selected_subcommands_),  
581 - std::end(selected_subcommands_), subcom)  
582 - != std::end(selected_subcommands_); 635 + /// Get a pointer to the help flag.
  636 + Option* get_help_ptr() {
  637 + return help_ptr_;
583 } 638 }
584 639
585 - /// Check with name instead of pointer  
586 - bool got_subcommand(std::string name) const {  
587 - for(const auto subcomptr : selected_subcommands_)  
588 - if(subcomptr->check_name(name))  
589 - return true;  
590 - return false; 640 + /// Get a pointer to the config option.
  641 + Option* get_config_ptr() {
  642 + return config_ptr_;
591 } 643 }
592 - 644 +
593 /// Get the name of the current app 645 /// Get the name of the current app
594 std::string get_name() const { 646 std::string get_name() const {
595 return name_; 647 return name_;
596 } 648 }
597 649
598 - /// Check the name_, case insensitive if set 650 + /// Check the name, case insensitive if set
599 bool check_name(std::string name_to_check) const { 651 bool check_name(std::string name_to_check) const {
600 std::string local_name = name_; 652 std::string local_name = name_;
601 if(ignore_case_) { 653 if(ignore_case_) {
@@ -606,23 +658,8 @@ public: @@ -606,23 +658,8 @@ public:
606 return local_name == name_to_check; 658 return local_name == name_to_check;
607 } 659 }
608 660
609 - /// Ignore case  
610 - App* ignore_case(bool value = true) {  
611 - ignore_case_ = value;  
612 - if(parent_ != nullptr) {  
613 - for(const auto &subc : parent_->subcommands_) {  
614 - if(subc.get() != this && (this->check_name(subc->name_) || subc->check_name(this->name_)))  
615 - throw OptionAlreadyAdded(subc->name_);  
616 - }  
617 - }  
618 - return this;  
619 - } 661 + ///@}
620 662
621 - /// Require a subcommand to be given (does not affect help call)  
622 - /// Does not return a pointer since it is supposed to be called on the main App.  
623 - void require_subcommand(int value = -1) {  
624 - require_subcommand_ = value;  
625 - }  
626 663
627 protected: 664 protected:
628 665