26struct argument_parser_test_fixture;
254 template <util::c_range_of<default_argument> AR>
291 template <util::c_argument_value_type T = std::
string>
303 template <util::c_argument_value_type T = std::
string>
328 template <util::c_argument_value_type T = std::
string>
330 const std::string_view
name,
344 template <util::c_argument_value_type T = std::
string>
362 template <util::c_argument_value_type T = std::
string>
365 const std::string_view
name,
397 template <util::c_argument_value_type T = std::
string>
429 template <
bool StoreImplicitly = true>
431 const std::string_view
name,
448 template <
bool StoreImplicitly = true>
467 template <
bool StoreImplicitly = true>
470 const std::string_view
name,
488 template <
bool StoreImplicitly = true>
519 throw std::logic_error(std::format(
520 "A subparser with the given name () already exists in parser '{}'",
521 (*subparser_it)->_name,
555 template <util::c_forward_range_of<std::
string, util::type_val
idator::convertible> AR>
562 "Failed to deduce the argument for values [{}]",
util::join(
state.unknown_args)
594 template <util::c_forward_range_of<std::
string, util::type_val
idator::convertible> AR>
600 std::cerr <<
"[ap::error] " <<
err.what() << std::endl
642 template <util::c_forward_range_of<std::
string, util::type_val
idator::convertible> AR>
646 return std::move(
state.unknown_args);
679 template <util::c_forward_range_of<std::
string, util::type_val
idator::convertible> AR>
685 std::cerr <<
"[ap::error] " <<
err.what() << std::endl
778 template <util::c_argument_value_type T = std::
string>
788 catch (
const std::bad_any_cast&) {
789 throw type_error::invalid_value_type<T>(
arg->
name());
802 template <util::c_argument_value_type T = std::
string, std::convertible_to<T> U>
812 catch (
const std::logic_error&) {
817 catch (
const std::bad_any_cast&) {
818 throw type_error::invalid_value_type<T>(
arg->
name());
829 template <util::c_argument_value_type T = std::
string>
839 util::any_range_cast_view<T>(
arg->
values()), std::back_inserter(
values)
843 catch (
const std::bad_any_cast&) {
844 throw type_error::invalid_value_type<T>(
arg->
name());
898 friend struct ::ap_testing::argument_parser_test_fixture;
902 using arg_ptr_t = std::shared_ptr<detail::argument_base>;
958 arg_name,
"An argument name cannot be empty."
963 arg_name,
"An argument name cannot contain whitespaces."
970 "An argument name cannot begin with a flag prefix character ({}).",
977 arg_name,
"An argument name cannot begin with a digit."
1036 if (
group._parser !=
this)
1037 throw std::logic_error(std::format(
1038 "An argument group '{}' does not belong to the given parser.",
group.
_name
1051 template <util::c_forward_iterator_of<std::
string, util::type_val
idator::convertible> AIt>
1087 if (
not arg->is_required()) {
1088 non_required_arg =
arg;
1094 "Required positional argument [{}] cannot be defined after a non-required "
1095 "positional argument [{}].",
1111 template <util::c_forward_iterator_of<std::
string, util::type_val
idator::convertible> AIt>
1137 toks.emplace_back(std::move(
tok));
1143 if (
state.parse_known_only) {
1144 toks.emplace_back(std::move(
tok));
1152 std::cerr <<
"[ap::warning] Unknown argument '" <<
tok.
value <<
"' will be ignored."
1159 toks.emplace_back(std::move(
tok));
1218 const auto opt_arg_it = std::ranges::find_if(
1249 const auto match_type =
1254 return std::ranges::find_if(
1288 if (
tok.is_flag_token())
1301 if (
not tok.is_valid_flag_token()) {
1302 if (
state.parse_known_only) {
1303 state.curr_arg.reset();
1313 for (
const auto&
arg :
tok.args) {
1314 if (
arg->mark_used())
1317 state.curr_arg.reset();
1347 if (
state.curr_arg->set_value(std::string(
value)))
1351 if (
state.curr_arg->is_positional()
1353 ++
state.curr_pos_arg_it;
1355 state.curr_arg.reset();
1375 bool suppress_group_checks =
false;
1376 bool suppress_arg_checks =
false;
1380 if (
arg->suppresses_group_checks())
1381 suppress_group_checks =
true;
1382 if (
arg->suppresses_arg_checks())
1383 suppress_arg_checks =
true;
1390 return {suppress_group_checks, suppress_arg_checks};
1401 const bool suppress_group_checks,
1402 const bool suppress_arg_checks
1404 if (
group._arguments.empty())
1407 if (
not suppress_group_checks) {
1408 const auto n_used_args =
static_cast<std::size_t
>(std::ranges::count_if(
1409 group._arguments, [](
const auto&
arg) { return arg->is_used(); }
1412 if (
group._mutually_exclusive) {
1415 "At most one argument from the mutually exclusive group '{}' can be used",
1420 group._arguments, [](
const auto&
arg) { return arg->is_used(); }
1432 "At least one argument from the required group '{}' must be used",
group.
_name
1437 for (
const auto&
arg :
group._arguments)
1448 if (suppress_arg_checks)
1453 std::format(
"No values parsed for a required argument [{}]",
arg->
name().str())
1484 os <<
"\nCommands:\n";
1486 std::vector<detail::help_builder>
builders;
1512 return not arg->is_hidden();
1521 if (
group._required)
1523 if (
group._mutually_exclusive)
1535 std::vector<detail::help_builder>
builders;
1588 switch (arg_discriminator) {
1590 arg_parser.add_positional_argument(
"input")
1592 .help(
"Input file path");
1596 arg_parser.add_positional_argument(
"output").help(
"Output file path");
1600 arg_parser.add_optional_argument<
none_type>(
"help",
"h")
1602 .help(
"Display the help message");
1606 arg_parser.add_optional_argument<
none_type>(
"version",
"v")
1607 .action<action_type::on_flag>([&arg_parser]() {
1608 arg_parser.print_version();
1609 std::exit(EXIT_SUCCESS);
1611 .help(
"Dsiplay program version info");
1615 arg_parser.add_optional_argument(
"input",
"i")
1618 .help(
"Input file path");
1622 arg_parser.add_optional_argument(
"output",
"o").nargs(1ull).help(
"Output file path");
1626 arg_parser.add_optional_argument(
"input",
"i")
1629 .help(
"Input files paths");
1633 arg_parser.add_optional_argument(
"output",
"o")
1635 .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< arg_ptr_t > arg_ptr_vec_t
std::string _program_name
The name of the program in the format "<parent-parser-names>... <program-name>".
argument_parser & program_version(const version &version) noexcept
Set the program version.
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.
std::vector< std::string > try_parse_known_args(int argc, char *argv[])
Parses the known command-line arguments and exits on error.
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.
void try_parse_args(const AR &argv_rng)
Parses the command-line arguments and exits on error.
void _validate_group(const argument_group &group)
Check if the given group belongs to the parser.
std::string_view program_name() const noexcept
void _parse_flag_token(const detail::argument_token &tok, parsing_state &state)
Parse a single command-line argument flag token.
bool finalized() const noexcept
Check whether the parser has finalized parsing its own arguments.
static constexpr std::uint8_t _indent_width
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.
~argument_parser()=default
std::shared_ptr< detail::argument_base > arg_ptr_t
arg_group_ptr_vec_t _argument_groups
The list of argument groups.
arg_ptr_vec_t _optional_args
The list of optional arguments.
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...
argument_parser & program_version(std::string_view version)
Set the program version.
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.
std::optional< std::string > _program_description
The description of the program.
bool _validate_flag_token(detail::argument_token &tok) noexcept
Check if a flag token is valid based on its value.
std::pair< bool, bool > _are_checks_suppressed() const noexcept
Check whether required argument group checks or argument checks suppressing is enabled.
void print_help(const bool verbose, std::ostream &os=std::cout) const noexcept
Prints the argument parser's help message to an output stream.
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...
argument_parser(const argument_parser &)=delete
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.
void _parse_token(const detail::argument_token &tok, parsing_state &state)
Parse a single command-line argument token.
std::string _name
The name of the parser.
std::string_view name() const noexcept
Returns the parser's name.
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 _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::unique_ptr< argument_group > arg_group_ptr_t
arg_ptr_vec_t _positional_args
The list of positional arguments.
arg_parser_ptr_vec_t _subparsers
The list of subparsers.
argument_parser & program_description(std::string_view description) noexcept
Set the program description.
T value(std::string_view arg_name) const
Get the value of the given argument.
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.
bool _invoked
A flag indicating whether the parser has been invoked to parse arguments.
std::string_view _strip_flag_prefix(const detail::argument_token &tok) const noexcept
Removes the flag prefix from a flag token's value.
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...
static constexpr char _flag_prefix_char
void _validate_argument_configuration() const
Validate whether the definition/configuration of the parser's arguments is correct.
void _parse_args_impl(AIt args_begin, const AIt args_end, parsing_state &state)
Implementation of parsing command-line arguments.
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.
void _verify_final_state() const
Verifies the correctness of the parsed command-line arguments.
bool has_value(std::string_view arg_name) const noexcept
Check if the given argument has a value.
bool _verbose
Verbosity flag.
argument_group & _gr_optional_args
The optional argument group.
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.
arg_ptr_t _get_argument(std::string_view arg_name) const noexcept
Get the argument with the specified name.
argument_parser(argument_parser &&)=delete
argument_parser & resolved_parser() noexcept
Returns the deepest invoked parser.
argument_group & add_group(const std::string_view name) noexcept
Adds an argument group with the given name to the parser's configuration.
argument_parser & operator=(const argument_parser &)=delete
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.
std::vector< T > values(std::string_view arg_name) const
Get all values of the given argument.
void _parse_value_token(const detail::argument_token &tok, parsing_state &state)
Parse a single command-line argument value token.
void _set_argument_value(const std::string_view value, parsing_state &state) noexcept
Set the value for the currently processed argument.
std::vector< std::string > parse_known_args(const AR &argv_rng)
Parses the known command-line arguments.
argument_parser & default_arguments(const AR &arg_discriminators) noexcept
Add default arguments to the argument parser.
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.
void _print_group(std::ostream &os, const argument_group &group, const bool verbose) const noexcept
Print the given argument list to an output stream.
static constexpr std::uint8_t _primary_flag_prefix_length
std::unique_ptr< argument_parser > arg_parser_ptr_t
std::vector< arg_group_ptr_t > arg_group_ptr_vec_t
std::vector< std::string > parse_known_args(int argc, char *argv[])
Parses the known command-line arguments.
argument_parser & verbose(const bool v=true) noexcept
Set the verbosity mode.
static constexpr std::string_view _flag_prefix
typename arg_ptr_vec_t::iterator arg_ptr_vec_iter_t
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.
std::vector< arg_parser_ptr_t > arg_parser_ptr_vec_t
argument_parser(const std::string_view name, const std::string_view parent_name)
unknown_policy _unknown_policy
Policy for unknown arguments.
void try_parse_args(int argc, char *argv[])
Parses the command-line arguments and exits on error.
positional_argument< T > & add_positional_argument(const std::string_view name)
Adds a positional argument 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.
std::vector< detail::argument_token > arg_token_vec_t
arg_ptr_vec_iter_t _find_opt_arg(const detail::argument_token &flag_tok) noexcept
Find an optional argument based on a flag token.
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 & add_subparser(const std::string_view name)
Adds an subparser with the given name to the parser's configuration.
argument_parser & default_arguments(const std::initializer_list< default_argument > &arg_discriminators) noexcept
Add default arguments to the argument parser.
typename arg_token_vec_t::const_iterator arg_token_vec_iter_t
bool is_used(std::string_view arg_name) const noexcept
Check if a specific argument was used in the command-line.
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.
std::vector< std::string > try_parse_known_args(const AR &argv_rng)
Parses known the command-line arguments and exits on error.
argument_parser & unknown_arguments_policy(const unknown_policy policy) noexcept
Set the unknown argument flags handling policy.
argument_parser(const std::string_view name)
argument_parser & default_arguments(const std::same_as< default_argument > auto... arg_discriminators) noexcept
Add default arguments to the argument parser.
std::size_t count(std::string_view arg_name) const noexcept
Get the given argument's usage count.
void _print_subparsers(std::ostream &os) const noexcept
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.
bool _finalized
A flag indicating whether the parsing process has been finalized.
static constexpr std::uint8_t _secondary_flag_prefix_length
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.
void parse_args(const AR &argv_rng)
Parses the command-line arguments.
friend std::ostream & operator<<(std::ostream &os, const argument_parser &parser) noexcept
Prints the argument parser's details to an output stream.
std::optional< std::string > _program_version
The version of the program.
argument_parser & operator=(argument_parser &&)=delete
void parse_args(int argc, char *argv[])
Parses the command-line arguments.
argument_group & _gr_positional_args
The positional argument group.
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.
ap::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< ap::action_type::observe, std::string > check_file_exists() noexcept
Returns an observe action which checks whether lower_bound file with the given name exists.
argument_name_discriminator
Argument name member discriminator.
void add_default_argument(const default_argument, argument_parser &) noexcept
Adds a predefined/default positional argument to the parser.
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.
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.
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:
An observing value action specifier.
A collection of values used during the parsing process.
void set_parser(argument_parser &parser)
Update the parser-specific parameters of the state object.
parsing_state(argument_parser &parser, const bool parse_known_only=false)
std::vector< std::string > unknown_args
A vector of unknown argument values.
const bool parse_known_only
A flag indicating whether only known arguments should be parsed.
arg_ptr_vec_iter_t curr_pos_arg_it
An iterator pointing to the next positional argument to be processed.
arg_ptr_t curr_arg
The currently processed argument.
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.
std::string value
The actual token's value.
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.
Exception type used for invalid configuration of an argument parser or its arguments.
static invalid_configuration argument_name_used(const detail::argument_name &arg_name) noexcept
static invalid_configuration invalid_argument_name(const std::string_view arg_name, const std::string_view reason) 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 invalid_nvalues(const detail::argument_name &arg_name, const std::weak_ordering ordering) noexcept
static parsing_failure unknown_argument(const std::string_view arg_name) 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.