Ookii.CommandLine for C++  2.0.0
command_line_parser.h
Go to the documentation of this file.
1 #ifndef OOKII_COMMAND_LINE_PARSER_H_
7 #define OOKII_COMMAND_LINE_PARSER_H_
8 
9 #pragma once
10 
11 #include <map>
12 #include <filesystem>
13 #include "command_line_argument.h"
14 #include "usage_writer.h"
15 #include "parse_result.h"
16 #include "range_helper.h"
17 
23 namespace ookii
24 {
25  namespace details
26  {
27  template<typename CharType, typename Traits, typename Alloc>
28  struct parser_storage
29  {
30  using string_type = std::basic_string<CharType, Traits, Alloc>;
31  using string_provider_type = basic_localized_string_provider<CharType, Traits, Alloc>;
32 
33  parser_storage(string_type command_name, const string_provider_type *string_provider)
34  : command_name{command_name},
35  string_provider{string_provider}
36  {
37  if (this->string_provider == nullptr)
38  {
39  this->string_provider = &string_provider_type::get_default();
40  }
41  }
42 
43  string_type command_name;
44  string_type description;
45  std::vector<string_type> prefixes;
46  string_type long_prefix;
47  std::locale locale;
48  const string_provider_type *string_provider;
49  parsing_mode mode{};
50  CharType argument_value_separator{':'};
51  usage_help_request show_usage_on_error{};
52  bool allow_white_space_separator{true};
53  bool allow_duplicate_arguments{false};
54  };
55 
56  template<typename CharType, typename Traits, typename Alloc>
57  struct creation_options
58  {
59  using string_type = std::basic_string<CharType, Traits, Alloc>;
60 
61  bool case_sensitive{};
62  bool automatic_help_argument{true};
63  };
64  }
65 
68  enum class on_parsed_action
69  {
71  none,
77  };
78 
104  template<typename CharType = details::default_char_type, typename Traits = std::char_traits<CharType>, typename Alloc = std::allocator<CharType>>
106  {
107  public:
113  using string_view_type = std::basic_string_view<CharType, Traits>;
119  using storage_type = details::parser_storage<CharType, Traits, Alloc>;
121  using creation_options_type = details::creation_options<CharType, Traits, Alloc>;
123  using on_parsed_callback = std::function<on_parsed_action(argument_base_type &, std::optional<string_view_type> value)>;
126 
130  template<typename T>
132 
136  template<typename T>
138 
144  static constexpr std::vector<string_type> get_default_prefixes()
145  {
146  std::vector<string_type> result;
147 
148 #ifdef _WIN32
149  result.reserve(2);
150 #else
151  result.reserve(1);
152 #endif
153 
154  constexpr auto prefix1 = literal_cast<CharType>("-");
155  result.push_back(prefix1.data());
156 
157 #ifdef _WIN32
158  constexpr auto prefix2 = literal_cast<CharType>("/");
159  result.push_back(prefix2.data());
160 #endif
161 
162  return result;
163  }
164 
175  template<typename Range>
177  : _storage{std::move(storage)},
178  _arguments_by_name{string_less{options.case_sensitive, _storage.locale}},
179  _arguments_by_short_name{char_less{options.case_sensitive, _storage.locale}}
180  {
181  for (const auto &argument_builder : arguments)
182  {
183  add_argument(argument_builder->to_argument(*this));
184  }
185 
186  add_automatic_help_argument(options);
187 
188  // Sort the full argument list.
189  std::sort(_arguments.begin(), _arguments.end(),
190  [this](const auto &left, const auto &right)
191  {
192  // Positional arguments come before non-positional ones, and must be sorted by
193  // position.
194  if (left->position())
195  {
196  return right->position()
197  ? *left->position() < *right->position()
198  : true;
199  }
200  else if (right->position())
201  {
202  return false;
203  }
204 
205  // Non-positional required arguments come before optional arguments.
206  if (left->is_required())
207  {
208  if (!right->is_required())
209  {
210  return true;
211  }
212  }
213  else if (right->is_required())
214  {
215  return false;
216  }
217 
218  return _arguments_by_name.key_comp()(left->name(), right->name());
219  });
220 
221  // Build the prefix info.
222  if (_storage.mode == parsing_mode::long_short)
223  {
224  _sorted_prefixes.push_back(prefix_info { _storage.long_prefix, false });
225  }
226 
227  std::transform(_storage.prefixes.begin(), _storage.prefixes.end(), std::back_inserter(_sorted_prefixes),
228  [this](const auto &prefix)
229  {
230  return prefix_info{ prefix, _storage.mode == parsing_mode::long_short };
231  });
232 
233  std::sort(_sorted_prefixes.begin(), _sorted_prefixes.end(),
234  [](const auto &left, const auto &right)
235  {
236  return left.prefix.size() > right.prefix.size();
237  });
238  }
239 
243  parsing_mode mode() const noexcept
244  {
245  return _storage.mode;
246  }
247 
251  const string_type &command_name() const noexcept
252  {
253  return _storage.command_name;
254  }
255 
259  const string_type &description() const noexcept
260  {
261  return _storage.description;
262  }
263 
267  bool allow_white_space_separator() const noexcept
268  {
269  return _storage.allow_white_space_separator;
270  }
271 
275  bool allow_duplicate_arguments() const noexcept
276  {
277  return _storage.allow_duplicate_arguments;
278  }
279 
283  CharType argument_value_separator() const noexcept
284  {
285  return _storage.argument_value_separator;
286  }
287 
293  const std::vector<string_type> &prefixes() const noexcept
294  {
295  return _storage.prefixes;
296  }
297 
303  const string_type &long_prefix() const noexcept
304  {
305  return _storage.long_prefix;
306  }
307 
311  const std::locale &locale() const noexcept
312  {
313  return _storage.locale;
314  }
315 
319  const string_provider_type &string_provider() const noexcept
320  {
321  return *_storage.string_provider;
322  }
323 
327  void help_requested(bool help_requested) noexcept
328  {
329  _help_requested = help_requested;
330  }
331 
342  bool help_requested() const noexcept
343  {
344  return _help_requested;
345  }
346 
350  auto arguments() const
351  {
352  return details::range_filter<const argument_base_type&, typename std::vector<std::unique_ptr<argument_base_type>>::const_iterator>{
353  _arguments.begin(),
354  _arguments.end(),
355  [](const auto &a) -> auto&
356  {
357  return *a;
358  },
359  {}
360  };
361  }
362 
364  size_t argument_count() const
365  {
366  return _arguments.size();
367  }
368 
373  auto argument_comparer() const
374  {
375  return _arguments_by_name.key_comp();
376  }
377 
382  {
383  return _arguments_by_short_name.key_comp();
384  }
385 
390  {
391  return _positional_argument_count;
392  }
393 
403  const argument_base_type &get_argument(size_t pos) const
404  {
405  if (pos >= _positional_argument_count)
406  {
407  throw std::out_of_range("pos");
408  }
409 
410  return *_arguments.at(pos);
411  }
412 
423  {
424  if (pos >= _positional_argument_count)
425  {
426  throw std::out_of_range("pos");
427  }
428 
429  return *_arguments.at(pos);
430  }
431 
439  {
440  auto it = this->_arguments_by_name.find(name);
441  if (it == this->_arguments_by_name.end())
442  return nullptr;
443 
444  return it->second;
445  }
446 
454  {
455  auto it = this->_arguments_by_name.find(name);
456  if (it == this->_arguments_by_name.end())
457  return nullptr;
458 
459  return it->second;
460  }
461 
468  const argument_base_type *get_short_argument(CharType name) const noexcept
469  {
470  auto it = this->_arguments_by_short_name.find(name);
471  if (it == this->_arguments_by_short_name.end())
472  return nullptr;
473 
474  return it->second;
475  }
476 
483  argument_base_type *get_short_argument(CharType name) noexcept
484  {
485  auto it = this->_arguments_by_short_name.find(name);
486  if (it == this->_arguments_by_short_name.end())
487  return nullptr;
488 
489  return it->second;
490  }
491 
496  const argument_base_type *get_help_argument() const noexcept
497  {
498  return _help_argument;
499  }
500 
511  template<typename Iterator>
512  result_type parse(Iterator begin, Iterator end)
513  {
514  help_requested(false);
515  for (auto &arg : _arguments)
516  arg->reset();
517 
518  size_t position = 0;
519  for (auto current = begin; current != end; ++current)
520  {
521  auto arg = *current;
522  auto prefix = check_prefix(arg);
523  if (prefix)
524  {
525  auto [without_prefix, is_short] = *prefix;
526 
527  // Current is updated if parsing used the next argument for a value.
528  auto result = parse_named_argument(without_prefix, is_short, current, end);
529  if (!result)
530  {
531  return result;
532  }
533  }
534  else
535  {
536  // If this is a multi-value argument then we're on the last argument, otherwise search for the next argument without a value
537  // Skip positional arguments that have already been specified by name
538  while (position < _positional_argument_count &&
539  !_arguments[position]->is_multi_value() &&
540  _arguments[position]->has_value())
541  {
542  ++position;
543  }
544 
545  if (position >= _positional_argument_count)
546  {
547  return create_result(parse_error::too_many_arguments);
548  }
549 
550  auto result = set_argument_value(*_arguments[position], arg);
551  if (!result)
552  {
553  return result;
554  }
555  }
556  }
557 
558  for (const auto &arg : _arguments)
559  {
560  if (arg->is_required())
561  {
562  if (!arg->has_value())
563  {
564  return create_result(parse_error::missing_required_argument, arg->name());
565  }
566  }
567  else
568  {
569  arg->apply_default_value();
570  }
571  }
572 
573  help_requested(false);
574  return create_result(parse_error::none);
575  }
576 
590  template<typename Iterator>
591  result_type parse(Iterator begin, Iterator end, usage_writer_type *usage)
592  {
593  auto result = parse(begin, end);
594  handle_error(result, usage);
595  return result;
596  }
597 
607  template<typename Range>
608  result_type parse(const Range &range)
609  {
610  // Using allows ADL.
611  using std::begin;
612  using std::end;
613  return parse(begin(range), end(range));
614  }
615 
628  template<typename Range>
629  result_type parse(Range range, usage_writer_type *usage)
630  {
631  auto result = parse(range);
632  handle_error(result, usage);
633  return result;
634  }
635 
645  template<typename T>
646  result_type parse(std::initializer_list<T> args)
647  {
648  return parse(args.begin(), args.end());
649  }
650 
663  template<typename T>
664  result_type parse(std::initializer_list<T> args, usage_writer_type *usage)
665  {
666  auto result = parse(args);
667  handle_error(result, usage);
668  return result;
669  }
670 
680  result_type parse(int argc, const CharType *const argv[])
681  {
682  if (argc < 1)
683  return parse<const CharType *>({});
684  else
685  return parse(argv + 1, argv + argc);
686  }
687 
700  result_type parse(int argc, const CharType *const argv[], usage_writer_type *usage)
701  {
702  auto result = parse(argc, argv);
703  handle_error(result, usage);
704  return result;
705  }
706 
714  void write_usage(usage_writer_type *usage = nullptr, usage_help_request request = usage_help_request::full)
715  {
716  if (usage == nullptr)
717  {
718  usage_writer_type{}.write_parser_usage(*this, request);
719  }
720  else
721  {
722  usage->write_parser_usage(*this, request);
723  }
724  }
725 
741  {
742  _on_parsed_callback = callback;
743  }
744 
754  static string_type get_executable_name(int argc, const CharType *const argv[], bool include_extension = false)
755  {
756  if (argc < 1)
757  {
758  return {};
759  }
760 
761  std::filesystem::path path{argv[0]};
762  if (include_extension)
763  {
764  path = path.filename();
765  }
766  else
767  {
768  path = path.stem();
769  }
770 
771  return path.string<CharType, Traits, Alloc>();
772  }
773 
774  private:
775  struct prefix_info
776  {
777  string_type prefix;
778  bool is_short;
779  };
780 
781  void add_argument(std::unique_ptr<argument_base_type> argument)
782  {
783  if (argument->has_long_name())
784  {
785  auto name = argument->name();
786  const auto [it, success] = _arguments_by_name.insert(std::pair{name, argument.get()});
787  if (!success)
788  throw std::logic_error("Duplicate argument name.");
789 
790  for (const auto &alias : argument->aliases())
791  {
792  const auto [alias_it, alias_success] = _arguments_by_name.insert(std::pair{alias, argument.get()});
793  if (!alias_success)
794  throw std::logic_error("Duplicate argument name.");
795  }
796  }
797 
798  if (argument->has_short_name())
799  {
800  auto name = argument->short_name();
801  const auto [it, success] = _arguments_by_short_name.insert(std::pair{name, argument.get()});
802  if (!success)
803  throw std::logic_error("Duplicate short argument name.");
804 
805  for (const auto &alias : argument->short_aliases())
806  {
807  const auto [alias_it, alias_success] = _arguments_by_short_name.insert(std::pair{alias, argument.get()});
808  if (!alias_success)
809  throw std::logic_error("Duplicate short argument name.");
810  }
811  }
812 
813 
814  if (argument->position())
815  {
816  ++_positional_argument_count;
817  }
818 
819  _arguments.push_back(std::move(argument));
820  }
821 
822  void add_automatic_help_argument(creation_options_type &options)
823  {
824  if (!options.automatic_help_argument)
825  {
826  return;
827  }
828 
829  auto name = _storage.string_provider->automatic_help_name();
830 
831  // Try to match the case of the other arguments; based on the first argument.
832  if (!_arguments.empty())
833  {
834  if (std::isupper(_arguments[0]->name()[0], _storage.locale))
835  {
836  name[0] = std::toupper(name[0], _storage.locale);
837  }
838  else
839  {
840  name[0] = std::tolower(name[0], _storage.locale);
841  }
842  }
843 
844  auto short_name = _storage.string_provider->automatic_help_short_name();
845  auto short_alias = std::tolower(name[0], _storage.locale);
846  const auto *existing_arg = get_argument(name);
847  if (existing_arg == nullptr)
848  {
849  if (_storage.mode == parsing_mode::long_short)
850  {
851  existing_arg = get_short_argument(short_name);
852  if (existing_arg == nullptr)
853  {
854  existing_arg = get_short_argument(short_alias);
855  }
856  }
857  else
858  {
859  existing_arg = get_argument(string_view_type{&short_name, 1});
860  if (existing_arg == nullptr)
861  {
862  existing_arg = get_argument(string_view_type{&short_alias, 1});
863  }
864  }
865  }
866 
867  if (existing_arg != nullptr)
868  {
869  _help_argument = existing_arg;
870  return;
871  }
872 
873  bool has_alias;
874  if (options.case_sensitive)
875  {
876  has_alias = short_name != short_alias;
877  }
878  else
879  {
880  has_alias = std::toupper(short_name, _storage.locale) != std::toupper(short_alias, _storage.locale);
881  }
882 
883  details::argument_storage<CharType, Traits, Alloc> storage{name};
884  if (_storage.mode == parsing_mode::long_short)
885  {
886  storage.short_name = short_name;
887  if (has_alias)
888  {
889  storage.short_aliases.push_back(short_alias);
890  }
891  }
892  else
893  {
894  // Cannot use {} because it gets treated as an initializer list.
895  storage.aliases.push_back(string_type(1, short_name));
896  if (has_alias)
897  {
898  storage.aliases.push_back(string_type(1, short_alias));
899  }
900  }
901 
902  storage.cancel_parsing = true;
903  storage.description = _storage.string_provider->automatic_help_description();
904  storage.value_description = value_description<bool, CharType, Traits, Alloc>::get();
905 
906  details::action_argument_storage<bool, CharType, Traits, Alloc> action_storage{automatic_help_handler};
907  auto argument = std::make_unique<action_command_line_argument<bool, CharType, Traits, Alloc>>(
908  *this, std::move(storage), std::move(action_storage));
909 
910  _help_argument = argument.get();
911  add_argument(std::move(argument));
912  }
913 
914  static bool automatic_help_handler(bool, basic_command_line_parser &)
915  {
916  return true;
917  }
918 
919  void handle_error(const result_type &result, usage_writer_type *usage)
920  {
921  if (!result)
922  {
923  auto request = usage_help_request::full;
924  // If parsing is canceled that is not really an error, so we just show usage in
925  // that case.
926  if (result.error != parse_error::parsing_cancelled)
927  {
928  request = _storage.show_usage_on_error;
929  if (usage == nullptr)
930  {
931  usage_writer_type{}.write_error(result.get_error_message());
932  }
933  else
934  {
935  usage->write_error(result.get_error_message());
936  }
937  }
938 
939  if (help_requested())
940  {
941  write_usage(usage, request);
942  }
943  }
944  }
945 
946  std::optional<std::tuple<string_view_type, bool>> check_prefix(string_view_type argument) const
947  {
948  // Even if the named argument switch is '-', we treat a '-' followed by a digit as a
949  // value, because it could denote a negative number.
950  if (argument.length() >= 2 && argument[0] == '-' && std::isdigit(argument[1], _storage.locale))
951  return {};
952 
953  for (const auto &prefix : _sorted_prefixes)
954  {
955  auto stripped = strip_prefix(argument, string_view_type{prefix.prefix});
956  if (stripped)
957  {
958  return make_tuple(*stripped, prefix.is_short);
959  }
960  }
961 
962  return {};
963  }
964 
965  template<typename Iterator>
966  result_type parse_named_argument(string_view_type arg_string, bool is_short, Iterator &current, Iterator end)
967  {
968  auto [name, value] = split_once(arg_string, _storage.argument_value_separator);
969  if (is_short && name.length() > 1)
970  {
971  return parse_combined_short_argument(name, value);
972  }
973 
974  auto arg = find_argument(name, is_short);
975  if (arg == nullptr)
976  {
977  return create_result(parse_error::unknown_argument, string_type{name});
978  }
979 
980  if (!value && !arg->is_switch())
981  {
982  auto value_it = current;
983  if (!_storage.allow_white_space_separator || ++value_it == end || check_prefix(*value_it))
984  {
985  return create_result(parse_error::missing_value, arg->name());
986  }
987 
988  current = value_it;
989  value = *current;
990  }
991 
992  return set_argument_value(*arg, value);
993  }
994 
995  result_type parse_combined_short_argument(string_view_type name, std::optional<string_view_type> value)
996  {
997  for (CharType ch : name)
998  {
999  auto arg = get_short_argument(ch);
1000  if (arg == nullptr)
1001  {
1002  return create_result(parse_error::unknown_argument, string_type{ch});
1003  }
1004 
1005  if (!arg->is_switch())
1006  {
1007  return create_result(parse_error::combined_short_name_non_switch, string_type{name});
1008  }
1009 
1010  auto result = set_argument_value(*arg, value);
1011  if (!result)
1012  {
1013  return result;
1014  }
1015  }
1016 
1017  return create_result(parse_error::none);
1018  }
1019 
1020  argument_base_type *find_argument(string_view_type name, bool is_short) noexcept
1021  {
1022  if (is_short)
1023  {
1024  assert(name.length() == 1);
1025  return get_short_argument(name[0]);
1026  }
1027 
1028  return get_argument(name);
1029  }
1030 
1031  result_type set_argument_value(argument_base_type &arg, std::optional<string_view_type> value)
1032  {
1033  if (!_storage.allow_duplicate_arguments && !arg.is_multi_value() && arg.has_value())
1034  return create_result(parse_error::duplicate_argument, arg.name());
1035 
1036  set_value_result result;
1037  if (!value)
1038  {
1039  assert(arg.is_switch());
1040  result = arg.set_switch_value(*this);
1041  }
1042  else
1043  {
1044  result = arg.set_value(*value, *this);
1045  if (result == set_value_result::error)
1046  {
1047  return create_result(parse_error::invalid_value, arg.name());
1048  }
1049  }
1050 
1051  return post_process_argument(arg, value, result);
1052  }
1053 
1054  result_type post_process_argument(argument_base_type &arg, std::optional<string_view_type> value, set_value_result result)
1055  {
1056  auto action = on_parsed_action::none;
1057  if (_on_parsed_callback)
1058  action = _on_parsed_callback(arg, value);
1059 
1060  if (action == on_parsed_action::cancel_parsing ||
1061  ((arg.cancel_parsing() || result == set_value_result::cancel) && action != on_parsed_action::always_continue))
1062  {
1063  // Automatically request help for the event and cancel_parsing, but not for action arguments.
1064  if (action == on_parsed_action::cancel_parsing || arg.cancel_parsing())
1065  {
1066  help_requested(true);
1067  }
1068 
1069  return create_result(parse_error::parsing_cancelled, arg.name());
1070  }
1071 
1072  return create_result(parse_error::none);
1073  }
1074 
1075  result_type create_result(parse_error error, string_type arg_name = {})
1076  {
1077  if (error != parse_error::none && error != parse_error::parsing_cancelled)
1078  {
1079  help_requested(true);
1080  }
1081 
1082  return {*_storage.string_provider, error, arg_name};
1083  }
1084 
1085  storage_type _storage;
1086  std::vector<prefix_info> _sorted_prefixes;
1087 
1088  // _arguments_by_name and _argument_by_short_name contain pointers to items owned by
1089  // _arguments. Since they all have the same lifetime, this is okay.
1090  std::vector<std::unique_ptr<argument_base_type>> _arguments;
1091  std::map<string_type, argument_base_type *, string_less> _arguments_by_name;
1092  std::map<CharType, argument_base_type *, char_less> _arguments_by_short_name;
1093  size_t _positional_argument_count{};
1094  on_parsed_callback _on_parsed_callback;
1095  const argument_base_type* _help_argument{};
1096  bool _help_requested{};
1097  };
1098 
1103 
1104 }
1105 
1106 #endif
Parses command line arguments into strongly-typed values.
Definition: command_line_parser.h:106
void write_usage(usage_writer_type *usage=nullptr, usage_help_request request=usage_help_request::full)
Writes usage help for this parser's arguments.
Definition: command_line_parser.h:714
auto short_argument_comparer() const
Gets the comparer used for short argument names.
Definition: command_line_parser.h:381
result_type parse(int argc, const CharType *const argv[])
Parses the provided arguments.
Definition: command_line_parser.h:680
const argument_base_type * get_help_argument() const noexcept
Gets the help argument, if there is one.
Definition: command_line_parser.h:496
const string_provider_type & string_provider() const noexcept
Gets the basic_localized_string_provider implementation used to get strings for error messages etc.
Definition: command_line_parser.h:319
CharType argument_value_separator() const noexcept
Definition: command_line_parser.h:283
result_type parse(std::initializer_list< T > args)
Parses the arguments in the specified initializer list.
Definition: command_line_parser.h:646
const argument_base_type & get_argument(size_t pos) const
Gets an argument by position.
Definition: command_line_parser.h:403
parsing_mode mode() const noexcept
Gets the parsing mode used by this parser.
Definition: command_line_parser.h:243
void on_parsed(on_parsed_callback callback)
Sets a callback that will be invoked every time an argument is parsed.
Definition: command_line_parser.h:740
argument_base_type & get_argument(size_t pos)
Gets an argument by position.
Definition: command_line_parser.h:422
static string_type get_executable_name(int argc, const CharType *const argv[], bool include_extension=false)
Extracts the executable name from the application's arguments.
Definition: command_line_parser.h:754
typename argument_type< T >::typed_storage_type::converter_type converter_type
The specialized type of the custom command line converter function used.
Definition: command_line_parser.h:137
const argument_base_type * get_short_argument(CharType name) const noexcept
Gets an argument by short name.
Definition: command_line_parser.h:468
const string_type & command_name() const noexcept
Returns the command name used when generating usage help.
Definition: command_line_parser.h:251
argument_base_type * get_argument(string_view_type name) noexcept
Gets an argument by name.
Definition: command_line_parser.h:453
static constexpr std::vector< string_type > get_default_prefixes()
Gets the default prefixes accepted by the parser.
Definition: command_line_parser.h:144
const string_type & description() const noexcept
Returns the description used when generating usage help.
Definition: command_line_parser.h:259
size_t positional_argument_count() const
Gets the number of positional arguments.
Definition: command_line_parser.h:389
bool help_requested() const noexcept
Gets a value that indicates help should be shown if parse() returns a parse_result with parse_error::...
Definition: command_line_parser.h:342
const std::vector< string_type > & prefixes() const noexcept
Gets a list of all the argument name prefixes accepted by the parser.
Definition: command_line_parser.h:293
const std::locale & locale() const noexcept
Gets the locale used to parse argument values and to format strings.
Definition: command_line_parser.h:311
bool allow_duplicate_arguments() const noexcept
Indicates whether duplicate arguments are allowed.
Definition: command_line_parser.h:275
const string_type & long_prefix() const noexcept
Gets the long argument prefix.
Definition: command_line_parser.h:303
details::parser_storage< CharType, Traits, Alloc > storage_type
The specialized type of parser parameter storage used. For internal use.
Definition: command_line_parser.h:119
result_type parse(const Range &range)
Parses the arguments in the specified range.
Definition: command_line_parser.h:608
bool allow_white_space_separator() const noexcept
Indicates whether argument names and values can be separated by white space.
Definition: command_line_parser.h:267
std::basic_string_view< CharType, Traits > string_view_type
The specialized type of std::basic_string_view used.
Definition: command_line_parser.h:113
auto arguments() const
Gets a view of all the arguments defined by the parser.
Definition: command_line_parser.h:350
result_type parse(std::initializer_list< T > args, usage_writer_type *usage)
Parses the arguments in the specified initializer list, and writes error and usage information to the...
Definition: command_line_parser.h:664
result_type parse(Range range, usage_writer_type *usage)
Parses the arguments in the specified range, and writes error and usage information to the console if...
Definition: command_line_parser.h:629
details::creation_options< CharType, Traits, Alloc > creation_options_type
The specialized type of parser creation options used. For internal use.
Definition: command_line_parser.h:121
auto argument_comparer() const
Gets the comparer used for argument names.
Definition: command_line_parser.h:373
std::function< on_parsed_action(argument_base_type &, std::optional< string_view_type > value)> on_parsed_callback
The callback function type for on_parsed().
Definition: command_line_parser.h:123
argument_base_type * get_short_argument(CharType name) noexcept
Gets an argument by short name.
Definition: command_line_parser.h:483
const argument_base_type * get_argument(string_view_type name) const noexcept
Gets an argument by name.
Definition: command_line_parser.h:438
basic_command_line_parser(const Range &arguments, storage_type &&storage, creation_options_type &options)
Creates a new instance of the basic_command_line_parser class.
Definition: command_line_parser.h:176
size_t argument_count() const
Gets the total number of arguments.
Definition: command_line_parser.h:364
result_type parse(int argc, const CharType *const argv[], usage_writer_type *usage)
Parses the provided arguments, and writes error and usage information to the console if a parsing err...
Definition: command_line_parser.h:700
typename argument_base_type::string_type string_type
The specialized type of std::basic_string used.
Definition: command_line_parser.h:111
result_type parse(Iterator begin, Iterator end, usage_writer_type *usage)
Parses the arguments in the range specified by the iterators, and writes error and usage information ...
Definition: command_line_parser.h:591
void help_requested(bool help_requested) noexcept
Sets a value that indicates help should be shown if parse() returns a parse_result with parse_error::...
Definition: command_line_parser.h:327
result_type parse(Iterator begin, Iterator end)
Parses the arguments in the range specified by the iterators.
Definition: command_line_parser.h:512
Provides custom localized strings.
Definition: localized_string_provider.h:30
static basic_localized_string_provider & get_default() noexcept
Gets a default instance of the basic_localized_string_provider.
Definition: localized_string_provider.h:38
Creates usage help for the basic_command_line_parser and basic_command_manager classes.
Definition: usage_writer.h:99
virtual void write_parser_usage(const parser_type &parser, usage_help_request request=usage_help_request::full)
Creates usage help for the specified parser.
Definition: usage_writer.h:368
Abstract base class for regular and multi-value arguments.
Definition: command_line_argument.h:108
typename storage_type::string_type string_type
The concrete type of std::basic_string used.
Definition: command_line_argument.h:113
Class that provides information about arguments that are not multi-value arguments.
Definition: command_line_argument.h:432
Provides the ookii::command_line_argument class.
Namespace containing the core Ookii.CommandLine.Cpp types.
Definition: command_line_argument.h:16
usage_help_request
Indicates if and how usage is shown if an error occurred parsing the command line.
Definition: usage_writer.h:26
std::optional< std::basic_string_view< CharType, Traits > > strip_prefix(std::basic_string_view< CharType, Traits > value, std::basic_string_view< CharType, Traits > prefix)
Removes a prefix from a string.
Definition: string_helper.h:369
std::tuple< std::basic_string_view< CharType, Traits >, std::optional< std::basic_string_view< CharType, Traits > > > split_once(std::basic_string_view< CharType, Traits > value, CharType separator)
Splits a string on the first occurrence of a separator.
Definition: string_helper.h:389
parsing_mode
Indicates what argument parsing rules should be used to interpret the command line.
Definition: parsing_mode.h:14
@ long_short
Use POSIX-like rules where arguments have separate long and short names.
set_value_result
The result of attempting to set a value for an argument.
Definition: command_line_argument.h:91
@ success
The operation was successful.
@ error
There was an error converting the value to the element type of the argument.
on_parsed_action
Value to be returned from the callback passed to the basic_command_line_parser::on_parsed() method.
Definition: command_line_parser.h:69
@ always_continue
Continue parsing even if command_line_argument::cancel_parsing() returns true.
@ none
Don't take any special action.
@ cancel_parsing
Cancel parsing immediately, disregarding the rest of the command line. Parsing will return with parse...
parse_error
The type of error that occurred while parsing the command line.
Definition: parse_result.h:14
Provides error handling for the ookii::basic_command_line_parser class.
Provides helpers for working with iterator ranges.
A version of the std::less predicate for characters that supports case insensitive comparison.
Definition: string_helper.h:79
Provides the result, success or error, of a command line argument parsing operation.
Definition: parse_result.h:62
A version of the std::less predicate for strings that supports case insensitive comparison.
Definition: string_helper.h:30
Provides the ookii::basic_usage_writer class.