189 char const *
const *
const argv,
192 version_check_dev_decision{version_updates},
193 subcommands{std::move(subcommands)}
195 for (
auto & sub : this->subcommands)
197 if (!std::regex_match(sub, app_name_regex))
199 throw design_error{
"The subcommand name must only contain alpha-numeric characters or '_' and '-' "
200 "(regex: \"^[a-zA-Z0-9_-]+$\")."};
213 if (version_check_future.
valid())
243 template <
typename option_type,
typename val
idator_type>
245 && std::invocable<validator_type, option_type>
248 verify_option_config(
config);
253 [&value, &
config](
auto & f)
255 f.add_option(value,
config);
270 template <
typename val
idator_type>
271 requires std::invocable<validator_type, bool>
274 verify_flag_config(
config);
277 throw design_error(
"A flag's default value must be false.");
282 [&value, &
config](
auto & f)
284 f.add_flag(value,
config);
311 template <
typename option_type,
typename val
idator_type>
313 && std::invocable<validator_type, option_type>
316 verify_positional_option_config(
config);
318 if constexpr (detail::is_container_option<option_type>)
319 has_positional_list_option =
true;
324 [&value, &
config](
auto & f)
326 f.add_positional_option(value,
config);
401 if (parse_was_called)
402 throw design_error(
"The function parse() must only be called once!");
408 throw design_error{(
"The application name must only contain alpha-numeric characters or '_' and '-' "
409 "(regex: \"^[a-zA-Z0-9_-]+$\").")};
414 if (std::holds_alternative<detail::format_parse>(format) && !subcommands.empty() && sub_parser ==
nullptr)
416 assert(!subcommands.empty());
419 subcommands_str += command +
", ";
420 subcommands_str.
replace(subcommands_str.size() - 2, 2,
"]");
422 throw too_few_arguments{
"You misspelled the subcommand! Please specify which sub-program "
423 "you want to use: one of "
425 +
". Use -h/--help for more "
429 if (app_version.decide_if_check_is_performed(version_check_dev_decision, version_check_user_decision))
433 version_check_future = app_version_prom.
get_future();
434 app_version(std::move(app_version_prom));
437 [
this]<
typename T>(T & f)
439 if constexpr (std::same_as<T, detail::format_tdl>)
441 f.parse(
info, executable_name);
449 parse_was_called =
true;
452 if (!std::holds_alternative<detail::format_parse>(format))
453 std::exit(EXIT_SUCCESS);
464 if (sub_parser ==
nullptr)
466 throw design_error(
"No subcommand was provided at the construction of the argument parser!");
502 template <
typename id_type>
503 requires std::same_as<id_type, char> || std::constructible_from<std::string, id_type>
507 if (!parse_was_called)
508 throw design_error{
"You can only ask which options have been set after calling the function `parse()`."};
512 char_or_string_t short_or_long_id = {
id};
514 if constexpr (!std::same_as<id_type, char>)
516 if (short_or_long_id.size() == 1)
518 throw design_error{
"Long option identifiers must be longer than one character! If " + short_or_long_id
519 +
"' was meant to be a short identifier, please pass it as a char ('') not a string"
525 throw design_error{
"You can only ask for option identifiers that you added with add_option() before."};
528 auto end_of_options = std::find(cmd_arguments.
begin(), cmd_arguments.
end(), end_of_options_indentifier);
529 auto option_it = detail::format_parse::find_option_id(cmd_arguments.
begin(), end_of_options, short_or_long_id);
530 return option_it != end_of_options;
548 [&title, advanced_only](
auto & f)
550 f.add_section(title, advanced_only);
567 [&title, advanced_only](
auto & f)
569 f.add_subsection(title, advanced_only);
587 [&text, is_paragraph, advanced_only](
auto & f)
589 f.add_line(text, is_paragraph, advanced_only);
616 [&key, &desc, advanced_only](
auto & f)
618 f.add_list_item(key, desc, advanced_only);
678 bool parse_was_called{
false};
681 bool has_positional_list_option{
false};
690 friend struct ::sharg::detail::test_accessor;
696 std::regex app_name_regex{
"^[a-zA-Z0-9_-]+$"};
716 detail::format_short_help,
717 detail::format_version,
721 detail::format_copyright
722> format{detail::format_help{{}, {},
false}};
725 std::set<std::string> used_option_ids{
"h",
"hh",
"help",
"advanced-help",
"export-help",
"version",
"copyright"};
765 void init(
int argc,
char const *
const *
const argv)
770 bool special_format_was_set{
false};
772 for (
int i = 1, argv_len = argc; i < argv_len; ++i)
776 if (!subcommands.empty())
789 sub_parser->executable_name.insert(sub_parser->executable_name.begin(),
790 executable_name.
begin(),
791 executable_name.
end());
799 if (!arg.empty() && arg[0] !=
'-')
804 if (arg ==
"-h" || arg ==
"--help")
806 format = detail::format_help{subcommands, version_check_dev_decision,
false};
807 special_format_was_set =
true;
809 else if (arg ==
"-hh" || arg ==
"--advanced-help")
811 format = detail::format_help{subcommands, version_check_dev_decision,
true};
812 special_format_was_set =
true;
814 else if (arg ==
"--version")
816 format = detail::format_version{};
817 special_format_was_set =
true;
819 else if (arg.substr(0, 13) ==
"--export-help")
825 export_format = arg.
substr(14);
829 if (argv_len <= i + 1)
830 throw too_few_arguments{
"Option --export-help must be followed by a value."};
834 if (export_format ==
"html")
835 format = detail::format_html{subcommands, version_check_dev_decision};
836 else if (export_format ==
"man")
837 format = detail::format_man{subcommands, version_check_dev_decision};
838 else if (export_format ==
"ctd")
839 format = detail::format_tdl{detail::format_tdl::FileFormat::CTD};
840 else if (export_format ==
"cwl")
841 format = detail::format_tdl{detail::format_tdl::FileFormat::CWL};
843 throw validation_error{
"Validation failed for option --export-help: "
844 "Value must be one of [html, man, ctd, cwl]."};
845 special_format_was_set =
true;
847 else if (arg ==
"--copyright")
849 format = detail::format_copyright{};
850 special_format_was_set =
true;
852 else if (arg ==
"--version-check")
855 throw too_few_arguments{
"Option --version-check must be followed by a value."};
859 if (arg ==
"1" || arg ==
"true")
860 version_check_user_decision =
true;
861 else if (arg ==
"0" || arg ==
"false")
862 version_check_user_decision =
false;
864 throw validation_error{
"Value for option --version-check must be true (1) or false (0)."};
879 format = detail::format_short_help{};
883 if (!special_format_was_set)
884 format = detail::format_parse(argc, cmd_arguments);
892 template <
typename id_type>
893 bool id_exists(id_type
const &
id)
895 if (detail::format_parse::is_empty_id(
id))
909 void verify_identifiers(
char const short_id,
std::string const & long_id)
911 constexpr std::string_view valid_chars{
"@_0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"};
912 auto is_valid = [&valid_chars](
char const c)
914 return valid_chars.
find(c) != std::string::npos;
917 if (id_exists(short_id))
918 throw design_error(
"Option Identifier '" +
std::string(1, short_id) +
"' was already used before.");
919 if (id_exists(long_id))
920 throw design_error(
"Option Identifier '" + long_id +
"' was already used before.");
921 if (long_id.
length() == 1)
922 throw design_error(
"Long IDs must be either empty, or longer than one character.");
923 if ((short_id !=
'\0') && !is_valid(short_id))
924 throw design_error(
"Option identifiers may only contain alphanumeric characters, '_', or '@'.");
925 if (long_id.
size() > 0 && (long_id[0] ==
'-'))
926 throw design_error(
"First character of long ID cannot be '-'.");
932 if (!((c ==
'-') || is_valid(c)))
934 "Long identifiers may only contain alphanumeric characters, '_', '-', or '@'.");
936 if (detail::format_parse::is_empty_id(short_id) && detail::format_parse::is_empty_id(long_id))
937 throw design_error(
"Option Identifiers cannot both be empty.");
941 template <
typename val
idator_t>
942 void verify_option_config(config<validator_t>
const & config)
944 if (sub_parser !=
nullptr)
945 throw design_error{
"You may only specify flags for the top-level parser."};
947 verify_identifiers(config.short_id, config.long_id);
949 if (config.required && !config.default_message.empty())
950 throw design_error{
"A required option cannot have a default message."};
954 template <
typename val
idator_t>
955 void verify_flag_config(config<validator_t>
const & config)
957 verify_identifiers(config.short_id, config.long_id);
959 if (!config.default_message.empty())
960 throw design_error{
"A flag may not have a default message because the default is always `false`."};
964 template <
typename val
idator_t>
965 void verify_positional_option_config(config<validator_t>
const & config)
const
967 if (config.short_id !=
'\0' || config.long_id !=
"")
968 throw design_error{
"Positional options are identified by their position on the command line. "
969 "Short or long ids are not permitted!"};
971 if (config.advanced || config.hidden)
972 throw design_error{
"Positional options are always required and therefore cannot be advanced nor hidden!"};
974 if (sub_parser !=
nullptr)
975 throw design_error{
"You may only specify flags for the top-level parser."};
977 if (has_positional_list_option)
978 throw design_error{
"You added a positional option with a list value before so you cannot add "
979 "any other positional options."};
981 if (!config.default_message.empty())
982 throw design_error{
"A positional option may not have a default message because it is always required."};
Parser exception that is thrown whenever there is an design error directed at the developer of the ap...
Definition: exceptions.hpp:210
The Sharg command line parser.
Definition: parser.hpp:157
void add_option(option_type &value, config< validator_type > const &config)
Adds an option to the sharg::parser.
Definition: parser.hpp:246
void add_flag(bool &value, config< validator_type > const &config)
Adds a flag to the sharg::parser.
Definition: parser.hpp:272
void add_subsection(std::string const &title, bool const advanced_only=false)
Adds an help page subsection to the sharg::parser.
Definition: parser.hpp:564
bool is_option_set(id_type const &id) const
Checks whether the option identifier (id) was set on the command line by the user.
Definition: parser.hpp:504
void add_positional_option(option_type &value, config< validator_type > const &config)
Adds a positional option to the sharg::parser.
Definition: parser.hpp:314
parser_meta_data info
Aggregates all parser related meta data (see sharg::parser_meta_data struct).
Definition: parser.hpp:674
parser(std::string const &app_name, int const argc, char const *const *const argv, update_notifications version_updates=update_notifications::on, std::vector< std::string > subcommands={})
Initializes an sharg::parser object from the command line arguments.
Definition: parser.hpp:187
parser(parser &&)=default
Defaulted.
void parse()
Initiates the actual command line parsing.
Definition: parser.hpp:399
parser & operator=(parser const &)=delete
Deleted.
parser(parser const &)=delete
Deleted.
void add_list_item(std::string const &key, std::string const &desc, bool const advanced_only=false)
Adds an help page list item (key-value) to the sharg::parser.
Definition: parser.hpp:613
parser & operator=(parser &&)=default
Defaulted.
void add_section(std::string const &title, bool const advanced_only=false)
Adds an help page section to the sharg::parser.
Definition: parser.hpp:545
~parser()
The destructor.
Definition: parser.hpp:210
parser & get_sub_parser()
Returns a reference to the sub-parser instance if subcommand parsing was enabled.
Definition: parser.hpp:462
void add_line(std::string const &text, bool is_paragraph=false, bool const advanced_only=false)
Adds an help page text line to the sharg::parser.
Definition: parser.hpp:584
Parser exception thrown when too few arguments are provided.
Definition: exceptions.hpp:103
Checks whether the the type can be used in an add_(positional_)option call on the parser.
Definition: concept.hpp:94
Provides sharg::config class.
T emplace_back(T... args)
update_notifications
Indicates whether application allows automatic update notifications by the sharg::parser.
Definition: auxiliary.hpp:29
@ off
Automatic update notifications should be disabled.
@ on
Automatic update notifications should be enabled.
Option struct that is passed to the sharg::parser::add_option() function.
Definition: config.hpp:46
Provides the version check functionality.