Commit 84cfcc185bafc66089214a140b5a8522a9d9e4e8
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,6 +116,18 @@ protected: | ||
| 116 | 116 | ||
| 117 | public: | 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 | /// This class is true if option is passed. | 131 | /// This class is true if option is passed. |
| 120 | operator bool() const { | 132 | operator bool() const { |
| 121 | return results_.size() > 0; | 133 | return results_.size() > 0; |
| @@ -126,6 +138,10 @@ public: | @@ -126,6 +138,10 @@ public: | ||
| 126 | results_.clear(); | 138 | results_.clear(); |
| 127 | } | 139 | } |
| 128 | 140 | ||
| 141 | + ///@} | ||
| 142 | + /// @name Configuration | ||
| 143 | + ///@{ | ||
| 144 | + | ||
| 129 | /// Set the option as required | 145 | /// Set the option as required |
| 130 | Option* required(bool value = true) { | 146 | Option* required(bool value = true) { |
| 131 | required_ = value; | 147 | required_ = value; |
| @@ -137,11 +153,6 @@ public: | @@ -137,11 +153,6 @@ public: | ||
| 137 | return required(value); | 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 | /// Set the number of expected arguments (Flags bypass this) | 156 | /// Set the number of expected arguments (Flags bypass this) |
| 146 | Option* expected(int value) { | 157 | Option* expected(int value) { |
| 147 | if(value == 0) | 158 | if(value == 0) |
| @@ -152,31 +163,6 @@ public: | @@ -152,31 +163,6 @@ public: | ||
| 152 | return this; | 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 | /// Adds a validator | 166 | /// Adds a validator |
| 181 | Option* check(std::function<bool(std::string)> validator) { | 167 | Option* check(std::function<bool(std::string)> validator) { |
| 182 | 168 | ||
| @@ -190,15 +176,6 @@ public: | @@ -190,15 +176,6 @@ public: | ||
| 190 | return this; | 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 | /// Sets required options | 180 | /// Sets required options |
| 204 | Option* requires(Option* opt) { | 181 | Option* requires(Option* opt) { |
| @@ -236,6 +213,84 @@ public: | @@ -236,6 +213,84 @@ public: | ||
| 236 | return this; | 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 | /// The name and any extras needed for positionals | 294 | /// The name and any extras needed for positionals |
| 240 | std::string help_positional() const { | 295 | std::string help_positional() const { |
| 241 | std::string out = pname_; | 296 | std::string out = pname_; |
| @@ -247,12 +302,54 @@ public: | @@ -247,12 +302,54 @@ public: | ||
| 247 | return out; | 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 | /// Process the callback | 353 | /// Process the callback |
| 257 | void run_callback() const { | 354 | void run_callback() const { |
| 258 | if(!callback_(results_)) | 355 | if(!callback_(results_)) |
| @@ -283,31 +380,6 @@ public: | @@ -283,31 +380,6 @@ public: | ||
| 283 | return false; | 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 | /// Check a name. Requires "-" or "--" for short / long, supports positional name | 383 | /// Check a name. Requires "-" or "--" for short / long, supports positional name |
| 312 | bool check_name(std::string name) const { | 384 | bool check_name(std::string name) const { |
| 313 | 385 | ||
| @@ -359,57 +431,6 @@ public: | @@ -359,57 +431,6 @@ public: | ||
| 359 | return results_.size() - 1; | 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 | /// Produce a flattened vector of results, vs. a vector of vectors. | 435 | /// Produce a flattened vector of results, vs. a vector of vectors. |
| 415 | std::vector<std::string> flatten_results() const { | 436 | std::vector<std::string> flatten_results() const { |
| @@ -419,6 +440,8 @@ public: | @@ -419,6 +440,8 @@ public: | ||
| 419 | return output; | 440 | return output; |
| 420 | } | 441 | } |
| 421 | 442 | ||
| 443 | + ///@} | ||
| 444 | + | ||
| 422 | }; | 445 | }; |
| 423 | 446 | ||
| 424 | 447 |