Commit 200d0f277feb9c8846fff0b71e782726c26bf78f
1 parent
955dd950
Massive move to -a,--long,posit syntax
Showing
5 changed files
with
287 additions
and
183 deletions
examples/try.cpp
| ... | ... | @@ -6,13 +6,13 @@ int main (int argc, char** argv) { |
| 6 | 6 | CLI::App app("K3Pi goofit fitter"); |
| 7 | 7 | |
| 8 | 8 | std::string file; |
| 9 | - app.add_option("f,file", file, "File name"); | |
| 9 | + app.add_option("-f,--file", file, "File name"); | |
| 10 | 10 | |
| 11 | 11 | int count; |
| 12 | - app.add_flag("c,count", count, "Counter"); | |
| 12 | + app.add_flag("-c,--count", count, "Counter"); | |
| 13 | 13 | |
| 14 | 14 | double value = 3.14; |
| 15 | - app.add_option("-d,--double", value, "Some Value", CLI::DEFAULT); | |
| 15 | + app.add_option("-d,--double", value, "Some Value", CLI::Default); | |
| 16 | 16 | |
| 17 | 17 | try { |
| 18 | 18 | app.run(argc, argv); |
| ... | ... | @@ -20,8 +20,8 @@ int main (int argc, char** argv) { |
| 20 | 20 | return app.exit(e); |
| 21 | 21 | } |
| 22 | 22 | |
| 23 | - std::cout << "Working on file: " << file << ", direct count: " << app.count("file") << std::endl; | |
| 24 | - std::cout << "Working on count: " << count << ", direct count: " << app.count("count") << std::endl; | |
| 23 | + std::cout << "Working on file: " << file << ", direct count: " << app.count("--file") << std::endl; | |
| 24 | + std::cout << "Working on count: " << count << ", direct count: " << app.count("--count") << std::endl; | |
| 25 | 25 | std::cout << "Some value: " << value << std::endl; |
| 26 | 26 | |
| 27 | 27 | return 0; | ... | ... |
examples/try1.cpp
| ... | ... | @@ -9,10 +9,10 @@ int main (int argc, char** argv) { |
| 9 | 9 | |
| 10 | 10 | std::cout << app.help(); |
| 11 | 11 | std::string file; |
| 12 | - start->add_option("f,file", file, "File name"); | |
| 12 | + start->add_option("-f,--file", file, "File name"); | |
| 13 | 13 | |
| 14 | 14 | int count; |
| 15 | - stop->add_flag("c,count", count, "Counter"); | |
| 15 | + stop->add_flag("-c,--count", count, "Counter"); | |
| 16 | 16 | |
| 17 | 17 | try { |
| 18 | 18 | app.run(argc, argv); |
| ... | ... | @@ -20,8 +20,8 @@ int main (int argc, char** argv) { |
| 20 | 20 | return app.exit(e); |
| 21 | 21 | } |
| 22 | 22 | |
| 23 | - std::cout << "Working on file: " << file << ", direct count: " << start->count("file") << std::endl; | |
| 24 | - std::cout << "Working on count: " << count << ", direct count: " << stop->count("count") << std::endl; | |
| 23 | + std::cout << "Working on file: " << file << ", direct count: " << start->count("--file") << std::endl; | |
| 24 | + std::cout << "Working on count: " << count << ", direct count: " << stop->count("--count") << std::endl; | |
| 25 | 25 | if(app.get_subcommand() != nullptr) |
| 26 | 26 | std::cout << "Subcommand:" << app.get_subcommand()->get_name() << std::endl; |
| 27 | 27 | ... | ... |
include/CLI.hpp
| ... | ... | @@ -178,7 +178,6 @@ namespace detail { |
| 178 | 178 | |
| 179 | 179 | struct Combiner { |
| 180 | 180 | int num; |
| 181 | - bool positional; | |
| 182 | 181 | bool required; |
| 183 | 182 | bool defaulted; |
| 184 | 183 | std::vector<std::function<bool(std::string)>> validators; |
| ... | ... | @@ -187,7 +186,6 @@ namespace detail { |
| 187 | 186 | Combiner operator | (Combiner b) const { |
| 188 | 187 | Combiner self; |
| 189 | 188 | self.num = std::min(num, b.num) == -1 ? -1 : std::max(num, b.num); |
| 190 | - self.positional = positional || b.positional; | |
| 191 | 189 | self.required = required || b.required; |
| 192 | 190 | self.defaulted = defaulted || b.defaulted; |
| 193 | 191 | self.validators.reserve(validators.size() + b.validators.size()); |
| ... | ... | @@ -290,36 +288,39 @@ namespace detail { |
| 290 | 288 | } |
| 291 | 289 | |
| 292 | 290 | |
| 293 | - inline std::tuple<std::vector<std::string>,std::vector<std::string>> get_names(const std::vector<std::string> &input) { | |
| 291 | + inline std::tuple<std::vector<std::string>,std::vector<std::string>, std::string> | |
| 292 | + get_names(const std::vector<std::string> &input) { | |
| 293 | + | |
| 294 | 294 | std::vector<std::string> short_names; |
| 295 | 295 | std::vector<std::string> long_names; |
| 296 | + std::string pos_name; | |
| 296 | 297 | |
| 297 | 298 | for(std::string name : input) { |
| 298 | 299 | if(name.length() == 0) |
| 299 | 300 | continue; |
| 300 | - else if(name.length() == 1) | |
| 301 | - if(valid_first_char(name[0])) | |
| 302 | - short_names.push_back(name); | |
| 303 | - else | |
| 304 | - throw BadNameString("Invalid one char name: "+name); | |
| 305 | - else if(name.length() == 2 && name[0] == '-' && name[1] != '-') { | |
| 306 | - if(valid_first_char(name[1])) | |
| 301 | + else if(name.length() > 1 && name[0] == '-' && name[1] != '-') { | |
| 302 | + if(name.length()==2 && valid_first_char(name[1])) | |
| 307 | 303 | short_names.push_back(std::string(1,name[1])); |
| 308 | 304 | else |
| 309 | 305 | throw BadNameString("Invalid one char name: "+name); |
| 310 | - } else { | |
| 311 | - | |
| 312 | - if(name.substr(0,2) == "--") | |
| 313 | - name = name.substr(2); | |
| 306 | + } else if(name.length() > 2 && name.substr(0,2) == "--") { | |
| 307 | + name = name.substr(2); | |
| 314 | 308 | if(valid_name_string(name)) |
| 315 | 309 | long_names.push_back(name); |
| 316 | 310 | else |
| 317 | - throw BadNameString("Bad long name"+name); | |
| 311 | + throw BadNameString("Bad long name: "+name); | |
| 312 | + } else if(name == "-" || name == "--") { | |
| 313 | + throw BadNameString("Must have a name, not just dashes"); | |
| 314 | + } else { | |
| 315 | + if(pos_name.length() > 0) | |
| 316 | + throw BadNameString("Only one positional name allowed, remove: "+name); | |
| 317 | + pos_name = name; | |
| 318 | 318 | |
| 319 | 319 | } |
| 320 | 320 | } |
| 321 | 321 | |
| 322 | - return std::tuple<std::vector<std::string>,std::vector<std::string>>(short_names, long_names); | |
| 322 | + return std::tuple<std::vector<std::string>,std::vector<std::string>, std::string> | |
| 323 | + (short_names, long_names, pos_name); | |
| 323 | 324 | } |
| 324 | 325 | |
| 325 | 326 | // Integers |
| ... | ... | @@ -373,19 +374,18 @@ namespace detail { |
| 373 | 374 | |
| 374 | 375 | // Defines for common Combiners (don't use combiners directly) |
| 375 | 376 | |
| 376 | -const detail::Combiner NOTHING {0, false,false,false, {}}; | |
| 377 | -const detail::Combiner REQUIRED {1, false,true, false, {}}; | |
| 378 | -const detail::Combiner DEFAULT {1, false,false,true, {}}; | |
| 379 | -const detail::Combiner POSITIONAL {1, true, false,false, {}}; | |
| 380 | -const detail::Combiner ARGS {-1, false,false,false, {}}; | |
| 381 | -const detail::Combiner VALIDATORS {1, false, false, false, {}}; | |
| 377 | +const detail::Combiner Nothing {0, false, false, {}}; | |
| 378 | +const detail::Combiner Required {1, true, false, {}}; | |
| 379 | +const detail::Combiner Default {1, false, true, {}}; | |
| 380 | +const detail::Combiner Args {-1, false, false, {}}; | |
| 381 | +const detail::Combiner Validators {1, false, false, {}}; | |
| 382 | 382 | |
| 383 | 383 | // Warning about using these validators: |
| 384 | 384 | // The files could be added/deleted after the validation. This is not common, |
| 385 | 385 | // but if this is a possibility, check the file you open afterwards |
| 386 | -const detail::Combiner ExistingFile {1, false, false, false, {detail::_ExistingFile}}; | |
| 387 | -const detail::Combiner ExistingDirectory {1, false, false, false, {detail::_ExistingDirectory}}; | |
| 388 | -const detail::Combiner NonexistentPath {1, false, false, false, {detail::_NonexistentPath}}; | |
| 386 | +const detail::Combiner ExistingFile {1, false, false, {detail::_ExistingFile}}; | |
| 387 | +const detail::Combiner ExistingDirectory {1, false, false, {detail::_ExistingDirectory}}; | |
| 388 | +const detail::Combiner NonexistentPath {1, false, false, {detail::_NonexistentPath}}; | |
| 389 | 389 | |
| 390 | 390 | typedef std::vector<std::vector<std::string>> results_t; |
| 391 | 391 | typedef std::function<bool(results_t)> callback_t; |
| ... | ... | @@ -399,6 +399,8 @@ protected: |
| 399 | 399 | // Config |
| 400 | 400 | std::vector<std::string> snames; |
| 401 | 401 | std::vector<std::string> lnames; |
| 402 | + std::string pname; | |
| 403 | + | |
| 402 | 404 | detail::Combiner opts; |
| 403 | 405 | std::string discription; |
| 404 | 406 | callback_t callback; |
| ... | ... | @@ -412,31 +414,62 @@ protected: |
| 412 | 414 | |
| 413 | 415 | |
| 414 | 416 | public: |
| 415 | - Option(std::string name, std::string discription = "", detail::Combiner opts=NOTHING, std::function<bool(results_t)> callback=[](results_t){return true;}) : | |
| 417 | + Option(std::string name, std::string discription = "", detail::Combiner opts=Nothing, std::function<bool(results_t)> callback=[](results_t){return true;}) : | |
| 416 | 418 | opts(opts), discription(discription), callback(callback){ |
| 417 | - std::tie(snames, lnames) = detail::get_names(detail::split_names(name)); | |
| 419 | + std::tie(snames, lnames, pname) = detail::get_names(detail::split_names(name)); | |
| 418 | 420 | } |
| 419 | 421 | |
| 422 | + /// Clear the parsed results (mostly for testing) | |
| 420 | 423 | void clear() { |
| 421 | 424 | results.clear(); |
| 422 | 425 | } |
| 423 | 426 | |
| 427 | + /// True if option is required | |
| 424 | 428 | bool required() const { |
| 425 | 429 | return opts.required; |
| 426 | 430 | } |
| 427 | 431 | |
| 432 | + /// The number of arguments the option expects | |
| 428 | 433 | int expected() const { |
| 429 | 434 | return opts.num; |
| 430 | 435 | } |
| 431 | 436 | |
| 437 | + /// True if the argument can be given directly | |
| 432 | 438 | bool positional() const { |
| 433 | - return opts.positional; | |
| 439 | + return pname.length() > 0; | |
| 434 | 440 | } |
| 435 | 441 | |
| 442 | + /// True if option has at least one non-positional name | |
| 443 | + bool nonpositional() const { | |
| 444 | + return (snames.size() + lnames.size()) > 0; | |
| 445 | + } | |
| 446 | + | |
| 447 | + /// True if this should print the default string | |
| 436 | 448 | bool defaulted() const { |
| 437 | 449 | return opts.defaulted; |
| 438 | 450 | } |
| 439 | 451 | |
| 452 | + /// True if option has discription | |
| 453 | + bool has_discription() const { | |
| 454 | + return discription.length() > 0; | |
| 455 | + } | |
| 456 | + | |
| 457 | + /// Get the discription | |
| 458 | + const std::string& get_discription() const { | |
| 459 | + return discription; | |
| 460 | + } | |
| 461 | + | |
| 462 | + /// The name and any extras needed for positionals | |
| 463 | + std::string help_positional() const { | |
| 464 | + std::string out = pname; | |
| 465 | + if(expected()<1) | |
| 466 | + out = out + "x" + std::to_string(expected()); | |
| 467 | + else if(expected()==-1) | |
| 468 | + out = out + "..."; | |
| 469 | + out = required() ? out : "["+out+"]"; | |
| 470 | + return out; | |
| 471 | + } | |
| 472 | + | |
| 440 | 473 | /// Process the callback |
| 441 | 474 | bool run_callback() const { |
| 442 | 475 | if(opts.validators.size()>0) { |
| ... | ... | @@ -448,7 +481,7 @@ public: |
| 448 | 481 | return callback(results); |
| 449 | 482 | } |
| 450 | 483 | |
| 451 | - /// If options share any of the same names, they are equal | |
| 484 | + /// If options share any of the same names, they are equal (not counting positional) | |
| 452 | 485 | bool operator== (const Option& other) const { |
| 453 | 486 | for(const std::string &sname : snames) |
| 454 | 487 | for(const std::string &othersname : other.snames) |
| ... | ... | @@ -461,6 +494,7 @@ public: |
| 461 | 494 | return false; |
| 462 | 495 | } |
| 463 | 496 | |
| 497 | + /// Gets a , sep list of names. Does not include the positional name. | |
| 464 | 498 | std::string get_name() const { |
| 465 | 499 | std::vector<std::string> name_list; |
| 466 | 500 | for(const std::string& sname : snames) |
| ... | ... | @@ -470,30 +504,40 @@ public: |
| 470 | 504 | return detail::join(name_list); |
| 471 | 505 | } |
| 472 | 506 | |
| 507 | + /// Check a name. Requires "-" or "--" for short / long, supports positional name | |
| 473 | 508 | bool check_name(std::string name) const { |
| 474 | - for(int i=0; i<2; i++) | |
| 475 | - if(name.length()>2 && name[0] == '-') | |
| 476 | - name = name.substr(1); | |
| 477 | 509 | |
| 478 | - return check_sname(name) || check_lname(name); | |
| 510 | + if(name.length()>2 && name.substr(0,2) == "--") | |
| 511 | + return check_lname(name.substr(2)); | |
| 512 | + else if (name.length()>1 && name.substr(0,1) == "-") | |
| 513 | + return check_sname(name.substr(1)); | |
| 514 | + else | |
| 515 | + return name == pname; | |
| 479 | 516 | } |
| 480 | 517 | |
| 518 | + /// Requires "-" to be removed from string | |
| 481 | 519 | bool check_sname(const std::string& name) const { |
| 482 | 520 | return std::find(std::begin(snames), std::end(snames), name) != std::end(snames); |
| 483 | 521 | } |
| 484 | 522 | |
| 523 | + /// Requires "--" to be removed from string | |
| 485 | 524 | bool check_lname(const std::string& name) const { |
| 486 | 525 | return std::find(std::begin(lnames), std::end(lnames), name) != std::end(lnames); |
| 487 | 526 | } |
| 488 | 527 | |
| 489 | 528 | |
| 529 | + /// Puts a result at position r | |
| 490 | 530 | void add_result(int r, std::string s) { |
| 491 | 531 | results.at(r).push_back(s); |
| 492 | 532 | } |
| 533 | + | |
| 534 | + /// Starts a new results vector (used for r in add_result) | |
| 493 | 535 | int get_new() { |
| 494 | 536 | results.emplace_back(); |
| 495 | 537 | return results.size() - 1; |
| 496 | 538 | } |
| 539 | + | |
| 540 | + /// Count the total number of times an option was passed | |
| 497 | 541 | int count() const { |
| 498 | 542 | int out = 0; |
| 499 | 543 | for(const std::vector<std::string>& v : results) |
| ... | ... | @@ -501,6 +545,7 @@ public: |
| 501 | 545 | return out; |
| 502 | 546 | } |
| 503 | 547 | |
| 548 | + /// Diagnostic representation | |
| 504 | 549 | std::string string() const { |
| 505 | 550 | std::string val = "Option: " + get_name() + "\n" |
| 506 | 551 | + " " + discription + "\n" |
| ... | ... | @@ -514,6 +559,7 @@ public: |
| 514 | 559 | return val; |
| 515 | 560 | } |
| 516 | 561 | |
| 562 | + /// The first half of the help print, name plus default, etc | |
| 517 | 563 | std::string help_name() const { |
| 518 | 564 | std::stringstream out; |
| 519 | 565 | out << " " << get_name(); |
| ... | ... | @@ -530,10 +576,12 @@ public: |
| 530 | 576 | return out.str(); |
| 531 | 577 | } |
| 532 | 578 | |
| 579 | + /// The length of the name part of the help, for formatting | |
| 533 | 580 | int help_len() const { |
| 534 | 581 | return help_name().length(); |
| 535 | 582 | } |
| 536 | 583 | |
| 584 | + /// Make a help string, adjustable len. | |
| 537 | 585 | std::string help(int len = 0) const { |
| 538 | 586 | std::stringstream out; |
| 539 | 587 | if(help_len() > len) { |
| ... | ... | @@ -547,6 +595,7 @@ public: |
| 547 | 595 | return out.str(); |
| 548 | 596 | } |
| 549 | 597 | |
| 598 | + /// Produce a flattened vector of results, vs. a vector of vectors. | |
| 550 | 599 | std::vector<std::string> flatten_results() const { |
| 551 | 600 | std::vector<std::string> output; |
| 552 | 601 | for(const std::vector<std::string> result : results) |
| ... | ... | @@ -602,6 +651,7 @@ protected: |
| 602 | 651 | std::vector<std::unique_ptr<App>> subcommands; |
| 603 | 652 | bool parsed{false}; |
| 604 | 653 | App* subcommand = nullptr; |
| 654 | + std::string progname = "program"; | |
| 605 | 655 | |
| 606 | 656 | std::function<void()> app_callback; |
| 607 | 657 | |
| ... | ... | @@ -639,7 +689,7 @@ public: |
| 639 | 689 | App(std::string prog_discription="") |
| 640 | 690 | : prog_discription(prog_discription) { |
| 641 | 691 | |
| 642 | - add_flag("h,help", "Print this help message and exit"); | |
| 692 | + add_flag("-h,--help", "Print this help message and exit"); | |
| 643 | 693 | |
| 644 | 694 | } |
| 645 | 695 | |
| ... | ... | @@ -657,7 +707,7 @@ public: |
| 657 | 707 | * After start is called, you can use count to see if the value was passed, and |
| 658 | 708 | * the value will be initialized properly. |
| 659 | 709 | * |
| 660 | - * Program::REQUIRED, Program::DEFAULT, and Program::POSITIONAL are options, and can be `|` | |
| 710 | + * Program::Required, Program::Default, and the validators are options, and can be `|` | |
| 661 | 711 | * together. The positional options take an optional number of arguments. |
| 662 | 712 | * |
| 663 | 713 | * For example, |
| ... | ... | @@ -666,10 +716,10 @@ public: |
| 666 | 716 | * program.add_option("filename", filename, "discription of filename"); |
| 667 | 717 | */ |
| 668 | 718 | Option* add_option( |
| 669 | - std::string name, ///< The name, long,short | |
| 670 | - callback_t callback, ///< The callback | |
| 671 | - std::string discription="", ///< Discription string | |
| 672 | - detail::Combiner opts=VALIDATORS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS()) | |
| 719 | + std::string name, | |
| 720 | + callback_t callback, | |
| 721 | + std::string discription="", | |
| 722 | + detail::Combiner opts=Validators | |
| 673 | 723 | ) { |
| 674 | 724 | Option myopt{name, discription, opts, callback}; |
| 675 | 725 | if(std::find(std::begin(options), std::end(options), myopt) == std::end(options)) |
| ... | ... | @@ -683,15 +733,15 @@ public: |
| 683 | 733 | /// Add option for string |
| 684 | 734 | template<typename T, enable_if_t<!is_vector<T>::value, detail::enabler> = detail::dummy> |
| 685 | 735 | Option* add_option( |
| 686 | - std::string name, ///< The name, long,short | |
| 736 | + std::string name, | |
| 687 | 737 | T &variable, ///< The variable to set |
| 688 | - std::string discription="", ///< Discription string | |
| 689 | - detail::Combiner opts=VALIDATORS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS()) | |
| 738 | + std::string discription="", | |
| 739 | + detail::Combiner opts=Validators | |
| 690 | 740 | ) { |
| 691 | 741 | |
| 692 | 742 | |
| 693 | 743 | if(opts.num!=1) |
| 694 | - throw IncorrectConstruction("Must have ARGS(1) or be a vector."); | |
| 744 | + throw IncorrectConstruction("Must have Args(1) or be a vector."); | |
| 695 | 745 | CLI::callback_t fun = [&variable](CLI::results_t res){ |
| 696 | 746 | if(res.size()!=1) { |
| 697 | 747 | return false; |
| ... | ... | @@ -715,14 +765,14 @@ public: |
| 715 | 765 | /// Add option for vector of results |
| 716 | 766 | template<typename T> |
| 717 | 767 | Option* add_option( |
| 718 | - std::string name, ///< The name, long,short | |
| 719 | - std::vector<T> &variable, ///< The variable to set | |
| 720 | - std::string discription="", ///< Discription string | |
| 721 | - detail::Combiner opts=ARGS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS()) | |
| 768 | + std::string name, | |
| 769 | + std::vector<T> &variable, ///< The variable vector to set | |
| 770 | + std::string discription="", | |
| 771 | + detail::Combiner opts=Args | |
| 722 | 772 | ) { |
| 723 | 773 | |
| 724 | 774 | if(opts.num==0) |
| 725 | - throw IncorrectConstruction("Must have ARGS or be a vector."); | |
| 775 | + throw IncorrectConstruction("Must have Args or be a vector."); | |
| 726 | 776 | CLI::callback_t fun = [&variable](CLI::results_t res){ |
| 727 | 777 | bool retval = true; |
| 728 | 778 | variable.clear(); |
| ... | ... | @@ -746,10 +796,10 @@ public: |
| 746 | 796 | /// Multiple options are supported |
| 747 | 797 | template<typename T, typename... Args> |
| 748 | 798 | Option* add_option( |
| 749 | - std::string name, ///< The name, long,short | |
| 799 | + std::string name, | |
| 750 | 800 | T &variable, ///< The variable to set |
| 751 | - std::string discription, ///< Discription string | |
| 752 | - detail::Combiner opts, ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS()) | |
| 801 | + std::string discription, | |
| 802 | + detail::Combiner opts, | |
| 753 | 803 | detail::Combiner opts2, |
| 754 | 804 | Args... args ///< More options |
| 755 | 805 | ) { |
| ... | ... | @@ -757,23 +807,26 @@ public: |
| 757 | 807 | } |
| 758 | 808 | /// Add option for flag |
| 759 | 809 | Option* add_flag( |
| 760 | - std::string name, ///< The name, short,long | |
| 761 | - std::string discription="" ///< Discription string | |
| 810 | + std::string name, | |
| 811 | + std::string discription="" | |
| 762 | 812 | ) { |
| 763 | 813 | CLI::callback_t fun = [](CLI::results_t){ |
| 764 | 814 | return true; |
| 765 | 815 | }; |
| 766 | 816 | |
| 767 | - return add_option(name, fun, discription, NOTHING); | |
| 817 | + Option* opt = add_option(name, fun, discription, Nothing); | |
| 818 | + if(opt->positional()) | |
| 819 | + throw IncorrectConstruction("Flags cannot be positional"); | |
| 820 | + return opt; | |
| 768 | 821 | } |
| 769 | 822 | |
| 770 | 823 | /// Add option for flag |
| 771 | 824 | template<typename T, |
| 772 | 825 | enable_if_t<std::is_integral<T>::value && !is_bool<T>::value, detail::enabler> = detail::dummy> |
| 773 | 826 | Option* add_flag( |
| 774 | - std::string name, ///< The name, short,long | |
| 827 | + std::string name, | |
| 775 | 828 | T &count, ///< A varaible holding the count |
| 776 | - std::string discription="" ///< Discription string | |
| 829 | + std::string discription="" | |
| 777 | 830 | ) { |
| 778 | 831 | |
| 779 | 832 | count = 0; |
| ... | ... | @@ -782,16 +835,19 @@ public: |
| 782 | 835 | return true; |
| 783 | 836 | }; |
| 784 | 837 | |
| 785 | - return add_option(name, fun, discription, NOTHING); | |
| 838 | + Option* opt = add_option(name, fun, discription, Nothing); | |
| 839 | + if(opt->positional()) | |
| 840 | + throw IncorrectConstruction("Flags cannot be positional"); | |
| 841 | + return opt; | |
| 786 | 842 | } |
| 787 | 843 | |
| 788 | 844 | /// Bool version only allows the flag once |
| 789 | 845 | template<typename T, |
| 790 | 846 | enable_if_t<is_bool<T>::value, detail::enabler> = detail::dummy> |
| 791 | 847 | Option* add_flag( |
| 792 | - std::string name, ///< The name, short,long | |
| 793 | - T &count, ///< A varaible holding true if passed | |
| 794 | - std::string discription="" ///< Discription string | |
| 848 | + std::string name, | |
| 849 | + T &count, ///< A varaible holding true if passed | |
| 850 | + std::string discription="" | |
| 795 | 851 | ) { |
| 796 | 852 | |
| 797 | 853 | count = false; |
| ... | ... | @@ -800,22 +856,25 @@ public: |
| 800 | 856 | return res.size() == 1; |
| 801 | 857 | }; |
| 802 | 858 | |
| 803 | - return add_option(name, fun, discription, NOTHING); | |
| 859 | + Option* opt = add_option(name, fun, discription, Nothing); | |
| 860 | + if(opt->positional()) | |
| 861 | + throw IncorrectConstruction("Flags cannot be positional"); | |
| 862 | + return opt; | |
| 804 | 863 | } |
| 805 | 864 | |
| 806 | 865 | |
| 807 | 866 | /// Add set of options |
| 808 | 867 | template<typename T> |
| 809 | 868 | Option* add_set( |
| 810 | - std::string name, ///< The name, short,long | |
| 869 | + std::string name, | |
| 811 | 870 | T &member, ///< The selected member of the set |
| 812 | - std::set<T> options, ///< The set of posibilities | |
| 813 | - std::string discription="", ///< Discription string | |
| 814 | - detail::Combiner opts=VALIDATORS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS()) | |
| 871 | + std::set<T> options, ///< The set of posibilities | |
| 872 | + std::string discription="", | |
| 873 | + detail::Combiner opts=Validators | |
| 815 | 874 | ) { |
| 816 | 875 | |
| 817 | 876 | if(opts.num!=1) |
| 818 | - throw IncorrectConstruction("Must have ARGS(1)."); | |
| 877 | + throw IncorrectConstruction("Must have Args(1)."); | |
| 819 | 878 | |
| 820 | 879 | CLI::callback_t fun = [&member, options](CLI::results_t res){ |
| 821 | 880 | if(res.size()!=1) { |
| ... | ... | @@ -844,11 +903,11 @@ public: |
| 844 | 903 | |
| 845 | 904 | template<typename T, typename... Args> |
| 846 | 905 | Option* add_set( |
| 847 | - std::string name, ///< The name, short,long | |
| 848 | - T &member, ///< The selected member of the set | |
| 849 | - std::set<T> options, ///< The set of posibilities | |
| 850 | - std::string discription, ///< Discription string | |
| 851 | - detail::Combiner opts, ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS()) | |
| 906 | + std::string name, | |
| 907 | + T &member, | |
| 908 | + std::set<T> options, ///< The set of posibilities | |
| 909 | + std::string discription, | |
| 910 | + detail::Combiner opts, | |
| 852 | 911 | detail::Combiner opts2, |
| 853 | 912 | Args... args |
| 854 | 913 | ) { |
| ... | ... | @@ -862,13 +921,13 @@ public: |
| 862 | 921 | template<typename T = std::string, |
| 863 | 922 | enable_if_t<!is_vector<T>::value, detail::enabler> = detail::dummy> |
| 864 | 923 | Value<T> make_option( |
| 865 | - std::string name, ///< The name, short,long | |
| 924 | + std::string name, | |
| 866 | 925 | std::string discription="", |
| 867 | - detail::Combiner opts=VALIDATORS | |
| 926 | + detail::Combiner opts=Validators | |
| 868 | 927 | ) { |
| 869 | 928 | |
| 870 | 929 | if(opts.num!=1) |
| 871 | - throw IncorrectConstruction("Must have ARGS(1)."); | |
| 930 | + throw IncorrectConstruction("Must have Args(1)."); | |
| 872 | 931 | |
| 873 | 932 | Value<T> out(name); |
| 874 | 933 | std::shared_ptr<std::unique_ptr<T>> ptr = out.value; |
| ... | ... | @@ -890,7 +949,7 @@ public: |
| 890 | 949 | |
| 891 | 950 | template<typename T = std::string, typename... Args> |
| 892 | 951 | Value<T> make_option( |
| 893 | - std::string name, ///< The name, short,long | |
| 952 | + std::string name, | |
| 894 | 953 | std::string discription, |
| 895 | 954 | detail::Combiner opts, |
| 896 | 955 | detail::Combiner opts2, |
| ... | ... | @@ -903,14 +962,14 @@ public: |
| 903 | 962 | template<typename T, |
| 904 | 963 | enable_if_t<!is_vector<T>::value, detail::enabler> = detail::dummy> |
| 905 | 964 | Value<T> make_option( |
| 906 | - std::string name, ///< The name, short,long | |
| 965 | + std::string name, | |
| 907 | 966 | const T& default_value, |
| 908 | 967 | std::string discription="", |
| 909 | - detail::Combiner opts=VALIDATORS | |
| 968 | + detail::Combiner opts=Validators | |
| 910 | 969 | ) { |
| 911 | 970 | |
| 912 | 971 | if(opts.num!=1) |
| 913 | - throw IncorrectConstruction("Must have ARGS(1)."); | |
| 972 | + throw IncorrectConstruction("Must have Args(1)."); | |
| 914 | 973 | |
| 915 | 974 | Value<T> out(name); |
| 916 | 975 | std::shared_ptr<std::unique_ptr<T>> ptr = out.value; |
| ... | ... | @@ -938,13 +997,13 @@ public: |
| 938 | 997 | template<typename T, |
| 939 | 998 | enable_if_t<is_vector<T>::value, detail::enabler> = detail::dummy> |
| 940 | 999 | Value<T> make_option( |
| 941 | - std::string name, ///< The name, short,long | |
| 1000 | + std::string name, | |
| 942 | 1001 | std::string discription="", |
| 943 | - detail::Combiner opts=VALIDATORS | |
| 1002 | + detail::Combiner opts=Args | |
| 944 | 1003 | ) { |
| 945 | 1004 | |
| 946 | 1005 | if(opts.num==0) |
| 947 | - throw IncorrectConstruction("Must have ARGS or be a vector."); | |
| 1006 | + throw IncorrectConstruction("Must have Args or be a vector."); | |
| 948 | 1007 | |
| 949 | 1008 | Value<T> out(name); |
| 950 | 1009 | std::shared_ptr<std::unique_ptr<T>> ptr = out.value; |
| ... | ... | @@ -967,7 +1026,7 @@ public: |
| 967 | 1026 | |
| 968 | 1027 | template<typename T, typename... Args> |
| 969 | 1028 | Value<T> make_option( |
| 970 | - std::string name, ///< The name, short,long | |
| 1029 | + std::string name, | |
| 971 | 1030 | const T& default_value, |
| 972 | 1031 | std::string discription, |
| 973 | 1032 | detail::Combiner opts, |
| ... | ... | @@ -979,7 +1038,7 @@ public: |
| 979 | 1038 | |
| 980 | 1039 | /// Prototype for new output style: flag |
| 981 | 1040 | Value<int> make_flag( |
| 982 | - std::string name, ///< The name, short,long | |
| 1041 | + std::string name, | |
| 983 | 1042 | std::string discription="" |
| 984 | 1043 | ) { |
| 985 | 1044 | |
| ... | ... | @@ -992,24 +1051,27 @@ public: |
| 992 | 1051 | **ptr = (int) res.size(); |
| 993 | 1052 | return true; |
| 994 | 1053 | }; |
| 995 | - add_option(name, fun, discription, NOTHING); | |
| 1054 | + | |
| 1055 | + Option* opt = add_option(name, fun, discription, Nothing); | |
| 1056 | + if(opt->positional()) | |
| 1057 | + throw IncorrectConstruction("Flags cannot be positional"); | |
| 996 | 1058 | return out; |
| 997 | 1059 | } |
| 998 | 1060 | |
| 999 | 1061 | /// Add set of options |
| 1000 | 1062 | template<typename T> |
| 1001 | 1063 | Value<T> make_set( |
| 1002 | - std::string name, ///< The name, short,long | |
| 1064 | + std::string name, | |
| 1003 | 1065 | std::set<T> options, ///< The set of posibilities |
| 1004 | - std::string discription="", ///< Discription string | |
| 1005 | - detail::Combiner opts=VALIDATORS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS()) | |
| 1066 | + std::string discription="", | |
| 1067 | + detail::Combiner opts=Validators | |
| 1006 | 1068 | ) { |
| 1007 | 1069 | |
| 1008 | 1070 | Value<T> out(name); |
| 1009 | 1071 | std::shared_ptr<std::unique_ptr<T>> ptr = out.value; |
| 1010 | 1072 | |
| 1011 | 1073 | if(opts.num!=1) |
| 1012 | - throw IncorrectConstruction("Must have ARGS(1)."); | |
| 1074 | + throw IncorrectConstruction("Must have Args(1)."); | |
| 1013 | 1075 | |
| 1014 | 1076 | CLI::callback_t fun = [ptr, options](CLI::results_t res){ |
| 1015 | 1077 | if(res.size()!=1) { |
| ... | ... | @@ -1046,6 +1108,7 @@ public: |
| 1046 | 1108 | |
| 1047 | 1109 | /// Parses the command line - throws errors |
| 1048 | 1110 | void parse(int argc, char **argv) { |
| 1111 | + progname = argv[0]; | |
| 1049 | 1112 | std::vector<std::string> args; |
| 1050 | 1113 | for(int i=argc-1; i>0; i--) |
| 1051 | 1114 | args.push_back(argv[i]); |
| ... | ... | @@ -1081,7 +1144,7 @@ public: |
| 1081 | 1144 | } |
| 1082 | 1145 | } |
| 1083 | 1146 | |
| 1084 | - if (count("help") > 0) { | |
| 1147 | + if (count("--help") > 0) { | |
| 1085 | 1148 | throw CallForHelp(); |
| 1086 | 1149 | } |
| 1087 | 1150 | |
| ... | ... | @@ -1259,12 +1322,50 @@ public: |
| 1259 | 1322 | if(name != "") |
| 1260 | 1323 | out << "Subcommand: " << name << " "; |
| 1261 | 1324 | out << prog_discription << std::endl; |
| 1325 | + out << "Usage: " << progname; | |
| 1326 | + | |
| 1327 | + // Positionals | |
| 1328 | + bool pos=false; | |
| 1329 | + for(const Option &opt : options) | |
| 1330 | + if(opt.positional()) { | |
| 1331 | + out << " " << opt.help_positional(); | |
| 1332 | + if(opt.has_discription()) | |
| 1333 | + pos=true; | |
| 1334 | + } | |
| 1335 | + out << std::endl << std::endl; | |
| 1336 | + | |
| 1337 | + // Positional discriptions | |
| 1338 | + if(pos) { | |
| 1339 | + out << "Positionals:" << std::endl; | |
| 1340 | + for(const Option &opt : options) | |
| 1341 | + if(opt.positional() && opt.has_discription()) { | |
| 1342 | + out << " " << std::setw(30) << std::right << opt.help_positional(); | |
| 1343 | + out << opt.get_discription() << std::endl; | |
| 1344 | + } | |
| 1345 | + out << std::endl; | |
| 1346 | + | |
| 1347 | + } | |
| 1348 | + | |
| 1349 | + | |
| 1350 | + // Options | |
| 1262 | 1351 | int len = std::accumulate(std::begin(options), std::end(options), 0, |
| 1263 | 1352 | [](int val, const Option &opt){ |
| 1264 | 1353 | return std::max(opt.help_len()+3, val);}); |
| 1354 | + | |
| 1355 | + bool npos = false; | |
| 1265 | 1356 | for(const Option &opt : options) { |
| 1266 | - out << opt.help(len) << std::endl; | |
| 1357 | + if(opt.nonpositional()) { | |
| 1358 | + if(!npos) { | |
| 1359 | + out << "Options:" << std::endl; | |
| 1360 | + npos=true; | |
| 1361 | + } | |
| 1362 | + out << opt.help(len) << std::endl; | |
| 1363 | + } | |
| 1364 | + if(npos) | |
| 1365 | + out << std::endl; | |
| 1267 | 1366 | } |
| 1367 | + | |
| 1368 | + // Subcommands | |
| 1268 | 1369 | if(subcommands.size()> 0) { |
| 1269 | 1370 | out << "Subcommands:" << std::endl; |
| 1270 | 1371 | int max = std::accumulate(std::begin(subcommands), std::end(subcommands), 0, | ... | ... |
tests/CLITest.cpp
| ... | ... | @@ -37,19 +37,19 @@ struct TApp : public ::testing::Test { |
| 37 | 37 | }; |
| 38 | 38 | |
| 39 | 39 | TEST_F(TApp, OneFlagShort) { |
| 40 | - app.add_flag("c,count"); | |
| 40 | + app.add_flag("-c,--count"); | |
| 41 | 41 | args = {"-c"}; |
| 42 | 42 | EXPECT_NO_THROW(run()); |
| 43 | - EXPECT_EQ(1, app.count("c")); | |
| 44 | - EXPECT_EQ(1, app.count("count")); | |
| 43 | + EXPECT_EQ(1, app.count("-c")); | |
| 44 | + EXPECT_EQ(1, app.count("--count")); | |
| 45 | 45 | } |
| 46 | 46 | |
| 47 | 47 | TEST_F(TApp, OneFlagLong) { |
| 48 | - app.add_flag("c,count"); | |
| 48 | + app.add_flag("-c,--count"); | |
| 49 | 49 | args = {"--count"}; |
| 50 | 50 | EXPECT_NO_THROW(run()); |
| 51 | - EXPECT_EQ(1, app.count("c")); | |
| 52 | - EXPECT_EQ(1, app.count("count")); | |
| 51 | + EXPECT_EQ(1, app.count("-c")); | |
| 52 | + EXPECT_EQ(1, app.count("--count")); | |
| 53 | 53 | } |
| 54 | 54 | |
| 55 | 55 | TEST_F(TApp, DashedOptions) { |
| ... | ... | @@ -59,9 +59,9 @@ TEST_F(TApp, DashedOptions) { |
| 59 | 59 | |
| 60 | 60 | args = {"-c", "--q", "--this", "--that"}; |
| 61 | 61 | EXPECT_NO_THROW(run()); |
| 62 | - EXPECT_EQ(1, app.count("c")); | |
| 63 | - EXPECT_EQ(1, app.count("q")); | |
| 64 | - EXPECT_EQ(2, app.count("this")); | |
| 62 | + EXPECT_EQ(1, app.count("-c")); | |
| 63 | + EXPECT_EQ(1, app.count("--q")); | |
| 64 | + EXPECT_EQ(2, app.count("--this")); | |
| 65 | 65 | EXPECT_EQ(2, app.count("--that")); |
| 66 | 66 | |
| 67 | 67 | } |
| ... | ... | @@ -69,76 +69,76 @@ TEST_F(TApp, DashedOptions) { |
| 69 | 69 | |
| 70 | 70 | TEST_F(TApp, OneFlagRef) { |
| 71 | 71 | int ref; |
| 72 | - app.add_flag("c,count", ref); | |
| 72 | + app.add_flag("-c,--count", ref); | |
| 73 | 73 | args = {"--count"}; |
| 74 | 74 | EXPECT_NO_THROW(run()); |
| 75 | - EXPECT_EQ(1, app.count("c")); | |
| 76 | - EXPECT_EQ(1, app.count("count")); | |
| 75 | + EXPECT_EQ(1, app.count("-c")); | |
| 76 | + EXPECT_EQ(1, app.count("--count")); | |
| 77 | 77 | EXPECT_EQ(1, ref); |
| 78 | 78 | } |
| 79 | 79 | |
| 80 | 80 | TEST_F(TApp, OneString) { |
| 81 | 81 | std::string str; |
| 82 | - app.add_option("s,string", str); | |
| 82 | + app.add_option("-s,--string", str); | |
| 83 | 83 | args = {"--string", "mystring"}; |
| 84 | 84 | EXPECT_NO_THROW(run()); |
| 85 | - EXPECT_EQ(1, app.count("s")); | |
| 86 | - EXPECT_EQ(1, app.count("string")); | |
| 85 | + EXPECT_EQ(1, app.count("-s")); | |
| 86 | + EXPECT_EQ(1, app.count("--string")); | |
| 87 | 87 | EXPECT_EQ(str, "mystring"); |
| 88 | 88 | } |
| 89 | 89 | |
| 90 | 90 | |
| 91 | 91 | TEST_F(TApp, TogetherInt) { |
| 92 | 92 | int i; |
| 93 | - app.add_option("i,int", i); | |
| 93 | + app.add_option("-i,--int", i); | |
| 94 | 94 | args = {"-i4"}; |
| 95 | 95 | EXPECT_NO_THROW(run()); |
| 96 | - EXPECT_EQ(1, app.count("int")); | |
| 97 | - EXPECT_EQ(1, app.count("i")); | |
| 96 | + EXPECT_EQ(1, app.count("--int")); | |
| 97 | + EXPECT_EQ(1, app.count("-i")); | |
| 98 | 98 | EXPECT_EQ(i, 4); |
| 99 | 99 | } |
| 100 | 100 | |
| 101 | 101 | TEST_F(TApp, SepInt) { |
| 102 | 102 | int i; |
| 103 | - app.add_option("i,int", i); | |
| 103 | + app.add_option("-i,--int", i); | |
| 104 | 104 | args = {"-i","4"}; |
| 105 | 105 | EXPECT_NO_THROW(run()); |
| 106 | - EXPECT_EQ(1, app.count("int")); | |
| 107 | - EXPECT_EQ(1, app.count("i")); | |
| 106 | + EXPECT_EQ(1, app.count("--int")); | |
| 107 | + EXPECT_EQ(1, app.count("-i")); | |
| 108 | 108 | EXPECT_EQ(i, 4); |
| 109 | 109 | } |
| 110 | 110 | |
| 111 | 111 | TEST_F(TApp, OneStringAgain) { |
| 112 | 112 | std::string str; |
| 113 | - app.add_option("s,string", str); | |
| 113 | + app.add_option("-s,--string", str); | |
| 114 | 114 | args = {"--string", "mystring"}; |
| 115 | 115 | EXPECT_NO_THROW(run()); |
| 116 | - EXPECT_EQ(1, app.count("s")); | |
| 117 | - EXPECT_EQ(1, app.count("string")); | |
| 116 | + EXPECT_EQ(1, app.count("-s")); | |
| 117 | + EXPECT_EQ(1, app.count("--string")); | |
| 118 | 118 | EXPECT_EQ(str, "mystring"); |
| 119 | 119 | } |
| 120 | 120 | |
| 121 | 121 | |
| 122 | 122 | TEST_F(TApp, DefaultStringAgain) { |
| 123 | 123 | std::string str = "previous"; |
| 124 | - app.add_option("s,string", str); | |
| 124 | + app.add_option("-s,--string", str); | |
| 125 | 125 | EXPECT_NO_THROW(run()); |
| 126 | - EXPECT_EQ(0, app.count("s")); | |
| 127 | - EXPECT_EQ(0, app.count("string")); | |
| 126 | + EXPECT_EQ(0, app.count("-s")); | |
| 127 | + EXPECT_EQ(0, app.count("--string")); | |
| 128 | 128 | EXPECT_EQ(str, "previous"); |
| 129 | 129 | } |
| 130 | 130 | |
| 131 | 131 | TEST_F(TApp, LotsOfFlags) { |
| 132 | 132 | |
| 133 | - app.add_flag("a"); | |
| 134 | - app.add_flag("A"); | |
| 135 | - app.add_flag("b"); | |
| 133 | + app.add_flag("-a"); | |
| 134 | + app.add_flag("-A"); | |
| 135 | + app.add_flag("-b"); | |
| 136 | 136 | |
| 137 | 137 | args = {"-a","-b","-aA"}; |
| 138 | 138 | EXPECT_NO_THROW(run()); |
| 139 | - EXPECT_EQ(2, app.count("a")); | |
| 140 | - EXPECT_EQ(1, app.count("b")); | |
| 141 | - EXPECT_EQ(1, app.count("A")); | |
| 139 | + EXPECT_EQ(2, app.count("-a")); | |
| 140 | + EXPECT_EQ(1, app.count("-b")); | |
| 141 | + EXPECT_EQ(1, app.count("-A")); | |
| 142 | 142 | } |
| 143 | 143 | |
| 144 | 144 | |
| ... | ... | @@ -148,9 +148,9 @@ TEST_F(TApp, BoolAndIntFlags) { |
| 148 | 148 | int iflag; |
| 149 | 149 | unsigned int uflag; |
| 150 | 150 | |
| 151 | - app.add_flag("b", bflag); | |
| 152 | - app.add_flag("i", iflag); | |
| 153 | - app.add_flag("u", uflag); | |
| 151 | + app.add_flag("-b", bflag); | |
| 152 | + app.add_flag("-i", iflag); | |
| 153 | + app.add_flag("-u", uflag); | |
| 154 | 154 | |
| 155 | 155 | args = {"-b", "-i", "-u"}; |
| 156 | 156 | EXPECT_NO_THROW(run()); |
| ... | ... | @@ -177,15 +177,15 @@ TEST_F(TApp, ShortOpts) { |
| 177 | 177 | |
| 178 | 178 | unsigned long long funnyint; |
| 179 | 179 | std::string someopt; |
| 180 | - app.add_flag("z", funnyint); | |
| 181 | - app.add_option("y", someopt); | |
| 180 | + app.add_flag("-z", funnyint); | |
| 181 | + app.add_option("-y", someopt); | |
| 182 | 182 | |
| 183 | 183 | args = {"-zzyzyz",}; |
| 184 | 184 | |
| 185 | 185 | EXPECT_NO_THROW(run()); |
| 186 | 186 | |
| 187 | - EXPECT_EQ(2, app.count("z")); | |
| 188 | - EXPECT_EQ(1, app.count("y")); | |
| 187 | + EXPECT_EQ(2, app.count("-z")); | |
| 188 | + EXPECT_EQ(1, app.count("-y")); | |
| 189 | 189 | EXPECT_EQ((unsigned long long) 2, funnyint); |
| 190 | 190 | EXPECT_EQ("zyz", someopt); |
| 191 | 191 | } |
| ... | ... | @@ -195,15 +195,15 @@ TEST_F(TApp, Flags) { |
| 195 | 195 | int i = 3; |
| 196 | 196 | std::string s = "HI"; |
| 197 | 197 | |
| 198 | - app.add_option("-i", i, "", CLI::DEFAULT, CLI::POSITIONAL); | |
| 199 | - app.add_option("-s", s, "", CLI::DEFAULT, CLI::POSITIONAL); | |
| 198 | + app.add_option("-i,i", i, "", CLI::Default); | |
| 199 | + app.add_option("-s,s", s, "", CLI::Default); | |
| 200 | 200 | |
| 201 | 201 | args = {"-i2", "9"}; |
| 202 | 202 | |
| 203 | 203 | EXPECT_NO_THROW(run()); |
| 204 | 204 | |
| 205 | 205 | EXPECT_EQ(1, app.count("i")); |
| 206 | - EXPECT_EQ(1, app.count("s")); | |
| 206 | + EXPECT_EQ(1, app.count("-s")); | |
| 207 | 207 | EXPECT_EQ(2, i); |
| 208 | 208 | EXPECT_EQ("9", s); |
| 209 | 209 | } |
| ... | ... | @@ -212,8 +212,8 @@ TEST_F(TApp, Positionals) { |
| 212 | 212 | |
| 213 | 213 | std::string posit1; |
| 214 | 214 | std::string posit2; |
| 215 | - app.add_option("posit1", posit1, "", CLI::POSITIONAL); | |
| 216 | - app.add_option("posit2", posit2, "", CLI::POSITIONAL); | |
| 215 | + app.add_option("posit1", posit1); | |
| 216 | + app.add_option("posit2", posit2); | |
| 217 | 217 | |
| 218 | 218 | args = {"thing1","thing2"}; |
| 219 | 219 | |
| ... | ... | @@ -229,42 +229,42 @@ TEST_F(TApp, MixedPositionals) { |
| 229 | 229 | |
| 230 | 230 | int positional_int; |
| 231 | 231 | std::string positional_string; |
| 232 | - app.add_option("posit1", positional_int, "", CLI::POSITIONAL); | |
| 233 | - app.add_option("posit2", positional_string, "", CLI::POSITIONAL); | |
| 232 | + app.add_option("posit1,--posit1", positional_int, ""); | |
| 233 | + app.add_option("posit2,--posit2", positional_string, ""); | |
| 234 | 234 | |
| 235 | 235 | args = {"--posit2","thing2","7"}; |
| 236 | 236 | |
| 237 | 237 | EXPECT_NO_THROW(run()); |
| 238 | 238 | |
| 239 | 239 | EXPECT_EQ(1, app.count("posit2")); |
| 240 | - EXPECT_EQ(1, app.count("posit1")); | |
| 240 | + EXPECT_EQ(1, app.count("--posit1")); | |
| 241 | 241 | EXPECT_EQ(7, positional_int); |
| 242 | 242 | EXPECT_EQ("thing2", positional_string); |
| 243 | 243 | } |
| 244 | 244 | |
| 245 | 245 | TEST_F(TApp, Reset) { |
| 246 | 246 | |
| 247 | - app.add_flag("simple"); | |
| 247 | + app.add_flag("--simple"); | |
| 248 | 248 | double doub; |
| 249 | - app.add_option("d,double", doub); | |
| 249 | + app.add_option("-d,--double", doub); | |
| 250 | 250 | |
| 251 | 251 | args = {"--simple", "--double", "1.2"}; |
| 252 | 252 | |
| 253 | 253 | EXPECT_NO_THROW(run()); |
| 254 | 254 | |
| 255 | - EXPECT_EQ(1, app.count("simple")); | |
| 256 | - EXPECT_EQ(1, app.count("d")); | |
| 255 | + EXPECT_EQ(1, app.count("--simple")); | |
| 256 | + EXPECT_EQ(1, app.count("-d")); | |
| 257 | 257 | EXPECT_FLOAT_EQ(1.2, doub); |
| 258 | 258 | |
| 259 | 259 | app.reset(); |
| 260 | 260 | |
| 261 | - EXPECT_EQ(0, app.count("simple")); | |
| 262 | - EXPECT_EQ(0, app.count("d")); | |
| 261 | + EXPECT_EQ(0, app.count("--simple")); | |
| 262 | + EXPECT_EQ(0, app.count("-d")); | |
| 263 | 263 | |
| 264 | 264 | EXPECT_NO_THROW(run()); |
| 265 | 265 | |
| 266 | - EXPECT_EQ(1, app.count("simple")); | |
| 267 | - EXPECT_EQ(1, app.count("d")); | |
| 266 | + EXPECT_EQ(1, app.count("--simple")); | |
| 267 | + EXPECT_EQ(1, app.count("-d")); | |
| 268 | 268 | EXPECT_FLOAT_EQ(1.2, doub); |
| 269 | 269 | |
| 270 | 270 | } |
| ... | ... | @@ -275,7 +275,7 @@ TEST_F(TApp, FileNotExists) { |
| 275 | 275 | EXPECT_TRUE(CLI::detail::_NonexistentPath(myfile)); |
| 276 | 276 | |
| 277 | 277 | std::string filename; |
| 278 | - app.add_option("file", filename, "", CLI::NonexistentPath); | |
| 278 | + app.add_option("--file", filename, "", CLI::NonexistentPath); | |
| 279 | 279 | args = {"--file", myfile}; |
| 280 | 280 | |
| 281 | 281 | EXPECT_NO_THROW(run()); |
| ... | ... | @@ -297,7 +297,7 @@ TEST_F(TApp, FileExists) { |
| 297 | 297 | EXPECT_FALSE(CLI::detail::_ExistingFile(myfile)); |
| 298 | 298 | |
| 299 | 299 | std::string filename = "Failed"; |
| 300 | - app.add_option("file", filename, "", CLI::ExistingFile); | |
| 300 | + app.add_option("--file", filename, "", CLI::ExistingFile); | |
| 301 | 301 | args = {"--file", myfile}; |
| 302 | 302 | |
| 303 | 303 | EXPECT_THROW(run(), CLI::ParseError); |
| ... | ... | @@ -317,7 +317,7 @@ TEST_F(TApp, FileExists) { |
| 317 | 317 | TEST_F(TApp, InSet) { |
| 318 | 318 | |
| 319 | 319 | std::string choice; |
| 320 | - app.add_set("q,quick", choice, {"one", "two", "three"}); | |
| 320 | + app.add_set("-q,--quick", choice, {"one", "two", "three"}); | |
| 321 | 321 | |
| 322 | 322 | args = {"--quick", "two"}; |
| 323 | 323 | |
| ... | ... | @@ -334,12 +334,12 @@ TEST_F(TApp, VectorFixedString) { |
| 334 | 334 | std::vector<std::string> strvec; |
| 335 | 335 | std::vector<std::string> answer{"mystring", "mystring2", "mystring3"}; |
| 336 | 336 | |
| 337 | - CLI::Option* opt = app.add_option("s,string", strvec, "", CLI::ARGS(3)); | |
| 337 | + CLI::Option* opt = app.add_option("-s,--string", strvec, "", CLI::Args(3)); | |
| 338 | 338 | EXPECT_EQ(3, opt->expected()); |
| 339 | 339 | |
| 340 | 340 | args = {"--string", "mystring", "mystring2", "mystring3"}; |
| 341 | 341 | run(); |
| 342 | - EXPECT_EQ(3, app.count("string")); | |
| 342 | + EXPECT_EQ(3, app.count("--string")); | |
| 343 | 343 | EXPECT_EQ(answer, strvec); |
| 344 | 344 | } |
| 345 | 345 | |
| ... | ... | @@ -349,12 +349,12 @@ TEST_F(TApp, VectorUnlimString) { |
| 349 | 349 | std::vector<std::string> strvec; |
| 350 | 350 | std::vector<std::string> answer{"mystring", "mystring2", "mystring3"}; |
| 351 | 351 | |
| 352 | - CLI::Option* opt = app.add_option("s,string", strvec, "", CLI::ARGS); | |
| 352 | + CLI::Option* opt = app.add_option("-s,--string", strvec); | |
| 353 | 353 | EXPECT_EQ(-1, opt->expected()); |
| 354 | 354 | |
| 355 | 355 | args = {"--string", "mystring", "mystring2", "mystring3"}; |
| 356 | 356 | EXPECT_NO_THROW(run()); |
| 357 | - EXPECT_EQ(3, app.count("string")); | |
| 357 | + EXPECT_EQ(3, app.count("--string")); | |
| 358 | 358 | EXPECT_EQ(answer, strvec); |
| 359 | 359 | } |
| 360 | 360 | |
| ... | ... | @@ -417,9 +417,9 @@ struct SubcommandProgram : public TApp { |
| 417 | 417 | start = app.add_subcommand("start", "Start prog"); |
| 418 | 418 | stop = app.add_subcommand("stop", "Stop prog"); |
| 419 | 419 | |
| 420 | - app.add_flag("d", dummy, "My dummy var"); | |
| 421 | - start->add_option("f,file", file, "File name"); | |
| 422 | - stop->add_flag("c,count", count, "Some flag opt"); | |
| 420 | + app.add_flag("-d", dummy, "My dummy var"); | |
| 421 | + start->add_option("-f,--file", file, "File name"); | |
| 422 | + stop->add_flag("-c,--count", count, "Some flag opt"); | |
| 423 | 423 | } |
| 424 | 424 | }; |
| 425 | 425 | |
| ... | ... | @@ -449,7 +449,7 @@ TEST_F(SubcommandProgram, SpareSub) { |
| 449 | 449 | class TAppValue : public TApp {}; |
| 450 | 450 | |
| 451 | 451 | TEST_F(TAppValue, OneString) { |
| 452 | - auto str = app.make_option("s,string"); | |
| 452 | + auto str = app.make_option("-s,--string"); | |
| 453 | 453 | std::string v; |
| 454 | 454 | args = {"--string", "mystring"}; |
| 455 | 455 | EXPECT_FALSE((bool) str); |
| ... | ... | @@ -461,15 +461,15 @@ TEST_F(TAppValue, OneString) { |
| 461 | 461 | EXPECT_NO_THROW(v = *str); |
| 462 | 462 | EXPECT_NO_THROW(v = str); |
| 463 | 463 | |
| 464 | - EXPECT_EQ(1, app.count("s")); | |
| 465 | - EXPECT_EQ(1, app.count("string")); | |
| 464 | + EXPECT_EQ(1, app.count("-s")); | |
| 465 | + EXPECT_EQ(1, app.count("--string")); | |
| 466 | 466 | EXPECT_EQ(*str, "mystring"); |
| 467 | 467 | |
| 468 | 468 | } |
| 469 | 469 | |
| 470 | 470 | TEST_F(TAppValue, SeveralInts) { |
| 471 | - auto value = app.make_option<int>("first"); | |
| 472 | - CLI::Value<int> value2 = app.make_option<int>("s"); | |
| 471 | + auto value = app.make_option<int>("--first"); | |
| 472 | + CLI::Value<int> value2 = app.make_option<int>("-s"); | |
| 473 | 473 | int v; |
| 474 | 474 | args = {"--first", "12", "-s", "19"}; |
| 475 | 475 | EXPECT_FALSE((bool) value); |
| ... | ... | @@ -482,16 +482,16 @@ TEST_F(TAppValue, SeveralInts) { |
| 482 | 482 | EXPECT_NO_THROW(v = *value); |
| 483 | 483 | EXPECT_NO_THROW(v = value); |
| 484 | 484 | |
| 485 | - EXPECT_EQ(1, app.count("s")); | |
| 486 | - EXPECT_EQ(1, app.count("first")); | |
| 485 | + EXPECT_EQ(1, app.count("-s")); | |
| 486 | + EXPECT_EQ(1, app.count("--first")); | |
| 487 | 487 | EXPECT_EQ(*value, 12); |
| 488 | 488 | EXPECT_EQ(*value2, 19); |
| 489 | 489 | |
| 490 | 490 | } |
| 491 | 491 | |
| 492 | 492 | TEST_F(TAppValue, Vector) { |
| 493 | - auto value = app.make_option<std::vector<int>>("first", "", CLI::ARGS); | |
| 494 | - auto value2 = app.make_option<std::vector<std::string>>("second", "", CLI::ARGS); | |
| 493 | + auto value = app.make_option<std::vector<int>>("--first", "", CLI::Args); | |
| 494 | + auto value2 = app.make_option<std::vector<std::string>>("--second"); | |
| 495 | 495 | |
| 496 | 496 | std::vector<int> i; |
| 497 | 497 | std::vector<std::string> s; |
| ... | ... | @@ -515,8 +515,8 @@ TEST_F(TAppValue, Vector) { |
| 515 | 515 | EXPECT_NO_THROW(s = *value2); |
| 516 | 516 | //EXPECT_NO_THROW(s = value2); |
| 517 | 517 | |
| 518 | - EXPECT_EQ(3, app.count("first")); | |
| 519 | - EXPECT_EQ(2, app.count("second")); | |
| 518 | + EXPECT_EQ(3, app.count("--first")); | |
| 519 | + EXPECT_EQ(2, app.count("--second")); | |
| 520 | 520 | |
| 521 | 521 | EXPECT_EQ(std::vector<int>({12,3,9}), *value); |
| 522 | 522 | EXPECT_EQ(std::vector<std::string>({"thing", "try"}), *value2); |
| ... | ... | @@ -524,7 +524,7 @@ TEST_F(TAppValue, Vector) { |
| 524 | 524 | } |
| 525 | 525 | |
| 526 | 526 | TEST_F(TAppValue, DoubleVector) { |
| 527 | - auto value = app.make_option<std::vector<double>>("simple", "", CLI::ARGS); | |
| 527 | + auto value = app.make_option<std::vector<double>>("--simple"); | |
| 528 | 528 | std::vector<double> d; |
| 529 | 529 | |
| 530 | 530 | args = {"--simple", "1.2", "3.4", "-1"}; |
| ... | ... | @@ -535,7 +535,7 @@ TEST_F(TAppValue, DoubleVector) { |
| 535 | 535 | |
| 536 | 536 | EXPECT_NO_THROW(d = *value); |
| 537 | 537 | |
| 538 | - EXPECT_EQ(3, app.count("simple")); | |
| 538 | + EXPECT_EQ(3, app.count("--simple")); | |
| 539 | 539 | EXPECT_EQ(std::vector<double>({1.2, 3.4, -1}), *value); |
| 540 | 540 | } |
| 541 | 541 | ... | ... |
tests/SmallTest.cpp
| ... | ... | @@ -87,17 +87,20 @@ TEST(Regex, SplittingNew) { |
| 87 | 87 | |
| 88 | 88 | std::vector<std::string> shorts; |
| 89 | 89 | std::vector<std::string> longs; |
| 90 | + std::string pname; | |
| 90 | 91 | |
| 91 | - EXPECT_NO_THROW(std::tie(shorts, longs) = CLI::detail::get_names({"--long", "s", "-q", "also-long"})); | |
| 92 | + EXPECT_NO_THROW(std::tie(shorts, longs, pname) = CLI::detail::get_names({"--long", "-s", "-q", "--also-long"})); | |
| 92 | 93 | EXPECT_EQ(std::vector<std::string>({"long", "also-long"}), longs); |
| 93 | 94 | EXPECT_EQ(std::vector<std::string>({"s", "q"}), shorts); |
| 95 | + EXPECT_EQ("", pname); | |
| 94 | 96 | |
| 95 | - EXPECT_NO_THROW(std::tie(shorts, longs) = CLI::detail::get_names({"--long", "", "s", "-q", "", "also-long"})); | |
| 97 | + EXPECT_NO_THROW(std::tie(shorts, longs, pname) = CLI::detail::get_names({"--long", "", "-s", "-q", "", "--also-long"})); | |
| 96 | 98 | EXPECT_EQ(std::vector<std::string>({"long", "also-long"}), longs); |
| 97 | 99 | EXPECT_EQ(std::vector<std::string>({"s", "q"}), shorts); |
| 98 | 100 | |
| 99 | - EXPECT_THROW(std::tie(shorts, longs) = CLI::detail::get_names({"-"}), CLI::BadNameString); | |
| 100 | - EXPECT_THROW(std::tie(shorts, longs) = CLI::detail::get_names({"--"}), CLI::BadNameString); | |
| 101 | - EXPECT_THROW(std::tie(shorts, longs) = CLI::detail::get_names({"-hi"}), CLI::BadNameString); | |
| 101 | + EXPECT_THROW(std::tie(shorts, longs, pname) = CLI::detail::get_names({"-"}), CLI::BadNameString); | |
| 102 | + EXPECT_THROW(std::tie(shorts, longs, pname) = CLI::detail::get_names({"--"}), CLI::BadNameString); | |
| 103 | + EXPECT_THROW(std::tie(shorts, longs, pname) = CLI::detail::get_names({"-hi"}), CLI::BadNameString); | |
| 104 | + EXPECT_THROW(std::tie(shorts, longs, pname) = CLI::detail::get_names({"one","two"}), CLI::BadNameString); | |
| 102 | 105 | |
| 103 | 106 | } | ... | ... |