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
This commit is contained in:
2026-04-20 18:43:44 +04:00
parent 5e1f203713
commit 2d018e94d5
16 changed files with 245 additions and 86 deletions

View File

@@ -14,8 +14,13 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
file(GLOB_RECURSE SRC_FILES "src/source/*.cpp" "src/source/**/*.cpp" "src/source/**/**/*.cpp") file(GLOB_RECURSE SRC_FILES "src/source/*.cpp" "src/source/**/*.cpp" "src/source/**/**/*.cpp")
add_library(argument_parser ${SRC_FILES}) add_library(argument_parser ${SRC_FILES})
add_library(argument_parser::argument_parser ALIAS argument_parser)
include(GNUInstallDirs) 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 target_include_directories(argument_parser PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/headers> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/headers>
@@ -24,12 +29,12 @@ target_include_directories(argument_parser PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/headers/conventions/implementations> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/headers/conventions/implementations>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/headers/parser/platform_headers> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/headers/parser/platform_headers>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/headers/parser/parsing_traits> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/headers/parser/parsing_traits>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> $<INSTALL_INTERFACE:${ARGUMENT_PARSER_INSTALL_INCLUDEDIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/parser> $<INSTALL_INTERFACE:${ARGUMENT_PARSER_INSTALL_INCLUDEDIR}/parser>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/conventions> $<INSTALL_INTERFACE:${ARGUMENT_PARSER_INSTALL_INCLUDEDIR}/conventions>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/conventions/implementations> $<INSTALL_INTERFACE:${ARGUMENT_PARSER_INSTALL_INCLUDEDIR}/conventions/implementations>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/parser/platform_headers> $<INSTALL_INTERFACE:${ARGUMENT_PARSER_INSTALL_INCLUDEDIR}/parser/platform_headers>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/parser/parsing_traits> $<INSTALL_INTERFACE:${ARGUMENT_PARSER_INSTALL_INCLUDEDIR}/parser/parsing_traits>
) )
install(TARGETS argument_parser install(TARGETS argument_parser
@@ -37,21 +42,33 @@ install(TARGETS argument_parser
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} INCLUDES DESTINATION ${ARGUMENT_PARSER_INSTALL_INCLUDEDIR}
) )
install(DIRECTORY src/headers/ install(DIRECTORY src/headers/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} DESTINATION ${ARGUMENT_PARSER_INSTALL_INCLUDEDIR}
) )
install(EXPORT argument_parserTargets install(EXPORT argument_parserTargets
FILE argument_parserTargets.cmake FILE argument_parserTargets.cmake
NAMESPACE argument_parser:: NAMESPACE argument_parser::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/argument_parser DESTINATION ${ARGUMENT_PARSER_INSTALL_CMAKEDIR}
) )
add_executable(test src/main.cpp) configure_package_config_file(
target_link_libraries(test PRIVATE argument_parser) "${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) write_basic_package_version_file(
target_link_libraries(positional_tests PRIVATE argument_parser) "${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}"
)

View File

@@ -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)

View File

@@ -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"
}
]

View File

@@ -2,6 +2,7 @@
#ifndef ARGPARSE_HPP #ifndef ARGPARSE_HPP
#define ARGPARSE_HPP #define ARGPARSE_HPP
#include <argument_parser.hpp> #include <argument_parser.hpp>
#include "macros.h"
#ifdef __linux__ #ifdef __linux__
#include <linux_parser.hpp> #include <linux_parser.hpp>
@@ -37,4 +38,4 @@ namespace argument_parser::v2 {
#include <base_convention.hpp> #include <base_convention.hpp>
#include <gnu_argument_convention.hpp> #include <gnu_argument_convention.hpp>
#include <windows_argument_convention.hpp> #include <windows_argument_convention.hpp>

8
src/headers/macros.h Normal file
View File

@@ -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

View File

@@ -1,5 +1,6 @@
#pragma once #pragma once
#include "parser_v2.hpp"
#ifndef FAKE_PARSER_HPP #ifndef FAKE_PARSER_HPP
#define 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_program_name(std::string const &program_name);
void set_parsed_arguments(std::vector<std::string> const &parsed_arguments); void set_parsed_arguments(std::vector<std::string> 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<std::string> const &arguments);
fake_parser(std::string const &program_name, std::vector<std::string> &&arguments);
fake_parser(std::string const &program_name, std::initializer_list<std::string> const &arguments);
void set_program_name(std::string const &program_name);
void set_parsed_arguments(std::vector<std::string> const &parsed_arguments);
};
}
} // namespace argument_parser } // namespace argument_parser
#endif #endif

View File

@@ -3,7 +3,6 @@
#include <argument_parser.hpp> #include <argument_parser.hpp>
#include <array> #include <array>
#include <cstdlib> #include <cstdlib>
#include <fake_parser.hpp>
#include <initializer_list> #include <initializer_list>
#include <memory> #include <memory>
#include <optional> #include <optional>
@@ -91,12 +90,14 @@ namespace argument_parser::v2 {
using argument_parser::base_parser::current_conventions; using argument_parser::base_parser::current_conventions;
using argument_parser::base_parser::reset_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"}, add_argument({{flags::ShortArgument, "h"},
{flags::LongArgument, "help"}, {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()); this->display_help(this->current_conventions());
std::exit(0); if (should_exit) {
std::exit(0);
}
})}, })},
{flags::HelpText, "Prints this help text."}}); {flags::HelpText, "Prints this help text."}});
} }

View File

@@ -10,39 +10,46 @@ namespace argument_parser::parsing_traits {
template <typename T_> struct parser_trait { template <typename T_> struct parser_trait {
using type = T_; using type = T_;
static T_ parse(const std::string &input); static T_ parse(const std::string &input);
static bool validate(T_ const&);
static constexpr hint_type format_hint = "value"; static constexpr hint_type format_hint = "value";
static constexpr hint_type purpose_hint = "value"; static constexpr hint_type purpose_hint = "value";
}; };
template <> struct parser_trait<std::string> { template <> struct parser_trait<std::string> {
static std::string parse(const std::string &input); static std::string parse(const std::string &input);
static constexpr hint_type format_hint = "string"; static constexpr hint_type format_hint = "string";
static constexpr hint_type purpose_hint = "string value"; static constexpr hint_type purpose_hint = "string value";
}; };
template <> struct parser_trait<bool> { template <> struct parser_trait<bool> {
static bool parse(const std::string &input); static bool parse(const std::string &input);
static constexpr hint_type format_hint = "true/false"; static constexpr hint_type format_hint = "true/false";
static constexpr hint_type purpose_hint = "boolean value"; static constexpr hint_type purpose_hint = "boolean value";
}; };
template <> struct parser_trait<int> { template <> struct parser_trait<int> {
static int parse(const std::string &input); static int parse(const std::string &input);
static constexpr hint_type format_hint = "123"; static constexpr hint_type format_hint = "123";
static constexpr hint_type purpose_hint = "integer value"; static constexpr hint_type purpose_hint = "integer value";
}; };
template <> struct parser_trait<float> { template <> struct parser_trait<float> {
static float parse(const std::string &input); static float parse(const std::string &input);
static constexpr hint_type format_hint = "3.14"; 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<double> { template <> struct parser_trait<double> {
static double parse(const std::string &input); static double parse(const std::string &input);
static constexpr hint_type format_hint = "3.14"; static constexpr hint_type format_hint = "3.14";
static constexpr hint_type purpose_hint = "double precision floating point number"; static constexpr hint_type purpose_hint = "double precision floating point number";
}; };
} // namespace argument_parser::parsing_traits } // namespace argument_parser::parsing_traits
#endif #endif

View File

@@ -16,11 +16,11 @@ namespace argument_parser {
namespace v2 { namespace v2 {
class linux_parser : public v2::base_parser { class linux_parser : public v2::base_parser {
public: public:
linux_parser(); linux_parser(bool should_exit = true);
using base_parser::display_help; using base_parser::display_help;
}; };
} // namespace v2 } // namespace v2
} // namespace argument_parser } // namespace argument_parser
#endif #endif
#endif #endif

View File

@@ -4,9 +4,7 @@
#define MACOS_PARSER_HPP #define MACOS_PARSER_HPP
#include <argument_parser.hpp> #include <argument_parser.hpp>
#include <crt_externs.h>
#include <parser_v2.hpp> #include <parser_v2.hpp>
#include <string>
namespace argument_parser { namespace argument_parser {
class macos_parser : public base_parser { class macos_parser : public base_parser {
@@ -17,11 +15,11 @@ namespace argument_parser {
namespace v2 { namespace v2 {
class macos_parser : public v2::base_parser { class macos_parser : public v2::base_parser {
public: public:
macos_parser(); macos_parser(bool should_exit = true);
using base_parser::display_help; using base_parser::display_help;
}; };
} // namespace v2 } // namespace v2
} // namespace argument_parser } // namespace argument_parser
#endif #endif
#endif #endif

View File

@@ -12,9 +12,9 @@ namespace argument_parser {
namespace v2 { namespace v2 {
class windows_parser : public v2::base_parser { class windows_parser : public v2::base_parser {
public: public:
windows_parser(); windows_parser(bool should_exit = true);
using base_parser::display_help; using base_parser::display_help;
}; };
} // namespace v2 } // namespace v2
} // namespace argument_parser } // namespace argument_parser
#endif #endif

View File

@@ -1,4 +1,7 @@
#include "macros.h"
#include "traits.hpp"
#include <exception> #include <exception>
#include <memory>
#include <string> #include <string>
#include <argparse> #include <argparse>
@@ -22,31 +25,23 @@ template <> struct argument_parser::parsing_traits::parser_trait<Point> {
int y = std::stoi(input.substr(comma_pos + 1)); int y = std::stoi(input.substr(comma_pos + 1));
return {x, y}; 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<std::regex> { template <> struct argument_parser::parsing_traits::parser_trait<std::regex> {
static std::regex parse(const std::string &input) { static std::regex parse(const std::string &input) {
return std::regex(input); return std::regex(input);
} }
static constexpr argument_parser::parsing_traits::hint_type format_hint = "regex"; ARGPARSE_TRAIT_FORMAT_HINT = "regex";
static constexpr argument_parser::parsing_traits::hint_type purpose_hint = "regular expression"; ARGPARSE_TRAIT_PURPOSE_HINT = "regular expression";
}; };
template <> struct argument_parser::parsing_traits::parser_trait<std::vector<int>> {
static std::vector<int> parse(const std::string &input) {
std::vector<int> 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<std::vector<std::string>> { template <> struct argument_parser::parsing_traits::parser_trait<std::vector<std::string>> {
static std::vector<std::string> parse(const std::string &input) { static std::vector<std::string> parse(const std::string &input) {
@@ -58,8 +53,24 @@ template <> struct argument_parser::parsing_traits::parser_trait<std::vector<std
} }
return result; return result;
} }
static constexpr argument_parser::parsing_traits::hint_type format_hint = "string,string,string";
static constexpr argument_parser::parsing_traits::hint_type purpose_hint = "list of strings"; ARGPARSE_TRAIT_FORMAT_HINT = "string,string,string";
ARGPARSE_TRAIT_PURPOSE_HINT = "list of strings";
};
template <typename VT> struct argument_parser::parsing_traits::parser_trait<std::vector<VT>> {
static std::vector<VT> parse(const std::string &input) {
std::vector<VT> result;
std::stringstream ss{input};
std::string item;
while (std::getline(ss, item, ',')) {
result.push_back(argument_parser::parsing_traits::parser_trait<VT>::parse(item));
}
return result;
}
ARGPARSE_TRAIT_FORMAT_HINT = "VT,VT,VT";
ARGPARSE_TRAIT_PURPOSE_HINT = "list of VT";
}; };
const std::initializer_list<argument_parser::conventions::convention const *const> conventions = { const std::initializer_list<argument_parser::conventions::convention const *const> conventions = {
@@ -88,6 +99,7 @@ const auto cat = argument_parser::helpers::make_parametered_action<std::string>(
file.close(); file.close();
}); });
auto grep(argument_parser::base_parser const &parser, std::string const &filename, std::regex const &pattern) { auto grep(argument_parser::base_parser const &parser, std::string const &filename, std::regex const &pattern) {
if (filename.empty()) { if (filename.empty()) {
std::cerr << "Missing filename" << std::endl; std::cerr << "Missing filename" << std::endl;
@@ -135,7 +147,7 @@ void run_store_point(argument_parser::base_parser const &parser) {
int v2Examples() { int v2Examples() {
using namespace argument_parser::v2::flags; using namespace argument_parser::v2::flags;
argument_parser::v2::parser parser; argument_parser::v2::parser parser{ false };
parser.add_argument<std::string>( parser.add_argument<std::string>(
{{ShortArgument, "e"}, {LongArgument, "echo"}, {Action, echo}, {HelpText, "echoes given variable"}}); {{ShortArgument, "e"}, {LongArgument, "echo"}, {Action, echo}, {HelpText, "echoes given variable"}});
@@ -159,7 +171,8 @@ int v2Examples() {
}); });
parser.add_argument<std::string>( parser.add_argument<std::string>(
{{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<Point>({ parser.add_argument<Point>({
// { ShortArgument, "sp" }, // now if ShortArgument or LongArgument is missing, it will use it for the other. // { 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"}, {HelpText, "Output file path"},
}); });
parser.add_argument<std::vector<Point>>({{LongArgument, "points"}, {HelpText, "List of points to store"}});
parser.on_complete(::run_grep); parser.on_complete(::run_grep);
parser.on_complete(::run_store_point); parser.on_complete(::run_store_point);
parser.on_complete([](argument_parser::base_parser const &p) { parser.on_complete([](argument_parser::base_parser const &p) {
@@ -197,10 +212,43 @@ int v2Examples() {
return 0; return 0;
} }
int main() { auto unique_copy(std::unique_ptr<std::string> ptr) {
std::cout << *ptr << std::endl;
}
auto unique_reference(std::unique_ptr<std::string> const& ptr) {
std::cout << *ptr << std::endl;
}
auto unique_move(std::unique_ptr<std::string>&& ptr) {
std::cout << *ptr << std::endl;
}
template<typename T>
T return_example(std::function<T()> func) {
if constexpr (std::is_same_v<void, T>) {
return func();
} else {
return func();
}
}
template<typename T>
void log_result(std::function<T()> func) {
if constexpr (std::is_same_v<void, T>) {
func();
} else {
std::cout << "result: " << func() << std::endl;
}
}
int main(int argc, char **argv) {
try { try {
return_example<void>([]{});
return v2Examples(); return v2Examples();
} catch (std::exception const &e) { } catch (std::exception const &e) {
std::cout << e.what() << std::endl; std::cout << e.what() << std::endl;
} }
} }

View File

@@ -21,4 +21,30 @@ namespace argument_parser {
void fake_parser::set_parsed_arguments(std::vector<std::string> const &parsed_arguments) { void fake_parser::set_parsed_arguments(std::vector<std::string> const &parsed_arguments) {
this->parsed_arguments = parsed_arguments; this->parsed_arguments = parsed_arguments;
} }
} // namespace argument_parser
namespace v2 {
fake_parser::fake_parser(std::string program_name, std::vector<std::string> 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<std::string> &&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<std::string> const &arguments)
: fake_parser(program_name, std::vector<std::string>(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<std::string> const &parsed_arguments) {
ref_parsed_args() = parsed_arguments;
}
}
} // namespace argument_parser

View File

@@ -15,7 +15,7 @@ namespace argument_parser {
} }
namespace v2 { namespace v2 {
linux_parser::linux_parser() { linux_parser::linux_parser(bool should_exit) {
std::ifstream command_line_file{"/proc/self/cmdline"}; std::ifstream command_line_file{"/proc/self/cmdline"};
std::string program_name; std::string program_name;
std::getline(command_line_file, program_name, '\0'); std::getline(command_line_file, program_name, '\0');
@@ -25,7 +25,7 @@ namespace argument_parser {
parsed_arguments.emplace_back(line); parsed_arguments.emplace_back(line);
} }
prepare_help_flag(); prepare_help_flag(should_exit);
} }
} // namespace v2 } // namespace v2
} // namespace argument_parser } // namespace argument_parser

View File

@@ -2,32 +2,36 @@
#include "macos_parser.hpp" #include "macos_parser.hpp"
#include <crt_externs.h>
#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 { namespace argument_parser {
macos_parser::macos_parser() { macos_parser::macos_parser() {
const int argc = *_NSGetArgc(); MACOS_GETARGS_LOOP(argc, argv, program_name = argv[0], {
if (char **argv = *_NSGetArgv(); argc > 0 && argv != nullptr && argv[0] != nullptr) { if (argv[i] != nullptr)
program_name = (argv[0]); parsed_arguments.emplace_back(argv[i]);
for (int i = 1; i < argc; ++i) { });
if (argv[i] != nullptr)
parsed_arguments.emplace_back(argv[i]);
}
}
} }
namespace v2 { namespace v2 {
macos_parser::macos_parser() { macos_parser::macos_parser(bool should_exit) {
const int argc = *_NSGetArgc(); MACOS_GETARGS_LOOP(argc, argv, set_program_name(argv[0]), {
if (char **argv = *_NSGetArgv(); argc > 0 && argv != nullptr && argv[0] != nullptr) { if (argv[i] != nullptr)
set_program_name(argv[0]); ref_parsed_args().emplace_back(argv[i]);
for (int i = 1; i < argc; ++i) { });
if (argv[i] != nullptr) prepare_help_flag(should_exit);
ref_parsed_args().emplace_back(argv[i]);
}
}
prepare_help_flag();
} }
} // namespace v2 } // namespace v2
} // namespace argument_parser } // namespace argument_parser
#endif #endif

View File

@@ -95,12 +95,12 @@ namespace argument_parser {
} // namespace argument_parser } // namespace argument_parser
namespace argument_parser::v2 { namespace argument_parser::v2 {
windows_parser::windows_parser() { windows_parser::windows_parser(bool should_exit) {
parse_windows_arguments(ref_parsed_args(), parse_windows_arguments(ref_parsed_args(),
[this](std::string const &program_name) { this->set_program_name(program_name); }); [this](std::string const &program_name) { this->set_program_name(program_name); });
prepare_help_flag(); prepare_help_flag(should_exit);
} }
} // namespace argument_parser::v2 } // namespace argument_parser::v2
#endif #endif