Commit b2e7efe7f4c2e738a42b0bceea2761ce32d6cc21
1 parent
8844335d
positional arguments parse into multiple options
Showing
2 changed files
with
58 additions
and
9 deletions
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& option, const std::string& arg) | @@ -1005,9 +1031,14 @@ Options::add_to_option(const std::string& option, const std::string& 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; |