Commit 84cfcc185bafc66089214a140b5a8522a9d9e4e8

Authored by Henry Fredrick Schreiner
1 parent a8f5b328

Adding nicer docs

Showing 1 changed file with 141 additions and 118 deletions
include/CLI/Option.hpp
... ... @@ -116,6 +116,18 @@ protected:
116 116  
117 117 public:
118 118  
  119 + /// @name Basic
  120 + ///@{
  121 +
  122 + /// Count the total number of times an option was passed
  123 + int count() const {
  124 + int out = 0;
  125 + for(const std::vector<std::string>& vec : results_)
  126 + out += vec.size();
  127 + return out;
  128 + }
  129 +
  130 +
119 131 /// This class is true if option is passed.
120 132 operator bool() const {
121 133 return results_.size() > 0;
... ... @@ -126,6 +138,10 @@ public:
126 138 results_.clear();
127 139 }
128 140  
  141 + ///@}
  142 + /// @name Configuration
  143 + ///@{
  144 +
129 145 /// Set the option as required
130 146 Option* required(bool value = true) {
131 147 required_ = value;
... ... @@ -137,11 +153,6 @@ public:
137 153 return required(value);
138 154 }
139 155  
140   - /// True if this is a required option
141   - bool get_required() const {
142   - return required_;
143   - }
144   -
145 156 /// Set the number of expected arguments (Flags bypass this)
146 157 Option* expected(int value) {
147 158 if(value == 0)
... ... @@ -152,31 +163,6 @@ public:
152 163 return this;
153 164 }
154 165  
155   - /// The number of arguments the option expects
156   - int get_expected() const {
157   - return expected_;
158   - }
159   -
160   - /// True if this has a default value
161   - int get_default() const {
162   - return default_;
163   - }
164   -
165   - /// True if the argument can be given directly
166   - bool get_positional() const {
167   - return pname_.length() > 0;
168   - }
169   -
170   - /// True if option has at least one non-positional name
171   - bool nonpositional() const {
172   - return (snames_.size() + lnames_.size()) > 0;
173   - }
174   -
175   - /// True if option has description
176   - bool has_description() const {
177   - return description_.length() > 0;
178   - }
179   -
180 166 /// Adds a validator
181 167 Option* check(std::function<bool(std::string)> validator) {
182 168  
... ... @@ -190,15 +176,6 @@ public:
190 176 return this;
191 177 }
192 178  
193   - /// Get the group of this option
194   - const std::string& get_group() const {
195   - return group_;
196   - }
197   -
198   - /// Get the description
199   - const std::string& get_description() const {
200   - return description_;
201   - }
202 179  
203 180 /// Sets required options
204 181 Option* requires(Option* opt) {
... ... @@ -236,6 +213,84 @@ public:
236 213 return this;
237 214 }
238 215  
  216 + /// Ignore case
  217 + ///
  218 + /// The template hides the fact that we don't have the definition of App yet.
  219 + /// You are never expected to add an argument to the template here.
  220 + template<typename T=App>
  221 + Option* ignore_case(bool value = true) {
  222 + ignore_case_ = value;
  223 + for(const Option_p& opt : dynamic_cast<T*>(parent_)->options_)
  224 + if(opt.get() != this && *opt == *this)
  225 + throw OptionAlreadyAdded(opt->get_name());
  226 + return this;
  227 + }
  228 +
  229 + ///@}
  230 + /// @name Accessors
  231 + ///@{
  232 +
  233 + /// True if this is a required option
  234 + bool get_required() const {
  235 + return required_;
  236 + }
  237 +
  238 + /// The number of arguments the option expects
  239 + int get_expected() const {
  240 + return expected_;
  241 + }
  242 +
  243 + /// True if this has a default value
  244 + int get_default() const {
  245 + return default_;
  246 + }
  247 +
  248 + /// True if the argument can be given directly
  249 + bool get_positional() const {
  250 + return pname_.length() > 0;
  251 + }
  252 +
  253 + /// True if option has at least one non-positional name
  254 + bool nonpositional() const {
  255 + return (snames_.size() + lnames_.size()) > 0;
  256 + }
  257 +
  258 + /// True if option has description
  259 + bool has_description() const {
  260 + return description_.length() > 0;
  261 + }
  262 +
  263 + /// Get the group of this option
  264 + const std::string& get_group() const {
  265 + return group_;
  266 + }
  267 +
  268 + /// Get the description
  269 + const std::string& get_description() const {
  270 + return description_;
  271 + }
  272 +
  273 + // Just the pname
  274 + std::string get_pname() const {
  275 + return pname_;
  276 + }
  277 +
  278 + ///@}
  279 + /// @name Help
  280 + ///@{
  281 +
  282 + /// Gets a , sep list of names. Does not include the positional name if opt_only=true.
  283 + std::string get_name(bool opt_only=false) const {
  284 + std::vector<std::string> name_list;
  285 + if(!opt_only && pname_.length() > 0)
  286 + name_list.push_back(pname_);
  287 + for(const std::string& sname : snames_)
  288 + name_list.push_back("-"+sname);
  289 + for(const std::string& lname : lnames_)
  290 + name_list.push_back("--"+lname);
  291 + return detail::join(name_list);
  292 + }
  293 +
239 294 /// The name and any extras needed for positionals
240 295 std::string help_positional() const {
241 296 std::string out = pname_;
... ... @@ -247,12 +302,54 @@ public:
247 302 return out;
248 303 }
249 304  
250   - // Just the pname
251   - std::string get_pname() const {
252   - return pname_;
  305 + /// The first half of the help print, name plus default, etc
  306 + std::string help_name() const {
  307 + std::stringstream out;
  308 + out << get_name(true) << help_aftername();
  309 + return out.str();
  310 + }
  311 +
  312 + /// pname with type info
  313 + std::string help_pname() const {
  314 + std::stringstream out;
  315 + out << get_pname() << help_aftername();
  316 + return out.str();
253 317 }
254 318  
  319 + /// This is the part after the name is printed but before the description
  320 + std::string help_aftername() const {
  321 + std::stringstream out;
255 322  
  323 + if(get_expected() != 0) {
  324 + if(typeval_ != "")
  325 + out << " " << typeval_;
  326 + if(defaultval_ != "")
  327 + out << "=" << defaultval_;
  328 + if(get_expected() > 1)
  329 + out << " x " << get_expected();
  330 + if(get_expected() == -1)
  331 + out << " ...";
  332 + }
  333 + if(envname_ != "")
  334 + out << " (env:" << envname_ << ")";
  335 + if(requires_.size() > 0) {
  336 + out << " Requires:";
  337 + for(const Option* opt : requires_)
  338 + out << " " << opt->get_name();
  339 + }
  340 + if(excludes_.size() > 0) {
  341 + out << " Excludes:";
  342 + for(const Option* opt : excludes_)
  343 + out << " " << opt->get_name();
  344 + }
  345 + return out.str();
  346 +
  347 + }
  348 +
  349 + ///@}
  350 + /// @name Parser tools
  351 + ///@{
  352 +
256 353 /// Process the callback
257 354 void run_callback() const {
258 355 if(!callback_(results_))
... ... @@ -283,31 +380,6 @@ public:
283 380 return false;
284 381 }
285 382  
286   - /// Gets a , sep list of names. Does not include the positional name if opt_only=true.
287   - std::string get_name(bool opt_only=false) const {
288   - std::vector<std::string> name_list;
289   - if(!opt_only && pname_.length() > 0)
290   - name_list.push_back(pname_);
291   - for(const std::string& sname : snames_)
292   - name_list.push_back("-"+sname);
293   - for(const std::string& lname : lnames_)
294   - name_list.push_back("--"+lname);
295   - return detail::join(name_list);
296   - }
297   -
298   - /// Ignore case
299   - ///
300   - /// The template hides the fact that we don't have the definition of App yet.
301   - /// You are never expected to add an argument to the template here.
302   - template<typename T=App>
303   - Option* ignore_case(bool value = true) {
304   - ignore_case_ = value;
305   - for(const Option_p& opt : dynamic_cast<T*>(parent_)->options_)
306   - if(opt.get() != this && *opt == *this)
307   - throw OptionAlreadyAdded(opt->get_name());
308   - return this;
309   - }
310   -
311 383 /// Check a name. Requires "-" or "--" for short / long, supports positional name
312 384 bool check_name(std::string name) const {
313 385  
... ... @@ -359,57 +431,6 @@ public:
359 431 return results_.size() - 1;
360 432 }
361 433  
362   - /// Count the total number of times an option was passed
363   - int count() const {
364   - int out = 0;
365   - for(const std::vector<std::string>& vec : results_)
366   - out += vec.size();
367   - return out;
368   - }
369   -
370   - /// The first half of the help print, name plus default, etc
371   - std::string help_name() const {
372   - std::stringstream out;
373   - out << get_name(true) << _help_aftername();
374   - return out.str();
375   - }
376   -
377   - /// pname with type info
378   - std::string help_pname() const {
379   - std::stringstream out;
380   - out << get_pname() << _help_aftername();
381   - return out.str();
382   - }
383   -
384   - /// This is the part after the name is printed but before the description
385   - std::string _help_aftername() const {
386   - std::stringstream out;
387   -
388   - if(get_expected() != 0) {
389   - if(typeval_ != "")
390   - out << " " << typeval_;
391   - if(defaultval_ != "")
392   - out << "=" << defaultval_;
393   - if(get_expected() > 1)
394   - out << " x " << get_expected();
395   - if(get_expected() == -1)
396   - out << " ...";
397   - }
398   - if(envname_ != "")
399   - out << " (env:" << envname_ << ")";
400   - if(requires_.size() > 0) {
401   - out << " Requires:";
402   - for(const Option* opt : requires_)
403   - out << " " << opt->get_name();
404   - }
405   - if(excludes_.size() > 0) {
406   - out << " Excludes:";
407   - for(const Option* opt : excludes_)
408   - out << " " << opt->get_name();
409   - }
410   - return out.str();
411   -
412   - }
413 434  
414 435 /// Produce a flattened vector of results, vs. a vector of vectors.
415 436 std::vector<std::string> flatten_results() const {
... ... @@ -419,6 +440,8 @@ public:
419 440 return output;
420 441 }
421 442  
  443 + ///@}
  444 +
422 445 };
423 446  
424 447  
... ...