Commit 048f968504e3157ab2348f111221271a9dd86992

Authored by Rafi Wiener
Committed by Henry Schreiner
1 parent 598046c3

Add support for delimiter when parsing vector (#209)

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
include/CLI/App.hpp
@@ -417,14 +417,19 @@ class App { @@ -417,14 +417,19 @@ class App {
417 template <typename T> 417 template <typename T>
418 Option *add_option(std::string option_name, 418 Option *add_option(std::string option_name,
419 std::vector<T> &variable, ///< The variable vector to set 419 std::vector<T> &variable, ///< The variable vector to set
420 - std::string description = "") { 420 + std::string description = "",
  421 + char delimiter = ' ') {
421 422
422 - CLI::callback_t fun = [&variable](CLI::results_t res) { 423 + CLI::callback_t fun = [&variable, delimiter](CLI::results_t res) {
423 bool retval = true; 424 bool retval = true;
424 variable.clear(); 425 variable.clear();
425 - for(const auto &a : res) {  
426 - variable.emplace_back();  
427 - retval &= detail::lexical_cast(a, variable.back()); 426 + for(const auto &elem : res) {
  427 + for(const auto &var : CLI::detail::split(elem, delimiter)) {
  428 + if(!var.empty()) {
  429 + variable.emplace_back();
  430 + retval &= detail::lexical_cast(var, variable.back());
  431 + }
  432 + }
428 } 433 }
429 return (!variable.empty()) && retval; 434 return (!variable.empty()) && retval;
430 }; 435 };
@@ -439,14 +444,19 @@ class App { @@ -439,14 +444,19 @@ class App {
439 Option *add_option(std::string option_name, 444 Option *add_option(std::string option_name,
440 std::vector<T> &variable, ///< The variable vector to set 445 std::vector<T> &variable, ///< The variable vector to set
441 std::string description, 446 std::string description,
442 - bool defaulted) { 447 + bool defaulted,
  448 + char delimiter = ' ') {
443 449
444 - CLI::callback_t fun = [&variable](CLI::results_t res) { 450 + CLI::callback_t fun = [&variable, delimiter](CLI::results_t res) {
445 bool retval = true; 451 bool retval = true;
446 variable.clear(); 452 variable.clear();
447 for(const auto &a : res) { 453 for(const auto &a : res) {
448 - variable.emplace_back();  
449 - retval &= detail::lexical_cast(a, variable.back()); 454 + for(const auto &var : CLI::detail::split(a, delimiter)) {
  455 + if(!var.empty()) {
  456 + variable.emplace_back();
  457 + retval &= detail::lexical_cast(var, variable.back());
  458 + }
  459 + }
450 } 460 }
451 return (!variable.empty()) && retval; 461 return (!variable.empty()) && retval;
452 }; 462 };
scripts/check_style_docker.sh 0 → 100755
  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
@@ -1961,3 +1961,94 @@ TEST_F(TApp, BeforeRequirements) { @@ -1961,3 +1961,94 @@ TEST_F(TApp, BeforeRequirements) {
1961 // args = {"-b", "-a", "extra"}; 1961 // args = {"-b", "-a", "extra"};
1962 // EXPECT_THROW(run(), CLI::CallForHelp); 1962 // EXPECT_THROW(run(), CLI::CallForHelp);
1963 } 1963 }
  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 +}