Skip to content

Commit

Permalink
Add support for delimiter when parsing vector (#209)
Browse files Browse the repository at this point in the history
This commit allows parsing any char separated list given by the user.
E.g app -a 1,2,3
std::vector<int> params;
app.add_option("-a", params, "Parse the params", ',');

Signed-off-by: Rafi Wiener <rafiw@mellanox.com>

add tests for delimiter parsing

Signed-off-by: Rafi Wiener <rafiw@mellanox.com>

Fixing style, adding docker version of clang-format
  • Loading branch information
rafiw authored and henryiii committed Feb 6, 2019
1 parent 598046c commit 048f968
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 9 deletions.
28 changes: 19 additions & 9 deletions include/CLI/App.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -417,14 +417,19 @@ class App {
template <typename T>
Option *add_option(std::string option_name,
std::vector<T> &variable, ///< The variable vector to set
std::string description = "") {
std::string description = "",
char delimiter = ' ') {

CLI::callback_t fun = [&variable](CLI::results_t res) {
CLI::callback_t fun = [&variable, delimiter](CLI::results_t res) {
bool retval = true;
variable.clear();
for(const auto &a : res) {
variable.emplace_back();
retval &= detail::lexical_cast(a, variable.back());
for(const auto &elem : res) {
for(const auto &var : CLI::detail::split(elem, delimiter)) {
if(!var.empty()) {
variable.emplace_back();
retval &= detail::lexical_cast(var, variable.back());
}
}
}
return (!variable.empty()) && retval;
};
Expand All @@ -439,14 +444,19 @@ class App {
Option *add_option(std::string option_name,
std::vector<T> &variable, ///< The variable vector to set
std::string description,
bool defaulted) {
bool defaulted,
char delimiter = ' ') {

CLI::callback_t fun = [&variable](CLI::results_t res) {
CLI::callback_t fun = [&variable, delimiter](CLI::results_t res) {
bool retval = true;
variable.clear();
for(const auto &a : res) {
variable.emplace_back();
retval &= detail::lexical_cast(a, variable.back());
for(const auto &var : CLI::detail::split(a, delimiter)) {
if(!var.empty()) {
variable.emplace_back();
retval &= detail::lexical_cast(var, variable.back());
}
}
}
return (!variable.empty()) && retval;
};
Expand Down
13 changes: 13 additions & 0 deletions scripts/check_style_docker.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env sh

# Also good but untagged: CLANG_FORMAT=unibeautify/clang-format
CLANG_FORMAT=saschpe/clang-format:5.0.1

set -evx

docker run -it ${CLANG_FORMAT} --version
docker run -it -v "$(pwd)":/workdir -w /workdir ${CLANG_FORMAT} -style=file -sort-includes -i $(git ls-files -- '*.cpp' '*.hpp')

git diff --exit-code --color

set +evx
91 changes: 91 additions & 0 deletions tests/AppTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1961,3 +1961,94 @@ TEST_F(TApp, BeforeRequirements) {
// args = {"-b", "-a", "extra"};
// EXPECT_THROW(run(), CLI::CallForHelp);
}

// #209
TEST_F(TApp, CustomUserSepParse) {

std::vector<int> vals = {1, 2, 3};
args = {"--idx", "1,2,3"};
auto opt = app.add_option("--idx", vals, "", ',');
run();
EXPECT_EQ(vals, std::vector<int>({1, 2, 3}));

app.remove_option(opt);

app.add_option("--idx", vals, "", true, ',');
run();
EXPECT_EQ(vals, std::vector<int>({1, 2, 3}));
}

// #209
TEST_F(TApp, DefaultUserSepParse) {

std::vector<int> vals = {1, 2, 3};
args = {"--idx", "1 2 3"};
auto opt = app.add_option("--idx", vals, "");
run();
EXPECT_EQ(vals, std::vector<int>({1, 2, 3}));
app.remove_option(opt);
app.add_option("--idx", vals, "", true);
run();
EXPECT_EQ(vals, std::vector<int>({1, 2, 3}));
}

// #209
TEST_F(TApp, BadUserSepParse) {

std::vector<int> vals;
app.add_option("--idx", vals, "");

args = {"--idx", "1,2,3"};

EXPECT_THROW(run(), CLI::ConversionError);
}

// #209
TEST_F(TApp, CustomUserSepParse2) {

std::vector<int> vals = {1, 2, 3};
args = {"--idx", "1,2,"};
auto opt = app.add_option("--idx", vals, "", ',');
run();
EXPECT_EQ(vals, std::vector<int>({1, 2}));

app.remove_option(opt);

app.add_option("--idx", vals, "", true, ',');
run();
EXPECT_EQ(vals, std::vector<int>({1, 2}));
}

// #209
TEST_F(TApp, CustomUserSepParse3) {

std::vector<int> vals = {1, 2, 3};
args = {"--idx",
"1",
","
"2"};
auto opt = app.add_option("--idx", vals, "", ',');
run();
EXPECT_EQ(vals, std::vector<int>({1, 2}));
app.remove_option(opt);

app.add_option("--idx", vals, "", false, ',');
run();
EXPECT_EQ(vals, std::vector<int>({1, 2}));
}

// #209
TEST_F(TApp, CustomUserSepParse4) {

std::vector<int> vals;
args = {"--idx", "1, 2"};
auto opt = app.add_option("--idx", vals, "", ',');
run();
EXPECT_EQ(vals, std::vector<int>({1, 2}));

app.remove_option(opt);

app.add_option("--idx", vals, "", true, ',');
run();
EXPECT_EQ(vals, std::vector<int>({1, 2}));
}

0 comments on commit 048f968

Please sign in to comment.