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 417 template <typename T>
418 418 Option *add_option(std::string option_name,
419 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 424 bool retval = true;
424 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 434 return (!variable.empty()) && retval;
430 435 };
... ... @@ -439,14 +444,19 @@ class App {
439 444 Option *add_option(std::string option_name,
440 445 std::vector<T> &variable, ///< The variable vector to set
441 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 451 bool retval = true;
446 452 variable.clear();
447 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 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 1961 // args = {"-b", "-a", "extra"};
1962 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 +}
... ...