19struct optional_argument_test_fixture;
24namespace ap::argument {
30template <detail::c_argument_value_type T = std::
string>
52 return this->_name == other._name;
61 this->_help_msg = help_msg;
72 this->_required =
true;
81 this->_bypass_required =
true;
91 this->_nargs_range = range;
112 this->_nargs_range =
nargs::range(lower_bound, upper_bound);
123 template <action::detail::c_action_specifier AS,
typename F>
127 this->_value_actions.emplace_back(std::forward<callable_type>(
action));
130 this->_flag_actions.emplace_back(std::forward<flag_action_type>(
action));
144 template <detail::c_range_of<value_type, detail::type_val
idator::convertible> CR>
146 requires(std::equality_comparable<value_type>)
148 for (
const auto& choice :
choices)
149 this->_choices.emplace_back(choice);
160 requires(std::equality_comparable<value_type>)
162 return this->choices<>(
choices);
186 friend class ::ap::argument_parser;
192 friend struct ::ap_testing::optional_argument_test_fixture;
196 using value_action_type =
198 using flag_action_type =
typename action_type::on_flag::type;
206 const noexcept override {
212 desc.params.reserve(6);
215 if (this->_bypass_required)
216 desc.
add_param(
"bypass required",
"true");
218 desc.
add_param(
"nargs", this->_nargs_range);
220 if (not this->_choices.empty())
222 if (this->_default_value.has_value())
223 desc.
add_param(
"default value", std::any_cast<value_type>(this->_default_value));
224 if (this->_implicit_value.has_value())
225 desc.
add_param(
"implicit value", std::any_cast<value_type>(this->_implicit_value));
232 [[nodiscard]]
bool is_required() const noexcept
override {
233 return this->_required;
237 [[nodiscard]]
bool bypass_required_enabled() const noexcept
override {
238 return this->_bypass_required;
242 bool mark_used()
override {
244 for (
const auto& action : this->_flag_actions)
246 return this->_accepts_further_values();
250 [[nodiscard]]
bool is_used() const noexcept
override {
251 return this->_count > 0;
255 [[nodiscard]] std::size_t count() const noexcept
override {
265 bool set_value(
const std::string& str_value)
override {
266 if (not this->_accepts_further_values())
267 throw parsing_failure::invalid_nvalues(this->_name, std::weak_ordering::greater);
270 if (not (std::istringstream(str_value) >> value))
271 throw parsing_failure::invalid_value(this->_name, str_value);
273 if (not detail::is_valid_choice(value, this->_choices))
274 throw parsing_failure::invalid_choice(this->_name, str_value);
276 const auto apply_visitor = action::detail::apply_visitor<value_type>{value};
277 for (
const auto& action : this->_value_actions)
278 std::visit(apply_visitor,
action);
280 this->_values.emplace_back(std::move(value));
281 return this->_accepts_further_values();
285 [[nodiscard]]
bool has_value() const noexcept
override {
286 return this->has_parsed_values() or this->_has_predefined_value();
290 [[nodiscard]]
bool has_parsed_values() const noexcept
override {
291 return not this->_values.empty();
295 [[nodiscard]] std::weak_ordering nvalues_ordering() const noexcept
override {
296 if (this->_values.empty() and this->_has_predefined_value())
297 return std::weak_ordering::equivalent;
299 return this->_nargs_range.
ordering(this->_values.size());
303 [[nodiscard]]
const std::any& value()
const override {
304 return this->_values.empty() ? this->_predefined_value() : this->_values.front();
308 [[nodiscard]]
const std::vector<std::any>& values()
const override {
309 return this->_values;
313 [[nodiscard]]
bool _has_predefined_value() const noexcept {
314 return this->_default_value.has_value()
315 or (this->is_used() and this->_implicit_value.has_value());
322 [[nodiscard]]
const std::any& _predefined_value()
const {
323 if (this->is_used()) {
324 if (not this->_implicit_value.has_value())
325 throw(std::logic_error(
326 std::format(
"No implicit value specified for argument `{}`.", this->_name.
str())
329 return this->_implicit_value;
332 if (not this->_default_value.has_value())
333 throw(std::logic_error(
334 std::format(
"No default value specified for argument `{}`.", this->_name.
str())
337 return this->_default_value;
340 [[nodiscard]]
bool _accepts_further_values() const noexcept {
341 return not std::is_gt(this->_nargs_range.
ordering(this->_values.size() + 1ull));
344 bool _required =
false;
345 bool _bypass_required =
false;
346 nargs::range _nargs_range = nargs::any();
347 std::any _default_value;
348 std::any _implicit_value;
349 std::vector<value_type> _choices;
350 std::vector<flag_action_type> _flag_actions;
351 std::vector<value_action_type> _value_actions;
353 std::size_t _count = 0ull;
354 std::vector<std::any> _values;
Defines the base argument class and common utility.
Defines structures for formatting argument descriptions.
The optioanl argument class.
optional & help(std::string_view help_msg) noexcept
Set the help message for the optional argument.
optional(const detail::argument_name &name)
Constructor for optional argument with the name identifier.
optional & default_value(const value_type &default_value) noexcept
Set the default value for the optional argument.
optional & choices(std::initializer_list< value_type > choices) noexcept
Set the choices for the optional argument.
optional & required() noexcept
Mark the optional argument as required.
optional & action(F &&action) noexcept
Set the action for the optional argument.
optional & implicit_value(const value_type &implicit_value) noexcept
Set the implicit value for the optional argument.
T value_type
The argument's value type.
optional & nargs(const nargs::range &range) noexcept
Set the nargs range for the optional argument.
optional & bypass_required() noexcept
Enable bypassing the required status for the optional argument.
optional & nargs(const count_type lower_bound, const count_type upper_bound) noexcept
Set the nargs range for the optional argument.
optional & choices(const CR &choices) noexcept
Set the choices for the optional argument.
nargs::range::count_type count_type
The argument's value count type.
bool operator==(const optional &other) const noexcept
Equality comparison operator for optional argument.
optional & nargs(const count_type n) noexcept
Set the nargs range for the optional argument.
Argument class interface.
const ap::detail::argument_name & name() const noexcept
A structure used to represent an argument's description.
void add_range_param(const std::string &name, const R &range, const std::string_view delimiter=default_delimiter)
Adds a range parameter descriptor with the given value.
void add_param(const std::string &name, const std::string &value)
Adds a parameter descriptor with the given string value.
Argument's number of values managing class.
std::weak_ordering ordering(const range::count_type n) const noexcept
Determines the ordering of the count against a range instance.
bool is_bound() const noexcept
Returns true if at least one bound (lower, upper) is set. Otherwise returns false
The concept is satisfied when AS is a valid value action action specifier.
The concept is satisfied when T overloads the std::ostream operator <<.
Provides the general concept definitions.
Defines the nargs::range class and it's builder functions.
Structure holding the argument's name.
std::string str(const std::optional< char > flag_char=std::nullopt) const noexcept
Get a string representation of the argument_name.
Defines general action-related utility.
typename AS::template type< T > callable_type
Template argument action callable type alias.
std::variant< callable_type< action_type::observe, T >, callable_type< action_type::transform, T >, callable_type< action_type::modify, T > > value_action_variant_type
Template argument action callabla variant type alias.