26namespace argon_testing {
27struct argument_parser_test_fixture;
255 template <util::c_range_of<default_argument> AR>
292 template <util::c_argument_value_type T = std::
string>
304 template <util::c_argument_value_type T = std::
string>
329 template <util::c_argument_value_type T = std::
string>
331 const std::string_view
name,
345 template <util::c_argument_value_type T = std::
string>
363 template <util::c_argument_value_type T = std::
string>
366 const std::string_view
name,
398 template <util::c_argument_value_type T = std::
string>
430 template <
bool StoreImplicitly = true>
432 const std::string_view
name,
449 template <
bool StoreImplicitly = true>
468 template <
bool StoreImplicitly = true>
471 const std::string_view
name,
489 template <
bool StoreImplicitly = true>
520 throw std::logic_error(std::format(
521 "A subparser with the given name () already exists in parser '{}'",
522 (*subparser_it)->_name,
556 template <util::c_forward_range_of<std::
string, util::type_val
idator::convertible> AR>
563 "Failed to deduce the argument for values [{}]",
util::join(
state.unknown_args)
595 template <util::c_forward_range_of<std::
string, util::type_val
idator::convertible> AR>
601 std::cerr <<
"[argon::error] " <<
err.what() << std::endl
643 template <util::c_forward_range_of<std::
string, util::type_val
idator::convertible> AR>
647 return std::move(
state.unknown_args);
680 template <util::c_forward_range_of<std::
string, util::type_val
idator::convertible> AR>
686 std::cerr <<
"[argon::error] " <<
err.what() << std::endl
779 template <util::c_argument_value_type T = std::
string>
789 catch (
const std::bad_any_cast&) {
790 throw type_error::invalid_value_type<T>(
arg->
name());
803 template <util::c_argument_value_type T = std::
string, std::convertible_to<T> U>
813 catch (
const std::logic_error&) {
818 catch (
const std::bad_any_cast&) {
819 throw type_error::invalid_value_type<T>(
arg->
name());
831 template <util::c_argument_value_type T = std::
string>
840 util::any_range_cast_view<T>(
arg->
values()), std::back_inserter(
values)
844 catch (
const std::bad_any_cast&) {
845 throw type_error::invalid_value_type<T>(
arg->
name());
899 friend struct ::argon_testing::argument_parser_test_fixture;
903 using arg_ptr_t = std::shared_ptr<detail::argument_base>;
959 arg_name,
"An argument name cannot be empty."
964 arg_name,
"An argument name cannot contain whitespaces."
971 "An argument name cannot begin with a flag prefix character ({}).",
978 arg_name,
"An argument name cannot begin with a digit."
1037 if (
group._parser !=
this)
1038 throw std::logic_error(std::format(
1039 "An argument group '{}' does not belong to the given parser.",
group.
_name
1052 template <util::c_forward_iterator_of<std::
string, util::type_val
idator::convertible> AIt>
1088 if (
not arg->is_required()) {
1089 non_required_arg =
arg;
1095 "Required positional argument [{}] cannot be defined after a non-required "
1096 "positional argument [{}].",
1112 template <util::c_forward_iterator_of<std::
string, util::type_val
idator::convertible> AIt>
1138 toks.emplace_back(std::move(
tok));
1144 if (
state.parse_known_only) {
1145 toks.emplace_back(std::move(
tok));
1153 std::cerr <<
"[argon::warning] Unknown argument '" <<
tok.
value <<
"' will be ignored."
1160 toks.emplace_back(std::move(
tok));
1219 const auto opt_arg_it = std::ranges::find_if(
1250 const auto match_type =
1255 return std::ranges::find_if(
1289 if (
tok.is_flag_token())
1302 if (
not tok.is_valid_flag_token()) {
1303 if (
state.parse_known_only) {
1304 state.curr_arg.reset();
1314 for (
const auto&
arg :
tok.args) {
1315 if (
arg->mark_used())
1318 state.curr_arg.reset();
1348 if (
state.curr_arg->set_value(std::string(
value)))
1352 if (
state.curr_arg->is_positional()
1354 ++
state.curr_pos_arg_it;
1356 state.curr_arg.reset();
1376 bool suppress_group_checks =
false;
1377 bool suppress_arg_checks =
false;
1381 if (
arg->suppresses_group_checks())
1382 suppress_group_checks =
true;
1383 if (
arg->suppresses_arg_checks())
1384 suppress_arg_checks =
true;
1391 return {suppress_group_checks, suppress_arg_checks};
1402 const bool suppress_group_checks,
1403 const bool suppress_arg_checks
1405 if (
group._arguments.empty())
1408 if (
not suppress_group_checks) {
1409 const auto n_used_args =
static_cast<std::size_t
>(std::ranges::count_if(
1410 group._arguments, [](
const auto&
arg) { return arg->is_used(); }
1413 if (
group._mutually_exclusive) {
1416 "At most one argument from the mutually exclusive group '{}' can be used",
1421 group._arguments, [](
const auto&
arg) { return arg->is_used(); }
1433 "At least one argument from the required group '{}' must be used",
group.
_name
1438 for (
const auto&
arg :
group._arguments)
1449 if (suppress_arg_checks)
1454 std::format(
"No values parsed for a required argument [{}]",
arg->
name().str())
1485 os <<
"\nCommands:\n";
1487 std::vector<detail::help_builder>
builders;
1516 return not arg->is_hidden();
1525 if (
group._required)
1527 if (
group._mutually_exclusive)
1538 std::vector<detail::help_builder>
builders;
1591 switch (arg_discriminator) {
1593 arg_parser.add_positional_argument(
"input")
1595 .help(
"Input file path");
1599 arg_parser.add_positional_argument(
"output").help(
"Output file path");
1603 arg_parser.add_optional_argument<
none_type>(
"help",
"h")
1605 .help(
"Display the help message");
1609 arg_parser.add_optional_argument<
none_type>(
"version",
"v")
1610 .action<action_type::on_flag>([&arg_parser]() {
1611 arg_parser.print_version();
1612 std::exit(EXIT_SUCCESS);
1614 .help(
"Dsiplay program version info");
1618 arg_parser.add_optional_argument(
"input",
"i")
1621 .help(
"Input file path");
1625 arg_parser.add_optional_argument(
"output",
"o").nargs(1ull).help(
"Output file path");
1629 arg_parser.add_optional_argument(
"input",
"i")
1632 .help(
"Input files paths");
1636 arg_parser.add_optional_argument(
"output",
"o")
1638 .help(
"Output files paths");
Represents a group of arguments.
static std::unique_ptr< argument_group > create(argument_parser &parser, std::string_view name)
Factory method to create an argument group.
The main argument parser class.
std::vector< detail::argument_token > arg_token_vec_t
void print_help(const bool verbose, std::ostream &os=std::cout) const noexcept
Prints the argument parser's help message to an output stream.
argument_group & add_group(const std::string_view name) noexcept
Adds an argument group with the given name to the parser's configuration.
void print_version(std::ostream &os=std::cout) const noexcept
Prints the argument parser's version info to an output stream.
arg_ptr_vec_t _positional_args
The list of positional arguments.
void _parse_token(const detail::argument_token &tok, parsing_state &state)
Parse a single command-line argument token.
static constexpr char _flag_prefix_char
argument_parser(const std::string_view name, const std::string_view parent_name)
bool invoked() const noexcept
Check whether this parser was invoked.
optional_argument< T > & add_optional_argument(argument_group &group, const std::string_view primary_name, const std::string_view secondary_name)
Adds an optional argument to the parser's configuration and binds it to the given group.
argument_parser & operator=(argument_parser &&)=delete
std::vector< arg_group_ptr_t > arg_group_ptr_vec_t
std::string_view program_name() const noexcept
std::vector< arg_ptr_t > arg_ptr_vec_t
bool has_value(std::string_view arg_name) const noexcept
Check if the given argument has a value.
void _set_argument_value(const std::string_view value, parsing_state &state) noexcept
Set the value for the currently processed argument.
std::string _name
The name of the parser.
static constexpr std::string_view _flag_prefix
typename arg_token_vec_t::const_iterator arg_token_vec_iter_t
std::optional< std::string > _program_description
The description of the program.
positional_argument< T > & add_positional_argument(argument_group &group, const std::string_view name)
Adds a positional argument to the parser's configuration and binds it to the given group.
argument_parser & unknown_arguments_policy(const unknown_policy policy) noexcept
Set the unknown argument flags handling policy.
optional_argument< T > & add_optional_argument(argument_group &group, const std::string_view name, const detail::argument_name_discriminator name_discr=n_primary)
Adds an optional argument to the parser's configuration and binds it to the given group.
arg_parser_ptr_vec_t _subparsers
The list of subparsers.
argument_group & _gr_optional_args
The optional argument group.
argument_parser & program_description(std::string_view description) noexcept
Set the program description.
void _parse_flag_token(const detail::argument_token &tok, parsing_state &state)
Parse a single command-line argument flag token.
bool _verbose
Verbosity flag.
argument_parser & default_arguments(const AR &arg_discriminators) noexcept
Add default arguments to the argument parser.
optional_argument< bool > & add_flag(const std::string_view name, const detail::argument_name_discriminator name_discr=n_primary)
Adds a boolean flag argument (an optional argument with value_type = bool) to the parser's configurat...
arg_group_ptr_vec_t _argument_groups
The list of argument groups.
std::pair< bool, bool > _are_checks_suppressed() const noexcept
Check whether required argument group checks or argument checks suppressing is enabled.
void parse_args(int argc, char *argv[])
Parses the command-line arguments.
~argument_parser()=default
void parse_args(const AR &argv_rng)
Parses the command-line arguments.
std::vector< std::string > parse_known_args(int argc, char *argv[])
Parses the known command-line arguments.
optional_argument< T > & add_optional_argument(const std::string_view primary_name, const std::string_view secondary_name)
Adds an optional argument to the parser's configuration.
std::vector< T > values(std::string_view arg_name) const
Get all values of the given argument.
bool _finalized
A flag indicating whether the parsing process has been finalized.
arg_token_vec_t _tokenize(AIt args_begin, const AIt args_end, const parsing_state &state)
Converts the command-line arguments into a list of tokens.
optional_argument< T > & add_optional_argument(const std::string_view name, const detail::argument_name_discriminator name_discr=n_primary)
Adds an optional argument to the parser's configuration.
typename arg_ptr_vec_t::iterator arg_ptr_vec_iter_t
std::optional< std::string > _program_version
The version of the program.
argument_parser & default_arguments(const std::initializer_list< default_argument > &arg_discriminators) noexcept
Add default arguments to the argument parser.
std::string_view name() const noexcept
Returns the parser's name.
arg_ptr_vec_iter_t _find_opt_arg(const detail::argument_token &flag_tok) noexcept
Find an optional argument based on a flag token.
void try_parse_args(const AR &argv_rng)
Parses the command-line arguments and exits on error.
static constexpr std::uint8_t _primary_flag_prefix_length
void _parse_args_impl(AIt args_begin, const AIt args_end, parsing_state &state)
Implementation of parsing command-line arguments.
auto _name_match_predicate(const detail::argument_name &arg_name, const detail::argument_name::match_type m_type=detail::argument_name::m_any) const noexcept
Returns a unary predicate function which checks if the given name matches the argument's name.
auto _name_match_predicate(const std::string_view arg_name, const detail::argument_name::match_type m_type=detail::argument_name::m_any) const noexcept
Returns a unary predicate function which checks if the given name matches the argument's name.
void _validate_group(const argument_group &group)
Check if the given group belongs to the parser.
static constexpr std::uint8_t _indent_width
void _verify_arg_name_pattern(const std::string_view arg_name) const
Verifies the pattern of an argument name and if it's invalid, an error is thrown.
bool _validate_flag_token(detail::argument_token &tok) noexcept
Check if a flag token is valid based on its value.
std::vector< std::string > try_parse_known_args(const AR &argv_rng)
Parses known the command-line arguments and exits on error.
std::string _program_name
The name of the program in the format "<parent-parser-names>... <program-name>".
void _print_subparsers(std::ostream &os) const noexcept
argument_parser & add_subparser(const std::string_view name)
Adds an subparser with the given name to the parser's configuration.
T value(std::string_view arg_name) const
Get the value of the given argument.
void _print_group(std::ostream &os, const argument_group &group, const bool verbose) const noexcept
Print the given argument list to an output stream.
argument_parser & operator=(const argument_parser &)=delete
optional_argument< bool > & add_flag(argument_group &group, const std::string_view name, const detail::argument_name_discriminator name_discr=n_primary)
Adds a boolean flag argument (an optional argument with value_type = bool) to the parser's configurat...
argument_parser & verbose(const bool v=true) noexcept
Set the verbosity mode.
std::vector< std::string > try_parse_known_args(int argc, char *argv[])
Parses the known command-line arguments and exits on error.
void _tokenize_arg(const std::string_view arg_value, arg_token_vec_t &toks, const parsing_state &state)
Appends an argument token(s) created from arg_value to the toks vector.
detail::argument_token::token_type _deduce_token_type(const std::string_view arg_value) const noexcept
Returns the most appropriate initial token type based on a command-line argument's value.
std::vector< arg_parser_ptr_t > arg_parser_ptr_vec_t
void _verify_final_state() const
Verifies the correctness of the parsed command-line arguments.
void _parse_value_token(const detail::argument_token &tok, parsing_state &state)
Parse a single command-line argument value token.
argument_parser(argument_parser &&)=delete
argument_parser & program_version(const version &version) noexcept
Set the program version.
void _verify_argument_requirements(const arg_ptr_t &arg, const bool suppress_arg_checks) const
Verifies whether the requirements of the given argument are satisfied.
bool finalized() const noexcept
Check whether the parser has finalized parsing its own arguments.
bool _invoked
A flag indicating whether the parser has been invoked to parse arguments.
static constexpr std::uint8_t _secondary_flag_prefix_length
unknown_policy _unknown_policy
Policy for unknown arguments.
bool _is_arg_name_used(const detail::argument_name &arg_name, const detail::argument_name::match_type m_type=detail::argument_name::m_any) const noexcept
Check if an argument name is already used.
std::size_t count(std::string_view arg_name) const noexcept
Get the given argument's usage count.
optional_argument< bool > & add_flag(argument_group &group, const std::string_view primary_name, const std::string_view secondary_name)
Adds a boolean flag argument (an optional argument with value_type = bool) to the parser's configurat...
void _validate_argument_configuration() const
Validate whether the definition/configuration of the parser's arguments is correct.
argument_parser(const argument_parser &)=delete
positional_argument< T > & add_positional_argument(const std::string_view name)
Adds a positional argument to the parser's configuration.
argument_parser & resolved_parser() noexcept
Returns the deepest invoked parser.
arg_ptr_vec_t _optional_args
The list of optional arguments.
bool _validate_compound_flag_token(detail::argument_token &tok) noexcept
Check if a flag token is a valid compound argument flag based on its value.
argument_parser & default_arguments(const std::same_as< default_argument > auto... arg_discriminators) noexcept
Add default arguments to the argument parser.
argument_group & _gr_positional_args
The positional argument group.
optional_argument< bool > & add_flag(const std::string_view primary_name, const std::string_view secondary_name)
Adds a boolean flag argument (an optional argument with value_type = bool) to the parser's configurat...
bool is_used(std::string_view arg_name) const noexcept
Check if a specific argument was used in the command-line.
void _verify_group_requirements(const argument_group &group, const bool suppress_group_checks, const bool suppress_arg_checks) const
Verifies whether the requirements of the given argument group are satisfied.
std::unique_ptr< argument_group > arg_group_ptr_t
void try_parse_args(int argc, char *argv[])
Parses the command-line arguments and exits on error.
argument_parser & program_version(std::string_view version)
Set the program version.
friend std::ostream & operator<<(std::ostream &os, const argument_parser &parser) noexcept
Prints the argument parser's details to an output stream.
std::vector< std::string > parse_known_args(const AR &argv_rng)
Parses the known command-line arguments.
arg_ptr_t _get_argument(std::string_view arg_name) const noexcept
Get the argument with the specified name.
std::string_view _strip_flag_prefix(const detail::argument_token &tok) const noexcept
Removes the flag prefix from a flag token's value.
std::unique_ptr< argument_parser > arg_parser_ptr_t
T value_or(std::string_view arg_name, U &&fallback_value) const
Get the value of the given argument, if it has any, or a fallback value, if not.
std::shared_ptr< detail::argument_base > arg_ptr_t
argument_parser(const std::string_view name)
Represents a command-line argument, either positional or optional.
std::string join(const R &range, const std::string_view delimiter=", ")
Joins elements of a range into a single string with a delimiter.
argon::action_type::on_flag::type print_help(const argument_parser &parser, const std::optional< int > exit_code=std::nullopt, std::ostream &os=std::cout) noexcept
Returns an on-flag action which prints the argument parser's help message.
util::callable_type< argon::action_type::observe, std::string > check_file_exists() noexcept
Returns an observe action which checks whether lower_bound file with the given name exists.
void add_default_argument(const default_argument, argument_parser &) noexcept
Adds a predefined/default positional argument to the parser.
argument_name_discriminator
Argument name member discriminator.
constexpr range at_least(const count_type n) noexcept
range class builder function. Creates a range [n, inf).
bool contains_whitespaces(std::string_view str) noexcept
Checks whether a string contains any whitespace characters.
default_argument
The enumeration of default arguments provided by the library.
@ p_output
A positional argument representing a single output file path. Equivalent to:
@ o_help
An optional argument representing the program's help flag. Equivalent to:
@ p_input
A positional argument representing a single input file path. Equivalent to:
@ o_input
A positional argument representing multiple input file paths. Equivalent to:
@ o_multi_input
A positional argument representing multiple input file paths. Equivalent to:
@ o_version
An optional argument representing the program's version flag. Equivalent to:
@ o_output
A positional argument representing multiple output file paths. Equivalent to:
@ o_multi_output
A positional argument representing multiple output file paths. Equivalent to:
unknown_policy
The enumeration of policies for handling unknown arguments.
@ warn
Issue a warning when an unknown argument is encountered.
@ as_values
Treat unknown arguments as positional values.
@ ignore
Ignore unknown arguments.
@ fail
Throw an exception when an unknown argument is encountered.
Provides common ranges utility functions.
An observing value action specifier.
A collection of values used during the parsing process.
arg_ptr_t curr_arg
The currently processed argument.
std::vector< std::string > unknown_args
A vector of unknown argument values.
parsing_state(argument_parser &parser, const bool parse_known_only=false)
void set_parser(argument_parser &parser)
Update the parser-specific parameters of the state object.
arg_ptr_vec_iter_t curr_pos_arg_it
An iterator pointing to the next positional argument to be processed.
const bool parse_known_only
A flag indicating whether only known arguments should be parsed.
Base type for the argument parser functionality errors/exceptions.
Structure holding the argument's name.
match_type
Specifies the type of argument name match.
@ m_any
Matches either the primary or the secondary name.
@ m_primary
Matches only the primary name.
@ m_secondary
Matches only the secondary name.
Structure representing a single command-line argument token.
token_type
The token type discriminator.
@ t_flag_compound
Represents a compound flag argument (secondary flag matching multiple arguments).
@ t_value
Represents a value argument.
@ t_flag_secondary
Represents a secondary (-) flag argument.
@ t_flag_primary
Represents a primary (–) flag argument.
std::string value
The actual token's value.
Exception type used for invalid configuration of an argument parser or its arguments.
static invalid_configuration invalid_argument_name(const std::string_view arg_name, const std::string_view reason) noexcept
static invalid_configuration argument_name_used(const detail::argument_name &arg_name) noexcept
static lookup_failure argument_not_found(const std::string_view &arg_name) noexcept
A type representing the absence of a value. This type is used for arguments that should not store any...
Exception type used for errors encountered during the argument parsing operation.
static parsing_failure unknown_argument(const std::string_view arg_name) noexcept
static parsing_failure invalid_nvalues(const detail::argument_name &arg_name, const std::weak_ordering ordering) noexcept
A helper structure used to represent a program's version.
std::string str() const noexcept
Converts the structure into a string in the v{major}.{minor}.{path} format.