Skip to content

Commit 434a247

Browse files
committed
Add support for delimiter when parsing vector
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
1 parent b4910df commit 434a247

File tree

3 files changed

+123
-9
lines changed

3 files changed

+123
-9
lines changed

include/CLI/App.hpp

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -413,14 +413,19 @@ class App {
413413
template <typename T>
414414
Option *add_option(std::string option_name,
415415
std::vector<T> &variable, ///< The variable vector to set
416-
std::string description = "") {
416+
std::string description = "",
417+
char delimiter = ' ') {
417418

418-
CLI::callback_t fun = [&variable](CLI::results_t res) {
419+
CLI::callback_t fun = [&variable, delimiter](CLI::results_t res) {
419420
bool retval = true;
420421
variable.clear();
421-
for(const auto &a : res) {
422-
variable.emplace_back();
423-
retval &= detail::lexical_cast(a, variable.back());
422+
for(const auto &elem : res) {
423+
for(const auto &var : CLI::detail::split(elem, delimiter)) {
424+
if(!var.empty()) {
425+
variable.emplace_back();
426+
retval &= detail::lexical_cast(var, variable.back());
427+
}
428+
}
424429
}
425430
return (!variable.empty()) && retval;
426431
};
@@ -435,14 +440,19 @@ class App {
435440
Option *add_option(std::string option_name,
436441
std::vector<T> &variable, ///< The variable vector to set
437442
std::string description,
438-
bool defaulted) {
443+
bool defaulted,
444+
char delimiter = ' ') {
439445

440-
CLI::callback_t fun = [&variable](CLI::results_t res) {
446+
CLI::callback_t fun = [&variable, delimiter](CLI::results_t res) {
441447
bool retval = true;
442448
variable.clear();
443449
for(const auto &a : res) {
444-
variable.emplace_back();
445-
retval &= detail::lexical_cast(a, variable.back());
450+
for(const auto &var : CLI::detail::split(a, delimiter)) {
451+
if(!var.empty()) {
452+
variable.emplace_back();
453+
retval &= detail::lexical_cast(var, variable.back());
454+
}
455+
}
446456
}
447457
return (!variable.empty()) && retval;
448458
};

scripts/check_style_docker.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/usr/bin/env sh
2+
3+
# Also good but untagged: CLANG_FORMAT=unibeautify/clang-format
4+
CLANG_FORMAT=saschpe/clang-format:5.0.1
5+
6+
set -evx
7+
8+
docker run -it ${CLANG_FORMAT} --version
9+
docker run -it -v "$(pwd)":/workdir -w /workdir ${CLANG_FORMAT} -style=file -sort-includes -i $(git ls-files -- '*.cpp' '*.hpp')
10+
11+
git diff --exit-code --color
12+
13+
set +evx

tests/AppTest.cpp

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1961,3 +1961,94 @@ TEST_F(TApp, BeforeRequirements) {
19611961
// args = {"-b", "-a", "extra"};
19621962
// EXPECT_THROW(run(), CLI::CallForHelp);
19631963
}
1964+
1965+
// #209
1966+
TEST_F(TApp, CustomUserSepParse) {
1967+
1968+
std::vector<int> vals = {1, 2, 3};
1969+
args = {"--idx", "1,2,3"};
1970+
auto opt = app.add_option("--idx", vals, "", ',');
1971+
run();
1972+
EXPECT_EQ(vals, std::vector<int>({1, 2, 3}));
1973+
1974+
app.remove_option(opt);
1975+
1976+
app.add_option("--idx", vals, "", true, ',');
1977+
run();
1978+
EXPECT_EQ(vals, std::vector<int>({1, 2, 3}));
1979+
}
1980+
1981+
// #209
1982+
TEST_F(TApp, DefaultUserSepParse) {
1983+
1984+
std::vector<int> vals = {1, 2, 3};
1985+
args = {"--idx", "1 2 3"};
1986+
auto opt = app.add_option("--idx", vals, "");
1987+
run();
1988+
EXPECT_EQ(vals, std::vector<int>({1, 2, 3}));
1989+
app.remove_option(opt);
1990+
app.add_option("--idx", vals, "", true);
1991+
run();
1992+
EXPECT_EQ(vals, std::vector<int>({1, 2, 3}));
1993+
}
1994+
1995+
// #209
1996+
TEST_F(TApp, BadUserSepParse) {
1997+
1998+
std::vector<int> vals;
1999+
app.add_option("--idx", vals, "");
2000+
2001+
args = {"--idx", "1,2,3"};
2002+
2003+
EXPECT_THROW(run(), CLI::ConversionError);
2004+
}
2005+
2006+
// #209
2007+
TEST_F(TApp, CustomUserSepParse2) {
2008+
2009+
std::vector<int> vals = {1, 2, 3};
2010+
args = {"--idx", "1,2,"};
2011+
auto opt = app.add_option("--idx", vals, "", ',');
2012+
run();
2013+
EXPECT_EQ(vals, std::vector<int>({1, 2}));
2014+
2015+
app.remove_option(opt);
2016+
2017+
app.add_option("--idx", vals, "", true, ',');
2018+
run();
2019+
EXPECT_EQ(vals, std::vector<int>({1, 2}));
2020+
}
2021+
2022+
// #209
2023+
TEST_F(TApp, CustomUserSepParse3) {
2024+
2025+
std::vector<int> vals = {1, 2, 3};
2026+
args = {"--idx",
2027+
"1",
2028+
","
2029+
"2"};
2030+
auto opt = app.add_option("--idx", vals, "", ',');
2031+
run();
2032+
EXPECT_EQ(vals, std::vector<int>({1, 2}));
2033+
app.remove_option(opt);
2034+
2035+
app.add_option("--idx", vals, "", false, ',');
2036+
run();
2037+
EXPECT_EQ(vals, std::vector<int>({1, 2}));
2038+
}
2039+
2040+
// #209
2041+
TEST_F(TApp, CustomUserSepParse4) {
2042+
2043+
std::vector<int> vals;
2044+
args = {"--idx", "1, 2"};
2045+
auto opt = app.add_option("--idx", vals, "", ',');
2046+
run();
2047+
EXPECT_EQ(vals, std::vector<int>({1, 2}));
2048+
2049+
app.remove_option(opt);
2050+
2051+
app.add_option("--idx", vals, "", true, ',');
2052+
run();
2053+
EXPECT_EQ(vals, std::vector<int>({1, 2}));
2054+
}

0 commit comments

Comments
 (0)