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 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 }
... ...