Commit 200d0f277feb9c8846fff0b71e782726c26bf78f

Authored by Henry Fredrick Schreiner
1 parent 955dd950

Massive move to -a,--long,posit syntax

examples/try.cpp
@@ -6,13 +6,13 @@ int main (int argc, char** argv) { @@ -6,13 +6,13 @@ int main (int argc, char** argv) {
6 CLI::App app("K3Pi goofit fitter"); 6 CLI::App app("K3Pi goofit fitter");
7 7
8 std::string file; 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 int count; 11 int count;
12 - app.add_flag("c,count", count, "Counter"); 12 + app.add_flag("-c,--count", count, "Counter");
13 13
14 double value = 3.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 try { 17 try {
18 app.run(argc, argv); 18 app.run(argc, argv);
@@ -20,8 +20,8 @@ int main (int argc, char** argv) { @@ -20,8 +20,8 @@ int main (int argc, char** argv) {
20 return app.exit(e); 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 std::cout << "Some value: " << value << std::endl; 25 std::cout << "Some value: " << value << std::endl;
26 26
27 return 0; 27 return 0;
examples/try1.cpp
@@ -9,10 +9,10 @@ int main (int argc, char** argv) { @@ -9,10 +9,10 @@ int main (int argc, char** argv) {
9 9
10 std::cout << app.help(); 10 std::cout << app.help();
11 std::string file; 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 int count; 14 int count;
15 - stop->add_flag("c,count", count, "Counter"); 15 + stop->add_flag("-c,--count", count, "Counter");
16 16
17 try { 17 try {
18 app.run(argc, argv); 18 app.run(argc, argv);
@@ -20,8 +20,8 @@ int main (int argc, char** argv) { @@ -20,8 +20,8 @@ int main (int argc, char** argv) {
20 return app.exit(e); 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 if(app.get_subcommand() != nullptr) 25 if(app.get_subcommand() != nullptr)
26 std::cout << "Subcommand:" << app.get_subcommand()->get_name() << std::endl; 26 std::cout << "Subcommand:" << app.get_subcommand()->get_name() << std::endl;
27 27
include/CLI.hpp
@@ -178,7 +178,6 @@ namespace detail { @@ -178,7 +178,6 @@ namespace detail {
178 178
179 struct Combiner { 179 struct Combiner {
180 int num; 180 int num;
181 - bool positional;  
182 bool required; 181 bool required;
183 bool defaulted; 182 bool defaulted;
184 std::vector<std::function<bool(std::string)>> validators; 183 std::vector<std::function<bool(std::string)>> validators;
@@ -187,7 +186,6 @@ namespace detail { @@ -187,7 +186,6 @@ namespace detail {
187 Combiner operator | (Combiner b) const { 186 Combiner operator | (Combiner b) const {
188 Combiner self; 187 Combiner self;
189 self.num = std::min(num, b.num) == -1 ? -1 : std::max(num, b.num); 188 self.num = std::min(num, b.num) == -1 ? -1 : std::max(num, b.num);
190 - self.positional = positional || b.positional;  
191 self.required = required || b.required; 189 self.required = required || b.required;
192 self.defaulted = defaulted || b.defaulted; 190 self.defaulted = defaulted || b.defaulted;
193 self.validators.reserve(validators.size() + b.validators.size()); 191 self.validators.reserve(validators.size() + b.validators.size());
@@ -290,36 +288,39 @@ namespace detail { @@ -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 std::vector<std::string> short_names; 294 std::vector<std::string> short_names;
295 std::vector<std::string> long_names; 295 std::vector<std::string> long_names;
  296 + std::string pos_name;
296 297
297 for(std::string name : input) { 298 for(std::string name : input) {
298 if(name.length() == 0) 299 if(name.length() == 0)
299 continue; 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 short_names.push_back(std::string(1,name[1])); 303 short_names.push_back(std::string(1,name[1]));
308 else 304 else
309 throw BadNameString("Invalid one char name: "+name); 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 if(valid_name_string(name)) 308 if(valid_name_string(name))
315 long_names.push_back(name); 309 long_names.push_back(name);
316 else 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 // Integers 326 // Integers
@@ -373,19 +374,18 @@ namespace detail { @@ -373,19 +374,18 @@ namespace detail {
373 374
374 // Defines for common Combiners (don't use combiners directly) 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 // Warning about using these validators: 383 // Warning about using these validators:
384 // The files could be added/deleted after the validation. This is not common, 384 // The files could be added/deleted after the validation. This is not common,
385 // but if this is a possibility, check the file you open afterwards 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 typedef std::vector<std::vector<std::string>> results_t; 390 typedef std::vector<std::vector<std::string>> results_t;
391 typedef std::function<bool(results_t)> callback_t; 391 typedef std::function<bool(results_t)> callback_t;
@@ -399,6 +399,8 @@ protected: @@ -399,6 +399,8 @@ protected:
399 // Config 399 // Config
400 std::vector<std::string> snames; 400 std::vector<std::string> snames;
401 std::vector<std::string> lnames; 401 std::vector<std::string> lnames;
  402 + std::string pname;
  403 +
402 detail::Combiner opts; 404 detail::Combiner opts;
403 std::string discription; 405 std::string discription;
404 callback_t callback; 406 callback_t callback;
@@ -412,31 +414,62 @@ protected: @@ -412,31 +414,62 @@ protected:
412 414
413 415
414 public: 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 opts(opts), discription(discription), callback(callback){ 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 void clear() { 423 void clear() {
421 results.clear(); 424 results.clear();
422 } 425 }
423 426
  427 + /// True if option is required
424 bool required() const { 428 bool required() const {
425 return opts.required; 429 return opts.required;
426 } 430 }
427 431
  432 + /// The number of arguments the option expects
428 int expected() const { 433 int expected() const {
429 return opts.num; 434 return opts.num;
430 } 435 }
431 436
  437 + /// True if the argument can be given directly
432 bool positional() const { 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 bool defaulted() const { 448 bool defaulted() const {
437 return opts.defaulted; 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 /// Process the callback 473 /// Process the callback
441 bool run_callback() const { 474 bool run_callback() const {
442 if(opts.validators.size()>0) { 475 if(opts.validators.size()>0) {
@@ -448,7 +481,7 @@ public: @@ -448,7 +481,7 @@ public:
448 return callback(results); 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 bool operator== (const Option& other) const { 485 bool operator== (const Option& other) const {
453 for(const std::string &sname : snames) 486 for(const std::string &sname : snames)
454 for(const std::string &othersname : other.snames) 487 for(const std::string &othersname : other.snames)
@@ -461,6 +494,7 @@ public: @@ -461,6 +494,7 @@ public:
461 return false; 494 return false;
462 } 495 }
463 496
  497 + /// Gets a , sep list of names. Does not include the positional name.
464 std::string get_name() const { 498 std::string get_name() const {
465 std::vector<std::string> name_list; 499 std::vector<std::string> name_list;
466 for(const std::string& sname : snames) 500 for(const std::string& sname : snames)
@@ -470,30 +504,40 @@ public: @@ -470,30 +504,40 @@ public:
470 return detail::join(name_list); 504 return detail::join(name_list);
471 } 505 }
472 506
  507 + /// Check a name. Requires "-" or "--" for short / long, supports positional name
473 bool check_name(std::string name) const { 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 bool check_sname(const std::string& name) const { 519 bool check_sname(const std::string& name) const {
482 return std::find(std::begin(snames), std::end(snames), name) != std::end(snames); 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 bool check_lname(const std::string& name) const { 524 bool check_lname(const std::string& name) const {
486 return std::find(std::begin(lnames), std::end(lnames), name) != std::end(lnames); 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 void add_result(int r, std::string s) { 530 void add_result(int r, std::string s) {
491 results.at(r).push_back(s); 531 results.at(r).push_back(s);
492 } 532 }
  533 +
  534 + /// Starts a new results vector (used for r in add_result)
493 int get_new() { 535 int get_new() {
494 results.emplace_back(); 536 results.emplace_back();
495 return results.size() - 1; 537 return results.size() - 1;
496 } 538 }
  539 +
  540 + /// Count the total number of times an option was passed
497 int count() const { 541 int count() const {
498 int out = 0; 542 int out = 0;
499 for(const std::vector<std::string>& v : results) 543 for(const std::vector<std::string>& v : results)
@@ -501,6 +545,7 @@ public: @@ -501,6 +545,7 @@ public:
501 return out; 545 return out;
502 } 546 }
503 547
  548 + /// Diagnostic representation
504 std::string string() const { 549 std::string string() const {
505 std::string val = "Option: " + get_name() + "\n" 550 std::string val = "Option: " + get_name() + "\n"
506 + " " + discription + "\n" 551 + " " + discription + "\n"
@@ -514,6 +559,7 @@ public: @@ -514,6 +559,7 @@ public:
514 return val; 559 return val;
515 } 560 }
516 561
  562 + /// The first half of the help print, name plus default, etc
517 std::string help_name() const { 563 std::string help_name() const {
518 std::stringstream out; 564 std::stringstream out;
519 out << " " << get_name(); 565 out << " " << get_name();
@@ -530,10 +576,12 @@ public: @@ -530,10 +576,12 @@ public:
530 return out.str(); 576 return out.str();
531 } 577 }
532 578
  579 + /// The length of the name part of the help, for formatting
533 int help_len() const { 580 int help_len() const {
534 return help_name().length(); 581 return help_name().length();
535 } 582 }
536 583
  584 + /// Make a help string, adjustable len.
537 std::string help(int len = 0) const { 585 std::string help(int len = 0) const {
538 std::stringstream out; 586 std::stringstream out;
539 if(help_len() > len) { 587 if(help_len() > len) {
@@ -547,6 +595,7 @@ public: @@ -547,6 +595,7 @@ public:
547 return out.str(); 595 return out.str();
548 } 596 }
549 597
  598 + /// Produce a flattened vector of results, vs. a vector of vectors.
550 std::vector<std::string> flatten_results() const { 599 std::vector<std::string> flatten_results() const {
551 std::vector<std::string> output; 600 std::vector<std::string> output;
552 for(const std::vector<std::string> result : results) 601 for(const std::vector<std::string> result : results)
@@ -602,6 +651,7 @@ protected: @@ -602,6 +651,7 @@ protected:
602 std::vector<std::unique_ptr<App>> subcommands; 651 std::vector<std::unique_ptr<App>> subcommands;
603 bool parsed{false}; 652 bool parsed{false};
604 App* subcommand = nullptr; 653 App* subcommand = nullptr;
  654 + std::string progname = "program";
605 655
606 std::function<void()> app_callback; 656 std::function<void()> app_callback;
607 657
@@ -639,7 +689,7 @@ public: @@ -639,7 +689,7 @@ public:
639 App(std::string prog_discription="") 689 App(std::string prog_discription="")
640 : prog_discription(prog_discription) { 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,7 +707,7 @@ public:
657 * After start is called, you can use count to see if the value was passed, and 707 * After start is called, you can use count to see if the value was passed, and
658 * the value will be initialized properly. 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 * together. The positional options take an optional number of arguments. 711 * together. The positional options take an optional number of arguments.
662 * 712 *
663 * For example, 713 * For example,
@@ -666,10 +716,10 @@ public: @@ -666,10 +716,10 @@ public:
666 * program.add_option("filename", filename, "discription of filename"); 716 * program.add_option("filename", filename, "discription of filename");
667 */ 717 */
668 Option* add_option( 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 Option myopt{name, discription, opts, callback}; 724 Option myopt{name, discription, opts, callback};
675 if(std::find(std::begin(options), std::end(options), myopt) == std::end(options)) 725 if(std::find(std::begin(options), std::end(options), myopt) == std::end(options))
@@ -683,15 +733,15 @@ public: @@ -683,15 +733,15 @@ public:
683 /// Add option for string 733 /// Add option for string
684 template<typename T, enable_if_t<!is_vector<T>::value, detail::enabler> = detail::dummy> 734 template<typename T, enable_if_t<!is_vector<T>::value, detail::enabler> = detail::dummy>
685 Option* add_option( 735 Option* add_option(
686 - std::string name, ///< The name, long,short 736 + std::string name,
687 T &variable, ///< The variable to set 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 if(opts.num!=1) 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 CLI::callback_t fun = [&variable](CLI::results_t res){ 745 CLI::callback_t fun = [&variable](CLI::results_t res){
696 if(res.size()!=1) { 746 if(res.size()!=1) {
697 return false; 747 return false;
@@ -715,14 +765,14 @@ public: @@ -715,14 +765,14 @@ public:
715 /// Add option for vector of results 765 /// Add option for vector of results
716 template<typename T> 766 template<typename T>
717 Option* add_option( 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 if(opts.num==0) 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 CLI::callback_t fun = [&variable](CLI::results_t res){ 776 CLI::callback_t fun = [&variable](CLI::results_t res){
727 bool retval = true; 777 bool retval = true;
728 variable.clear(); 778 variable.clear();
@@ -746,10 +796,10 @@ public: @@ -746,10 +796,10 @@ public:
746 /// Multiple options are supported 796 /// Multiple options are supported
747 template<typename T, typename... Args> 797 template<typename T, typename... Args>
748 Option* add_option( 798 Option* add_option(
749 - std::string name, ///< The name, long,short 799 + std::string name,
750 T &variable, ///< The variable to set 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 detail::Combiner opts2, 803 detail::Combiner opts2,
754 Args... args ///< More options 804 Args... args ///< More options
755 ) { 805 ) {
@@ -757,23 +807,26 @@ public: @@ -757,23 +807,26 @@ public:
757 } 807 }
758 /// Add option for flag 808 /// Add option for flag
759 Option* add_flag( 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 CLI::callback_t fun = [](CLI::results_t){ 813 CLI::callback_t fun = [](CLI::results_t){
764 return true; 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 /// Add option for flag 823 /// Add option for flag
771 template<typename T, 824 template<typename T,
772 enable_if_t<std::is_integral<T>::value && !is_bool<T>::value, detail::enabler> = detail::dummy> 825 enable_if_t<std::is_integral<T>::value && !is_bool<T>::value, detail::enabler> = detail::dummy>
773 Option* add_flag( 826 Option* add_flag(
774 - std::string name, ///< The name, short,long 827 + std::string name,
775 T &count, ///< A varaible holding the count 828 T &count, ///< A varaible holding the count
776 - std::string discription="" ///< Discription string 829 + std::string discription=""
777 ) { 830 ) {
778 831
779 count = 0; 832 count = 0;
@@ -782,16 +835,19 @@ public: @@ -782,16 +835,19 @@ public:
782 return true; 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 /// Bool version only allows the flag once 844 /// Bool version only allows the flag once
789 template<typename T, 845 template<typename T,
790 enable_if_t<is_bool<T>::value, detail::enabler> = detail::dummy> 846 enable_if_t<is_bool<T>::value, detail::enabler> = detail::dummy>
791 Option* add_flag( 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 count = false; 853 count = false;
@@ -800,22 +856,25 @@ public: @@ -800,22 +856,25 @@ public:
800 return res.size() == 1; 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 /// Add set of options 866 /// Add set of options
808 template<typename T> 867 template<typename T>
809 Option* add_set( 868 Option* add_set(
810 - std::string name, ///< The name, short,long 869 + std::string name,
811 T &member, ///< The selected member of the set 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 if(opts.num!=1) 876 if(opts.num!=1)
818 - throw IncorrectConstruction("Must have ARGS(1)."); 877 + throw IncorrectConstruction("Must have Args(1).");
819 878
820 CLI::callback_t fun = [&member, options](CLI::results_t res){ 879 CLI::callback_t fun = [&member, options](CLI::results_t res){
821 if(res.size()!=1) { 880 if(res.size()!=1) {
@@ -844,11 +903,11 @@ public: @@ -844,11 +903,11 @@ public:
844 903
845 template<typename T, typename... Args> 904 template<typename T, typename... Args>
846 Option* add_set( 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 detail::Combiner opts2, 911 detail::Combiner opts2,
853 Args... args 912 Args... args
854 ) { 913 ) {
@@ -862,13 +921,13 @@ public: @@ -862,13 +921,13 @@ public:
862 template<typename T = std::string, 921 template<typename T = std::string,
863 enable_if_t<!is_vector<T>::value, detail::enabler> = detail::dummy> 922 enable_if_t<!is_vector<T>::value, detail::enabler> = detail::dummy>
864 Value<T> make_option( 923 Value<T> make_option(
865 - std::string name, ///< The name, short,long 924 + std::string name,
866 std::string discription="", 925 std::string discription="",
867 - detail::Combiner opts=VALIDATORS 926 + detail::Combiner opts=Validators
868 ) { 927 ) {
869 928
870 if(opts.num!=1) 929 if(opts.num!=1)
871 - throw IncorrectConstruction("Must have ARGS(1)."); 930 + throw IncorrectConstruction("Must have Args(1).");
872 931
873 Value<T> out(name); 932 Value<T> out(name);
874 std::shared_ptr<std::unique_ptr<T>> ptr = out.value; 933 std::shared_ptr<std::unique_ptr<T>> ptr = out.value;
@@ -890,7 +949,7 @@ public: @@ -890,7 +949,7 @@ public:
890 949
891 template<typename T = std::string, typename... Args> 950 template<typename T = std::string, typename... Args>
892 Value<T> make_option( 951 Value<T> make_option(
893 - std::string name, ///< The name, short,long 952 + std::string name,
894 std::string discription, 953 std::string discription,
895 detail::Combiner opts, 954 detail::Combiner opts,
896 detail::Combiner opts2, 955 detail::Combiner opts2,
@@ -903,14 +962,14 @@ public: @@ -903,14 +962,14 @@ public:
903 template<typename T, 962 template<typename T,
904 enable_if_t<!is_vector<T>::value, detail::enabler> = detail::dummy> 963 enable_if_t<!is_vector<T>::value, detail::enabler> = detail::dummy>
905 Value<T> make_option( 964 Value<T> make_option(
906 - std::string name, ///< The name, short,long 965 + std::string name,
907 const T& default_value, 966 const T& default_value,
908 std::string discription="", 967 std::string discription="",
909 - detail::Combiner opts=VALIDATORS 968 + detail::Combiner opts=Validators
910 ) { 969 ) {
911 970
912 if(opts.num!=1) 971 if(opts.num!=1)
913 - throw IncorrectConstruction("Must have ARGS(1)."); 972 + throw IncorrectConstruction("Must have Args(1).");
914 973
915 Value<T> out(name); 974 Value<T> out(name);
916 std::shared_ptr<std::unique_ptr<T>> ptr = out.value; 975 std::shared_ptr<std::unique_ptr<T>> ptr = out.value;
@@ -938,13 +997,13 @@ public: @@ -938,13 +997,13 @@ public:
938 template<typename T, 997 template<typename T,
939 enable_if_t<is_vector<T>::value, detail::enabler> = detail::dummy> 998 enable_if_t<is_vector<T>::value, detail::enabler> = detail::dummy>
940 Value<T> make_option( 999 Value<T> make_option(
941 - std::string name, ///< The name, short,long 1000 + std::string name,
942 std::string discription="", 1001 std::string discription="",
943 - detail::Combiner opts=VALIDATORS 1002 + detail::Combiner opts=Args
944 ) { 1003 ) {
945 1004
946 if(opts.num==0) 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 Value<T> out(name); 1008 Value<T> out(name);
950 std::shared_ptr<std::unique_ptr<T>> ptr = out.value; 1009 std::shared_ptr<std::unique_ptr<T>> ptr = out.value;
@@ -967,7 +1026,7 @@ public: @@ -967,7 +1026,7 @@ public:
967 1026
968 template<typename T, typename... Args> 1027 template<typename T, typename... Args>
969 Value<T> make_option( 1028 Value<T> make_option(
970 - std::string name, ///< The name, short,long 1029 + std::string name,
971 const T& default_value, 1030 const T& default_value,
972 std::string discription, 1031 std::string discription,
973 detail::Combiner opts, 1032 detail::Combiner opts,
@@ -979,7 +1038,7 @@ public: @@ -979,7 +1038,7 @@ public:
979 1038
980 /// Prototype for new output style: flag 1039 /// Prototype for new output style: flag
981 Value<int> make_flag( 1040 Value<int> make_flag(
982 - std::string name, ///< The name, short,long 1041 + std::string name,
983 std::string discription="" 1042 std::string discription=""
984 ) { 1043 ) {
985 1044
@@ -992,24 +1051,27 @@ public: @@ -992,24 +1051,27 @@ public:
992 **ptr = (int) res.size(); 1051 **ptr = (int) res.size();
993 return true; 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 return out; 1058 return out;
997 } 1059 }
998 1060
999 /// Add set of options 1061 /// Add set of options
1000 template<typename T> 1062 template<typename T>
1001 Value<T> make_set( 1063 Value<T> make_set(
1002 - std::string name, ///< The name, short,long 1064 + std::string name,
1003 std::set<T> options, ///< The set of posibilities 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 Value<T> out(name); 1070 Value<T> out(name);
1009 std::shared_ptr<std::unique_ptr<T>> ptr = out.value; 1071 std::shared_ptr<std::unique_ptr<T>> ptr = out.value;
1010 1072
1011 if(opts.num!=1) 1073 if(opts.num!=1)
1012 - throw IncorrectConstruction("Must have ARGS(1)."); 1074 + throw IncorrectConstruction("Must have Args(1).");
1013 1075
1014 CLI::callback_t fun = [ptr, options](CLI::results_t res){ 1076 CLI::callback_t fun = [ptr, options](CLI::results_t res){
1015 if(res.size()!=1) { 1077 if(res.size()!=1) {
@@ -1046,6 +1108,7 @@ public: @@ -1046,6 +1108,7 @@ public:
1046 1108
1047 /// Parses the command line - throws errors 1109 /// Parses the command line - throws errors
1048 void parse(int argc, char **argv) { 1110 void parse(int argc, char **argv) {
  1111 + progname = argv[0];
1049 std::vector<std::string> args; 1112 std::vector<std::string> args;
1050 for(int i=argc-1; i>0; i--) 1113 for(int i=argc-1; i>0; i--)
1051 args.push_back(argv[i]); 1114 args.push_back(argv[i]);
@@ -1081,7 +1144,7 @@ public: @@ -1081,7 +1144,7 @@ public:
1081 } 1144 }
1082 } 1145 }
1083 1146
1084 - if (count("help") > 0) { 1147 + if (count("--help") > 0) {
1085 throw CallForHelp(); 1148 throw CallForHelp();
1086 } 1149 }
1087 1150
@@ -1259,12 +1322,50 @@ public: @@ -1259,12 +1322,50 @@ public:
1259 if(name != "") 1322 if(name != "")
1260 out << "Subcommand: " << name << " "; 1323 out << "Subcommand: " << name << " ";
1261 out << prog_discription << std::endl; 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 int len = std::accumulate(std::begin(options), std::end(options), 0, 1351 int len = std::accumulate(std::begin(options), std::end(options), 0,
1263 [](int val, const Option &opt){ 1352 [](int val, const Option &opt){
1264 return std::max(opt.help_len()+3, val);}); 1353 return std::max(opt.help_len()+3, val);});
  1354 +
  1355 + bool npos = false;
1265 for(const Option &opt : options) { 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 if(subcommands.size()> 0) { 1369 if(subcommands.size()> 0) {
1269 out << "Subcommands:" << std::endl; 1370 out << "Subcommands:" << std::endl;
1270 int max = std::accumulate(std::begin(subcommands), std::end(subcommands), 0, 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,19 +37,19 @@ struct TApp : public ::testing::Test {
37 }; 37 };
38 38
39 TEST_F(TApp, OneFlagShort) { 39 TEST_F(TApp, OneFlagShort) {
40 - app.add_flag("c,count"); 40 + app.add_flag("-c,--count");
41 args = {"-c"}; 41 args = {"-c"};
42 EXPECT_NO_THROW(run()); 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 TEST_F(TApp, OneFlagLong) { 47 TEST_F(TApp, OneFlagLong) {
48 - app.add_flag("c,count"); 48 + app.add_flag("-c,--count");
49 args = {"--count"}; 49 args = {"--count"};
50 EXPECT_NO_THROW(run()); 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 TEST_F(TApp, DashedOptions) { 55 TEST_F(TApp, DashedOptions) {
@@ -59,9 +59,9 @@ TEST_F(TApp, DashedOptions) { @@ -59,9 +59,9 @@ TEST_F(TApp, DashedOptions) {
59 59
60 args = {"-c", "--q", "--this", "--that"}; 60 args = {"-c", "--q", "--this", "--that"};
61 EXPECT_NO_THROW(run()); 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 EXPECT_EQ(2, app.count("--that")); 65 EXPECT_EQ(2, app.count("--that"));
66 66
67 } 67 }
@@ -69,76 +69,76 @@ TEST_F(TApp, DashedOptions) { @@ -69,76 +69,76 @@ TEST_F(TApp, DashedOptions) {
69 69
70 TEST_F(TApp, OneFlagRef) { 70 TEST_F(TApp, OneFlagRef) {
71 int ref; 71 int ref;
72 - app.add_flag("c,count", ref); 72 + app.add_flag("-c,--count", ref);
73 args = {"--count"}; 73 args = {"--count"};
74 EXPECT_NO_THROW(run()); 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 EXPECT_EQ(1, ref); 77 EXPECT_EQ(1, ref);
78 } 78 }
79 79
80 TEST_F(TApp, OneString) { 80 TEST_F(TApp, OneString) {
81 std::string str; 81 std::string str;
82 - app.add_option("s,string", str); 82 + app.add_option("-s,--string", str);
83 args = {"--string", "mystring"}; 83 args = {"--string", "mystring"};
84 EXPECT_NO_THROW(run()); 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 EXPECT_EQ(str, "mystring"); 87 EXPECT_EQ(str, "mystring");
88 } 88 }
89 89
90 90
91 TEST_F(TApp, TogetherInt) { 91 TEST_F(TApp, TogetherInt) {
92 int i; 92 int i;
93 - app.add_option("i,int", i); 93 + app.add_option("-i,--int", i);
94 args = {"-i4"}; 94 args = {"-i4"};
95 EXPECT_NO_THROW(run()); 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 EXPECT_EQ(i, 4); 98 EXPECT_EQ(i, 4);
99 } 99 }
100 100
101 TEST_F(TApp, SepInt) { 101 TEST_F(TApp, SepInt) {
102 int i; 102 int i;
103 - app.add_option("i,int", i); 103 + app.add_option("-i,--int", i);
104 args = {"-i","4"}; 104 args = {"-i","4"};
105 EXPECT_NO_THROW(run()); 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 EXPECT_EQ(i, 4); 108 EXPECT_EQ(i, 4);
109 } 109 }
110 110
111 TEST_F(TApp, OneStringAgain) { 111 TEST_F(TApp, OneStringAgain) {
112 std::string str; 112 std::string str;
113 - app.add_option("s,string", str); 113 + app.add_option("-s,--string", str);
114 args = {"--string", "mystring"}; 114 args = {"--string", "mystring"};
115 EXPECT_NO_THROW(run()); 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 EXPECT_EQ(str, "mystring"); 118 EXPECT_EQ(str, "mystring");
119 } 119 }
120 120
121 121
122 TEST_F(TApp, DefaultStringAgain) { 122 TEST_F(TApp, DefaultStringAgain) {
123 std::string str = "previous"; 123 std::string str = "previous";
124 - app.add_option("s,string", str); 124 + app.add_option("-s,--string", str);
125 EXPECT_NO_THROW(run()); 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 EXPECT_EQ(str, "previous"); 128 EXPECT_EQ(str, "previous");
129 } 129 }
130 130
131 TEST_F(TApp, LotsOfFlags) { 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 args = {"-a","-b","-aA"}; 137 args = {"-a","-b","-aA"};
138 EXPECT_NO_THROW(run()); 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,9 +148,9 @@ TEST_F(TApp, BoolAndIntFlags) {
148 int iflag; 148 int iflag;
149 unsigned int uflag; 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 args = {"-b", "-i", "-u"}; 155 args = {"-b", "-i", "-u"};
156 EXPECT_NO_THROW(run()); 156 EXPECT_NO_THROW(run());
@@ -177,15 +177,15 @@ TEST_F(TApp, ShortOpts) { @@ -177,15 +177,15 @@ TEST_F(TApp, ShortOpts) {
177 177
178 unsigned long long funnyint; 178 unsigned long long funnyint;
179 std::string someopt; 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 args = {"-zzyzyz",}; 183 args = {"-zzyzyz",};
184 184
185 EXPECT_NO_THROW(run()); 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 EXPECT_EQ((unsigned long long) 2, funnyint); 189 EXPECT_EQ((unsigned long long) 2, funnyint);
190 EXPECT_EQ("zyz", someopt); 190 EXPECT_EQ("zyz", someopt);
191 } 191 }
@@ -195,15 +195,15 @@ TEST_F(TApp, Flags) { @@ -195,15 +195,15 @@ TEST_F(TApp, Flags) {
195 int i = 3; 195 int i = 3;
196 std::string s = "HI"; 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 args = {"-i2", "9"}; 201 args = {"-i2", "9"};
202 202
203 EXPECT_NO_THROW(run()); 203 EXPECT_NO_THROW(run());
204 204
205 EXPECT_EQ(1, app.count("i")); 205 EXPECT_EQ(1, app.count("i"));
206 - EXPECT_EQ(1, app.count("s")); 206 + EXPECT_EQ(1, app.count("-s"));
207 EXPECT_EQ(2, i); 207 EXPECT_EQ(2, i);
208 EXPECT_EQ("9", s); 208 EXPECT_EQ("9", s);
209 } 209 }
@@ -212,8 +212,8 @@ TEST_F(TApp, Positionals) { @@ -212,8 +212,8 @@ TEST_F(TApp, Positionals) {
212 212
213 std::string posit1; 213 std::string posit1;
214 std::string posit2; 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 args = {"thing1","thing2"}; 218 args = {"thing1","thing2"};
219 219
@@ -229,42 +229,42 @@ TEST_F(TApp, MixedPositionals) { @@ -229,42 +229,42 @@ TEST_F(TApp, MixedPositionals) {
229 229
230 int positional_int; 230 int positional_int;
231 std::string positional_string; 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 args = {"--posit2","thing2","7"}; 235 args = {"--posit2","thing2","7"};
236 236
237 EXPECT_NO_THROW(run()); 237 EXPECT_NO_THROW(run());
238 238
239 EXPECT_EQ(1, app.count("posit2")); 239 EXPECT_EQ(1, app.count("posit2"));
240 - EXPECT_EQ(1, app.count("posit1")); 240 + EXPECT_EQ(1, app.count("--posit1"));
241 EXPECT_EQ(7, positional_int); 241 EXPECT_EQ(7, positional_int);
242 EXPECT_EQ("thing2", positional_string); 242 EXPECT_EQ("thing2", positional_string);
243 } 243 }
244 244
245 TEST_F(TApp, Reset) { 245 TEST_F(TApp, Reset) {
246 246
247 - app.add_flag("simple"); 247 + app.add_flag("--simple");
248 double doub; 248 double doub;
249 - app.add_option("d,double", doub); 249 + app.add_option("-d,--double", doub);
250 250
251 args = {"--simple", "--double", "1.2"}; 251 args = {"--simple", "--double", "1.2"};
252 252
253 EXPECT_NO_THROW(run()); 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 EXPECT_FLOAT_EQ(1.2, doub); 257 EXPECT_FLOAT_EQ(1.2, doub);
258 258
259 app.reset(); 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 EXPECT_NO_THROW(run()); 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 EXPECT_FLOAT_EQ(1.2, doub); 268 EXPECT_FLOAT_EQ(1.2, doub);
269 269
270 } 270 }
@@ -275,7 +275,7 @@ TEST_F(TApp, FileNotExists) { @@ -275,7 +275,7 @@ TEST_F(TApp, FileNotExists) {
275 EXPECT_TRUE(CLI::detail::_NonexistentPath(myfile)); 275 EXPECT_TRUE(CLI::detail::_NonexistentPath(myfile));
276 276
277 std::string filename; 277 std::string filename;
278 - app.add_option("file", filename, "", CLI::NonexistentPath); 278 + app.add_option("--file", filename, "", CLI::NonexistentPath);
279 args = {"--file", myfile}; 279 args = {"--file", myfile};
280 280
281 EXPECT_NO_THROW(run()); 281 EXPECT_NO_THROW(run());
@@ -297,7 +297,7 @@ TEST_F(TApp, FileExists) { @@ -297,7 +297,7 @@ TEST_F(TApp, FileExists) {
297 EXPECT_FALSE(CLI::detail::_ExistingFile(myfile)); 297 EXPECT_FALSE(CLI::detail::_ExistingFile(myfile));
298 298
299 std::string filename = "Failed"; 299 std::string filename = "Failed";
300 - app.add_option("file", filename, "", CLI::ExistingFile); 300 + app.add_option("--file", filename, "", CLI::ExistingFile);
301 args = {"--file", myfile}; 301 args = {"--file", myfile};
302 302
303 EXPECT_THROW(run(), CLI::ParseError); 303 EXPECT_THROW(run(), CLI::ParseError);
@@ -317,7 +317,7 @@ TEST_F(TApp, FileExists) { @@ -317,7 +317,7 @@ TEST_F(TApp, FileExists) {
317 TEST_F(TApp, InSet) { 317 TEST_F(TApp, InSet) {
318 318
319 std::string choice; 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 args = {"--quick", "two"}; 322 args = {"--quick", "two"};
323 323
@@ -334,12 +334,12 @@ TEST_F(TApp, VectorFixedString) { @@ -334,12 +334,12 @@ TEST_F(TApp, VectorFixedString) {
334 std::vector<std::string> strvec; 334 std::vector<std::string> strvec;
335 std::vector<std::string> answer{"mystring", "mystring2", "mystring3"}; 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 EXPECT_EQ(3, opt->expected()); 338 EXPECT_EQ(3, opt->expected());
339 339
340 args = {"--string", "mystring", "mystring2", "mystring3"}; 340 args = {"--string", "mystring", "mystring2", "mystring3"};
341 run(); 341 run();
342 - EXPECT_EQ(3, app.count("string")); 342 + EXPECT_EQ(3, app.count("--string"));
343 EXPECT_EQ(answer, strvec); 343 EXPECT_EQ(answer, strvec);
344 } 344 }
345 345
@@ -349,12 +349,12 @@ TEST_F(TApp, VectorUnlimString) { @@ -349,12 +349,12 @@ TEST_F(TApp, VectorUnlimString) {
349 std::vector<std::string> strvec; 349 std::vector<std::string> strvec;
350 std::vector<std::string> answer{"mystring", "mystring2", "mystring3"}; 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 EXPECT_EQ(-1, opt->expected()); 353 EXPECT_EQ(-1, opt->expected());
354 354
355 args = {"--string", "mystring", "mystring2", "mystring3"}; 355 args = {"--string", "mystring", "mystring2", "mystring3"};
356 EXPECT_NO_THROW(run()); 356 EXPECT_NO_THROW(run());
357 - EXPECT_EQ(3, app.count("string")); 357 + EXPECT_EQ(3, app.count("--string"));
358 EXPECT_EQ(answer, strvec); 358 EXPECT_EQ(answer, strvec);
359 } 359 }
360 360
@@ -417,9 +417,9 @@ struct SubcommandProgram : public TApp { @@ -417,9 +417,9 @@ struct SubcommandProgram : public TApp {
417 start = app.add_subcommand("start", "Start prog"); 417 start = app.add_subcommand("start", "Start prog");
418 stop = app.add_subcommand("stop", "Stop prog"); 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,7 +449,7 @@ TEST_F(SubcommandProgram, SpareSub) {
449 class TAppValue : public TApp {}; 449 class TAppValue : public TApp {};
450 450
451 TEST_F(TAppValue, OneString) { 451 TEST_F(TAppValue, OneString) {
452 - auto str = app.make_option("s,string"); 452 + auto str = app.make_option("-s,--string");
453 std::string v; 453 std::string v;
454 args = {"--string", "mystring"}; 454 args = {"--string", "mystring"};
455 EXPECT_FALSE((bool) str); 455 EXPECT_FALSE((bool) str);
@@ -461,15 +461,15 @@ TEST_F(TAppValue, OneString) { @@ -461,15 +461,15 @@ TEST_F(TAppValue, OneString) {
461 EXPECT_NO_THROW(v = *str); 461 EXPECT_NO_THROW(v = *str);
462 EXPECT_NO_THROW(v = str); 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 EXPECT_EQ(*str, "mystring"); 466 EXPECT_EQ(*str, "mystring");
467 467
468 } 468 }
469 469
470 TEST_F(TAppValue, SeveralInts) { 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 int v; 473 int v;
474 args = {"--first", "12", "-s", "19"}; 474 args = {"--first", "12", "-s", "19"};
475 EXPECT_FALSE((bool) value); 475 EXPECT_FALSE((bool) value);
@@ -482,16 +482,16 @@ TEST_F(TAppValue, SeveralInts) { @@ -482,16 +482,16 @@ TEST_F(TAppValue, SeveralInts) {
482 EXPECT_NO_THROW(v = *value); 482 EXPECT_NO_THROW(v = *value);
483 EXPECT_NO_THROW(v = value); 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 EXPECT_EQ(*value, 12); 487 EXPECT_EQ(*value, 12);
488 EXPECT_EQ(*value2, 19); 488 EXPECT_EQ(*value2, 19);
489 489
490 } 490 }
491 491
492 TEST_F(TAppValue, Vector) { 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 std::vector<int> i; 496 std::vector<int> i;
497 std::vector<std::string> s; 497 std::vector<std::string> s;
@@ -515,8 +515,8 @@ TEST_F(TAppValue, Vector) { @@ -515,8 +515,8 @@ TEST_F(TAppValue, Vector) {
515 EXPECT_NO_THROW(s = *value2); 515 EXPECT_NO_THROW(s = *value2);
516 //EXPECT_NO_THROW(s = value2); 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 EXPECT_EQ(std::vector<int>({12,3,9}), *value); 521 EXPECT_EQ(std::vector<int>({12,3,9}), *value);
522 EXPECT_EQ(std::vector<std::string>({"thing", "try"}), *value2); 522 EXPECT_EQ(std::vector<std::string>({"thing", "try"}), *value2);
@@ -524,7 +524,7 @@ TEST_F(TAppValue, Vector) { @@ -524,7 +524,7 @@ TEST_F(TAppValue, Vector) {
524 } 524 }
525 525
526 TEST_F(TAppValue, DoubleVector) { 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 std::vector<double> d; 528 std::vector<double> d;
529 529
530 args = {"--simple", "1.2", "3.4", "-1"}; 530 args = {"--simple", "1.2", "3.4", "-1"};
@@ -535,7 +535,7 @@ TEST_F(TAppValue, DoubleVector) { @@ -535,7 +535,7 @@ TEST_F(TAppValue, DoubleVector) {
535 535
536 EXPECT_NO_THROW(d = *value); 536 EXPECT_NO_THROW(d = *value);
537 537
538 - EXPECT_EQ(3, app.count("simple")); 538 + EXPECT_EQ(3, app.count("--simple"));
539 EXPECT_EQ(std::vector<double>({1.2, 3.4, -1}), *value); 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,17 +87,20 @@ TEST(Regex, SplittingNew) {
87 87
88 std::vector<std::string> shorts; 88 std::vector<std::string> shorts;
89 std::vector<std::string> longs; 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 EXPECT_EQ(std::vector<std::string>({"long", "also-long"}), longs); 93 EXPECT_EQ(std::vector<std::string>({"long", "also-long"}), longs);
93 EXPECT_EQ(std::vector<std::string>({"s", "q"}), shorts); 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 EXPECT_EQ(std::vector<std::string>({"long", "also-long"}), longs); 98 EXPECT_EQ(std::vector<std::string>({"long", "also-long"}), longs);
97 EXPECT_EQ(std::vector<std::string>({"s", "q"}), shorts); 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 }