Commit b2e7efe7f4c2e738a42b0bceea2761ce32d6cc21

Authored by Jarryd Beck
1 parent 8844335d

positional arguments parse into multiple options

src/cxxopts.hpp
1 /* 1 /*
2 2
3 -Copyright (c) 2014 Jarryd Beck 3 +Copyright (c) 2014, 2015 Jarryd Beck
4 4
5 Permission is hereby granted, free of charge, to any person obtaining a copy 5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal 6 of this software and associated documentation files (the "Software"), to deal
@@ -244,6 +244,9 @@ namespace cxxopts @@ -244,6 +244,9 @@ namespace cxxopts
244 has_default() const = 0; 244 has_default() const = 0;
245 245
246 virtual bool 246 virtual bool
  247 + is_container() const = 0;
  248 +
  249 + virtual bool
247 has_implicit() const = 0; 250 has_implicit() const = 0;
248 251
249 virtual std::string 252 virtual std::string
@@ -436,6 +439,18 @@ namespace cxxopts @@ -436,6 +439,18 @@ namespace cxxopts
436 }; 439 };
437 440
438 template <typename T> 441 template <typename T>
  442 + struct type_is_container
  443 + {
  444 + static constexpr bool value = false;
  445 + };
  446 +
  447 + template <typename T>
  448 + struct type_is_container<std::vector<T>>
  449 + {
  450 + static constexpr bool value = true;
  451 + };
  452 +
  453 + template <typename T>
439 class standard_value : public Value 454 class standard_value : public Value
440 { 455 {
441 public: 456 public:
@@ -463,6 +478,12 @@ namespace cxxopts @@ -463,6 +478,12 @@ namespace cxxopts
463 } 478 }
464 } 479 }
465 480
  481 + bool
  482 + is_container() const
  483 + {
  484 + return type_is_container<T>::value;
  485 + }
  486 +
466 void 487 void
467 parse() const 488 parse() const
468 { 489 {
@@ -700,6 +721,10 @@ namespace cxxopts @@ -700,6 +721,10 @@ namespace cxxopts
700 parse_positional(std::string option); 721 parse_positional(std::string option);
701 722
702 inline 723 inline
  724 + void
  725 + parse_positional(std::vector<std::string> options);
  726 +
  727 + inline
703 std::string 728 std::string
704 help(const std::vector<std::string>& groups = {""}) const; 729 help(const std::vector<std::string>& groups = {""}) const;
705 730
@@ -757,7 +782,8 @@ namespace cxxopts @@ -757,7 +782,8 @@ namespace cxxopts
757 String m_help_string; 782 String m_help_string;
758 783
759 std::map<std::string, std::shared_ptr<OptionDetails>> m_options; 784 std::map<std::string, std::shared_ptr<OptionDetails>> m_options;
760 - std::string m_positional; 785 + std::vector<std::string> m_positional;
  786 + std::vector<std::string>::iterator m_next_positional;
761 787
762 //mapping from groups to help options 788 //mapping from groups to help options
763 std::map<std::string, HelpGroupDetails> m_help; 789 std::map<std::string, HelpGroupDetails> m_help;
@@ -1005,9 +1031,14 @@ Options::add_to_option(const std::string&amp; option, const std::string&amp; arg) @@ -1005,9 +1031,14 @@ Options::add_to_option(const std::string&amp; option, const std::string&amp; arg)
1005 bool 1031 bool
1006 Options::consume_positional(std::string a) 1032 Options::consume_positional(std::string a)
1007 { 1033 {
1008 - if (m_positional.size() > 0) 1034 + if (m_next_positional != m_positional.end())
1009 { 1035 {
1010 - add_to_option(m_positional, a); 1036 + add_to_option(*m_next_positional, a);
  1037 +
  1038 + auto iter = m_options.find(*m_next_positional);
  1039 + if (iter != m_options.end() && !iter->second->value().is_container()) {
  1040 + ++m_next_positional;
  1041 + }
1011 return true; 1042 return true;
1012 } 1043 }
1013 else 1044 else
@@ -1019,7 +1050,14 @@ Options::consume_positional(std::string a) @@ -1019,7 +1050,14 @@ Options::consume_positional(std::string a)
1019 void 1050 void
1020 Options::parse_positional(std::string option) 1051 Options::parse_positional(std::string option)
1021 { 1052 {
1022 - m_positional = std::move(option); 1053 + parse_positional(std::vector<std::string>{option});
  1054 +}
  1055 +
  1056 +void
  1057 +Options::parse_positional(std::vector<std::string> options)
  1058 +{
  1059 + m_positional = std::move(options);
  1060 + m_next_positional = m_positional.begin();
1023 } 1061 }
1024 1062
1025 void 1063 void
src/example.cpp
@@ -38,11 +38,12 @@ int main(int argc, char* argv[]) @@ -38,11 +38,12 @@ int main(int argc, char* argv[])
38 ("a,apple", "an apple", cxxopts::value<bool>(apple)) 38 ("a,apple", "an apple", cxxopts::value<bool>(apple))
39 ("b,bob", "Bob") 39 ("b,bob", "Bob")
40 ("f,file", "File", cxxopts::value<std::vector<std::string>>(), "FILE") 40 ("f,file", "File", cxxopts::value<std::vector<std::string>>(), "FILE")
  41 + ("i,input", "Input", cxxopts::value<std::string>())
41 ("o,output", "Output file", cxxopts::value<std::string>() 42 ("o,output", "Output file", cxxopts::value<std::string>()
42 ->default_value("a.out")->implicit_value("b.def"), "BIN") 43 ->default_value("a.out")->implicit_value("b.def"), "BIN")
43 ("positional", 44 ("positional",
44 "Positional arguments: these are the arguments that are entered " 45 "Positional arguments: these are the arguments that are entered "
45 - "without an option", cxxopts::value<std::string>()) 46 + "without an option", cxxopts::value<std::vector<std::string>>())
46 ("long-description", 47 ("long-description",
47 "thisisareallylongwordthattakesupthewholelineandcannotbebrokenataspace") 48 "thisisareallylongwordthattakesupthewholelineandcannotbebrokenataspace")
48 ("help", "Print help") 49 ("help", "Print help")
@@ -58,7 +59,7 @@ int main(int argc, char* argv[]) @@ -58,7 +59,7 @@ int main(int argc, char* argv[])
58 ("c,compile", "compile") 59 ("c,compile", "compile")
59 ("d,drop", "drop", cxxopts::value<std::vector<std::string>>()); 60 ("d,drop", "drop", cxxopts::value<std::vector<std::string>>());
60 61
61 - options.parse_positional("positional"); 62 + options.parse_positional({"input", "output", "positional"});
62 63
63 options.parse(argc, argv); 64 options.parse(argc, argv);
64 65
@@ -88,9 +89,9 @@ int main(int argc, char* argv[]) @@ -88,9 +89,9 @@ int main(int argc, char* argv[])
88 } 89 }
89 } 90 }
90 91
91 - if (options.count("positional")) 92 + if (options.count("input"))
92 { 93 {
93 - std::cout << "Positional = " << options["positional"].as<std::string>() 94 + std::cout << "Input = " << options["input"].as<std::string>()
94 << std::endl; 95 << std::endl;
95 } 96 }
96 97
@@ -100,6 +101,16 @@ int main(int argc, char* argv[]) @@ -100,6 +101,16 @@ int main(int argc, char* argv[])
100 << std::endl; 101 << std::endl;
101 } 102 }
102 103
  104 + if (options.count("positional"))
  105 + {
  106 + std::cout << "Positional = {";
  107 + auto& v = options["positional"].as<std::vector<std::string>>();
  108 + for (const auto& s : v) {
  109 + std::cout << s << ", ";
  110 + }
  111 + std::cout << "}" << std::endl;
  112 + }
  113 +
103 if (options.count("int")) 114 if (options.count("int"))
104 { 115 {
105 std::cout << "int = " << options["int"].as<int>() << std::endl; 116 std::cout << "int = " << options["int"].as<int>() << std::endl;