From 10091cf3cc6eddb714dd21da1aab5b41a7833cdf Mon Sep 17 00:00:00 2001 From: Krzysiek Karbowiak Date: Fri, 14 Nov 2025 00:29:10 +0100 Subject: [PATCH 1/3] Refactor: move code --- include/argparse.hpp | 416 ++++++++++++++++++++++--------------------- 1 file changed, 209 insertions(+), 207 deletions(-) diff --git a/include/argparse.hpp b/include/argparse.hpp index ef09512..e05972a 100644 --- a/include/argparse.hpp +++ b/include/argparse.hpp @@ -643,192 +643,7 @@ namespace argparse std::unique_ptr type_handler = std::make_unique>(); }; - class ArgumentImpl - { - public: - explicit ArgumentImpl(Options options) - : m_options(std::move(options)) - { - } - - auto get_name() const -> std::string const & - { - return m_options.names.front(); - } - - auto get_names() const -> std::vector const & - { - return m_options.names; - } - - auto get_joined_names() const -> std::string - { - return join(m_options.names, "/"); - } - - auto has_nargs() const -> bool - { - return m_options.nargs.has_value(); - } - - auto has_nargs_number() const -> bool - { - return std::holds_alternative(*m_options.nargs); - } - - auto get_nargs_number() const -> std::size_t - { - return std::get(*m_options.nargs); - } - - auto get_nargs_option() const -> Nargs - { - return std::get(*m_options.nargs); - } - - auto is_mutually_exclusive() const -> bool - { - return m_options.mutually_exclusive_group != nullptr; - } - - auto is_mutually_exclusive_with(ArgumentImpl const & other) const -> bool - { - return (m_options.mutually_exclusive_group != nullptr) && (m_options.mutually_exclusive_group == other.m_options.mutually_exclusive_group); - } - - auto expects_argument() const -> bool - { - return m_options.action == store || m_options.action == append; - } - - auto get_help() const -> std::string const & - { - return m_options.help; - } - - auto get_default() const -> std::any const & - { - return m_options.default_; - } - - auto get_const() const -> std::any const & - { - return m_options.const_; - } - - auto get_metavar() const -> std::string const & - { - return m_options.metavar; - } - - auto get_dest() const -> std::string const & - { - return m_options.dest; - } - - auto get_required() const -> bool - { - return m_options.required; - } - - auto get_action() const -> Action - { - return m_options.action; - } - - auto has_choices() const -> bool - { - return !m_options.choices.empty(); - } - - auto get_joined_choices(std::string_view separator) const -> std::string - { - return join(m_options.choices | std::views::transform([&](auto const & choice) { return m_options.type_handler->to_string(choice); }), separator); - } - - auto parse_arguments(std::ranges::view auto tokens) const -> std::any - { - auto const values = consume_tokens(tokens); - return m_options.type_handler->transform(values); - } - - auto consume_token(Token & token) const -> std::any - { - token.m_consumed = true; - return process_token(token.m_token); - } - - auto process_token(std::string const & token) const -> std::any - { - auto const value = m_options.type_handler->from_string(token); - if (!value.has_value()) - { - throw parsing_error(std::format("argument {}: invalid value: '{}'", get_joined_names(), token)); - } - check_choices(value); - return value; - } - - auto consume_tokens(std::ranges::view auto tokens) const -> std::vector - { - auto result = std::vector(); - auto consumed = std::vector(); - for (auto & token : tokens) - { - result.push_back(process_token(token.m_token)); - consumed.push_back(&token); - } - std::ranges::for_each(consumed, [](auto token) { token->m_consumed = true; }); - return result; - } - - auto check_choices(std::any const & value) const -> void - { - if (m_options.choices.empty()) - { - return; - } - - if (!std::ranges::any_of( - m_options.choices, - [&](auto const & rhs) { return m_options.type_handler->compare(value, rhs); })) - { - auto const message = std::format( - "argument {}: invalid choice: {} (choose from {})", - get_joined_names(), - m_options.type_handler->to_string(value), - get_joined_choices(", ")); - throw parsing_error(message); - } - } - - auto get_transformed(std::vector const & values) const -> std::any - { - return m_options.type_handler->transform(values); - } - - auto get_size(std::any const & value) const -> std::size_t - { - return m_options.type_handler->size(value); - } - - auto append_value(std::any const & value, std::any & values) const -> void - { - m_options.type_handler->append(value, values); - } - - static auto is_negative_number(std::string const & token) -> bool - { - if (auto const parsed = from_string(token); parsed.has_value()) - { - return true; - } - return false; - } - - private: - Options m_options; - }; + class ArgumentImpl; class StoreAction { @@ -1100,6 +915,213 @@ namespace argparse } }; + class ArgumentImpl + { + public: + explicit ArgumentImpl(Options options) + : m_options(std::move(options)) + { + } + + auto get_name() const -> std::string const & + { + return m_options.names.front(); + } + + auto get_names() const -> std::vector const & + { + return m_options.names; + } + + auto get_joined_names() const -> std::string + { + return join(m_options.names, "/"); + } + + auto has_nargs() const -> bool + { + return m_options.nargs.has_value(); + } + + auto has_nargs_number() const -> bool + { + return std::holds_alternative(*m_options.nargs); + } + + auto get_nargs_number() const -> std::size_t + { + return std::get(*m_options.nargs); + } + + auto get_nargs_option() const -> Nargs + { + return std::get(*m_options.nargs); + } + + auto is_mutually_exclusive() const -> bool + { + return m_options.mutually_exclusive_group != nullptr; + } + + auto is_mutually_exclusive_with(ArgumentImpl const & other) const -> bool + { + return (m_options.mutually_exclusive_group != nullptr) && (m_options.mutually_exclusive_group == other.m_options.mutually_exclusive_group); + } + + auto expects_argument() const -> bool + { + return m_options.action == store || m_options.action == append; + } + + auto get_help() const -> std::string const & + { + return m_options.help; + } + + auto get_default() const -> std::any const & + { + return m_options.default_; + } + + auto get_const() const -> std::any const & + { + return m_options.const_; + } + + auto get_metavar() const -> std::string const & + { + return m_options.metavar; + } + + auto get_dest() const -> std::string const & + { + return m_options.dest; + } + + auto get_required() const -> bool + { + return m_options.required; + } + + auto get_action() const -> std::variant + { + switch (m_options.action) + { + case store: + return StoreAction(); + case store_true: + return StoreTrueAction(); + case store_false: + return StoreFalseAction(); + case store_const: + return StoreConstAction(); + case help: + return HelpAction(); + case version: + return VersionAction(); + case count: + return CountAction(); + case append: + return AppendAction(); + } + + std::unreachable(); + } + + auto has_choices() const -> bool + { + return !m_options.choices.empty(); + } + + auto get_joined_choices(std::string_view separator) const -> std::string + { + return join(m_options.choices | std::views::transform([&](auto const & choice) { return m_options.type_handler->to_string(choice); }), separator); + } + + auto parse_arguments(std::ranges::view auto tokens) const -> std::any + { + auto const values = consume_tokens(tokens); + return m_options.type_handler->transform(values); + } + + auto consume_token(Token & token) const -> std::any + { + token.m_consumed = true; + return process_token(token.m_token); + } + + auto process_token(std::string const & token) const -> std::any + { + auto const value = m_options.type_handler->from_string(token); + if (!value.has_value()) + { + throw parsing_error(std::format("argument {}: invalid value: '{}'", get_joined_names(), token)); + } + check_choices(value); + return value; + } + + auto consume_tokens(std::ranges::view auto tokens) const -> std::vector + { + auto result = std::vector(); + auto consumed = std::vector(); + for (auto & token : tokens) + { + result.push_back(process_token(token.m_token)); + consumed.push_back(&token); + } + std::ranges::for_each(consumed, [](auto token) { token->m_consumed = true; }); + return result; + } + + auto check_choices(std::any const & value) const -> void + { + if (m_options.choices.empty()) + { + return; + } + + if (!std::ranges::any_of( + m_options.choices, + [&](auto const & rhs) { return m_options.type_handler->compare(value, rhs); })) + { + auto const message = std::format( + "argument {}: invalid choice: {} (choose from {})", + get_joined_names(), + m_options.type_handler->to_string(value), + get_joined_choices(", ")); + throw parsing_error(message); + } + } + + auto get_transformed(std::vector const & values) const -> std::any + { + return m_options.type_handler->transform(values); + } + + auto get_size(std::any const & value) const -> std::size_t + { + return m_options.type_handler->size(value); + } + + auto append_value(std::any const & value, std::any & values) const -> void + { + m_options.type_handler->append(value, values); + } + + static auto is_negative_number(std::string const & token) -> bool + { + if (auto const parsed = from_string(token); parsed.has_value()) + { + return true; + } + return false; + } + + private: + Options m_options; + }; + class PositionalArgument final : public Argument, public Formattable { private: @@ -1444,27 +1466,7 @@ namespace argparse auto create_action() const -> std::variant { - switch (m_impl.get_action()) - { - case store: - return StoreAction(); - case store_true: - return StoreTrueAction(); - case store_false: - return StoreFalseAction(); - case store_const: - return StoreConstAction(); - case help: - return HelpAction(); - case version: - return VersionAction(); - case count: - return CountAction(); - case append: - return AppendAction(); - } - - std::unreachable(); + return m_impl.get_action(); } private: From 8b49c82448fb533d701aac84772e5e512a6aba50 Mon Sep 17 00:00:00 2001 From: Krzysiek Karbowiak Date: Fri, 14 Nov 2025 00:31:38 +0100 Subject: [PATCH 2/3] Simplify code --- include/argparse.hpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/include/argparse.hpp b/include/argparse.hpp index e05972a..4867a46 100644 --- a/include/argparse.hpp +++ b/include/argparse.hpp @@ -1464,11 +1464,6 @@ namespace argparse }); } - auto create_action() const -> std::variant - { - return m_impl.get_action(); - } - private: ArgumentImpl m_impl; std::any m_value; @@ -1478,7 +1473,7 @@ namespace argparse public: explicit OptionalArgument(Options options) : m_impl(std::move(options)) - , m_action(create_action()) + , m_action(m_impl.get_action()) { } From 82e37556441eca60ced0f438f6d8bbd53d3f9123 Mon Sep 17 00:00:00 2001 From: Krzysiek Karbowiak Date: Fri, 14 Nov 2025 00:39:24 +0100 Subject: [PATCH 3/3] Refactor: create action where needed --- include/argparse.hpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/include/argparse.hpp b/include/argparse.hpp index 4867a46..0999a7d 100644 --- a/include/argparse.hpp +++ b/include/argparse.hpp @@ -1347,7 +1347,8 @@ namespace argparse private: auto perform_action(std::string const & value, std::ranges::view auto tokens) -> void { - std::visit([&](auto const & action) { action.perform(m_impl, m_value, value, tokens); }, m_action); + auto const action = m_impl.get_action(); + std::visit([&](auto const & ac) { ac.perform(m_impl, m_value, value, tokens); }, action); } auto has_arg(auto it) const -> std::string_view @@ -1432,12 +1433,14 @@ namespace argparse auto check_errors(std::string_view value, std::ranges::view auto tokens) const -> void { - std::visit([&](auto const & action) { action.check_errors(m_impl, value, tokens); }, m_action); + auto const action = m_impl.get_action(); + std::visit([&](auto const & ac) { ac.check_errors(m_impl, value, tokens); }, action); } auto assign_non_present_value() -> void { - std::visit([&](auto const & action) { action.assign_non_present_value(m_impl, m_value); }, m_action); + auto const action = m_impl.get_action(); + std::visit([&](auto const & ac) { ac.assign_non_present_value(m_impl, m_value); }, action); } static auto get_consumable(Tokens & tokens) @@ -1468,12 +1471,10 @@ namespace argparse ArgumentImpl m_impl; std::any m_value; bool m_present = false; - std::variant m_action; public: explicit OptionalArgument(Options options) : m_impl(std::move(options)) - , m_action(m_impl.get_action()) { }