25 #ifndef OPTIONPP_PARSER_HPP
26 #define OPTIONPP_PARSER_HPP
28 #include <initializer_list>
58 const std::string
option =
"")
65 const std::string&
option() const noexcept {
return m_option; }
109 parser(
const std::initializer_list<option>& il) {
110 m_groups.emplace_back(
"", il.begin(), il.end());
126 template <
typename InputIt>
127 parser(InputIt first, InputIt last) { m_groups.emplace_back(
"", first, last); }
172 option&
add_option(
const std::string& long_name,
173 char short_name =
'\0',
174 const std::string& description =
"",
175 const std::string& arg_name =
"",
176 bool arg_required =
false,
177 const std::string& group_name =
"");
221 template <
typename InputIt>
222 parser_result
parse(InputIt first, InputIt last,
bool ignore_first =
true)
const;
240 parser_result
parse(
int argc,
char* argv[],
bool ignore_first =
true)
const;
259 parser_result
parse(
const std::string& cmd_line,
bool ignore_first =
false)
const;
279 const std::string& short_prefix =
"",
280 const std::string& long_prefix =
"",
281 const std::string& end_indicator =
"",
282 const std::string& equals =
"");
311 option&
operator[](
const std::string& long_name);
357 int max_line_length = 78,
358 int group_indent = 0,
359 int option_indent = 2,
360 int desc_first_line_indent = 30,
361 int desc_multiline_indent = 32)
const;
369 using group_container = std::vector<option_group>;
373 using group_iterator = group_container::iterator;
377 using group_const_iterator = group_container::const_iterator;
393 group_iterator find_group(
const std::string& name);
397 group_const_iterator find_group(
const std::string& name)
const;
404 option* find_option(
const std::string& long_name);
408 const option* find_option(
const std::string& long_name)
const;
415 option* find_option(
char short_name);
419 const option* find_option(
char short_name)
const;
427 bool is_end_indicator(
const std::string& argument)
const noexcept {
428 return argument == m_end_of_options;
437 bool is_long_option(
const std::string& argument)
const noexcept {
438 return argument.size() > m_long_option_prefix.size()
448 bool is_short_option_group(
const std::string& argument)
const noexcept {
449 return argument.size() > m_short_option_prefix.size()
458 bool is_non_option(
const std::string& argument)
const noexcept {
459 return !is_end_indicator(argument)
460 && !is_long_option(argument)
461 && !is_short_option_group(argument);
474 void write_option_argument(
const parsed_entry& entry)
const;
479 enum class cl_arg_type { non_option,
496 void parse_argument(
const std::string& argument,
497 parser_result& result, cl_arg_type& type)
const;
512 void parse_short_option_group(
const std::string& short_names,
513 const std::string& argument,
bool has_arg,
514 parser_result& result, cl_arg_type& type)
const;
516 group_container m_groups;
518 std::string m_delims{
" \t\n\r"};
519 std::string m_short_option_prefix{
"-"};
520 std::string m_long_option_prefix{
"--"};
521 std::string m_end_of_options{
"--"};
522 std::string m_equals{
"="};
540 std::ostream&
operator<<(std::ostream& os,
const parser& parser);
548 #ifndef DOXYGEN_SHOULD_SKIP_THIS
550 template <
typename InputIt>
553 if (ignore_first && first != last)
558 parser_result result{};
559 cl_arg_type prev_type{cl_arg_type::non_option};
561 const std::string& arg{*it};
564 if (prev_type == cl_arg_type::arg_required
565 || prev_type == cl_arg_type::arg_optional) {
568 if (is_non_option(arg)
569 || prev_type == cl_arg_type::arg_required) {
570 auto& arg_info = result.back();
571 arg_info.argument = arg;
572 arg_info.original_text.push_back(
' ');
573 arg_info.original_text += arg;
574 prev_type = cl_arg_type::non_option;
575 if (arg_info.opt_info)
576 write_option_argument(arg_info);
578 prev_type = cl_arg_type::non_option;
581 }
else if (prev_type == cl_arg_type::end_indicator) {
582 parsed_entry arg_info;
583 arg_info.original_text = arg;
584 arg_info.is_option =
false;
585 result.push_back(std::move(arg_info));
587 parse_argument(arg, result, prev_type);
594 if (prev_type == cl_arg_type::arg_required) {
595 const auto& opt_name = result.back().original_text;
596 throw parse_error{
"option '" + opt_name +
"' requires an argument",
597 "optionpp::parser::parse", opt_name};
603 #endif // DOXYGEN_SHOULD_SKIP_THIS