Skip to content

Commit 72fc403

Browse files
authored
Merge pull request #160 from kkarbowiak/parsing-negative-numbers
Enable parsing negative numbers as values for optional arguments
2 parents cba3968 + 6275549 commit 72fc403

2 files changed

Lines changed: 119 additions & 33 deletions

File tree

include/argparse.hpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1406,7 +1406,21 @@ namespace argparse
14061406
auto get_consumable_args(auto it, std::ranges::view auto consumable) const
14071407
{
14081408
return std::ranges::subrange(std::ranges::next(it), consumable.end())
1409-
| std::views::take_while([](auto const & token) { return !token.m_token.starts_with("-"); });
1409+
| std::views::take_while([](auto const & token)
1410+
{
1411+
if (!token.m_token.starts_with("-"))
1412+
{
1413+
return true;
1414+
}
1415+
auto iss = std::istringstream(token.m_token);
1416+
auto num = double();
1417+
iss >> num;
1418+
if (!iss.fail() && (iss.eof() || iss.peek() == std::istringstream::traits_type::eof()))
1419+
{
1420+
return true;
1421+
}
1422+
return false;
1423+
});
14101424
}
14111425

14121426
private:

test/unittest/test_parsing_optional.cpp

Lines changed: 104 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2809,82 +2809,154 @@ TEST_CASE("Parsing joined flags does not affect long options")
28092809
CHECK(args.get_value<bool>("r") == true);
28102810
}
28112811

2812-
TEST_CASE("Parsing an optional argument yields correct value for positive number")
2812+
TEST_CASE_TEMPLATE("Parsing an optional argument yields correct value for positive number", T, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double)
28132813
{
28142814
auto parser = argparse::ArgumentParser();
2815-
parser.add_argument("-n").type<int>();
2815+
parser.add_argument("-n").type<T>();
28162816

2817-
auto const args = parser.parse_args(3, cstr_arr{"prog", "-n", "65"});
2817+
if constexpr (std::is_integral_v<T>)
2818+
{
2819+
auto const args = parser.parse_args(3, cstr_arr{"prog", "-n", "65"});
28182820

2819-
CHECK(args.get_value<int>("n") == 65);
2821+
CHECK(args.get_value<T>("n") == T(65));
2822+
}
2823+
else
2824+
{
2825+
auto const args = parser.parse_args(3, cstr_arr{"prog", "-n", "1.125"});
2826+
2827+
CHECK(args.get_value<T>("n") == T(1.125));
2828+
}
28202829
}
28212830

2822-
TEST_CASE("Parsing an optional argument yields correct value for positive number")
2831+
TEST_CASE_TEMPLATE("Parsing an optional argument yields correct value for positive number", T, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double)
28232832
{
28242833
auto parser = argparse::ArgumentParser();
2825-
parser.add_argument("-n").type<int>();
2834+
parser.add_argument("-n").type<T>();
28262835

2827-
auto const args = parser.parse_args(2, cstr_arr{"prog", "-n65"});
2836+
if constexpr (std::is_integral_v<T>)
2837+
{
2838+
auto const args = parser.parse_args(2, cstr_arr{"prog", "-n65"});
28282839

2829-
CHECK(args.get_value<int>("n") == 65);
2840+
CHECK(args.get_value<T>("n") == T(65));
2841+
}
2842+
else
2843+
{
2844+
auto const args = parser.parse_args(2, cstr_arr{"prog", "-n1.125"});
2845+
2846+
CHECK(args.get_value<T>("n") == T(1.125));
2847+
}
28302848
}
28312849

2832-
TEST_CASE("Parsing an optional argument yields correct value for positive number")
2850+
TEST_CASE_TEMPLATE("Parsing an optional argument yields correct value for positive number", T, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double)
28332851
{
28342852
auto parser = argparse::ArgumentParser();
2835-
parser.add_argument("--number").type<int>();
2853+
parser.add_argument("--number").type<T>();
28362854

2837-
auto const args = parser.parse_args(3, cstr_arr{"prog", "--number", "65"});
2855+
if constexpr (std::is_integral_v<T>)
2856+
{
2857+
auto const args = parser.parse_args(3, cstr_arr{"prog", "--number", "65"});
28382858

2839-
CHECK(args.get_value<int>("number") == 65);
2859+
CHECK(args.get_value<T>("number") == T(65));
2860+
}
2861+
else
2862+
{
2863+
auto const args = parser.parse_args(3, cstr_arr{"prog", "--number", "1.125"});
2864+
2865+
CHECK(args.get_value<T>("number") == T(1.125));
2866+
}
28402867
}
28412868

2842-
TEST_CASE("Parsing an optional argument yields correct value for positive number")
2869+
TEST_CASE_TEMPLATE("Parsing an optional argument yields correct value for positive number", T, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double)
28432870
{
28442871
auto parser = argparse::ArgumentParser();
2845-
parser.add_argument("--number").type<int>();
2872+
parser.add_argument("--number").type<T>();
28462873

2847-
auto const args = parser.parse_args(2, cstr_arr{"prog", "--number=65"});
2874+
if constexpr (std::is_integral_v<T>)
2875+
{
2876+
auto const args = parser.parse_args(2, cstr_arr{"prog", "--number=65"});
28482877

2849-
CHECK(args.get_value<int>("number") == 65);
2878+
CHECK(args.get_value<T>("number") == T(65));
2879+
}
2880+
else
2881+
{
2882+
auto const args = parser.parse_args(2, cstr_arr{"prog", "--number=1.125"});
2883+
2884+
CHECK(args.get_value<T>("number") == T(1.125));
2885+
}
28502886
}
28512887

2852-
TEST_CASE("Parsing an optional argument yields correct value for negative number" * doctest::skip())
2888+
TEST_CASE_TEMPLATE("Parsing an optional argument yields correct value for negative number", T, short int, int, long int, long long int, float, double, long double)
28532889
{
28542890
auto parser = argparse::ArgumentParser();
2855-
parser.add_argument("-n").type<int>();
2891+
parser.add_argument("-n").type<T>();
28562892

2857-
auto const args = parser.parse_args(3, cstr_arr{"prog", "-n", "-65"});
2893+
if constexpr (std::is_integral_v<T>)
2894+
{
2895+
auto const args = parser.parse_args(3, cstr_arr{"prog", "-n", "-65"});
28582896

2859-
CHECK(args.get_value<int>("n") == -65);
2897+
CHECK(args.get_value<T>("n") == T(-65));
2898+
}
2899+
else
2900+
{
2901+
auto const args = parser.parse_args(3, cstr_arr{"prog", "-n", "-1.125"});
2902+
2903+
CHECK(args.get_value<T>("n") == T(-1.125));
2904+
}
28602905
}
28612906

2862-
TEST_CASE("Parsing an optional argument yields correct value for negative number")
2907+
TEST_CASE_TEMPLATE("Parsing an optional argument yields correct value for negative number", T, short int, int, long int, long long int, float, double, long double)
28632908
{
28642909
auto parser = argparse::ArgumentParser();
2865-
parser.add_argument("-n").type<int>();
2910+
parser.add_argument("-n").type<T>();
28662911

2867-
auto const args = parser.parse_args(2, cstr_arr{"prog", "-n-65"});
2912+
if constexpr (std::is_integral_v<T>)
2913+
{
2914+
auto const args = parser.parse_args(2, cstr_arr{"prog", "-n-65"});
28682915

2869-
CHECK(args.get_value<int>("n") == -65);
2916+
CHECK(args.get_value<T>("n") == T(-65));
2917+
}
2918+
else
2919+
{
2920+
auto const args = parser.parse_args(2, cstr_arr{"prog", "-n-1.125"});
2921+
2922+
CHECK(args.get_value<T>("n") == T(-1.125));
2923+
}
28702924
}
28712925

2872-
TEST_CASE("Parsing an optional argument yields correct value for negative number" * doctest::skip())
2926+
TEST_CASE_TEMPLATE("Parsing an optional argument yields correct value for negative number", T, short int, int, long int, long long int, float, double, long double)
28732927
{
28742928
auto parser = argparse::ArgumentParser();
2875-
parser.add_argument("--number").type<int>();
2929+
parser.add_argument("--number").type<T>();
28762930

2877-
auto const args = parser.parse_args(3, cstr_arr{"prog", "--number", "-65"});
2931+
if constexpr (std::is_integral_v<T>)
2932+
{
2933+
auto const args = parser.parse_args(3, cstr_arr{"prog", "--number", "-65"});
28782934

2879-
CHECK(args.get_value<int>("number") == -65);
2935+
CHECK(args.get_value<T>("number") == T(-65));
2936+
}
2937+
else
2938+
{
2939+
auto const args = parser.parse_args(3, cstr_arr{"prog", "--number", "-1.125"});
2940+
2941+
CHECK(args.get_value<T>("number") == T(-1.125));
2942+
}
28802943
}
28812944

2882-
TEST_CASE("Parsing an optional argument yields correct value for negative number")
2945+
TEST_CASE_TEMPLATE("Parsing an optional argument yields correct value for negative number", T, short int, int, long int, long long int, float, double, long double)
28832946
{
28842947
auto parser = argparse::ArgumentParser();
2885-
parser.add_argument("--number").type<int>();
2948+
parser.add_argument("--number").type<T>();
28862949

2887-
auto const args = parser.parse_args(2, cstr_arr{"prog", "--number=-65"});
2950+
if constexpr (std::is_integral_v<T>)
2951+
{
2952+
auto const args = parser.parse_args(2, cstr_arr{"prog", "--number=-65"});
28882953

2889-
CHECK(args.get_value<int>("number") == -65);
2954+
CHECK(args.get_value<T>("number") == T(-65));
2955+
}
2956+
else
2957+
{
2958+
auto const args = parser.parse_args(2, cstr_arr{"prog", "--number=-1.125"});
2959+
2960+
CHECK(args.get_value<T>("number") == T(-1.125));
2961+
}
28902962
}

0 commit comments

Comments
 (0)