From 5b106b0c137acab6ca5b2c9c66df3d5ce9244b37 Mon Sep 17 00:00:00 2001 From: Krzysiek Karbowiak Date: Thu, 2 Oct 2025 19:31:29 +0200 Subject: [PATCH 01/11] Enable parsing negative numbers as values for optional arguments --- include/argparse.hpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/include/argparse.hpp b/include/argparse.hpp index 2c2124d..9a3878c 100644 --- a/include/argparse.hpp +++ b/include/argparse.hpp @@ -1406,7 +1406,21 @@ namespace argparse auto get_consumable_args(auto it, std::ranges::view auto consumable) const { return std::ranges::subrange(std::ranges::next(it), consumable.end()) - | std::views::take_while([](auto const & token) { return !token.m_token.starts_with("-"); }); + | std::views::take_while([](auto const & token) + { + if (!token.m_token.starts_with("-")) + { + return true; + } + auto iss = std::istringstream(token.m_token); + auto num = double(); + iss >> num; + if (!iss.fail() && (iss.eof() || iss.peek() == std::istringstream::traits_type::eof())) + { + return true; + } + return false; + }); } private: From fc92734814516507dbc62b08725d3de7c32c9f19 Mon Sep 17 00:00:00 2001 From: Krzysiek Karbowiak Date: Thu, 2 Oct 2025 19:31:36 +0200 Subject: [PATCH 02/11] Unskip unit test --- test/unittest/test_parsing_optional.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unittest/test_parsing_optional.cpp b/test/unittest/test_parsing_optional.cpp index 4b6e0d1..19837db 100644 --- a/test/unittest/test_parsing_optional.cpp +++ b/test/unittest/test_parsing_optional.cpp @@ -2849,7 +2849,7 @@ TEST_CASE("Parsing an optional argument yields correct value for positive number CHECK(args.get_value("number") == 65); } -TEST_CASE("Parsing an optional argument yields correct value for negative number" * doctest::skip()) +TEST_CASE("Parsing an optional argument yields correct value for negative number") { auto parser = argparse::ArgumentParser(); parser.add_argument("-n").type(); From 0b8666b1a4499ac0cf6b67d6eac4c22978b2402a Mon Sep 17 00:00:00 2001 From: Krzysiek Karbowiak Date: Thu, 2 Oct 2025 19:31:41 +0200 Subject: [PATCH 03/11] Unskip unit test --- test/unittest/test_parsing_optional.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unittest/test_parsing_optional.cpp b/test/unittest/test_parsing_optional.cpp index 19837db..a7729cc 100644 --- a/test/unittest/test_parsing_optional.cpp +++ b/test/unittest/test_parsing_optional.cpp @@ -2869,7 +2869,7 @@ TEST_CASE("Parsing an optional argument yields correct value for negative number CHECK(args.get_value("n") == -65); } -TEST_CASE("Parsing an optional argument yields correct value for negative number" * doctest::skip()) +TEST_CASE("Parsing an optional argument yields correct value for negative number") { auto parser = argparse::ArgumentParser(); parser.add_argument("--number").type(); From e1ba4876d8d509d64b219b14abdd1a9b3d8bb8b7 Mon Sep 17 00:00:00 2001 From: Krzysiek Karbowiak Date: Thu, 2 Oct 2025 19:35:50 +0200 Subject: [PATCH 04/11] Extend unit test --- test/unittest/test_parsing_optional.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/test/unittest/test_parsing_optional.cpp b/test/unittest/test_parsing_optional.cpp index a7729cc..d669f20 100644 --- a/test/unittest/test_parsing_optional.cpp +++ b/test/unittest/test_parsing_optional.cpp @@ -2809,14 +2809,23 @@ TEST_CASE("Parsing joined flags does not affect long options") CHECK(args.get_value("r") == true); } -TEST_CASE("Parsing an optional argument yields correct value for positive number") +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) { auto parser = argparse::ArgumentParser(); - parser.add_argument("-n").type(); + parser.add_argument("-n").type(); - auto const args = parser.parse_args(3, cstr_arr{"prog", "-n", "65"}); + if constexpr (std::is_integral_v) + { + auto const args = parser.parse_args(3, cstr_arr{"prog", "-n", "65"}); - CHECK(args.get_value("n") == 65); + CHECK(args.get_value("n") == T(65)); + } + else + { + auto const args = parser.parse_args(3, cstr_arr{"prog", "-n", "1.125"}); + + CHECK(args.get_value("n") == T(1.125)); + } } TEST_CASE("Parsing an optional argument yields correct value for positive number") From 868be968dbbd48f19b68599e1b654e68ab50726c Mon Sep 17 00:00:00 2001 From: Krzysiek Karbowiak Date: Thu, 2 Oct 2025 19:37:38 +0200 Subject: [PATCH 05/11] Extend unit test --- test/unittest/test_parsing_optional.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/test/unittest/test_parsing_optional.cpp b/test/unittest/test_parsing_optional.cpp index d669f20..63376b5 100644 --- a/test/unittest/test_parsing_optional.cpp +++ b/test/unittest/test_parsing_optional.cpp @@ -2828,14 +2828,23 @@ TEST_CASE_TEMPLATE("Parsing an optional argument yields correct value for positi } } -TEST_CASE("Parsing an optional argument yields correct value for positive number") +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) { auto parser = argparse::ArgumentParser(); - parser.add_argument("-n").type(); + parser.add_argument("-n").type(); - auto const args = parser.parse_args(2, cstr_arr{"prog", "-n65"}); + if constexpr (std::is_integral_v) + { + auto const args = parser.parse_args(2, cstr_arr{"prog", "-n65"}); - CHECK(args.get_value("n") == 65); + CHECK(args.get_value("n") == T(65)); + } + else + { + auto const args = parser.parse_args(2, cstr_arr{"prog", "-n1.125"}); + + CHECK(args.get_value("n") == T(1.125)); + } } TEST_CASE("Parsing an optional argument yields correct value for positive number") From 6db863e830b32650c45b79a7851e4f0caebbf2fb Mon Sep 17 00:00:00 2001 From: Krzysiek Karbowiak Date: Thu, 2 Oct 2025 19:39:27 +0200 Subject: [PATCH 06/11] Extend unit test --- test/unittest/test_parsing_optional.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/test/unittest/test_parsing_optional.cpp b/test/unittest/test_parsing_optional.cpp index 63376b5..66933b9 100644 --- a/test/unittest/test_parsing_optional.cpp +++ b/test/unittest/test_parsing_optional.cpp @@ -2847,14 +2847,23 @@ TEST_CASE_TEMPLATE("Parsing an optional argument yields correct value for positi } } -TEST_CASE("Parsing an optional argument yields correct value for positive number") +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) { auto parser = argparse::ArgumentParser(); - parser.add_argument("--number").type(); + parser.add_argument("--number").type(); - auto const args = parser.parse_args(3, cstr_arr{"prog", "--number", "65"}); + if constexpr (std::is_integral_v) + { + auto const args = parser.parse_args(3, cstr_arr{"prog", "--number", "65"}); - CHECK(args.get_value("number") == 65); + CHECK(args.get_value("number") == T(65)); + } + else + { + auto const args = parser.parse_args(3, cstr_arr{"prog", "--number", "1.125"}); + + CHECK(args.get_value("number") == T(1.125)); + } } TEST_CASE("Parsing an optional argument yields correct value for positive number") From 3598f459323c87bd3fc313783b8c88c30b8808b4 Mon Sep 17 00:00:00 2001 From: Krzysiek Karbowiak Date: Thu, 2 Oct 2025 19:41:53 +0200 Subject: [PATCH 07/11] Extend unit test --- test/unittest/test_parsing_optional.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/test/unittest/test_parsing_optional.cpp b/test/unittest/test_parsing_optional.cpp index 66933b9..98aef4c 100644 --- a/test/unittest/test_parsing_optional.cpp +++ b/test/unittest/test_parsing_optional.cpp @@ -2866,14 +2866,23 @@ TEST_CASE_TEMPLATE("Parsing an optional argument yields correct value for positi } } -TEST_CASE("Parsing an optional argument yields correct value for positive number") +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) { auto parser = argparse::ArgumentParser(); - parser.add_argument("--number").type(); + parser.add_argument("--number").type(); + + if constexpr (std::is_integral_v) + { + auto const args = parser.parse_args(2, cstr_arr{"prog", "--number=65"}); - auto const args = parser.parse_args(2, cstr_arr{"prog", "--number=65"}); + CHECK(args.get_value("number") == T(65)); + } + else + { + auto const args = parser.parse_args(2, cstr_arr{"prog", "--number=1.125"}); - CHECK(args.get_value("number") == 65); + CHECK(args.get_value("number") == T(1.125)); + } } TEST_CASE("Parsing an optional argument yields correct value for negative number") From 58c6c1dd810399712b9816b6c197a72d8268cfe8 Mon Sep 17 00:00:00 2001 From: Krzysiek Karbowiak Date: Thu, 2 Oct 2025 19:44:59 +0200 Subject: [PATCH 08/11] Extend unit test --- test/unittest/test_parsing_optional.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/test/unittest/test_parsing_optional.cpp b/test/unittest/test_parsing_optional.cpp index 98aef4c..8154916 100644 --- a/test/unittest/test_parsing_optional.cpp +++ b/test/unittest/test_parsing_optional.cpp @@ -2885,14 +2885,23 @@ TEST_CASE_TEMPLATE("Parsing an optional argument yields correct value for positi } } -TEST_CASE("Parsing an optional argument yields correct value for negative number") +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) { auto parser = argparse::ArgumentParser(); - parser.add_argument("-n").type(); + parser.add_argument("-n").type(); - auto const args = parser.parse_args(3, cstr_arr{"prog", "-n", "-65"}); + if constexpr (std::is_integral_v) + { + auto const args = parser.parse_args(3, cstr_arr{"prog", "-n", "-65"}); - CHECK(args.get_value("n") == -65); + CHECK(args.get_value("n") == T(-65)); + } + else + { + auto const args = parser.parse_args(3, cstr_arr{"prog", "-n", "-1.125"}); + + CHECK(args.get_value("n") == T(-1.125)); + } } TEST_CASE("Parsing an optional argument yields correct value for negative number") From ef542a5e9bedfb29d418abc4259be13f63f20b37 Mon Sep 17 00:00:00 2001 From: Krzysiek Karbowiak Date: Thu, 2 Oct 2025 19:46:52 +0200 Subject: [PATCH 09/11] Extend unit test --- test/unittest/test_parsing_optional.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/test/unittest/test_parsing_optional.cpp b/test/unittest/test_parsing_optional.cpp index 8154916..143c653 100644 --- a/test/unittest/test_parsing_optional.cpp +++ b/test/unittest/test_parsing_optional.cpp @@ -2904,14 +2904,23 @@ TEST_CASE_TEMPLATE("Parsing an optional argument yields correct value for negati } } -TEST_CASE("Parsing an optional argument yields correct value for negative number") +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) { auto parser = argparse::ArgumentParser(); - parser.add_argument("-n").type(); + parser.add_argument("-n").type(); + + if constexpr (std::is_integral_v) + { + auto const args = parser.parse_args(2, cstr_arr{"prog", "-n-65"}); - auto const args = parser.parse_args(2, cstr_arr{"prog", "-n-65"}); + CHECK(args.get_value("n") == T(-65)); + } + else + { + auto const args = parser.parse_args(2, cstr_arr{"prog", "-n-1.125"}); - CHECK(args.get_value("n") == -65); + CHECK(args.get_value("n") == T(-1.125)); + } } TEST_CASE("Parsing an optional argument yields correct value for negative number") From f7cbd8b60b44833fb6c2a33886b3ffdd8b7f714e Mon Sep 17 00:00:00 2001 From: Krzysiek Karbowiak Date: Thu, 2 Oct 2025 19:48:14 +0200 Subject: [PATCH 10/11] Extend unit test --- test/unittest/test_parsing_optional.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/test/unittest/test_parsing_optional.cpp b/test/unittest/test_parsing_optional.cpp index 143c653..559ab9a 100644 --- a/test/unittest/test_parsing_optional.cpp +++ b/test/unittest/test_parsing_optional.cpp @@ -2923,14 +2923,23 @@ TEST_CASE_TEMPLATE("Parsing an optional argument yields correct value for negati } } -TEST_CASE("Parsing an optional argument yields correct value for negative number") +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) { auto parser = argparse::ArgumentParser(); - parser.add_argument("--number").type(); + parser.add_argument("--number").type(); + + if constexpr (std::is_integral_v) + { + auto const args = parser.parse_args(3, cstr_arr{"prog", "--number", "-65"}); - auto const args = parser.parse_args(3, cstr_arr{"prog", "--number", "-65"}); + CHECK(args.get_value("number") == T(-65)); + } + else + { + auto const args = parser.parse_args(3, cstr_arr{"prog", "--number", "-1.125"}); - CHECK(args.get_value("number") == -65); + CHECK(args.get_value("number") == T(-1.125)); + } } TEST_CASE("Parsing an optional argument yields correct value for negative number") From 62755491f5a6569f530ec07a3cc57cda92a63339 Mon Sep 17 00:00:00 2001 From: Krzysiek Karbowiak Date: Thu, 2 Oct 2025 19:49:48 +0200 Subject: [PATCH 11/11] Extend unit test --- test/unittest/test_parsing_optional.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/test/unittest/test_parsing_optional.cpp b/test/unittest/test_parsing_optional.cpp index 559ab9a..19f40da 100644 --- a/test/unittest/test_parsing_optional.cpp +++ b/test/unittest/test_parsing_optional.cpp @@ -2942,12 +2942,21 @@ TEST_CASE_TEMPLATE("Parsing an optional argument yields correct value for negati } } -TEST_CASE("Parsing an optional argument yields correct value for negative number") +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) { auto parser = argparse::ArgumentParser(); - parser.add_argument("--number").type(); + parser.add_argument("--number").type(); - auto const args = parser.parse_args(2, cstr_arr{"prog", "--number=-65"}); + if constexpr (std::is_integral_v) + { + auto const args = parser.parse_args(2, cstr_arr{"prog", "--number=-65"}); - CHECK(args.get_value("number") == -65); + CHECK(args.get_value("number") == T(-65)); + } + else + { + auto const args = parser.parse_args(2, cstr_arr{"prog", "--number=-1.125"}); + + CHECK(args.get_value("number") == T(-1.125)); + } }