positional arguments parse into multiple options

This commit is contained in:
Jarryd Beck 2015-09-25 16:49:06 +10:00
parent 8844335d40
commit b2e7efe7f4
2 changed files with 58 additions and 9 deletions

View File

@ -1,6 +1,6 @@
/* /*
Copyright (c) 2014 Jarryd Beck Copyright (c) 2014, 2015 Jarryd Beck
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@ -243,6 +243,9 @@ namespace cxxopts
virtual bool virtual bool
has_default() const = 0; has_default() const = 0;
virtual bool
is_container() const = 0;
virtual bool virtual bool
has_implicit() const = 0; has_implicit() const = 0;
@ -435,6 +438,18 @@ namespace cxxopts
static constexpr bool value = false; static constexpr bool value = false;
}; };
template <typename T>
struct type_is_container
{
static constexpr bool value = false;
};
template <typename T>
struct type_is_container<std::vector<T>>
{
static constexpr bool value = true;
};
template <typename T> template <typename T>
class standard_value : public Value class standard_value : public Value
{ {
@ -463,6 +478,12 @@ namespace cxxopts
} }
} }
bool
is_container() const
{
return type_is_container<T>::value;
}
void void
parse() const parse() const
{ {
@ -699,6 +720,10 @@ namespace cxxopts
void void
parse_positional(std::string option); parse_positional(std::string option);
inline
void
parse_positional(std::vector<std::string> options);
inline inline
std::string std::string
help(const std::vector<std::string>& groups = {""}) const; help(const std::vector<std::string>& groups = {""}) const;
@ -757,7 +782,8 @@ namespace cxxopts
String m_help_string; String m_help_string;
std::map<std::string, std::shared_ptr<OptionDetails>> m_options; std::map<std::string, std::shared_ptr<OptionDetails>> m_options;
std::string m_positional; std::vector<std::string> m_positional;
std::vector<std::string>::iterator m_next_positional;
//mapping from groups to help options //mapping from groups to help options
std::map<std::string, HelpGroupDetails> m_help; std::map<std::string, HelpGroupDetails> m_help;
@ -1005,9 +1031,14 @@ Options::add_to_option(const std::string& option, const std::string& arg)
bool bool
Options::consume_positional(std::string a) Options::consume_positional(std::string a)
{ {
if (m_positional.size() > 0) if (m_next_positional != m_positional.end())
{ {
add_to_option(m_positional, a); add_to_option(*m_next_positional, a);
auto iter = m_options.find(*m_next_positional);
if (iter != m_options.end() && !iter->second->value().is_container()) {
++m_next_positional;
}
return true; return true;
} }
else else
@ -1019,7 +1050,14 @@ Options::consume_positional(std::string a)
void void
Options::parse_positional(std::string option) Options::parse_positional(std::string option)
{ {
m_positional = std::move(option); parse_positional(std::vector<std::string>{option});
}
void
Options::parse_positional(std::vector<std::string> options)
{
m_positional = std::move(options);
m_next_positional = m_positional.begin();
} }
void void

View File

@ -38,11 +38,12 @@ int main(int argc, char* argv[])
("a,apple", "an apple", cxxopts::value<bool>(apple)) ("a,apple", "an apple", cxxopts::value<bool>(apple))
("b,bob", "Bob") ("b,bob", "Bob")
("f,file", "File", cxxopts::value<std::vector<std::string>>(), "FILE") ("f,file", "File", cxxopts::value<std::vector<std::string>>(), "FILE")
("i,input", "Input", cxxopts::value<std::string>())
("o,output", "Output file", cxxopts::value<std::string>() ("o,output", "Output file", cxxopts::value<std::string>()
->default_value("a.out")->implicit_value("b.def"), "BIN") ->default_value("a.out")->implicit_value("b.def"), "BIN")
("positional", ("positional",
"Positional arguments: these are the arguments that are entered " "Positional arguments: these are the arguments that are entered "
"without an option", cxxopts::value<std::string>()) "without an option", cxxopts::value<std::vector<std::string>>())
("long-description", ("long-description",
"thisisareallylongwordthattakesupthewholelineandcannotbebrokenataspace") "thisisareallylongwordthattakesupthewholelineandcannotbebrokenataspace")
("help", "Print help") ("help", "Print help")
@ -58,7 +59,7 @@ int main(int argc, char* argv[])
("c,compile", "compile") ("c,compile", "compile")
("d,drop", "drop", cxxopts::value<std::vector<std::string>>()); ("d,drop", "drop", cxxopts::value<std::vector<std::string>>());
options.parse_positional("positional"); options.parse_positional({"input", "output", "positional"});
options.parse(argc, argv); options.parse(argc, argv);
@ -88,9 +89,9 @@ int main(int argc, char* argv[])
} }
} }
if (options.count("positional")) if (options.count("input"))
{ {
std::cout << "Positional = " << options["positional"].as<std::string>() std::cout << "Input = " << options["input"].as<std::string>()
<< std::endl; << std::endl;
} }
@ -100,6 +101,16 @@ int main(int argc, char* argv[])
<< std::endl; << std::endl;
} }
if (options.count("positional"))
{
std::cout << "Positional = {";
auto& v = options["positional"].as<std::vector<std::string>>();
for (const auto& s : v) {
std::cout << s << ", ";
}
std::cout << "}" << std::endl;
}
if (options.count("int")) if (options.count("int"))
{ {
std::cout << "int = " << options["int"].as<int>() << std::endl; std::cout << "int = " << options["int"].as<int>() << std::endl;