Skip to content

Commit

Permalink
Don't split by list delimiter in positional lists (#398)
Browse files Browse the repository at this point in the history
  • Loading branch information
agalanin authored Jun 14, 2023
1 parent bf1b5a9 commit ddc695e
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 5 deletions.
52 changes: 47 additions & 5 deletions include/cxxopts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,9 @@ class Value : public std::enable_shared_from_this<Value>
std::shared_ptr<Value>
clone() const = 0;

virtual void
add(const std::string& text) const = 0;

virtual void
parse(const std::string& text) const = 0;

Expand Down Expand Up @@ -1064,6 +1067,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
template <typename T>
void
Expand Down Expand Up @@ -1137,6 +1156,12 @@ class abstract_value : public Value
m_implicit_value = rhs.m_implicit_value;
}

void
add(const std::string& text) const override
{
add_value(text, *m_store);
}

void
parse(const std::string& text) const override
{
Expand Down Expand Up @@ -1422,6 +1447,19 @@ struct HelpGroupDetails
class OptionValue
{
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
parse
(
Expand Down Expand Up @@ -1792,7 +1830,7 @@ class OptionParser
);

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
parse_option
Expand Down Expand Up @@ -2339,9 +2377,13 @@ OptionParser::checked_parse_arg

inline
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
Expand All @@ -2358,14 +2400,14 @@ OptionParser::consume_positional(const std::string& a, PositionalListIterator& n
auto& result = m_parsed[iter->second->hash()];
if (result.count() == 0)
{
add_to_option(iter, *next, a);
add_to_option(iter->second, a);
++next;
return true;
}
++next;
continue;
}
add_to_option(iter, *next, a);
add_to_option(iter->second, a);
return true;
}
throw_or_mimic<exceptions::no_such_option>(*next);
Expand Down
31 changes: 31 additions & 0 deletions test/options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,37 @@ TEST_CASE("Positional with empty arguments", "[positional]") {
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]")
{
cxxopts::Options options("empty_implicit", "doesn't handle empty");
Expand Down

0 comments on commit ddc695e

Please sign in to comment.