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
of this software and associated documentation files (the "Software"), to deal
@ -243,6 +243,9 @@ namespace cxxopts
virtual bool
has_default() const = 0;
virtual bool
is_container() const = 0;
virtual bool
has_implicit() const = 0;
@ -435,6 +438,18 @@ namespace cxxopts
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>
class standard_value : public Value
{
@ -463,6 +478,12 @@ namespace cxxopts
}
}
bool
is_container() const
{
return type_is_container<T>::value;
}
void
parse() const
{
@ -699,6 +720,10 @@ namespace cxxopts
void
parse_positional(std::string option);
inline
void
parse_positional(std::vector<std::string> options);
inline
std::string
help(const std::vector<std::string>& groups = {""}) const;
@ -757,7 +782,8 @@ namespace cxxopts
String m_help_string;
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
std::map<std::string, HelpGroupDetails> m_help;
@ -1005,9 +1031,14 @@ Options::add_to_option(const std::string& option, const std::string& arg)
bool
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;
}
else
@ -1019,7 +1050,14 @@ Options::consume_positional(std::string a)
void
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

View File

@ -38,11 +38,12 @@ int main(int argc, char* argv[])
("a,apple", "an apple", cxxopts::value<bool>(apple))
("b,bob", "Bob")
("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>()
->default_value("a.out")->implicit_value("b.def"), "BIN")
("positional",
"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",
"thisisareallylongwordthattakesupthewholelineandcannotbebrokenataspace")
("help", "Print help")
@ -58,7 +59,7 @@ int main(int argc, char* argv[])
("c,compile", "compile")
("d,drop", "drop", cxxopts::value<std::vector<std::string>>());
options.parse_positional("positional");
options.parse_positional({"input", "output", "positional"});
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;
}
@ -100,6 +101,16 @@ int main(int argc, char* argv[])
<< 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"))
{
std::cout << "int = " << options["int"].as<int>() << std::endl;