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 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy |
| 6 | 6 | of this software and associated documentation files (the "Software"), to deal |
| ... | ... | @@ -244,6 +244,9 @@ namespace cxxopts |
| 244 | 244 | has_default() const = 0; |
| 245 | 245 | |
| 246 | 246 | virtual bool |
| 247 | + is_container() const = 0; | |
| 248 | + | |
| 249 | + virtual bool | |
| 247 | 250 | has_implicit() const = 0; |
| 248 | 251 | |
| 249 | 252 | virtual std::string |
| ... | ... | @@ -436,6 +439,18 @@ namespace cxxopts |
| 436 | 439 | }; |
| 437 | 440 | |
| 438 | 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 | 454 | class standard_value : public Value |
| 440 | 455 | { |
| 441 | 456 | public: |
| ... | ... | @@ -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 | 487 | void |
| 467 | 488 | parse() const |
| 468 | 489 | { |
| ... | ... | @@ -700,6 +721,10 @@ namespace cxxopts |
| 700 | 721 | parse_positional(std::string option); |
| 701 | 722 | |
| 702 | 723 | inline |
| 724 | + void | |
| 725 | + parse_positional(std::vector<std::string> options); | |
| 726 | + | |
| 727 | + inline | |
| 703 | 728 | std::string |
| 704 | 729 | help(const std::vector<std::string>& groups = {""}) const; |
| 705 | 730 | |
| ... | ... | @@ -757,7 +782,8 @@ namespace cxxopts |
| 757 | 782 | String m_help_string; |
| 758 | 783 | |
| 759 | 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 | 788 | //mapping from groups to help options |
| 763 | 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 | 1031 | bool |
| 1006 | 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 | 1042 | return true; |
| 1012 | 1043 | } |
| 1013 | 1044 | else |
| ... | ... | @@ -1019,7 +1050,14 @@ Options::consume_positional(std::string a) |
| 1019 | 1050 | void |
| 1020 | 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 | 1063 | void | ... | ... |
src/example.cpp
| ... | ... | @@ -38,11 +38,12 @@ int main(int argc, char* argv[]) |
| 38 | 38 | ("a,apple", "an apple", cxxopts::value<bool>(apple)) |
| 39 | 39 | ("b,bob", "Bob") |
| 40 | 40 | ("f,file", "File", cxxopts::value<std::vector<std::string>>(), "FILE") |
| 41 | + ("i,input", "Input", cxxopts::value<std::string>()) | |
| 41 | 42 | ("o,output", "Output file", cxxopts::value<std::string>() |
| 42 | 43 | ->default_value("a.out")->implicit_value("b.def"), "BIN") |
| 43 | 44 | ("positional", |
| 44 | 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 | 47 | ("long-description", |
| 47 | 48 | "thisisareallylongwordthattakesupthewholelineandcannotbebrokenataspace") |
| 48 | 49 | ("help", "Print help") |
| ... | ... | @@ -58,7 +59,7 @@ int main(int argc, char* argv[]) |
| 58 | 59 | ("c,compile", "compile") |
| 59 | 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 | 64 | options.parse(argc, argv); |
| 64 | 65 | |
| ... | ... | @@ -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 | 95 | << std::endl; |
| 95 | 96 | } |
| 96 | 97 | |
| ... | ... | @@ -100,6 +101,16 @@ int main(int argc, char* argv[]) |
| 100 | 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 | 114 | if (options.count("int")) |
| 104 | 115 | { |
| 105 | 116 | std::cout << "int = " << options["int"].as<int>() << std::endl; | ... | ... |