Don't split by list delimiter in positional lists
This commit is contained in:
parent
a526762eb8
commit
8774fded36
@ -360,6 +360,9 @@ class Value : public std::enable_shared_from_this<Value>
|
|||||||
std::shared_ptr<Value>
|
std::shared_ptr<Value>
|
||||||
clone() const = 0;
|
clone() const = 0;
|
||||||
|
|
||||||
|
virtual void
|
||||||
|
add(const std::string& text) const = 0;
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
parse(const std::string& text) const = 0;
|
parse(const std::string& text) const = 0;
|
||||||
|
|
||||||
@ -1056,6 +1059,22 @@ parse_value(const std::string& text, std::vector<T>& value)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void
|
||||||
|
add_value(const std::string& text, T& value)
|
||||||
|
{
|
||||||
|
parse_value(text, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void
|
||||||
|
add_value(const std::string& text, std::vector<T>& value)
|
||||||
|
{
|
||||||
|
T v;
|
||||||
|
add_value(text, v);
|
||||||
|
value.emplace_back(std::move(v));
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CXXOPTS_HAS_OPTIONAL
|
#ifdef CXXOPTS_HAS_OPTIONAL
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void
|
void
|
||||||
@ -1129,6 +1148,12 @@ class abstract_value : public Value
|
|||||||
m_implicit_value = rhs.m_implicit_value;
|
m_implicit_value = rhs.m_implicit_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
add(const std::string& text) const override
|
||||||
|
{
|
||||||
|
add_value(text, *m_store);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
parse(const std::string& text) const override
|
parse(const std::string& text) const override
|
||||||
{
|
{
|
||||||
@ -1414,6 +1439,19 @@ struct HelpGroupDetails
|
|||||||
class OptionValue
|
class OptionValue
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
void
|
||||||
|
add
|
||||||
|
(
|
||||||
|
const std::shared_ptr<const OptionDetails>& details,
|
||||||
|
const std::string& text
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ensure_value(details);
|
||||||
|
++m_count;
|
||||||
|
m_value->add(text);
|
||||||
|
m_long_names = &details->long_names();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
parse
|
parse
|
||||||
(
|
(
|
||||||
@ -1784,7 +1822,7 @@ class OptionParser
|
|||||||
);
|
);
|
||||||
|
|
||||||
void
|
void
|
||||||
add_to_option(OptionMap::const_iterator iter, const std::string& option, const std::string& arg);
|
add_to_option(const std::shared_ptr<OptionDetails>& value, const std::string& arg);
|
||||||
|
|
||||||
void
|
void
|
||||||
parse_option
|
parse_option
|
||||||
@ -2330,9 +2368,13 @@ OptionParser::checked_parse_arg
|
|||||||
|
|
||||||
inline
|
inline
|
||||||
void
|
void
|
||||||
OptionParser::add_to_option(OptionMap::const_iterator iter, const std::string& option, const std::string& arg)
|
OptionParser::add_to_option(const std::shared_ptr<OptionDetails>& value, const std::string& arg)
|
||||||
{
|
{
|
||||||
parse_option(iter->second, option, arg);
|
auto hash = value->hash();
|
||||||
|
auto& result = m_parsed[hash];
|
||||||
|
result.add(value, arg);
|
||||||
|
|
||||||
|
m_sequential.emplace_back(value->essential_name(), arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
@ -2349,14 +2391,14 @@ OptionParser::consume_positional(const std::string& a, PositionalListIterator& n
|
|||||||
auto& result = m_parsed[iter->second->hash()];
|
auto& result = m_parsed[iter->second->hash()];
|
||||||
if (result.count() == 0)
|
if (result.count() == 0)
|
||||||
{
|
{
|
||||||
add_to_option(iter, *next, a);
|
add_to_option(iter->second, a);
|
||||||
++next;
|
++next;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
++next;
|
++next;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
add_to_option(iter, *next, a);
|
add_to_option(iter->second, a);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
throw_or_mimic<exceptions::no_such_option>(*next);
|
throw_or_mimic<exceptions::no_such_option>(*next);
|
||||||
|
|||||||
@ -288,6 +288,37 @@ TEST_CASE("Positional with empty arguments", "[positional]") {
|
|||||||
REQUIRE(actual == expected);
|
REQUIRE(actual == expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Positional with list delimiter", "[positional]") {
|
||||||
|
std::string single;
|
||||||
|
std::vector<std::string> positional;
|
||||||
|
|
||||||
|
cxxopts::Options options("test_all_positional_list_delimiter", " - test all positional with list delimiters");
|
||||||
|
options.add_options()
|
||||||
|
("single", "Single positional param",
|
||||||
|
cxxopts::value<std::string>(single))
|
||||||
|
("positional", "Positional parameters vector",
|
||||||
|
cxxopts::value<std::vector<std::string>>(positional))
|
||||||
|
;
|
||||||
|
|
||||||
|
Argv av({"tester", "a,b", "c,d", "e"});
|
||||||
|
|
||||||
|
auto argc = av.argc();
|
||||||
|
auto argv = av.argv();
|
||||||
|
|
||||||
|
std::vector<std::string> pos_names = {"single", "positional"};
|
||||||
|
|
||||||
|
options.parse_positional(pos_names.begin(), pos_names.end());
|
||||||
|
|
||||||
|
auto result = options.parse(argc, argv);
|
||||||
|
|
||||||
|
CHECK(result.unmatched().size() == 0);
|
||||||
|
REQUIRE(positional.size() == 2);
|
||||||
|
|
||||||
|
CHECK(single == "a,b");
|
||||||
|
CHECK(positional[0] == "c,d");
|
||||||
|
CHECK(positional[1] == "e");
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("Empty with implicit value", "[implicit]")
|
TEST_CASE("Empty with implicit value", "[implicit]")
|
||||||
{
|
{
|
||||||
cxxopts::Options options("empty_implicit", "doesn't handle empty");
|
cxxopts::Options options("empty_implicit", "doesn't handle empty");
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user