From 2d018e94d53a577621b7ef885231360165924ec2 Mon Sep 17 00:00:00 2001 From: "killua.z" Date: Mon, 20 Apr 2026 18:43:44 +0400 Subject: [PATCH] Add should_exit support for v2 parsers - Add should_exit support to v2 platform parsers - Introduce macros.h and integrate trait hints - Wire CMake packaging with config, version, and install dirs - Update parser traits to include validation hooks and fixes --- CMakeLists.txt | 43 ++++++--- cmake/argument_parserConfig.cmake.in | 43 +++++++++ compile_commands.json | 8 -- src/headers/argparse | 3 +- src/headers/macros.h | 8 ++ src/headers/parser/fake_parser.hpp | 16 +++- src/headers/parser/parser_v2.hpp | 9 +- src/headers/parser/parsing_traits/traits.hpp | 11 ++- .../parser/platform_headers/linux_parser.hpp | 4 +- .../parser/platform_headers/macos_parser.hpp | 6 +- .../platform_headers/windows_parser.hpp | 4 +- src/main.cpp | 94 ++++++++++++++----- src/source/parser/fake_parser.cpp | 28 +++++- .../parser/platform_parsers/linux_parser.cpp | 4 +- .../parser/platform_parsers/macos_parser.cpp | 44 +++++---- .../platform_parsers/windows_parser.cpp | 6 +- 16 files changed, 245 insertions(+), 86 deletions(-) create mode 100644 cmake/argument_parserConfig.cmake.in delete mode 100644 compile_commands.json create mode 100644 src/headers/macros.h diff --git a/CMakeLists.txt b/CMakeLists.txt index d6fac42..3d429af 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,8 +14,13 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) file(GLOB_RECURSE SRC_FILES "src/source/*.cpp" "src/source/**/*.cpp" "src/source/**/**/*.cpp") add_library(argument_parser ${SRC_FILES}) +add_library(argument_parser::argument_parser ALIAS argument_parser) include(GNUInstallDirs) +include(CMakePackageConfigHelpers) + +set(ARGUMENT_PARSER_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/argument_parser") +set(ARGUMENT_PARSER_INSTALL_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}/argparse") target_include_directories(argument_parser PUBLIC $ @@ -24,12 +29,12 @@ target_include_directories(argument_parser PUBLIC $ $ $ - $ - $ - $ - $ - $ - $ + $ + $ + $ + $ + $ + $ ) install(TARGETS argument_parser @@ -37,21 +42,33 @@ install(TARGETS argument_parser LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + INCLUDES DESTINATION ${ARGUMENT_PARSER_INSTALL_INCLUDEDIR} ) install(DIRECTORY src/headers/ - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + DESTINATION ${ARGUMENT_PARSER_INSTALL_INCLUDEDIR} ) install(EXPORT argument_parserTargets FILE argument_parserTargets.cmake NAMESPACE argument_parser:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/argument_parser + DESTINATION ${ARGUMENT_PARSER_INSTALL_CMAKEDIR} ) -add_executable(test src/main.cpp) -target_link_libraries(test PRIVATE argument_parser) +configure_package_config_file( + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/argument_parserConfig.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/argument_parserConfig.cmake" + INSTALL_DESTINATION "${ARGUMENT_PARSER_INSTALL_CMAKEDIR}" +) -add_executable(positional_tests src/test.cpp) -target_link_libraries(positional_tests PRIVATE argument_parser) \ No newline at end of file +write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/argument_parserConfigVersion.cmake" + VERSION ${PROJECT_VERSION} + COMPATIBILITY SameMajorVersion +) + +install(FILES + "${CMAKE_CURRENT_BINARY_DIR}/argument_parserConfig.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/argument_parserConfigVersion.cmake" + DESTINATION "${ARGUMENT_PARSER_INSTALL_CMAKEDIR}" +) diff --git a/cmake/argument_parserConfig.cmake.in b/cmake/argument_parserConfig.cmake.in new file mode 100644 index 0000000..7aa3d94 --- /dev/null +++ b/cmake/argument_parserConfig.cmake.in @@ -0,0 +1,43 @@ +@PACKAGE_INIT@ + +include("${CMAKE_CURRENT_LIST_DIR}/argument_parserTargets.cmake") + +if(TARGET argument_parser::argument_parser) + get_target_property(_argument_parser_imported_configs argument_parser::argument_parser IMPORTED_CONFIGURATIONS) + + if(NOT _argument_parser_imported_configs) + get_target_property(_argument_parser_type argument_parser::argument_parser TYPE) + + if(_argument_parser_type STREQUAL "STATIC_LIBRARY") + set(_argument_parser_library_path + "${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_LIBDIR@/${CMAKE_STATIC_LIBRARY_PREFIX}argument_parser${CMAKE_STATIC_LIBRARY_SUFFIX}" + ) + + set_target_properties(argument_parser::argument_parser PROPERTIES + IMPORTED_CONFIGURATIONS NOCONFIG + IMPORTED_LINK_INTERFACE_LANGUAGES_NOCONFIG "CXX" + IMPORTED_LOCATION_NOCONFIG "${_argument_parser_library_path}" + ) + endif() + endif() + + set_target_properties(argument_parser::argument_parser PROPERTIES + MAP_IMPORTED_CONFIG_DEBUG NOCONFIG + MAP_IMPORTED_CONFIG_RELEASE NOCONFIG + MAP_IMPORTED_CONFIG_RELWITHDEBINFO NOCONFIG + MAP_IMPORTED_CONFIG_MINSIZEREL NOCONFIG + ) + + unset(_argument_parser_imported_configs) + unset(_argument_parser_type) + unset(_argument_parser_library_path) +endif() + +if(NOT TARGET argument_parser AND TARGET argument_parser::argument_parser) + add_library(argument_parser INTERFACE IMPORTED) + set_target_properties(argument_parser PROPERTIES + INTERFACE_LINK_LIBRARIES argument_parser::argument_parser + ) +endif() + +check_required_components(argument_parser) diff --git a/compile_commands.json b/compile_commands.json deleted file mode 100644 index 0664a7f..0000000 --- a/compile_commands.json +++ /dev/null @@ -1,8 +0,0 @@ -[ - { - "directory": "C:/Users/samet/Documents/CPP/argparser/argument-parser/build", - "command": "C:\\PROGRA~2\\MICROS~2\\18\\BUILDT~1\\VC\\Tools\\MSVC\\1450~1.357\\bin\\Hostx64\\x64\\cl.exe /nologo /TP -IC:\\Users\\samet\\Documents\\CPP\\argparser\\argument-parser\\src\\headers -IC:\\Users\\samet\\Documents\\CPP\\argparser\\argument-parser\\src\\headers\\parser -IC:\\Users\\samet\\Documents\\CPP\\argparser\\argument-parser\\src\\headers\\conventions -IC:\\Users\\samet\\Documents\\CPP\\argparser\\argument-parser\\src\\headers\\conventions\\implementations -IC:\\Users\\samet\\Documents\\CPP\\argparser\\argument-parser\\src\\headers\\parser\\platform_headers -IC:\\Users\\samet\\Documents\\CPP\\argparser\\argument-parser\\src\\headers\\parser\\parsing_traits /DWIN32 /D_WINDOWS /GR /EHsc /Zi /Ob0 /Od /RTC1 -std:c++17 -MDd /FoCMakeFiles\\test.dir\\src\\main.cpp.obj /FdCMakeFiles\\test.dir\\ /FS -c C:\\Users\\samet\\Documents\\CPP\\argparser\\argument-parser\\src\\main.cpp", - "file": "C:/Users/samet/Documents/CPP/argparser/argument-parser/src/main.cpp", - "output": "C:/Users/samet/Documents/CPP/argparser/argument-parser/build/CMakeFiles/test.dir/src/main.cpp.obj" - } -] \ No newline at end of file diff --git a/src/headers/argparse b/src/headers/argparse index 4396e66..d9376cd 100644 --- a/src/headers/argparse +++ b/src/headers/argparse @@ -2,6 +2,7 @@ #ifndef ARGPARSE_HPP #define ARGPARSE_HPP #include +#include "macros.h" #ifdef __linux__ #include @@ -37,4 +38,4 @@ namespace argument_parser::v2 { #include #include -#include \ No newline at end of file +#include diff --git a/src/headers/macros.h b/src/headers/macros.h new file mode 100644 index 0000000..34d55ed --- /dev/null +++ b/src/headers/macros.h @@ -0,0 +1,8 @@ +#pragma once +#ifndef MACROS_H +#define MACROS_H + +#define ARGPARSE_TRAIT_FORMAT_HINT static constexpr argument_parser::parsing_traits::hint_type format_hint +#define ARGPARSE_TRAIT_PURPOSE_HINT static constexpr argument_parser::parsing_traits::hint_type purpose_hint + +#endif // MACROS_H diff --git a/src/headers/parser/fake_parser.hpp b/src/headers/parser/fake_parser.hpp index e4cb306..b95d3d4 100644 --- a/src/headers/parser/fake_parser.hpp +++ b/src/headers/parser/fake_parser.hpp @@ -1,5 +1,6 @@ #pragma once +#include "parser_v2.hpp" #ifndef FAKE_PARSER_HPP #define FAKE_PARSER_HPP @@ -18,6 +19,19 @@ namespace argument_parser { void set_program_name(std::string const &program_name); void set_parsed_arguments(std::vector const &parsed_arguments); }; + + namespace v2 { + class fake_parser : public argument_parser::v2::base_parser { + public: + fake_parser() = default; + fake_parser(std::string program_name, std::vector const &arguments); + fake_parser(std::string const &program_name, std::vector &&arguments); + fake_parser(std::string const &program_name, std::initializer_list const &arguments); + + void set_program_name(std::string const &program_name); + void set_parsed_arguments(std::vector const &parsed_arguments); + }; + } } // namespace argument_parser -#endif \ No newline at end of file +#endif diff --git a/src/headers/parser/parser_v2.hpp b/src/headers/parser/parser_v2.hpp index 4454e86..e64a577 100644 --- a/src/headers/parser/parser_v2.hpp +++ b/src/headers/parser/parser_v2.hpp @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -91,12 +90,14 @@ namespace argument_parser::v2 { using argument_parser::base_parser::current_conventions; using argument_parser::base_parser::reset_current_conventions; - void prepare_help_flag() { + void prepare_help_flag(bool should_exit = true) { add_argument({{flags::ShortArgument, "h"}, {flags::LongArgument, "help"}, - {flags::Action, helpers::make_non_parametered_action([this]() { + {flags::Action, helpers::make_non_parametered_action([this, should_exit]() { this->display_help(this->current_conventions()); - std::exit(0); + if (should_exit) { + std::exit(0); + } })}, {flags::HelpText, "Prints this help text."}}); } diff --git a/src/headers/parser/parsing_traits/traits.hpp b/src/headers/parser/parsing_traits/traits.hpp index 6efd12e..c88664c 100644 --- a/src/headers/parser/parsing_traits/traits.hpp +++ b/src/headers/parser/parsing_traits/traits.hpp @@ -10,39 +10,46 @@ namespace argument_parser::parsing_traits { template struct parser_trait { using type = T_; static T_ parse(const std::string &input); + static bool validate(T_ const&); + static constexpr hint_type format_hint = "value"; static constexpr hint_type purpose_hint = "value"; }; template <> struct parser_trait { static std::string parse(const std::string &input); + static constexpr hint_type format_hint = "string"; static constexpr hint_type purpose_hint = "string value"; }; template <> struct parser_trait { static bool parse(const std::string &input); + static constexpr hint_type format_hint = "true/false"; static constexpr hint_type purpose_hint = "boolean value"; }; template <> struct parser_trait { static int parse(const std::string &input); + static constexpr hint_type format_hint = "123"; static constexpr hint_type purpose_hint = "integer value"; }; template <> struct parser_trait { static float parse(const std::string &input); + static constexpr hint_type format_hint = "3.14"; - static constexpr hint_type purpose_hint = "flaoting point number"; + static constexpr hint_type purpose_hint = "floating point number"; }; template <> struct parser_trait { static double parse(const std::string &input); + static constexpr hint_type format_hint = "3.14"; static constexpr hint_type purpose_hint = "double precision floating point number"; }; } // namespace argument_parser::parsing_traits -#endif \ No newline at end of file +#endif diff --git a/src/headers/parser/platform_headers/linux_parser.hpp b/src/headers/parser/platform_headers/linux_parser.hpp index 9d9e4cd..7a1a393 100644 --- a/src/headers/parser/platform_headers/linux_parser.hpp +++ b/src/headers/parser/platform_headers/linux_parser.hpp @@ -16,11 +16,11 @@ namespace argument_parser { namespace v2 { class linux_parser : public v2::base_parser { public: - linux_parser(); + linux_parser(bool should_exit = true); using base_parser::display_help; }; } // namespace v2 } // namespace argument_parser #endif -#endif \ No newline at end of file +#endif diff --git a/src/headers/parser/platform_headers/macos_parser.hpp b/src/headers/parser/platform_headers/macos_parser.hpp index 5703ab5..2ff1e51 100644 --- a/src/headers/parser/platform_headers/macos_parser.hpp +++ b/src/headers/parser/platform_headers/macos_parser.hpp @@ -4,9 +4,7 @@ #define MACOS_PARSER_HPP #include -#include #include -#include namespace argument_parser { class macos_parser : public base_parser { @@ -17,11 +15,11 @@ namespace argument_parser { namespace v2 { class macos_parser : public v2::base_parser { public: - macos_parser(); + macos_parser(bool should_exit = true); using base_parser::display_help; }; } // namespace v2 } // namespace argument_parser #endif -#endif \ No newline at end of file +#endif diff --git a/src/headers/parser/platform_headers/windows_parser.hpp b/src/headers/parser/platform_headers/windows_parser.hpp index d180676..d71747c 100644 --- a/src/headers/parser/platform_headers/windows_parser.hpp +++ b/src/headers/parser/platform_headers/windows_parser.hpp @@ -12,9 +12,9 @@ namespace argument_parser { namespace v2 { class windows_parser : public v2::base_parser { public: - windows_parser(); + windows_parser(bool should_exit = true); using base_parser::display_help; }; } // namespace v2 } // namespace argument_parser -#endif \ No newline at end of file +#endif diff --git a/src/main.cpp b/src/main.cpp index 801609f..193d784 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,4 +1,7 @@ +#include "macros.h" +#include "traits.hpp" #include +#include #include #include @@ -22,31 +25,23 @@ template <> struct argument_parser::parsing_traits::parser_trait { int y = std::stoi(input.substr(comma_pos + 1)); return {x, y}; } - static constexpr argument_parser::parsing_traits::hint_type format_hint = "x,y"; - static constexpr argument_parser::parsing_traits::hint_type purpose_hint = "coordinates"; + + static bool validate(Point const& p) { + return p.x >= 0 && p.y >= 0; + } + + ARGPARSE_TRAIT_FORMAT_HINT = "x,y"; + ARGPARSE_TRAIT_PURPOSE_HINT = "coordinates"; }; template <> struct argument_parser::parsing_traits::parser_trait { static std::regex parse(const std::string &input) { return std::regex(input); } - static constexpr argument_parser::parsing_traits::hint_type format_hint = "regex"; - static constexpr argument_parser::parsing_traits::hint_type purpose_hint = "regular expression"; + ARGPARSE_TRAIT_FORMAT_HINT = "regex"; + ARGPARSE_TRAIT_PURPOSE_HINT = "regular expression"; }; -template <> struct argument_parser::parsing_traits::parser_trait> { - static std::vector parse(const std::string &input) { - std::vector result; - std::stringstream ss{input}; - std::string item; - while (std::getline(ss, item, ',')) { - result.push_back(std::stoi(item)); - } - return result; - } - static constexpr argument_parser::parsing_traits::hint_type format_hint = "int,int,int"; - static constexpr argument_parser::parsing_traits::hint_type purpose_hint = "list of integers"; -}; template <> struct argument_parser::parsing_traits::parser_trait> { static std::vector parse(const std::string &input) { @@ -58,8 +53,24 @@ template <> struct argument_parser::parsing_traits::parser_trait struct argument_parser::parsing_traits::parser_trait> { + static std::vector parse(const std::string &input) { + std::vector result; + std::stringstream ss{input}; + std::string item; + + while (std::getline(ss, item, ',')) { + result.push_back(argument_parser::parsing_traits::parser_trait::parse(item)); + } + return result; + } + ARGPARSE_TRAIT_FORMAT_HINT = "VT,VT,VT"; + ARGPARSE_TRAIT_PURPOSE_HINT = "list of VT"; }; const std::initializer_list conventions = { @@ -88,6 +99,7 @@ const auto cat = argument_parser::helpers::make_parametered_action( file.close(); }); + auto grep(argument_parser::base_parser const &parser, std::string const &filename, std::regex const &pattern) { if (filename.empty()) { std::cerr << "Missing filename" << std::endl; @@ -135,7 +147,7 @@ void run_store_point(argument_parser::base_parser const &parser) { int v2Examples() { using namespace argument_parser::v2::flags; - argument_parser::v2::parser parser; + argument_parser::v2::parser parser{ false }; parser.add_argument( {{ShortArgument, "e"}, {LongArgument, "echo"}, {Action, echo}, {HelpText, "echoes given variable"}}); @@ -159,7 +171,8 @@ int v2Examples() { }); parser.add_argument( - {{ShortArgument, "c"}, {LongArgument, "cat"}, {Action, cat}, {HelpText, "Prints the content of the file"}}); + {{ShortArgument, "c"}, {LongArgument, "cat"}, {Action, cat}, {HelpText, "Prints the content of the file"}} + ); parser.add_argument({ // { ShortArgument, "sp" }, // now if ShortArgument or LongArgument is missing, it will use it for the other. @@ -180,6 +193,8 @@ int v2Examples() { {HelpText, "Output file path"}, }); + parser.add_argument>({{LongArgument, "points"}, {HelpText, "List of points to store"}}); + parser.on_complete(::run_grep); parser.on_complete(::run_store_point); parser.on_complete([](argument_parser::base_parser const &p) { @@ -197,10 +212,43 @@ int v2Examples() { return 0; } -int main() { +auto unique_copy(std::unique_ptr ptr) { + std::cout << *ptr << std::endl; +} + +auto unique_reference(std::unique_ptr const& ptr) { + std::cout << *ptr << std::endl; +} + +auto unique_move(std::unique_ptr&& ptr) { + std::cout << *ptr << std::endl; +} + +template +T return_example(std::function func) { + if constexpr (std::is_same_v) { + return func(); + } else { + return func(); + } +} + +template +void log_result(std::function func) { + if constexpr (std::is_same_v) { + func(); + } else { + std::cout << "result: " << func() << std::endl; + } +} + + +int main(int argc, char **argv) { try { + return_example([]{}); + return v2Examples(); } catch (std::exception const &e) { std::cout << e.what() << std::endl; } -} \ No newline at end of file +} diff --git a/src/source/parser/fake_parser.cpp b/src/source/parser/fake_parser.cpp index 3f7b287..d0a263c 100644 --- a/src/source/parser/fake_parser.cpp +++ b/src/source/parser/fake_parser.cpp @@ -21,4 +21,30 @@ namespace argument_parser { void fake_parser::set_parsed_arguments(std::vector const &parsed_arguments) { this->parsed_arguments = parsed_arguments; } -} // namespace argument_parser \ No newline at end of file + + namespace v2 { + fake_parser::fake_parser(std::string program_name, std::vector const &arguments) { + set_program_name(program_name); + ref_parsed_args() = arguments; + prepare_help_flag(false); + } + + fake_parser::fake_parser(std::string const &program_name, std::vector &&arguments) { + set_program_name(program_name); + ref_parsed_args() = std::move(arguments); + prepare_help_flag(false); + } + + fake_parser::fake_parser(std::string const &program_name, std::initializer_list const &arguments) + : fake_parser(program_name, std::vector(arguments)) { + } + + void fake_parser::set_program_name(std::string const &program_name) { + set_program_name(program_name); + } + + void fake_parser::set_parsed_arguments(std::vector const &parsed_arguments) { + ref_parsed_args() = parsed_arguments; + } + } +} // namespace argument_parser diff --git a/src/source/parser/platform_parsers/linux_parser.cpp b/src/source/parser/platform_parsers/linux_parser.cpp index 56b7c44..be6bf52 100644 --- a/src/source/parser/platform_parsers/linux_parser.cpp +++ b/src/source/parser/platform_parsers/linux_parser.cpp @@ -15,7 +15,7 @@ namespace argument_parser { } namespace v2 { - linux_parser::linux_parser() { + linux_parser::linux_parser(bool should_exit) { std::ifstream command_line_file{"/proc/self/cmdline"}; std::string program_name; std::getline(command_line_file, program_name, '\0'); @@ -25,7 +25,7 @@ namespace argument_parser { parsed_arguments.emplace_back(line); } - prepare_help_flag(); + prepare_help_flag(should_exit); } } // namespace v2 } // namespace argument_parser diff --git a/src/source/parser/platform_parsers/macos_parser.cpp b/src/source/parser/platform_parsers/macos_parser.cpp index 4b3c60e..d2b473c 100644 --- a/src/source/parser/platform_parsers/macos_parser.cpp +++ b/src/source/parser/platform_parsers/macos_parser.cpp @@ -2,32 +2,36 @@ #include "macos_parser.hpp" +#include + +#define MACOS_GETARGS_LOOP(argc_name, argv_name, before_for, for_body) \ + do { \ + const int argc_name = *_NSGetArgc(); \ + if (char **argv_name = *_NSGetArgv(); argc_name > 0 && argv_name != nullptr && argv_name[0] != nullptr) { \ + do { before_for; } while(false); \ + for (int i = 1; i < argc_name; ++i) { \ + for_body \ + } \ + } \ + } while (false) + namespace argument_parser { macos_parser::macos_parser() { - const int argc = *_NSGetArgc(); - if (char **argv = *_NSGetArgv(); argc > 0 && argv != nullptr && argv[0] != nullptr) { - program_name = (argv[0]); - for (int i = 1; i < argc; ++i) { - if (argv[i] != nullptr) - parsed_arguments.emplace_back(argv[i]); - } - } + MACOS_GETARGS_LOOP(argc, argv, program_name = argv[0], { + if (argv[i] != nullptr) + parsed_arguments.emplace_back(argv[i]); + }); } namespace v2 { - macos_parser::macos_parser() { - const int argc = *_NSGetArgc(); - if (char **argv = *_NSGetArgv(); argc > 0 && argv != nullptr && argv[0] != nullptr) { - set_program_name(argv[0]); - for (int i = 1; i < argc; ++i) { - if (argv[i] != nullptr) - ref_parsed_args().emplace_back(argv[i]); - } - } - - prepare_help_flag(); + macos_parser::macos_parser(bool should_exit) { + MACOS_GETARGS_LOOP(argc, argv, set_program_name(argv[0]), { + if (argv[i] != nullptr) + ref_parsed_args().emplace_back(argv[i]); + }); + prepare_help_flag(should_exit); } } // namespace v2 } // namespace argument_parser -#endif \ No newline at end of file +#endif diff --git a/src/source/parser/platform_parsers/windows_parser.cpp b/src/source/parser/platform_parsers/windows_parser.cpp index c557ae3..45c7d36 100644 --- a/src/source/parser/platform_parsers/windows_parser.cpp +++ b/src/source/parser/platform_parsers/windows_parser.cpp @@ -95,12 +95,12 @@ namespace argument_parser { } // namespace argument_parser namespace argument_parser::v2 { - windows_parser::windows_parser() { + windows_parser::windows_parser(bool should_exit) { parse_windows_arguments(ref_parsed_args(), [this](std::string const &program_name) { this->set_program_name(program_name); }); - prepare_help_flag(); + prepare_help_flag(should_exit); } } // namespace argument_parser::v2 -#endif \ No newline at end of file +#endif