mirror of
https://github.com/sametersoylu/argument-parser.git
synced 2026-05-28 20:08:10 +00:00
chore: refactor class names.
feat: introduce parser settings for controlling the exit behavior.
This commit is contained in:
@@ -22,8 +22,8 @@ namespace argument_parser::builder {
|
||||
reference,
|
||||
accumulate,
|
||||
count,
|
||||
nonparametered_action,
|
||||
parametered_action
|
||||
action_no_param,
|
||||
action_with_param
|
||||
};
|
||||
|
||||
enum class extra_capability : unsigned { Store = static_cast<unsigned>(v2_flag::Reference) + 1, Flag };
|
||||
@@ -321,9 +321,9 @@ namespace argument_parser::builder {
|
||||
argument<builder_mask::remove(current_mask, builder_mask::value_mode_group), non_type>;
|
||||
|
||||
next_argument next{*this};
|
||||
next.m_action = std::make_shared<argument_parser::non_parametered_action>(
|
||||
next.m_action = std::make_shared<argument_parser::action_no_param>(
|
||||
std::function<void()>(std::forward<Callable>(handler)));
|
||||
next.m_value_mode = value_mode::nonparametered_action;
|
||||
next.m_value_mode = value_mode::action_no_param;
|
||||
return next;
|
||||
}
|
||||
|
||||
@@ -338,9 +338,9 @@ namespace argument_parser::builder {
|
||||
using next_argument = argument<builder_mask::remove(current_mask, builder_mask::value_mode_group), T>;
|
||||
|
||||
next_argument next{*this};
|
||||
next.m_action = std::make_shared<argument_parser::parametered_action<T>>(
|
||||
next.m_action = std::make_shared<argument_parser::action_with_param<T>>(
|
||||
std::function<void(const T &)>(std::forward<Callable>(handler)));
|
||||
next.m_value_mode = value_mode::parametered_action;
|
||||
next.m_value_mode = value_mode::action_with_param;
|
||||
return next;
|
||||
}
|
||||
|
||||
@@ -352,8 +352,8 @@ namespace argument_parser::builder {
|
||||
case value_mode::flag:
|
||||
build_flag(parser);
|
||||
return;
|
||||
case value_mode::nonparametered_action:
|
||||
build_nonparametered_action(parser);
|
||||
case value_mode::action_no_param:
|
||||
build_action_with_no_param(parser);
|
||||
return;
|
||||
case value_mode::store:
|
||||
if constexpr (!std::is_same_v<store_type, non_type>) {
|
||||
@@ -374,9 +374,9 @@ namespace argument_parser::builder {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case value_mode::parametered_action:
|
||||
case value_mode::action_with_param:
|
||||
if constexpr (!std::is_same_v<store_type, non_type>) {
|
||||
build_parametered_action(parser);
|
||||
build_action_with_param(parser);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@@ -535,9 +535,9 @@ namespace argument_parser::builder {
|
||||
parser.template add_argument<store_type>(pairs);
|
||||
}
|
||||
|
||||
auto build_parametered_action(argument_parser::v2::base_parser &parser) const -> void {
|
||||
auto build_action_with_param(argument_parser::v2::base_parser &parser) const -> void {
|
||||
auto const *typed_action =
|
||||
dynamic_cast<argument_parser::parametered_action<store_type> const *>(m_action.get());
|
||||
dynamic_cast<argument_parser::action_with_param<store_type> const *>(m_action.get());
|
||||
if (typed_action == nullptr) {
|
||||
throw std::logic_error("Stored action is not compatible with the requested parameter type.");
|
||||
}
|
||||
@@ -547,15 +547,14 @@ namespace argument_parser::builder {
|
||||
parser.template add_argument<store_type>(pairs);
|
||||
}
|
||||
|
||||
auto build_nonparametered_action(argument_parser::v2::base_parser &parser) const -> void {
|
||||
auto const *nonparametered_action =
|
||||
dynamic_cast<argument_parser::non_parametered_action const *>(m_action.get());
|
||||
auto build_action_with_no_param(argument_parser::v2::base_parser &parser) const -> void {
|
||||
auto const *nonparametered_action = dynamic_cast<argument_parser::action_no_param const *>(m_action.get());
|
||||
if (nonparametered_action == nullptr) {
|
||||
throw std::logic_error("Stored action is not a non-parametered action.");
|
||||
}
|
||||
|
||||
if (is_positional()) {
|
||||
auto wrapped_action = argument_parser::helpers::make_parametered_action<std::string>(
|
||||
auto wrapped_action = argument_parser::helpers::make_action<std::string>(
|
||||
[action = *nonparametered_action](std::string const &) { action.invoke(); });
|
||||
auto pairs = make_typed_pairs<std::string>();
|
||||
pairs[argument_parser::v2::flags::Action] = wrapped_action;
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace argument_parser {
|
||||
copyable_atomic &operator=(copyable_atomic &&other) noexcept = default;
|
||||
~copyable_atomic() = default;
|
||||
|
||||
copyable_atomic& operator=(T desired) noexcept {
|
||||
copyable_atomic &operator=(T desired) noexcept {
|
||||
store(desired);
|
||||
return *this;
|
||||
}
|
||||
@@ -104,9 +104,9 @@ namespace argument_parser {
|
||||
[[nodiscard]] virtual std::unique_ptr<action_base> clone() const = 0;
|
||||
};
|
||||
|
||||
template <typename T> class parametered_action : public action_base {
|
||||
template <typename T> class action_with_param : public action_base {
|
||||
public:
|
||||
explicit parametered_action(std::function<void(const T &)> const &handler) : handler(handler) {}
|
||||
explicit action_with_param(std::function<void(const T &)> const &handler) : handler(handler) {}
|
||||
using parameter_type = T;
|
||||
void invoke(const T &arg) const {
|
||||
handler(arg);
|
||||
@@ -149,16 +149,16 @@ namespace argument_parser {
|
||||
}
|
||||
|
||||
[[nodiscard]] std::unique_ptr<action_base> clone() const override {
|
||||
return std::make_unique<parametered_action<T>>(handler);
|
||||
return std::make_unique<action_with_param<T>>(handler);
|
||||
}
|
||||
|
||||
private:
|
||||
std::function<void(const T &)> handler;
|
||||
};
|
||||
|
||||
class non_parametered_action : public action_base {
|
||||
class action_no_param : public action_base {
|
||||
public:
|
||||
explicit non_parametered_action(std::function<void()> const &handler) : handler(handler) {}
|
||||
explicit action_no_param(std::function<void()> const &handler) : handler(handler) {}
|
||||
|
||||
void invoke() const override {
|
||||
handler();
|
||||
@@ -177,7 +177,7 @@ namespace argument_parser {
|
||||
}
|
||||
|
||||
[[nodiscard]] std::unique_ptr<action_base> clone() const override {
|
||||
return std::make_unique<non_parametered_action>(handler);
|
||||
return std::make_unique<action_no_param>(handler);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -230,16 +230,27 @@ namespace argument_parser {
|
||||
};
|
||||
|
||||
namespace helpers {
|
||||
template <typename T>
|
||||
static parametered_action<T> make_parametered_action(std::function<void(const T &)> const &function) {
|
||||
return parametered_action<T>(function);
|
||||
template <typename T> static action_with_param<T> make_action(std::function<void(const T &)> const &function) {
|
||||
return action_with_param<T>(function);
|
||||
}
|
||||
|
||||
static non_parametered_action make_non_parametered_action(std::function<void()> const &function) {
|
||||
return non_parametered_action(function);
|
||||
static action_no_param make_action(std::function<void()> const &function) {
|
||||
return action_no_param(function);
|
||||
}
|
||||
} // namespace helpers
|
||||
|
||||
struct parser_settings {
|
||||
bool should_exit_on_error = true;
|
||||
bool should_exit_on_missing_required = true;
|
||||
bool should_exit_on_unknown_argument = true;
|
||||
bool should_exit_on_help = true;
|
||||
|
||||
bool ignore_unknown_arguments = false;
|
||||
bool ignore_errors = false;
|
||||
};
|
||||
|
||||
constexpr static inline parser_settings no_exit{false, false, false, false};
|
||||
|
||||
/**
|
||||
* @brief Base class for parsing arguments from the command line.
|
||||
*
|
||||
@@ -251,7 +262,7 @@ namespace argument_parser {
|
||||
public:
|
||||
template <typename T>
|
||||
void add_argument(std::string const &short_arg, std::string const &long_arg, std::string const &help_text,
|
||||
parametered_action<T> const &action, bool required) {
|
||||
action_with_param<T> const &action, bool required) {
|
||||
base_add_argument(short_arg, long_arg, help_text, action, required);
|
||||
}
|
||||
|
||||
@@ -262,7 +273,7 @@ namespace argument_parser {
|
||||
}
|
||||
|
||||
void add_argument(std::string const &short_arg, std::string const &long_arg, std::string const &help_text,
|
||||
non_parametered_action const &action, bool required) {
|
||||
action_no_param const &action, bool required) {
|
||||
base_add_argument(short_arg, long_arg, help_text, action, required);
|
||||
}
|
||||
|
||||
@@ -273,7 +284,7 @@ namespace argument_parser {
|
||||
|
||||
template <typename T>
|
||||
void add_positional_argument(std::string const &name, std::string const &help_text,
|
||||
parametered_action<T> const &action, bool required,
|
||||
action_with_param<T> const &action, bool required,
|
||||
std::optional<int> position = std::nullopt) {
|
||||
base_add_positional_argument(name, help_text, action, required, position);
|
||||
}
|
||||
@@ -286,7 +297,7 @@ namespace argument_parser {
|
||||
|
||||
template <typename T>
|
||||
void add_positional_accumulator(std::string const &name, std::string const &help_text,
|
||||
parametered_action<T> const &action, bool required,
|
||||
action_with_param<T> const &action, bool required,
|
||||
std::optional<int> position = std::nullopt) {
|
||||
base_add_positional_argument(name, help_text, action, required, position, true);
|
||||
}
|
||||
@@ -335,7 +346,12 @@ namespace argument_parser {
|
||||
|
||||
void on_complete(std::function<void(base_parser const &)> const &handler, bool to_start);
|
||||
|
||||
void set_settings(parser_settings const &settings) {
|
||||
m_settings = settings;
|
||||
}
|
||||
|
||||
private:
|
||||
parser_settings m_settings;
|
||||
struct found_argument {
|
||||
std::string key;
|
||||
argument arg;
|
||||
@@ -343,15 +359,12 @@ namespace argument_parser {
|
||||
};
|
||||
|
||||
bool test_conventions(std::initializer_list<conventions::convention const *const> convention_types,
|
||||
std::vector<found_argument> &found_arguments,
|
||||
std::optional<argument> &found_help, std::vector<std::string>::iterator &it,
|
||||
std::stringstream &error_stream);
|
||||
std::vector<found_argument> &found_arguments, std::optional<argument> &found_help,
|
||||
std::vector<std::string>::iterator &it, std::stringstream &error_stream);
|
||||
void extract_arguments(std::initializer_list<conventions::convention const *const> convention_types,
|
||||
std::vector<found_argument> &found_arguments,
|
||||
std::optional<argument> &found_help);
|
||||
std::vector<found_argument> &found_arguments, std::optional<argument> &found_help);
|
||||
|
||||
void invoke_arguments(std::vector<found_argument> &found_arguments,
|
||||
std::optional<argument> const &found_help);
|
||||
void invoke_arguments(std::vector<found_argument> &found_arguments, std::optional<argument> const &found_help);
|
||||
void enforce_creation_thread() const;
|
||||
|
||||
void assert_argument_not_exist(std::string const &short_arg, std::string const &long_arg) const;
|
||||
@@ -379,13 +392,12 @@ namespace argument_parser {
|
||||
assert_argument_not_exist(short_arg, long_arg);
|
||||
int id = id_counter.fetch_add(1);
|
||||
if constexpr (std::is_same_v<StoreType, void>) {
|
||||
auto action =
|
||||
helpers::make_non_parametered_action([id, this] { stored_arguments[id] = std::any{true}; });
|
||||
auto action = helpers::make_action([id, this] { stored_arguments[id] = std::any{true}; });
|
||||
argument arg(id, short_arg + "|" + long_arg, action);
|
||||
set_argument_status(required, help_text, arg);
|
||||
place_argument(id, arg, short_arg, long_arg);
|
||||
} else {
|
||||
auto action = helpers::make_parametered_action<StoreType>(
|
||||
auto action = helpers::make_action<StoreType>(
|
||||
[id, this](StoreType const &value) { stored_arguments[id] = std::any{value}; });
|
||||
argument arg(id, short_arg + "|" + long_arg, action);
|
||||
set_argument_status(required, help_text, arg);
|
||||
@@ -412,7 +424,7 @@ namespace argument_parser {
|
||||
std::optional<int> position = std::nullopt) {
|
||||
assert_positional_not_exist(name);
|
||||
int id = id_counter.fetch_add(1);
|
||||
auto action = helpers::make_parametered_action<StoreType>(
|
||||
auto action = helpers::make_action<StoreType>(
|
||||
[id, this](StoreType const &value) { stored_arguments[id] = std::any{value}; });
|
||||
argument arg(id, name, action);
|
||||
set_argument_status(required, help_text, arg);
|
||||
|
||||
18
src/headers/parser/exceptions.hpp
Normal file
18
src/headers/parser/exceptions.hpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef ARGUMENT_PARSER_EXCEPTIONS_HPP
|
||||
#define ARGUMENT_PARSER_EXCEPTIONS_HPP
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace argument_parser {
|
||||
namespace parser {
|
||||
class unknown_argument_exception : public std::runtime_error {
|
||||
public:
|
||||
unknown_argument_exception(const std::string &message) : std::runtime_error(message) {}
|
||||
};
|
||||
|
||||
} // namespace parser
|
||||
} // namespace argument_parser
|
||||
|
||||
#endif // ARGUMENT_PARSER_EXCEPTIONS_HPP
|
||||
@@ -57,15 +57,15 @@ namespace argument_parser::v2 {
|
||||
|
||||
class base_parser : argument_parser::base_parser {
|
||||
public:
|
||||
template <typename T> using typed_flag_value = std::variant<std::string, parametered_action<T>, bool, int, T *>;
|
||||
using non_typed_flag_value = std::variant<std::string, non_parametered_action, bool, int>;
|
||||
template <typename T> using typed_flag_value = std::variant<std::string, action_with_param<T>, bool, int, T *>;
|
||||
using non_typed_flag_value = std::variant<std::string, action_no_param, bool, int>;
|
||||
|
||||
template <typename T> using typed_argument_pair = std::pair<add_argument_flags, typed_flag_value<T>>;
|
||||
using non_typed_argument_pair = std::pair<add_argument_flags, non_typed_flag_value>;
|
||||
|
||||
template <typename T>
|
||||
void add_argument(std::unordered_map<add_argument_flags, typed_flag_value<T>> const &argument_pairs) {
|
||||
add_argument_impl<true, parametered_action<T>, T>(argument_pairs);
|
||||
add_argument_impl<true, action_with_param<T>, T>(argument_pairs);
|
||||
}
|
||||
|
||||
template <typename T> void add_argument(std::initializer_list<typed_argument_pair<T>> const &pairs) {
|
||||
@@ -89,7 +89,7 @@ namespace argument_parser::v2 {
|
||||
}
|
||||
|
||||
void add_argument(std::unordered_map<add_argument_flags, non_typed_flag_value> const &argument_pairs) {
|
||||
add_argument_impl<false, non_parametered_action, void>(argument_pairs);
|
||||
add_argument_impl<false, action_no_param, void>(argument_pairs);
|
||||
}
|
||||
|
||||
argument_parser::base_parser &to_v1() {
|
||||
@@ -122,7 +122,7 @@ namespace argument_parser::v2 {
|
||||
void prepare_help_flag(bool should_exit = true) {
|
||||
add_argument({{flags::ShortArgument, "h"},
|
||||
{flags::LongArgument, "help"},
|
||||
{flags::Action, helpers::make_non_parametered_action([this, should_exit] {
|
||||
{flags::Action, helpers::make_action([this, should_exit] {
|
||||
this->display_help(this->current_conventions());
|
||||
if (should_exit) {
|
||||
std::exit(0);
|
||||
@@ -131,6 +131,10 @@ namespace argument_parser::v2 {
|
||||
{flags::HelpText, "Prints this help text."}});
|
||||
}
|
||||
|
||||
void set_settings(parser_settings const &settings) {
|
||||
base::set_settings(settings);
|
||||
}
|
||||
|
||||
private:
|
||||
template <bool IsTyped, typename ActionType, typename T, typename ArgsMap>
|
||||
void add_argument_impl(ArgsMap const &argument_pairs) {
|
||||
@@ -224,7 +228,7 @@ namespace argument_parser::v2 {
|
||||
|
||||
base::add_argument<typename T::value_type>(
|
||||
short_arg, long_arg, help_text,
|
||||
*static_cast<parametered_action<typename T::value_type> *>(&(*action)), required);
|
||||
*static_cast<action_with_param<typename T::value_type> *>(&(*action)), required);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -375,7 +379,7 @@ namespace argument_parser::v2 {
|
||||
if constexpr (!std::is_same_v<T, void> && deducers::is_vector_v<T>) {
|
||||
base::add_positional_accumulator<typename T::value_type>(
|
||||
positional_name, help_text,
|
||||
*static_cast<parametered_action<typename T::value_type> *>(&(*action)), required, position);
|
||||
*static_cast<action_with_param<typename T::value_type> *>(&(*action)), required, position);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -452,16 +456,15 @@ namespace argument_parser::v2 {
|
||||
}
|
||||
|
||||
template <typename T> std::unique_ptr<action_base> make_reference_action(T *target) {
|
||||
return helpers::make_parametered_action<T>([target](T const &value) { *target = value; }).clone();
|
||||
return helpers::make_action<T>([target](T const &value) { *target = value; }).clone();
|
||||
}
|
||||
|
||||
template <typename Vector> std::unique_ptr<action_base> make_accumulate_ref_action(Vector *target) {
|
||||
if constexpr (std::is_same_v<Vector, int>) {
|
||||
return helpers::make_non_parametered_action([target]() { *target += 1; }).clone();
|
||||
return helpers::make_action([target]() { *target += 1; }).clone();
|
||||
} else {
|
||||
using Value = typename Vector::value_type;
|
||||
return helpers::make_parametered_action<Value>(
|
||||
[target](Value const &value) { target->emplace_back(value); })
|
||||
return helpers::make_action<Value>([target](Value const &value) { target->emplace_back(value); })
|
||||
.clone();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace argument_parser {
|
||||
namespace v2 {
|
||||
class linux_parser : public v2::base_parser {
|
||||
public:
|
||||
linux_parser(bool should_exit = true);
|
||||
linux_parser(parser_settings const &settings = {});
|
||||
using base_parser::display_help;
|
||||
};
|
||||
} // namespace v2
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace argument_parser {
|
||||
namespace v2 {
|
||||
class macos_parser : public v2::base_parser {
|
||||
public:
|
||||
explicit macos_parser(bool should_exit = true);
|
||||
explicit macos_parser(parser_settings const &settings = {});
|
||||
using base_parser::display_help;
|
||||
};
|
||||
} // namespace v2
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace argument_parser {
|
||||
namespace v2 {
|
||||
class windows_parser : public v2::base_parser {
|
||||
public:
|
||||
windows_parser(bool should_exit = true);
|
||||
windows_parser(parser_settings const &settings = {});
|
||||
using base_parser::display_help;
|
||||
};
|
||||
} // namespace v2
|
||||
|
||||
Reference in New Issue
Block a user