CLI11  2.2.0
App.hpp
Go to the documentation of this file.
1 // Copyright (c) 2017-2022, University of Cincinnati, developed by Henry Schreiner
2 // under NSF AWARD 1414736 and by the respective contributors.
3 // All rights reserved.
4 //
5 // SPDX-License-Identifier: BSD-3-Clause
6 
7 #pragma once
8 
9 // [CLI11:public_includes:set]
10 #include <algorithm>
11 #include <cstdint>
12 #include <functional>
13 #include <iostream>
14 #include <iterator>
15 #include <memory>
16 #include <numeric>
17 #include <set>
18 #include <sstream>
19 #include <string>
20 #include <utility>
21 #include <vector>
22 // [CLI11:public_includes:end]
23 
24 // CLI Library includes
25 #include "ConfigFwd.hpp"
26 #include "Error.hpp"
27 #include "FormatterFwd.hpp"
28 #include "Macros.hpp"
29 #include "Option.hpp"
30 #include "Split.hpp"
31 #include "StringTools.hpp"
32 #include "TypeTools.hpp"
33 
34 namespace CLI {
35 // [CLI11:app_hpp:verbatim]
36 
37 #ifndef CLI11_PARSE
38 #define CLI11_PARSE(app, argc, argv) \
39  try { \
40  (app).parse((argc), (argv)); \
41  } catch(const CLI::ParseError &e) { \
42  return (app).exit(e); \
43  }
44 #endif
45 
46 namespace detail {
48 struct AppFriend;
49 } // namespace detail
50 
51 namespace FailureMessage {
52 std::string simple(const App *app, const Error &e);
53 std::string help(const App *app, const Error &e);
54 } // namespace FailureMessage
55 
57 
58 enum class config_extras_mode : char { error = 0, ignore, ignore_all, capture };
59 
60 class App;
61 
62 using App_p = std::shared_ptr<App>;
63 
64 namespace detail {
66 
67 template <typename T, enable_if_t<!std::is_integral<T>::value || (sizeof(T) <= 1U), detail::enabler> = detail::dummy>
69  return opt->always_capture_default();
70 }
71 
73 template <typename T, enable_if_t<std::is_integral<T>::value && (sizeof(T) > 1U), detail::enabler> = detail::dummy>
76 }
77 
78 } // namespace detail
79 
80 class Option_group;
82 
85 class App {
86  friend Option;
87  friend detail::AppFriend;
88 
89  protected:
90  // This library follows the Google style guide for member names ending in underscores
91 
94 
96  std::string name_{};
97 
99  std::string description_{};
100 
102  bool allow_extras_{false};
103 
107 
109  bool prefix_command_{false};
110 
112  bool has_automatic_name_{false};
113 
115  bool required_{false};
116 
118  bool disabled_{false};
119 
121  bool pre_parse_called_{false};
122 
125  bool immediate_callback_{false};
126 
128  std::function<void(std::size_t)> pre_parse_callback_{};
129 
131  std::function<void()> parse_complete_callback_{};
132 
134  std::function<void()> final_callback_{};
135 
139 
142 
144  std::vector<Option_p> options_{};
145 
149 
151  std::string footer_{};
152 
154  std::function<std::string()> footer_callback_{};
155 
157  Option *help_ptr_{nullptr};
158 
161 
163  Option *version_ptr_{nullptr};
164 
166  std::shared_ptr<FormatterBase> formatter_{new Formatter()};
167 
169  std::function<std::string(const App *, const Error &e)> failure_message_{FailureMessage::simple};
170 
174 
175  using missing_t = std::vector<std::pair<detail::Classifier, std::string>>;
176 
181 
183  std::vector<Option *> parse_order_{};
184 
186  std::vector<App *> parsed_subcommands_{};
187 
189  std::set<App *> exclude_subcommands_{};
190 
193  std::set<Option *> exclude_options_{};
194 
197  std::set<App *> need_subcommands_{};
198 
201  std::set<Option *> need_options_{};
202 
206 
208  std::vector<App_p> subcommands_{};
209 
211  bool ignore_case_{false};
212 
214  bool ignore_underscore_{false};
215 
217  bool fallthrough_{false};
218 
221 #ifdef _WIN32
222  true
223 #else
224  false
225 #endif
226  };
228  bool positionals_at_end_{false};
229 
230  enum class startup_mode : char { stable, enabled, disabled };
234 
236  bool configurable_{false};
237 
240 
243 
246  bool silent_{false};
247 
249  std::uint32_t parsed_{0U};
250 
252  std::size_t require_subcommand_min_{0};
253 
255  std::size_t require_subcommand_max_{0};
256 
258  std::size_t require_option_min_{0};
259 
261  std::size_t require_option_max_{0};
262 
264  App *parent_{nullptr};
265 
267  std::string group_{"Subcommands"};
268 
270  std::vector<std::string> aliases_{};
271 
275 
277  Option *config_ptr_{nullptr};
278 
280  std::shared_ptr<Config> config_formatter_{new ConfigTOML()};
281 
283 
285  App(std::string app_description, std::string app_name, App *parent)
286  : name_(std::move(app_name)), description_(std::move(app_description)), parent_(parent) {
287  // Inherit if not from a nullptr
288  if(parent_ != nullptr) {
289  if(parent_->help_ptr_ != nullptr)
291  if(parent_->help_all_ptr_ != nullptr)
294 
297 
298  // INHERITABLE
311  group_ = parent_->group_;
316  }
317  }
318 
319  public:
322 
324  explicit App(std::string app_description = "", std::string app_name = "")
325  : App(app_description, app_name, nullptr) {
326  set_help_flag("-h,--help", "Print this help message and exit");
327  }
328 
329  App(const App &) = delete;
330  App &operator=(const App &) = delete;
331 
333  virtual ~App() = default;
334 
341  App *callback(std::function<void()> app_callback) {
342  if(immediate_callback_) {
343  parse_complete_callback_ = std::move(app_callback);
344  } else {
345  final_callback_ = std::move(app_callback);
346  }
347  return this;
348  }
349 
352  App *final_callback(std::function<void()> app_callback) {
353  final_callback_ = std::move(app_callback);
354  return this;
355  }
356 
359  App *parse_complete_callback(std::function<void()> pc_callback) {
360  parse_complete_callback_ = std::move(pc_callback);
361  return this;
362  }
363 
366  App *preparse_callback(std::function<void(std::size_t)> pp_callback) {
367  pre_parse_callback_ = std::move(pp_callback);
368  return this;
369  }
370 
372  App *name(std::string app_name = "") {
373 
374  if(parent_ != nullptr) {
375  auto oname = name_;
376  name_ = app_name;
377  auto &res = _compare_subcommand_names(*this, *_get_fallthrough_parent());
378  if(!res.empty()) {
379  name_ = oname;
380  throw(OptionAlreadyAdded(app_name + " conflicts with existing subcommand names"));
381  }
382  } else {
383  name_ = app_name;
384  }
385  has_automatic_name_ = false;
386  return this;
387  }
388 
390  App *alias(std::string app_name) {
391  if(app_name.empty() || !detail::valid_alias_name_string(app_name)) {
392  throw IncorrectConstruction("Aliases may not be empty or contain newlines or null characters");
393  }
394  if(parent_ != nullptr) {
395  aliases_.push_back(app_name);
396  auto &res = _compare_subcommand_names(*this, *_get_fallthrough_parent());
397  if(!res.empty()) {
398  aliases_.pop_back();
399  throw(OptionAlreadyAdded("alias already matches an existing subcommand: " + app_name));
400  }
401  } else {
402  aliases_.push_back(app_name);
403  }
404 
405  return this;
406  }
407 
409  App *allow_extras(bool allow = true) {
410  allow_extras_ = allow;
411  return this;
412  }
413 
415  App *required(bool require = true) {
416  required_ = require;
417  return this;
418  }
419 
421  App *disabled(bool disable = true) {
422  disabled_ = disable;
423  return this;
424  }
425 
427  App *silent(bool silence = true) {
428  silent_ = silence;
429  return this;
430  }
431 
433  App *disabled_by_default(bool disable = true) {
434  if(disable) {
436  } else {
438  }
439  return this;
440  }
441 
444  App *enabled_by_default(bool enable = true) {
445  if(enable) {
447  } else {
450  }
451  return this;
452  }
453 
455  App *immediate_callback(bool immediate = true) {
456  immediate_callback_ = immediate;
457  if(immediate_callback_) {
460  }
461  } else if(!(final_callback_) && parse_complete_callback_) {
463  }
464  return this;
465  }
466 
468  App *validate_positionals(bool validate = true) {
469  validate_positionals_ = validate;
470  return this;
471  }
472 
474  App *validate_optional_arguments(bool validate = true) {
475  validate_optional_arguments_ = validate;
476  return this;
477  }
478 
480  App *allow_config_extras(bool allow = true) {
481  if(allow) {
483  allow_extras_ = true;
484  } else {
486  }
487  return this;
488  }
489 
492  allow_config_extras_ = mode;
493  return this;
494  }
495 
497  App *prefix_command(bool allow = true) {
498  prefix_command_ = allow;
499  return this;
500  }
501 
503  App *ignore_case(bool value = true) {
504  if(value && !ignore_case_) {
505  ignore_case_ = true;
506  auto *p = (parent_ != nullptr) ? _get_fallthrough_parent() : this;
507  auto &match = _compare_subcommand_names(*this, *p);
508  if(!match.empty()) {
509  ignore_case_ = false; // we are throwing so need to be exception invariant
510  throw OptionAlreadyAdded("ignore case would cause subcommand name conflicts: " + match);
511  }
512  }
513  ignore_case_ = value;
514  return this;
515  }
516 
519  App *allow_windows_style_options(bool value = true) {
521  return this;
522  }
523 
525  App *positionals_at_end(bool value = true) {
526  positionals_at_end_ = value;
527  return this;
528  }
529 
531  App *configurable(bool value = true) {
532  configurable_ = value;
533  return this;
534  }
535 
537  App *ignore_underscore(bool value = true) {
538  if(value && !ignore_underscore_) {
539  ignore_underscore_ = true;
540  auto *p = (parent_ != nullptr) ? _get_fallthrough_parent() : this;
541  auto &match = _compare_subcommand_names(*this, *p);
542  if(!match.empty()) {
543  ignore_underscore_ = false;
544  throw OptionAlreadyAdded("ignore underscore would cause subcommand name conflicts: " + match);
545  }
546  }
547  ignore_underscore_ = value;
548  return this;
549  }
550 
552  App *formatter(std::shared_ptr<FormatterBase> fmt) {
553  formatter_ = fmt;
554  return this;
555  }
556 
558  App *formatter_fn(std::function<std::string(const App *, std::string, AppFormatMode)> fmt) {
559  formatter_ = std::make_shared<FormatterLambda>(fmt);
560  return this;
561  }
562 
564  App *config_formatter(std::shared_ptr<Config> fmt) {
565  config_formatter_ = fmt;
566  return this;
567  }
568 
570  bool parsed() const { return parsed_ > 0; }
571 
574 
578 
593  Option *add_option(std::string option_name,
594  callback_t option_callback,
595  std::string option_description = "",
596  bool defaulted = false,
597  std::function<std::string()> func = {}) {
598  Option myopt{option_name, option_description, option_callback, this};
599 
600  if(std::find_if(std::begin(options_), std::end(options_), [&myopt](const Option_p &v) {
601  return *v == myopt;
602  }) == std::end(options_)) {
603  options_.emplace_back();
604  Option_p &option = options_.back();
605  option.reset(new Option(option_name, option_description, option_callback, this));
606 
607  // Set the default string capture function
608  option->default_function(func);
609 
610  // For compatibility with CLI11 1.7 and before, capture the default string here
611  if(defaulted)
612  option->capture_default_str();
613 
614  // Transfer defaults to the new option
615  option_defaults_.copy_to(option.get());
616 
617  // Don't bother to capture if we already did
618  if(!defaulted && option->get_always_capture_default())
619  option->capture_default_str();
620 
621  return option.get();
622  }
623  // we know something matches now find what it is so we can produce more error information
624  for(auto &opt : options_) {
625  auto &matchname = opt->matching_name(myopt);
626  if(!matchname.empty()) {
627  throw(OptionAlreadyAdded("added option matched existing option name: " + matchname));
628  }
629  }
630  // this line should not be reached the above loop should trigger the throw
631  throw(OptionAlreadyAdded("added option matched existing option name")); // LCOV_EXCL_LINE
632  }
633 
635  template <typename AssignTo,
636  typename ConvertTo = AssignTo,
637  enable_if_t<!std::is_const<ConvertTo>::value, detail::enabler> = detail::dummy>
638  Option *add_option(std::string option_name,
639  AssignTo &variable,
640  std::string option_description = "") {
641 
642  auto fun = [&variable](const CLI::results_t &res) { // comment for spacing
643  return detail::lexical_conversion<AssignTo, ConvertTo>(res, variable);
644  };
645 
646  Option *opt = add_option(option_name, fun, option_description, false, [&variable]() {
647  return CLI::detail::checked_to_string<AssignTo, ConvertTo>(variable);
648  });
649  opt->type_name(detail::type_name<ConvertTo>());
650  // these must be actual lvalues since (std::max) sometimes is defined in terms of references and references
651  // to structs used in the evaluation can be temporary so that would cause issues.
654  opt->type_size(detail::type_count_min<ConvertTo>::value, (std::max)(Tcount, XCcount));
655  opt->expected(detail::expected_count<ConvertTo>::value);
657  return opt;
658  }
659 
661  template <typename AssignTo, enable_if_t<!std::is_const<AssignTo>::value, detail::enabler> = detail::dummy>
662  Option *add_option_no_stream(std::string option_name,
663  AssignTo &variable,
664  std::string option_description = "") {
665 
666  auto fun = [&variable](const CLI::results_t &res) { // comment for spacing
667  return detail::lexical_conversion<AssignTo, AssignTo>(res, variable);
668  };
669 
670  Option *opt = add_option(option_name, fun, option_description, false, []() { return std::string{}; });
671  opt->type_name(detail::type_name<AssignTo>());
672  opt->type_size(detail::type_count_min<AssignTo>::value, detail::type_count<AssignTo>::value);
673  opt->expected(detail::expected_count<AssignTo>::value);
675  return opt;
676  }
677 
679  template <typename ArgType>
680  Option *add_option_function(std::string option_name,
681  const std::function<void(const ArgType &)> &func,
682  std::string option_description = "") {
683 
684  auto fun = [func](const CLI::results_t &res) {
685  ArgType variable;
686  bool result = detail::lexical_conversion<ArgType, ArgType>(res, variable);
687  if(result) {
688  func(variable);
689  }
690  return result;
691  };
692 
693  Option *opt = add_option(option_name, std::move(fun), option_description, false);
694  opt->type_name(detail::type_name<ArgType>());
695  opt->type_size(detail::type_count_min<ArgType>::value, detail::type_count<ArgType>::value);
696  opt->expected(detail::expected_count<ArgType>::value);
697  return opt;
698  }
699 
701  Option *add_option(std::string option_name) {
702  return add_option(option_name, CLI::callback_t{}, std::string{}, false);
703  }
704 
706  template <typename T,
707  enable_if_t<std::is_const<T>::value && std::is_constructible<std::string, T>::value, detail::enabler> =
709  Option *add_option(std::string option_name, T &option_description) {
710  return add_option(option_name, CLI::callback_t(), option_description, false);
711  }
712 
714  Option *set_help_flag(std::string flag_name = "", const std::string &help_description = "") {
715  // take flag_description by const reference otherwise add_flag tries to assign to help_description
716  if(help_ptr_ != nullptr) {
718  help_ptr_ = nullptr;
719  }
720 
721  // Empty name will simply remove the help flag
722  if(!flag_name.empty()) {
723  help_ptr_ = add_flag(flag_name, help_description);
724  help_ptr_->configurable(false);
725  }
726 
727  return help_ptr_;
728  }
729 
731  Option *set_help_all_flag(std::string help_name = "", const std::string &help_description = "") {
732  // take flag_description by const reference otherwise add_flag tries to assign to flag_description
733  if(help_all_ptr_ != nullptr) {
735  help_all_ptr_ = nullptr;
736  }
737 
738  // Empty name will simply remove the help all flag
739  if(!help_name.empty()) {
740  help_all_ptr_ = add_flag(help_name, help_description);
741  help_all_ptr_->configurable(false);
742  }
743 
744  return help_all_ptr_;
745  }
746 
748  Option *set_version_flag(std::string flag_name = "",
749  const std::string &versionString = "",
750  const std::string &version_help = "Display program version information and exit") {
751  // take flag_description by const reference otherwise add_flag tries to assign to version_description
752  if(version_ptr_ != nullptr) {
754  version_ptr_ = nullptr;
755  }
756 
757  // Empty name will simply remove the version flag
758  if(!flag_name.empty()) {
760  flag_name, [versionString]() { throw(CLI::CallForVersion(versionString, 0)); }, version_help);
761  version_ptr_->configurable(false);
762  }
763 
764  return version_ptr_;
765  }
767  Option *set_version_flag(std::string flag_name,
768  std::function<std::string()> vfunc,
769  const std::string &version_help = "Display program version information and exit") {
770  if(version_ptr_ != nullptr) {
772  version_ptr_ = nullptr;
773  }
774 
775  // Empty name will simply remove the version flag
776  if(!flag_name.empty()) {
778  flag_name, [vfunc]() { throw(CLI::CallForVersion(vfunc(), 0)); }, version_help);
779  version_ptr_->configurable(false);
780  }
781 
782  return version_ptr_;
783  }
784 
785  private:
787  Option *_add_flag_internal(std::string flag_name, CLI::callback_t fun, std::string flag_description) {
788  Option *opt;
789  if(detail::has_default_flag_values(flag_name)) {
790  // check for default values and if it has them
791  auto flag_defaults = detail::get_default_flag_values(flag_name);
793  opt = add_option(std::move(flag_name), std::move(fun), std::move(flag_description), false);
794  for(const auto &fname : flag_defaults)
795  opt->fnames_.push_back(fname.first);
796  opt->default_flag_values_ = std::move(flag_defaults);
797  } else {
798  opt = add_option(std::move(flag_name), std::move(fun), std::move(flag_description), false);
799  }
800  // flags cannot have positional values
801  if(opt->get_positional()) {
802  auto pos_name = opt->get_name(true);
803  remove_option(opt);
804  throw IncorrectConstruction::PositionalFlag(pos_name);
805  }
807  opt->expected(0);
808  opt->required(false);
809  return opt;
810  }
811 
812  public:
814  Option *add_flag(std::string flag_name) { return _add_flag_internal(flag_name, CLI::callback_t(), std::string{}); }
815 
819  template <typename T,
820  enable_if_t<std::is_const<T>::value && std::is_constructible<std::string, T>::value, detail::enabler> =
822  Option *add_flag(std::string flag_name, T &flag_description) {
823  return _add_flag_internal(flag_name, CLI::callback_t(), flag_description);
824  }
825 
828  template <typename T,
829  enable_if_t<!detail::is_mutable_container<T>::value && !std::is_const<T>::value &&
830  !std::is_constructible<std::function<void(int)>, T>::value,
832  Option *add_flag(std::string flag_name,
833  T &flag_result,
834  std::string flag_description = "") {
835 
836  CLI::callback_t fun = [&flag_result](const CLI::results_t &res) {
837  return CLI::detail::lexical_cast(res[0], flag_result);
838  };
839  auto *opt = _add_flag_internal(flag_name, std::move(fun), std::move(flag_description));
840  return detail::default_flag_modifiers<T>(opt);
841  }
842 
844  template <typename T,
845  enable_if_t<!std::is_assignable<std::function<void(std::int64_t)> &, T>::value, detail::enabler> =
847  Option *add_flag(std::string flag_name,
848  std::vector<T> &flag_results,
849  std::string flag_description = "") {
850  CLI::callback_t fun = [&flag_results](const CLI::results_t &res) {
851  bool retval = true;
852  for(const auto &elem : res) {
853  flag_results.emplace_back();
854  retval &= detail::lexical_cast(elem, flag_results.back());
855  }
856  return retval;
857  };
858  return _add_flag_internal(flag_name, std::move(fun), std::move(flag_description))
861  }
862 
864  Option *add_flag_callback(std::string flag_name,
865  std::function<void(void)> function,
866  std::string flag_description = "") {
867 
868  CLI::callback_t fun = [function](const CLI::results_t &res) {
869  bool trigger{false};
870  auto result = CLI::detail::lexical_cast(res[0], trigger);
871  if(result && trigger) {
872  function();
873  }
874  return result;
875  };
876  return _add_flag_internal(flag_name, std::move(fun), std::move(flag_description));
877  }
878 
880  Option *add_flag_function(std::string flag_name,
881  std::function<void(std::int64_t)> function,
882  std::string flag_description = "") {
883 
884  CLI::callback_t fun = [function](const CLI::results_t &res) {
885  std::int64_t flag_count{0};
886  CLI::detail::lexical_cast(res[0], flag_count);
887  function(flag_count);
888  return true;
889  };
890  return _add_flag_internal(flag_name, std::move(fun), std::move(flag_description))
892  }
893 
894 #ifdef CLI11_CPP14
896  Option *add_flag(std::string flag_name,
897  std::function<void(std::int64_t)> function,
898  std::string flag_description = "") {
899  return add_flag_function(std::move(flag_name), std::move(function), std::move(flag_description));
900  }
901 #endif
902 
904  Option *set_config(std::string option_name = "",
905  std::string default_filename = "",
906  const std::string &help_message = "Read an ini file",
907  bool config_required = false) {
908 
909  // Remove existing config if present
910  if(config_ptr_ != nullptr) {
912  config_ptr_ = nullptr; // need to remove the config_ptr completely
913  }
914 
915  // Only add config if option passed
916  if(!option_name.empty()) {
917  config_ptr_ = add_option(option_name, help_message);
918  if(config_required) {
920  }
921  if(!default_filename.empty()) {
922  config_ptr_->default_str(std::move(default_filename));
923  }
924  config_ptr_->configurable(false);
925  }
926 
927  return config_ptr_;
928  }
929 
931  bool remove_option(Option *opt) {
932  // Make sure no links exist
933  for(Option_p &op : options_) {
934  op->remove_needs(opt);
935  op->remove_excludes(opt);
936  }
937 
938  if(help_ptr_ == opt)
939  help_ptr_ = nullptr;
940  if(help_all_ptr_ == opt)
941  help_all_ptr_ = nullptr;
942 
943  auto iterator =
944  std::find_if(std::begin(options_), std::end(options_), [opt](const Option_p &v) { return v.get() == opt; });
945  if(iterator != std::end(options_)) {
946  options_.erase(iterator);
947  return true;
948  }
949  return false;
950  }
951 
953  template <typename T = Option_group>
954  T *add_option_group(std::string group_name, std::string group_description = "") {
955  if(!detail::valid_alias_name_string(group_name)) {
956  throw IncorrectConstruction("option group names may not contain newlines or null characters");
957  }
958  auto option_group = std::make_shared<T>(std::move(group_description), group_name, this);
959  auto ptr = option_group.get();
960  // move to App_p for overload resolution on older gcc versions
961  App_p app_ptr = std::dynamic_pointer_cast<App>(option_group);
962  add_subcommand(std::move(app_ptr));
963  return ptr;
964  }
965 
969 
971  App *add_subcommand(std::string subcommand_name = "", std::string subcommand_description = "") {
972  if(!subcommand_name.empty() && !detail::valid_name_string(subcommand_name)) {
973  if(!detail::valid_first_char(subcommand_name[0])) {
974  throw IncorrectConstruction(
975  "Subcommand name starts with invalid character, '!' and '-' are not allowed");
976  }
977  for(auto c : subcommand_name) {
978  if(!detail::valid_later_char(c)) {
979  throw IncorrectConstruction(std::string("Subcommand name contains invalid character ('") + c +
980  "'), all characters are allowed except"
981  "'=',':','{','}', and ' '");
982  }
983  }
984  }
985  CLI::App_p subcom = std::shared_ptr<App>(new App(std::move(subcommand_description), subcommand_name, this));
986  return add_subcommand(std::move(subcom));
987  }
988 
991  if(!subcom)
992  throw IncorrectConstruction("passed App is not valid");
993  auto ckapp = (name_.empty() && parent_ != nullptr) ? _get_fallthrough_parent() : this;
994  auto &mstrg = _compare_subcommand_names(*subcom, *ckapp);
995  if(!mstrg.empty()) {
996  throw(OptionAlreadyAdded("subcommand name or alias matches existing subcommand: " + mstrg));
997  }
998  subcom->parent_ = this;
999  subcommands_.push_back(std::move(subcom));
1000  return subcommands_.back().get();
1001  }
1002 
1004  bool remove_subcommand(App *subcom) {
1005  // Make sure no links exist
1006  for(App_p &sub : subcommands_) {
1007  sub->remove_excludes(subcom);
1008  sub->remove_needs(subcom);
1009  }
1010 
1011  auto iterator = std::find_if(
1012  std::begin(subcommands_), std::end(subcommands_), [subcom](const App_p &v) { return v.get() == subcom; });
1013  if(iterator != std::end(subcommands_)) {
1014  subcommands_.erase(iterator);
1015  return true;
1016  }
1017  return false;
1018  }
1021  App *get_subcommand(const App *subcom) const {
1022  if(subcom == nullptr)
1023  throw OptionNotFound("nullptr passed");
1024  for(const App_p &subcomptr : subcommands_)
1025  if(subcomptr.get() == subcom)
1026  return subcomptr.get();
1027  throw OptionNotFound(subcom->get_name());
1028  }
1029 
1031  App *get_subcommand(std::string subcom) const {
1032  auto subc = _find_subcommand(subcom, false, false);
1033  if(subc == nullptr)
1034  throw OptionNotFound(subcom);
1035  return subc;
1036  }
1038  App *get_subcommand(int index = 0) const {
1039  if(index >= 0) {
1040  auto uindex = static_cast<unsigned>(index);
1041  if(uindex < subcommands_.size())
1042  return subcommands_[uindex].get();
1043  }
1044  throw OptionNotFound(std::to_string(index));
1045  }
1046 
1049  if(subcom == nullptr)
1050  throw OptionNotFound("nullptr passed");
1051  for(const App_p &subcomptr : subcommands_)
1052  if(subcomptr.get() == subcom)
1053  return subcomptr;
1054  throw OptionNotFound(subcom->get_name());
1055  }
1056 
1058  CLI::App_p get_subcommand_ptr(std::string subcom) const {
1059  for(const App_p &subcomptr : subcommands_)
1060  if(subcomptr->check_name(subcom))
1061  return subcomptr;
1062  throw OptionNotFound(subcom);
1063  }
1064 
1066  CLI::App_p get_subcommand_ptr(int index = 0) const {
1067  if(index >= 0) {
1068  auto uindex = static_cast<unsigned>(index);
1069  if(uindex < subcommands_.size())
1070  return subcommands_[uindex];
1071  }
1072  throw OptionNotFound(std::to_string(index));
1073  }
1074 
1076  App *get_option_group(std::string group_name) const {
1077  for(const App_p &app : subcommands_) {
1078  if(app->name_.empty() && app->group_ == group_name) {
1079  return app.get();
1080  }
1081  }
1082  throw OptionNotFound(group_name);
1083  }
1084 
1088  std::size_t count() const { return parsed_; }
1089 
1092  std::size_t count_all() const {
1093  std::size_t cnt{0};
1094  for(auto &opt : options_) {
1095  cnt += opt->count();
1096  }
1097  for(auto &sub : subcommands_) {
1098  cnt += sub->count_all();
1099  }
1100  if(!get_name().empty()) { // for named subcommands add the number of times the subcommand was called
1101  cnt += parsed_;
1102  }
1103  return cnt;
1104  }
1105 
1107  App *group(std::string group_name) {
1108  group_ = group_name;
1109  return this;
1110  }
1111 
1116  return this;
1117  }
1118 
1122  App *require_subcommand(int value) {
1123  if(value < 0) {
1125  require_subcommand_max_ = static_cast<std::size_t>(-value);
1126  } else {
1127  require_subcommand_min_ = static_cast<std::size_t>(value);
1128  require_subcommand_max_ = static_cast<std::size_t>(value);
1129  }
1130  return this;
1131  }
1132 
1135  App *require_subcommand(std::size_t min, std::size_t max) {
1138  return this;
1139  }
1140 
1143  require_option_min_ = 1;
1144  require_option_max_ = 0;
1145  return this;
1146  }
1147 
1151  App *require_option(int value) {
1152  if(value < 0) {
1153  require_option_min_ = 0;
1154  require_option_max_ = static_cast<std::size_t>(-value);
1155  } else {
1156  require_option_min_ = static_cast<std::size_t>(value);
1157  require_option_max_ = static_cast<std::size_t>(value);
1158  }
1159  return this;
1160  }
1161 
1164  App *require_option(std::size_t min, std::size_t max) {
1165  require_option_min_ = min;
1166  require_option_max_ = max;
1167  return this;
1168  }
1169 
1172  App *fallthrough(bool value = true) {
1173  fallthrough_ = value;
1174  return this;
1175  }
1176 
1179  explicit operator bool() const { return parsed_ > 0; }
1180 
1184 
1188  virtual void pre_callback() {}
1189 
1193  //
1195  void clear() {
1196 
1197  parsed_ = 0;
1198  pre_parse_called_ = false;
1199 
1200  missing_.clear();
1201  parsed_subcommands_.clear();
1202  for(const Option_p &opt : options_) {
1203  opt->clear();
1204  }
1205  for(const App_p &subc : subcommands_) {
1206  subc->clear();
1207  }
1208  }
1209 
1212  void parse(int argc, const char *const *argv) {
1213  // If the name is not set, read from command line
1214  if(name_.empty() || has_automatic_name_) {
1215  has_automatic_name_ = true;
1216  name_ = argv[0];
1217  }
1218 
1219  std::vector<std::string> args;
1220  args.reserve(static_cast<std::size_t>(argc) - 1U);
1221  for(auto i = static_cast<std::size_t>(argc) - 1U; i > 0U; --i)
1222  args.emplace_back(argv[i]);
1223  parse(std::move(args));
1224  }
1225 
1230  void parse(std::string commandline, bool program_name_included = false) {
1231 
1232  if(program_name_included) {
1233  auto nstr = detail::split_program_name(commandline);
1234  if((name_.empty()) || (has_automatic_name_)) {
1235  has_automatic_name_ = true;
1236  name_ = nstr.first;
1237  }
1238  commandline = std::move(nstr.second);
1239  } else {
1240  detail::trim(commandline);
1241  }
1242  // the next section of code is to deal with quoted arguments after an '=' or ':' for windows like operations
1243  if(!commandline.empty()) {
1244  commandline = detail::find_and_modify(commandline, "=", detail::escape_detect);
1246  commandline = detail::find_and_modify(commandline, ":", detail::escape_detect);
1247  }
1248 
1249  auto args = detail::split_up(std::move(commandline));
1250  // remove all empty strings
1251  args.erase(std::remove(args.begin(), args.end(), std::string{}), args.end());
1252  std::reverse(args.begin(), args.end());
1253 
1254  parse(std::move(args));
1255  }
1256 
1259  void parse(std::vector<std::string> &args) {
1260  // Clear if parsed
1261  if(parsed_ > 0)
1262  clear();
1263 
1264  // parsed_ is incremented in commands/subcommands,
1265  // but placed here to make sure this is cleared when
1266  // running parse after an error is thrown, even by _validate or _configure.
1267  parsed_ = 1;
1268  _validate();
1269  _configure();
1270  // set the parent as nullptr as this object should be the top now
1271  parent_ = nullptr;
1272  parsed_ = 0;
1273 
1274  _parse(args);
1275  run_callback();
1276  }
1277 
1279  void parse(std::vector<std::string> &&args) {
1280  // Clear if parsed
1281  if(parsed_ > 0)
1282  clear();
1283 
1284  // parsed_ is incremented in commands/subcommands,
1285  // but placed here to make sure this is cleared when
1286  // running parse after an error is thrown, even by _validate or _configure.
1287  parsed_ = 1;
1288  _validate();
1289  _configure();
1290  // set the parent as nullptr as this object should be the top now
1291  parent_ = nullptr;
1292  parsed_ = 0;
1293 
1294  _parse(std::move(args));
1295  run_callback();
1296  }
1297 
1298  void parse_from_stream(std::istream &input) {
1299  if(parsed_ == 0) {
1300  _validate();
1301  _configure();
1302  // set the parent as nullptr as this object should be the top now
1303  }
1304 
1305  _parse_stream(input);
1306  run_callback();
1307  }
1309  void failure_message(std::function<std::string(const App *, const Error &e)> function) {
1310  failure_message_ = function;
1311  }
1312 
1314  int exit(const Error &e, std::ostream &out = std::cout, std::ostream &err = std::cerr) const {
1315 
1317  if(e.get_name() == "RuntimeError")
1318  return e.get_exit_code();
1319 
1320  if(e.get_name() == "CallForHelp") {
1321  out << help();
1322  return e.get_exit_code();
1323  }
1324 
1325  if(e.get_name() == "CallForAllHelp") {
1326  out << help("", AppFormatMode::All);
1327  return e.get_exit_code();
1328  }
1329 
1330  if(e.get_name() == "CallForVersion") {
1331  out << e.what() << std::endl;
1332  return e.get_exit_code();
1333  }
1334 
1335  if(e.get_exit_code() != static_cast<int>(ExitCodes::Success)) {
1336  if(failure_message_)
1337  err << failure_message_(this, e) << std::flush;
1338  }
1339 
1340  return e.get_exit_code();
1341  }
1342 
1346 
1348  std::size_t count(std::string option_name) const { return get_option(option_name)->count(); }
1349 
1352  std::vector<App *> get_subcommands() const { return parsed_subcommands_; }
1353 
1356  std::vector<const App *> get_subcommands(const std::function<bool(const App *)> &filter) const {
1357  std::vector<const App *> subcomms(subcommands_.size());
1358  std::transform(std::begin(subcommands_), std::end(subcommands_), std::begin(subcomms), [](const App_p &v) {
1359  return v.get();
1360  });
1361 
1362  if(filter) {
1363  subcomms.erase(std::remove_if(std::begin(subcomms),
1364  std::end(subcomms),
1365  [&filter](const App *app) { return !filter(app); }),
1366  std::end(subcomms));
1367  }
1368 
1369  return subcomms;
1370  }
1371 
1374  std::vector<App *> get_subcommands(const std::function<bool(App *)> &filter) {
1375  std::vector<App *> subcomms(subcommands_.size());
1376  std::transform(std::begin(subcommands_), std::end(subcommands_), std::begin(subcomms), [](const App_p &v) {
1377  return v.get();
1378  });
1379 
1380  if(filter) {
1381  subcomms.erase(
1382  std::remove_if(std::begin(subcomms), std::end(subcomms), [&filter](App *app) { return !filter(app); }),
1383  std::end(subcomms));
1384  }
1385 
1386  return subcomms;
1387  }
1388 
1390  bool got_subcommand(const App *subcom) const {
1391  // get subcom needed to verify that this was a real subcommand
1392  return get_subcommand(subcom)->parsed_ > 0;
1393  }
1394 
1396  bool got_subcommand(std::string subcommand_name) const { return get_subcommand(subcommand_name)->parsed_ > 0; }
1397 
1400  if(opt == nullptr) {
1401  throw OptionNotFound("nullptr passed");
1402  }
1403  exclude_options_.insert(opt);
1404  return this;
1405  }
1406 
1408  App *excludes(App *app) {
1409  if(app == nullptr) {
1410  throw OptionNotFound("nullptr passed");
1411  }
1412  if(app == this) {
1413  throw OptionNotFound("cannot self reference in needs");
1414  }
1415  auto res = exclude_subcommands_.insert(app);
1416  // subcommand exclusion should be symmetric
1417  if(res.second) {
1418  app->exclude_subcommands_.insert(this);
1419  }
1420  return this;
1421  }
1422 
1423  App *needs(Option *opt) {
1424  if(opt == nullptr) {
1425  throw OptionNotFound("nullptr passed");
1426  }
1427  need_options_.insert(opt);
1428  return this;
1429  }
1430 
1431  App *needs(App *app) {
1432  if(app == nullptr) {
1433  throw OptionNotFound("nullptr passed");
1434  }
1435  if(app == this) {
1436  throw OptionNotFound("cannot self reference in needs");
1437  }
1438  need_subcommands_.insert(app);
1439  return this;
1440  }
1441 
1444  auto iterator = std::find(std::begin(exclude_options_), std::end(exclude_options_), opt);
1445  if(iterator == std::end(exclude_options_)) {
1446  return false;
1447  }
1448  exclude_options_.erase(iterator);
1449  return true;
1450  }
1451 
1453  bool remove_excludes(App *app) {
1454  auto iterator = std::find(std::begin(exclude_subcommands_), std::end(exclude_subcommands_), app);
1455  if(iterator == std::end(exclude_subcommands_)) {
1456  return false;
1457  }
1458  auto other_app = *iterator;
1459  exclude_subcommands_.erase(iterator);
1460  other_app->remove_excludes(this);
1461  return true;
1462  }
1463 
1465  bool remove_needs(Option *opt) {
1466  auto iterator = std::find(std::begin(need_options_), std::end(need_options_), opt);
1467  if(iterator == std::end(need_options_)) {
1468  return false;
1469  }
1470  need_options_.erase(iterator);
1471  return true;
1472  }
1473 
1475  bool remove_needs(App *app) {
1476  auto iterator = std::find(std::begin(need_subcommands_), std::end(need_subcommands_), app);
1477  if(iterator == std::end(need_subcommands_)) {
1478  return false;
1479  }
1480  need_subcommands_.erase(iterator);
1481  return true;
1482  }
1483 
1487 
1489  App *footer(std::string footer_string) {
1490  footer_ = std::move(footer_string);
1491  return this;
1492  }
1494  App *footer(std::function<std::string()> footer_function) {
1495  footer_callback_ = std::move(footer_function);
1496  return this;
1497  }
1500  std::string config_to_str(bool default_also = false, bool write_description = false) const {
1501  return config_formatter_->to_config(this, default_also, write_description, "");
1502  }
1503 
1506  std::string help(std::string prev = "", AppFormatMode mode = AppFormatMode::Normal) const {
1507  if(prev.empty())
1508  prev = get_name();
1509  else
1510  prev += " " + get_name();
1511 
1512  // Delegate to subcommand if needed
1513  auto selected_subcommands = get_subcommands();
1514  if(!selected_subcommands.empty()) {
1515  return selected_subcommands.at(0)->help(prev, mode);
1516  }
1517  return formatter_->make_help(this, prev, mode);
1518  }
1519 
1521  std::string version() const {
1522  std::string val;
1523  if(version_ptr_ != nullptr) {
1524  auto rv = version_ptr_->results();
1525  version_ptr_->clear();
1526  version_ptr_->add_result("true");
1527  try {
1529  } catch(const CLI::CallForVersion &cfv) {
1530  val = cfv.what();
1531  }
1532  version_ptr_->clear();
1533  version_ptr_->add_result(rv);
1534  }
1535  return val;
1536  }
1540 
1542  std::shared_ptr<FormatterBase> get_formatter() const { return formatter_; }
1543 
1545  std::shared_ptr<Config> get_config_formatter() const { return config_formatter_; }
1546 
1548  std::shared_ptr<ConfigBase> get_config_formatter_base() const {
1549  // This is safer as a dynamic_cast if we have RTTI, as Config -> ConfigBase
1550 #if CLI11_USE_STATIC_RTTI == 0
1551  return std::dynamic_pointer_cast<ConfigBase>(config_formatter_);
1552 #else
1553  return std::static_pointer_cast<ConfigBase>(config_formatter_);
1554 #endif
1555  }
1556 
1558  std::string get_description() const { return description_; }
1559 
1561  App *description(std::string app_description) {
1562  description_ = std::move(app_description);
1563  return this;
1564  }
1565 
1567  std::vector<const Option *> get_options(const std::function<bool(const Option *)> filter = {}) const {
1568  std::vector<const Option *> options(options_.size());
1569  std::transform(std::begin(options_), std::end(options_), std::begin(options), [](const Option_p &val) {
1570  return val.get();
1571  });
1572 
1573  if(filter) {
1574  options.erase(std::remove_if(std::begin(options),
1575  std::end(options),
1576  [&filter](const Option *opt) { return !filter(opt); }),
1577  std::end(options));
1578  }
1579 
1580  return options;
1581  }
1582 
1584  std::vector<Option *> get_options(const std::function<bool(Option *)> filter = {}) {
1585  std::vector<Option *> options(options_.size());
1586  std::transform(std::begin(options_), std::end(options_), std::begin(options), [](const Option_p &val) {
1587  return val.get();
1588  });
1589 
1590  if(filter) {
1591  options.erase(
1592  std::remove_if(std::begin(options), std::end(options), [&filter](Option *opt) { return !filter(opt); }),
1593  std::end(options));
1594  }
1595 
1596  return options;
1597  }
1598 
1600  Option *get_option_no_throw(std::string option_name) noexcept {
1601  for(Option_p &opt : options_) {
1602  if(opt->check_name(option_name)) {
1603  return opt.get();
1604  }
1605  }
1606  for(auto &subc : subcommands_) {
1607  // also check down into nameless subcommands
1608  if(subc->get_name().empty()) {
1609  auto opt = subc->get_option_no_throw(option_name);
1610  if(opt != nullptr) {
1611  return opt;
1612  }
1613  }
1614  }
1615  return nullptr;
1616  }
1617 
1619  const Option *get_option_no_throw(std::string option_name) const noexcept {
1620  for(const Option_p &opt : options_) {
1621  if(opt->check_name(option_name)) {
1622  return opt.get();
1623  }
1624  }
1625  for(const auto &subc : subcommands_) {
1626  // also check down into nameless subcommands
1627  if(subc->get_name().empty()) {
1628  auto opt = subc->get_option_no_throw(option_name);
1629  if(opt != nullptr) {
1630  return opt;
1631  }
1632  }
1633  }
1634  return nullptr;
1635  }
1636 
1638  const Option *get_option(std::string option_name) const {
1639  auto opt = get_option_no_throw(option_name);
1640  if(opt == nullptr) {
1641  throw OptionNotFound(option_name);
1642  }
1643  return opt;
1644  }
1645 
1647  Option *get_option(std::string option_name) {
1648  auto opt = get_option_no_throw(option_name);
1649  if(opt == nullptr) {
1650  throw OptionNotFound(option_name);
1651  }
1652  return opt;
1653  }
1654 
1656  const Option *operator[](const std::string &option_name) const { return get_option(option_name); }
1657 
1659  const Option *operator[](const char *option_name) const { return get_option(option_name); }
1660 
1662  bool get_ignore_case() const { return ignore_case_; }
1663 
1666 
1668  bool get_fallthrough() const { return fallthrough_; }
1669 
1672 
1675 
1677  bool get_configurable() const { return configurable_; }
1678 
1680  const std::string &get_group() const { return group_; }
1681 
1683  std::string get_footer() const { return (footer_callback_) ? footer_callback_() + '\n' + footer_ : footer_; }
1684 
1686  std::size_t get_require_subcommand_min() const { return require_subcommand_min_; }
1687 
1689  std::size_t get_require_subcommand_max() const { return require_subcommand_max_; }
1690 
1692  std::size_t get_require_option_min() const { return require_option_min_; }
1693 
1695  std::size_t get_require_option_max() const { return require_option_max_; }
1696 
1698  bool get_prefix_command() const { return prefix_command_; }
1699 
1701  bool get_allow_extras() const { return allow_extras_; }
1702 
1704  bool get_required() const { return required_; }
1705 
1707  bool get_disabled() const { return disabled_; }
1708 
1710  bool get_silent() const { return silent_; }
1711 
1714 
1717 
1724 
1727 
1730 
1732  const Option *get_help_ptr() const { return help_ptr_; }
1733 
1735  const Option *get_help_all_ptr() const { return help_all_ptr_; }
1736 
1739 
1741  const Option *get_config_ptr() const { return config_ptr_; }
1742 
1745 
1747  const Option *get_version_ptr() const { return version_ptr_; }
1748 
1750  App *get_parent() { return parent_; }
1751 
1753  const App *get_parent() const { return parent_; }
1754 
1756  const std::string &get_name() const { return name_; }
1757 
1759  const std::vector<std::string> &get_aliases() const { return aliases_; }
1760 
1763  aliases_.clear();
1764  return this;
1765  }
1766 
1768  std::string get_display_name(bool with_aliases = false) const {
1769  if(name_.empty()) {
1770  return std::string("[Option Group: ") + get_group() + "]";
1771  }
1772  if(aliases_.empty() || !with_aliases) {
1773  return name_;
1774  }
1775  std::string dispname = name_;
1776  for(const auto &lalias : aliases_) {
1777  dispname.push_back(',');
1778  dispname.push_back(' ');
1779  dispname.append(lalias);
1780  }
1781  return dispname;
1782  }
1783 
1785  bool check_name(std::string name_to_check) const {
1786  std::string local_name = name_;
1787  if(ignore_underscore_) {
1788  local_name = detail::remove_underscore(name_);
1789  name_to_check = detail::remove_underscore(name_to_check);
1790  }
1791  if(ignore_case_) {
1792  local_name = detail::to_lower(name_);
1793  name_to_check = detail::to_lower(name_to_check);
1794  }
1795 
1796  if(local_name == name_to_check) {
1797  return true;
1798  }
1799  for(auto les : aliases_) {
1800  if(ignore_underscore_) {
1801  les = detail::remove_underscore(les);
1802  }
1803  if(ignore_case_) {
1804  les = detail::to_lower(les);
1805  }
1806  if(les == name_to_check) {
1807  return true;
1808  }
1809  }
1810  return false;
1811  }
1812 
1814  std::vector<std::string> get_groups() const {
1815  std::vector<std::string> groups;
1816 
1817  for(const Option_p &opt : options_) {
1818  // Add group if it is not already in there
1819  if(std::find(groups.begin(), groups.end(), opt->get_group()) == groups.end()) {
1820  groups.push_back(opt->get_group());
1821  }
1822  }
1823 
1824  return groups;
1825  }
1826 
1828  const std::vector<Option *> &parse_order() const { return parse_order_; }
1829 
1831  std::vector<std::string> remaining(bool recurse = false) const {
1832  std::vector<std::string> miss_list;
1833  for(const std::pair<detail::Classifier, std::string> &miss : missing_) {
1834  miss_list.push_back(std::get<1>(miss));
1835  }
1836  // Get from a subcommand that may allow extras
1837  if(recurse) {
1838  if(!allow_extras_) {
1839  for(const auto &sub : subcommands_) {
1840  if(sub->name_.empty() && !sub->missing_.empty()) {
1841  for(const std::pair<detail::Classifier, std::string> &miss : sub->missing_) {
1842  miss_list.push_back(std::get<1>(miss));
1843  }
1844  }
1845  }
1846  }
1847  // Recurse into subcommands
1848 
1849  for(const App *sub : parsed_subcommands_) {
1850  std::vector<std::string> output = sub->remaining(recurse);
1851  std::copy(std::begin(output), std::end(output), std::back_inserter(miss_list));
1852  }
1853  }
1854  return miss_list;
1855  }
1856 
1858  std::vector<std::string> remaining_for_passthrough(bool recurse = false) const {
1859  std::vector<std::string> miss_list = remaining(recurse);
1860  std::reverse(std::begin(miss_list), std::end(miss_list));
1861  return miss_list;
1862  }
1863 
1865  std::size_t remaining_size(bool recurse = false) const {
1866  auto remaining_options = static_cast<std::size_t>(std::count_if(
1867  std::begin(missing_), std::end(missing_), [](const std::pair<detail::Classifier, std::string> &val) {
1868  return val.first != detail::Classifier::POSITIONAL_MARK;
1869  }));
1870 
1871  if(recurse) {
1872  for(const App_p &sub : subcommands_) {
1873  remaining_options += sub->remaining_size(recurse);
1874  }
1875  }
1876  return remaining_options;
1877  }
1878 
1880 
1881  protected:
1886  void _validate() const {
1887  // count the number of positional only args
1888  auto pcount = std::count_if(std::begin(options_), std::end(options_), [](const Option_p &opt) {
1889  return opt->get_items_expected_max() >= detail::expected_max_vector_size && !opt->nonpositional();
1890  });
1891  if(pcount > 1) {
1892  auto pcount_req = std::count_if(std::begin(options_), std::end(options_), [](const Option_p &opt) {
1893  return opt->get_items_expected_max() >= detail::expected_max_vector_size && !opt->nonpositional() &&
1894  opt->get_required();
1895  });
1896  if(pcount - pcount_req > 1) {
1897  throw InvalidError(name_);
1898  }
1899  }
1900 
1901  std::size_t nameless_subs{0};
1902  for(const App_p &app : subcommands_) {
1903  app->_validate();
1904  if(app->get_name().empty())
1905  ++nameless_subs;
1906  }
1907 
1908  if(require_option_min_ > 0) {
1909  if(require_option_max_ > 0) {
1911  throw(InvalidError("Required min options greater than required max options",
1913  }
1914  }
1915  if(require_option_min_ > (options_.size() + nameless_subs)) {
1916  throw(InvalidError("Required min options greater than number of available options",
1918  }
1919  }
1920  }
1921 
1925  void _configure() {
1927  disabled_ = false;
1928  } else if(default_startup == startup_mode::disabled) {
1929  disabled_ = true;
1930  }
1931  for(const App_p &app : subcommands_) {
1932  if(app->has_automatic_name_) {
1933  app->name_.clear();
1934  }
1935  if(app->name_.empty()) {
1936  app->fallthrough_ = false; // make sure fallthrough_ is false to prevent infinite loop
1937  app->prefix_command_ = false;
1938  }
1939  // make sure the parent is set to be this object in preparation for parse
1940  app->parent_ = this;
1941  app->_configure();
1942  }
1943  }
1944 
1946  void run_callback(bool final_mode = false, bool suppress_final_callback = false) {
1947  pre_callback();
1948  // in the main app if immediate_callback_ is set it runs the main callback before the used subcommands
1949  if(!final_mode && parse_complete_callback_) {
1951  }
1952  // run the callbacks for the received subcommands
1953  for(App *subc : get_subcommands()) {
1954  if(subc->parent_ == this) {
1955  subc->run_callback(true, suppress_final_callback);
1956  }
1957  }
1958  // now run callbacks for option_groups
1959  for(auto &subc : subcommands_) {
1960  if(subc->name_.empty() && subc->count_all() > 0) {
1961  subc->run_callback(true, suppress_final_callback);
1962  }
1963  }
1964 
1965  // finally run the main callback
1966  if(final_callback_ && (parsed_ > 0) && (!suppress_final_callback)) {
1967  if(!name_.empty() || count_all() > 0 || parent_ == nullptr) {
1968  final_callback_();
1969  }
1970  }
1971  }
1972 
1974  bool _valid_subcommand(const std::string &current, bool ignore_used = true) const {
1975  // Don't match if max has been reached - but still check parents
1977  return parent_ != nullptr && parent_->_valid_subcommand(current, ignore_used);
1978  }
1979  auto com = _find_subcommand(current, true, ignore_used);
1980  if(com != nullptr) {
1981  return true;
1982  }
1983  // Check parent if exists, else return false
1984  return parent_ != nullptr && parent_->_valid_subcommand(current, ignore_used);
1985  }
1986 
1988  detail::Classifier _recognize(const std::string &current, bool ignore_used_subcommands = true) const {
1989  std::string dummy1, dummy2;
1990 
1991  if(current == "--")
1993  if(_valid_subcommand(current, ignore_used_subcommands))
1995  if(detail::split_long(current, dummy1, dummy2))
1996  return detail::Classifier::LONG;
1997  if(detail::split_short(current, dummy1, dummy2)) {
1998  if(dummy1[0] >= '0' && dummy1[0] <= '9') {
1999  if(get_option_no_throw(std::string{'-', dummy1[0]}) == nullptr) {
2000  return detail::Classifier::NONE;
2001  }
2002  }
2004  }
2005  if((allow_windows_style_options_) && (detail::split_windows_style(current, dummy1, dummy2)))
2007  if((current == "++") && !name_.empty() && parent_ != nullptr)
2009  return detail::Classifier::NONE;
2010  }
2011 
2012  // The parse function is now broken into several parts, and part of process
2013 
2016  if(config_ptr_ != nullptr) {
2017  bool config_required = config_ptr_->get_required();
2018  auto file_given = config_ptr_->count() > 0;
2019  auto config_files = config_ptr_->as<std::vector<std::string>>();
2020  if(config_files.empty() || config_files.front().empty()) {
2021  if(config_required) {
2022  throw FileError::Missing("no specified config file");
2023  }
2024  return;
2025  }
2026  for(auto rit = config_files.rbegin(); rit != config_files.rend(); ++rit) {
2027  const auto &config_file = *rit;
2028  auto path_result = detail::check_path(config_file.c_str());
2029  if(path_result == detail::path_type::file) {
2030  try {
2031  std::vector<ConfigItem> values = config_formatter_->from_file(config_file);
2032  _parse_config(values);
2033  if(!file_given) {
2034  config_ptr_->add_result(config_file);
2035  }
2036  } catch(const FileError &) {
2037  if(config_required || file_given)
2038  throw;
2039  }
2040  } else if(config_required || file_given) {
2041  throw FileError::Missing(config_file);
2042  }
2043  }
2044  }
2045  }
2046 
2048  void _process_env() {
2049  for(const Option_p &opt : options_) {
2050  if(opt->count() == 0 && !opt->envname_.empty()) {
2051  char *buffer = nullptr;
2052  std::string ename_string;
2053 
2054 #ifdef _MSC_VER
2055  // Windows version
2056  std::size_t sz = 0;
2057  if(_dupenv_s(&buffer, &sz, opt->envname_.c_str()) == 0 && buffer != nullptr) {
2058  ename_string = std::string(buffer);
2059  free(buffer);
2060  }
2061 #else
2062  // This also works on Windows, but gives a warning
2063  buffer = std::getenv(opt->envname_.c_str());
2064  if(buffer != nullptr)
2065  ename_string = std::string(buffer);
2066 #endif
2067 
2068  if(!ename_string.empty()) {
2069  opt->add_result(ename_string);
2070  }
2071  }
2072  }
2073 
2074  for(App_p &sub : subcommands_) {
2075  if(sub->get_name().empty() || !sub->parse_complete_callback_)
2076  sub->_process_env();
2077  }
2078  }
2079 
2082 
2083  for(App_p &sub : subcommands_) {
2084  // process the priority option_groups first
2085  if(sub->get_name().empty() && sub->parse_complete_callback_) {
2086  if(sub->count_all() > 0) {
2087  sub->_process_callbacks();
2088  sub->run_callback();
2089  }
2090  }
2091  }
2092 
2093  for(const Option_p &opt : options_) {
2094  if((*opt) && !opt->get_callback_run()) {
2095  opt->run_callback();
2096  }
2097  }
2098  for(App_p &sub : subcommands_) {
2099  if(!sub->parse_complete_callback_) {
2100  sub->_process_callbacks();
2101  }
2102  }
2103  }
2104 
2108  void _process_help_flags(bool trigger_help = false, bool trigger_all_help = false) const {
2109  const Option *help_ptr = get_help_ptr();
2110  const Option *help_all_ptr = get_help_all_ptr();
2111 
2112  if(help_ptr != nullptr && help_ptr->count() > 0)
2113  trigger_help = true;
2114  if(help_all_ptr != nullptr && help_all_ptr->count() > 0)
2115  trigger_all_help = true;
2116 
2117  // If there were parsed subcommands, call those. First subcommand wins if there are multiple ones.
2118  if(!parsed_subcommands_.empty()) {
2119  for(const App *sub : parsed_subcommands_)
2120  sub->_process_help_flags(trigger_help, trigger_all_help);
2121 
2122  // Only the final subcommand should call for help. All help wins over help.
2123  } else if(trigger_all_help) {
2124  throw CallForAllHelp();
2125  } else if(trigger_help) {
2126  throw CallForHelp();
2127  }
2128  }
2129 
2132  // check excludes
2133  bool excluded{false};
2134  std::string excluder;
2135  for(auto &opt : exclude_options_) {
2136  if(opt->count() > 0) {
2137  excluded = true;
2138  excluder = opt->get_name();
2139  }
2140  }
2141  for(auto &subc : exclude_subcommands_) {
2142  if(subc->count_all() > 0) {
2143  excluded = true;
2144  excluder = subc->get_display_name();
2145  }
2146  }
2147  if(excluded) {
2148  if(count_all() > 0) {
2149  throw ExcludesError(get_display_name(), excluder);
2150  }
2151  // if we are excluded but didn't receive anything, just return
2152  return;
2153  }
2154 
2155  // check excludes
2156  bool missing_needed{false};
2157  std::string missing_need;
2158  for(auto &opt : need_options_) {
2159  if(opt->count() == 0) {
2160  missing_needed = true;
2161  missing_need = opt->get_name();
2162  }
2163  }
2164  for(auto &subc : need_subcommands_) {
2165  if(subc->count_all() == 0) {
2166  missing_needed = true;
2167  missing_need = subc->get_display_name();
2168  }
2169  }
2170  if(missing_needed) {
2171  if(count_all() > 0) {
2172  throw RequiresError(get_display_name(), missing_need);
2173  }
2174  // if we missing something but didn't have any options, just return
2175  return;
2176  }
2177 
2178  std::size_t used_options = 0;
2179  for(const Option_p &opt : options_) {
2180 
2181  if(opt->count() != 0) {
2182  ++used_options;
2183  }
2184  // Required but empty
2185  if(opt->get_required() && opt->count() == 0) {
2186  throw RequiredError(opt->get_name());
2187  }
2188  // Requires
2189  for(const Option *opt_req : opt->needs_)
2190  if(opt->count() > 0 && opt_req->count() == 0)
2191  throw RequiresError(opt->get_name(), opt_req->get_name());
2192  // Excludes
2193  for(const Option *opt_ex : opt->excludes_)
2194  if(opt->count() > 0 && opt_ex->count() != 0)
2195  throw ExcludesError(opt->get_name(), opt_ex->get_name());
2196  }
2197  // check for the required number of subcommands
2198  if(require_subcommand_min_ > 0) {
2199  auto selected_subcommands = get_subcommands();
2200  if(require_subcommand_min_ > selected_subcommands.size())
2201  throw RequiredError::Subcommand(require_subcommand_min_);
2202  }
2203 
2204  // Max error cannot occur, the extra subcommand will parse as an ExtrasError or a remaining item.
2205 
2206  // run this loop to check how many unnamed subcommands were actually used since they are considered options
2207  // from the perspective of an App
2208  for(App_p &sub : subcommands_) {
2209  if(sub->disabled_)
2210  continue;
2211  if(sub->name_.empty() && sub->count_all() > 0) {
2212  ++used_options;
2213  }
2214  }
2215 
2216  if(require_option_min_ > used_options || (require_option_max_ > 0 && require_option_max_ < used_options)) {
2217  auto option_list = detail::join(options_, [this](const Option_p &ptr) {
2218  if(ptr.get() == help_ptr_ || ptr.get() == help_all_ptr_) {
2219  return std::string{};
2220  }
2221  return ptr->get_name(false, true);
2222  });
2223 
2224  auto subc_list = get_subcommands([](App *app) { return ((app->get_name().empty()) && (!app->disabled_)); });
2225  if(!subc_list.empty()) {
2226  option_list += "," + detail::join(subc_list, [](const App *app) { return app->get_display_name(); });
2227  }
2228  throw RequiredError::Option(require_option_min_, require_option_max_, used_options, option_list);
2229  }
2230 
2231  // now process the requirements for subcommands if needed
2232  for(App_p &sub : subcommands_) {
2233  if(sub->disabled_)
2234  continue;
2235  if(sub->name_.empty() && sub->required_ == false) {
2236  if(sub->count_all() == 0) {
2237  if(require_option_min_ > 0 && require_option_min_ <= used_options) {
2238  continue;
2239  // if we have met the requirement and there is nothing in this option group skip checking
2240  // requirements
2241  }
2242  if(require_option_max_ > 0 && used_options >= require_option_min_) {
2243  continue;
2244  // if we have met the requirement and there is nothing in this option group skip checking
2245  // requirements
2246  }
2247  }
2248  }
2249  if(sub->count() > 0 || sub->name_.empty()) {
2250  sub->_process_requirements();
2251  }
2252 
2253  if(sub->required_ && sub->count_all() == 0) {
2254  throw(CLI::RequiredError(sub->get_display_name()));
2255  }
2256  }
2257  }
2258 
2260  void _process() {
2261  try {
2262  // the config file might generate a FileError but that should not be processed until later in the process
2263  // to allow for help, version and other errors to generate first.
2264  _process_config_file();
2265 
2266  // process env shouldn't throw but no reason to process it if config generated an error
2267  _process_env();
2268  } catch(const CLI::FileError &) {
2269  // callbacks and help_flags can generate exceptions which should take priority
2270  // over the config file error if one exists.
2271  _process_callbacks();
2272  _process_help_flags();
2273  throw;
2274  }
2275 
2276  _process_callbacks();
2277  _process_help_flags();
2278 
2279  _process_requirements();
2280  }
2281 
2284  if(!(allow_extras_ || prefix_command_)) {
2285  std::size_t num_left_over = remaining_size();
2286  if(num_left_over > 0) {
2287  throw ExtrasError(name_, remaining(false));
2288  }
2289  }
2290 
2291  for(App_p &sub : subcommands_) {
2292  if(sub->count() > 0)
2293  sub->_process_extras();
2294  }
2295  }
2296 
2299  void _process_extras(std::vector<std::string> &args) {
2300  if(!(allow_extras_ || prefix_command_)) {
2301  std::size_t num_left_over = remaining_size();
2302  if(num_left_over > 0) {
2303  args = remaining(false);
2304  throw ExtrasError(name_, args);
2305  }
2306  }
2307 
2308  for(App_p &sub : subcommands_) {
2309  if(sub->count() > 0)
2310  sub->_process_extras(args);
2311  }
2312  }
2313 
2316  ++parsed_;
2317  for(App_p &sub : subcommands_) {
2318  if(sub->get_name().empty())
2319  sub->increment_parsed();
2320  }
2321  }
2323  void _parse(std::vector<std::string> &args) {
2324  increment_parsed();
2325  _trigger_pre_parse(args.size());
2326  bool positional_only = false;
2327 
2328  while(!args.empty()) {
2329  if(!_parse_single(args, positional_only)) {
2330  break;
2331  }
2332  }
2333 
2334  if(parent_ == nullptr) {
2335  _process();
2336 
2337  // Throw error if any items are left over (depending on settings)
2338  _process_extras(args);
2339 
2340  // Convert missing (pairs) to extras (string only) ready for processing in another app
2341  args = remaining_for_passthrough(false);
2342  } else if(parse_complete_callback_) {
2343  _process_env();
2344  _process_callbacks();
2345  _process_help_flags();
2346  _process_requirements();
2347  run_callback(false, true);
2348  }
2349  }
2350 
2352  void _parse(std::vector<std::string> &&args) {
2353  // this can only be called by the top level in which case parent == nullptr by definition
2354  // operation is simplified
2355  increment_parsed();
2356  _trigger_pre_parse(args.size());
2357  bool positional_only = false;
2358 
2359  while(!args.empty()) {
2360  _parse_single(args, positional_only);
2361  }
2362  _process();
2363 
2364  // Throw error if any items are left over (depending on settings)
2365  _process_extras();
2366  }
2367 
2369  void _parse_stream(std::istream &input) {
2370  auto values = config_formatter_->from_config(input);
2371  _parse_config(values);
2372  increment_parsed();
2373  _trigger_pre_parse(values.size());
2374  _process();
2375 
2376  // Throw error if any items are left over (depending on settings)
2377  _process_extras();
2378  }
2379 
2384  void _parse_config(const std::vector<ConfigItem> &args) {
2385  for(const ConfigItem &item : args) {
2386  if(!_parse_single_config(item) && allow_config_extras_ == config_extras_mode::error)
2387  throw ConfigError::Extras(item.fullname());
2388  }
2389  }
2390 
2392  bool _parse_single_config(const ConfigItem &item, std::size_t level = 0) {
2393  if(level < item.parents.size()) {
2394  try {
2395  auto subcom = get_subcommand(item.parents.at(level));
2396  auto result = subcom->_parse_single_config(item, level + 1);
2397 
2398  return result;
2399  } catch(const OptionNotFound &) {
2400  return false;
2401  }
2402  }
2403  // check for section open
2404  if(item.name == "++") {
2405  if(configurable_) {
2406  increment_parsed();
2407  _trigger_pre_parse(2);
2408  if(parent_ != nullptr) {
2409  parent_->parsed_subcommands_.push_back(this);
2410  }
2411  }
2412  return true;
2413  }
2414  // check for section close
2415  if(item.name == "--") {
2416  if(configurable_) {
2417  _process_callbacks();
2418  _process_requirements();
2419  run_callback();
2420  }
2421  return true;
2422  }
2423  Option *op = get_option_no_throw("--" + item.name);
2424  if(op == nullptr) {
2425  if(item.name.size() == 1) {
2426  op = get_option_no_throw("-" + item.name);
2427  }
2428  }
2429  if(op == nullptr) {
2430  op = get_option_no_throw(item.name);
2431  }
2432  if(op == nullptr) {
2433  // If the option was not present
2434  if(get_allow_config_extras() == config_extras_mode::capture)
2435  // Should we worry about classifying the extras properly?
2436  missing_.emplace_back(detail::Classifier::NONE, item.fullname());
2437  return false;
2438  }
2439 
2440  if(!op->get_configurable()) {
2441  if(get_allow_config_extras() == config_extras_mode::ignore_all) {
2442  return false;
2443  }
2444  throw ConfigError::NotConfigurable(item.fullname());
2445  }
2446 
2447  if(op->empty()) {
2448 
2449  if(op->get_expected_min() == 0) {
2450  // Flag parsing
2451  auto res = config_formatter_->to_flag(item);
2452  res = op->get_flag_value(item.name, res);
2453 
2454  op->add_result(res);
2455 
2456  } else {
2457  op->add_result(item.inputs);
2458  op->run_callback();
2459  }
2460  }
2461 
2462  return true;
2463  }
2464 
2467  bool _parse_single(std::vector<std::string> &args, bool &positional_only) {
2468  bool retval = true;
2469  detail::Classifier classifier = positional_only ? detail::Classifier::NONE : _recognize(args.back());
2470  switch(classifier) {
2472  args.pop_back();
2473  positional_only = true;
2474  if((!_has_remaining_positionals()) && (parent_ != nullptr)) {
2475  retval = false;
2476  } else {
2477  _move_to_missing(classifier, "--");
2478  }
2479  break;
2481  // treat this like a positional mark if in the parent app
2482  args.pop_back();
2483  retval = false;
2484  break;
2486  retval = _parse_subcommand(args);
2487  break;
2491  // If already parsed a subcommand, don't accept options_
2492  _parse_arg(args, classifier);
2493  break;
2495  // Probably a positional or something for a parent (sub)command
2496  retval = _parse_positional(args, false);
2497  if(retval && positionals_at_end_) {
2498  positional_only = true;
2499  }
2500  break;
2501  // LCOV_EXCL_START
2502  default:
2503  throw HorribleError("unrecognized classifier (you should not see this!)");
2504  // LCOV_EXCL_STOP
2505  }
2506  return retval;
2507  }
2508 
2510  std::size_t _count_remaining_positionals(bool required_only = false) const {
2511  std::size_t retval = 0;
2512  for(const Option_p &opt : options_) {
2513  if(opt->get_positional() && (!required_only || opt->get_required())) {
2514  if(opt->get_items_expected_min() > 0 &&
2515  static_cast<int>(opt->count()) < opt->get_items_expected_min()) {
2516  retval += static_cast<std::size_t>(opt->get_items_expected_min()) - opt->count();
2517  }
2518  }
2519  }
2520  return retval;
2521  }
2522 
2525  for(const Option_p &opt : options_) {
2526  if(opt->get_positional() && ((static_cast<int>(opt->count()) < opt->get_items_expected_min()))) {
2527  return true;
2528  }
2529  }
2530 
2531  return false;
2532  }
2533 
2537  bool _parse_positional(std::vector<std::string> &args, bool haltOnSubcommand) {
2538 
2539  const std::string &positional = args.back();
2540 
2541  if(positionals_at_end_) {
2542  // deal with the case of required arguments at the end which should take precedence over other arguments
2543  auto arg_rem = args.size();
2544  auto remreq = _count_remaining_positionals(true);
2545  if(arg_rem <= remreq) {
2546  for(const Option_p &opt : options_) {
2547  if(opt->get_positional() && opt->required_) {
2548  if(static_cast<int>(opt->count()) < opt->get_items_expected_min()) {
2549  if(validate_positionals_) {
2550  std::string pos = positional;
2551  pos = opt->_validate(pos, 0);
2552  if(!pos.empty()) {
2553  continue;
2554  }
2555  }
2556 
2557  parse_order_.push_back(opt.get());
2559  if(opt->get_inject_separator()) {
2560  if(!opt->results().empty() && !opt->results().back().empty()) {
2561  opt->add_result(std::string{});
2562  }
2563  }
2564  if(opt->get_trigger_on_parse() &&
2566  opt->clear();
2567  }
2568  opt->add_result(positional);
2569  if(opt->get_trigger_on_parse()) {
2570  opt->run_callback();
2571  }
2572  args.pop_back();
2573  return true;
2574  }
2575  }
2576  }
2577  }
2578  }
2579  for(const Option_p &opt : options_) {
2580  // Eat options, one by one, until done
2581  if(opt->get_positional() &&
2582  (static_cast<int>(opt->count()) < opt->get_items_expected_min() || opt->get_allow_extra_args())) {
2583  if(validate_positionals_) {
2584  std::string pos = positional;
2585  pos = opt->_validate(pos, 0);
2586  if(!pos.empty()) {
2587  continue;
2588  }
2589  }
2590  if(opt->get_inject_separator()) {
2591  if(!opt->results().empty() && !opt->results().back().empty()) {
2592  opt->add_result(std::string{});
2593  }
2594  }
2596  opt->clear();
2597  }
2598  opt->add_result(positional);
2599  if(opt->get_trigger_on_parse()) {
2600  opt->run_callback();
2601  }
2602  parse_order_.push_back(opt.get());
2603  args.pop_back();
2604  return true;
2605  }
2606  }
2607 
2608  for(auto &subc : subcommands_) {
2609  if((subc->name_.empty()) && (!subc->disabled_)) {
2610  if(subc->_parse_positional(args, false)) {
2611  if(!subc->pre_parse_called_) {
2612  subc->_trigger_pre_parse(args.size());
2613  }
2614  return true;
2615  }
2616  }
2617  }
2618  // let the parent deal with it if possible
2619  if(parent_ != nullptr && fallthrough_)
2620  return _get_fallthrough_parent()->_parse_positional(args, static_cast<bool>(parse_complete_callback_));
2621 
2623  auto com = _find_subcommand(args.back(), true, false);
2624  if(com != nullptr && (require_subcommand_max_ == 0 || require_subcommand_max_ > parsed_subcommands_.size())) {
2625  if(haltOnSubcommand) {
2626  return false;
2627  }
2628  args.pop_back();
2629  com->_parse(args);
2630  return true;
2631  }
2634  auto parent_app = (parent_ != nullptr) ? _get_fallthrough_parent() : this;
2635  com = parent_app->_find_subcommand(args.back(), true, false);
2636  if(com != nullptr && (com->parent_->require_subcommand_max_ == 0 ||
2637  com->parent_->require_subcommand_max_ > com->parent_->parsed_subcommands_.size())) {
2638  return false;
2639  }
2640 
2641  if(positionals_at_end_) {
2642  throw CLI::ExtrasError(name_, args);
2643  }
2645  if(parent_ != nullptr && name_.empty()) {
2646  return false;
2647  }
2649  _move_to_missing(detail::Classifier::NONE, positional);
2650  args.pop_back();
2651  if(prefix_command_) {
2652  while(!args.empty()) {
2653  _move_to_missing(detail::Classifier::NONE, args.back());
2654  args.pop_back();
2655  }
2656  }
2657 
2658  return true;
2659  }
2660 
2663  App *_find_subcommand(const std::string &subc_name, bool ignore_disabled, bool ignore_used) const noexcept {
2664  for(const App_p &com : subcommands_) {
2665  if(com->disabled_ && ignore_disabled)
2666  continue;
2667  if(com->get_name().empty()) {
2668  auto subc = com->_find_subcommand(subc_name, ignore_disabled, ignore_used);
2669  if(subc != nullptr) {
2670  return subc;
2671  }
2672  }
2673  if(com->check_name(subc_name)) {
2674  if((!*com) || !ignore_used)
2675  return com.get();
2676  }
2677  }
2678  return nullptr;
2679  }
2680 
2685  bool _parse_subcommand(std::vector<std::string> &args) {
2686  if(_count_remaining_positionals(/* required */ true) > 0) {
2687  _parse_positional(args, false);
2688  return true;
2689  }
2690  auto com = _find_subcommand(args.back(), true, true);
2691  if(com != nullptr) {
2692  args.pop_back();
2693  if(!com->silent_) {
2694  parsed_subcommands_.push_back(com);
2695  }
2696  com->_parse(args);
2697  auto parent_app = com->parent_;
2698  while(parent_app != this) {
2699  parent_app->_trigger_pre_parse(args.size());
2700  if(!com->silent_) {
2701  parent_app->parsed_subcommands_.push_back(com);
2702  }
2703  parent_app = parent_app->parent_;
2704  }
2705  return true;
2706  }
2707 
2708  if(parent_ == nullptr)
2709  throw HorribleError("Subcommand " + args.back() + " missing");
2710  return false;
2711  }
2712 
2715  bool _parse_arg(std::vector<std::string> &args, detail::Classifier current_type) {
2716 
2717  std::string current = args.back();
2718 
2719  std::string arg_name;
2720  std::string value;
2721  std::string rest;
2722 
2723  switch(current_type) {
2725  if(!detail::split_long(current, arg_name, value))
2726  throw HorribleError("Long parsed but missing (you should not see this):" + args.back());
2727  break;
2729  if(!detail::split_short(current, arg_name, rest))
2730  throw HorribleError("Short parsed but missing! You should not see this");
2731  break;
2733  if(!detail::split_windows_style(current, arg_name, value))
2734  throw HorribleError("windows option parsed but missing! You should not see this");
2735  break;
2740  default:
2741  throw HorribleError("parsing got called with invalid option! You should not see this");
2742  }
2743 
2744  auto op_ptr =
2745  std::find_if(std::begin(options_), std::end(options_), [arg_name, current_type](const Option_p &opt) {
2746  if(current_type == detail::Classifier::LONG)
2747  return opt->check_lname(arg_name);
2748  if(current_type == detail::Classifier::SHORT)
2749  return opt->check_sname(arg_name);
2750  // this will only get called for detail::Classifier::WINDOWS_STYLE
2751  return opt->check_lname(arg_name) || opt->check_sname(arg_name);
2752  });
2753 
2754  // Option not found
2755  if(op_ptr == std::end(options_)) {
2756  for(auto &subc : subcommands_) {
2757  if(subc->name_.empty() && !subc->disabled_) {
2758  if(subc->_parse_arg(args, current_type)) {
2759  if(!subc->pre_parse_called_) {
2760  subc->_trigger_pre_parse(args.size());
2761  }
2762  return true;
2763  }
2764  }
2765  }
2766 
2767  // don't capture missing if this is a nameless subcommand and nameless subcommands can't fallthrough
2768  if(parent_ != nullptr && name_.empty()) {
2769  return false;
2770  }
2771 
2772  // If a subcommand, try the main command
2773  if(parent_ != nullptr && fallthrough_)
2774  return _get_fallthrough_parent()->_parse_arg(args, current_type);
2775 
2776  // Otherwise, add to missing
2777  args.pop_back();
2778  _move_to_missing(current_type, current);
2779  return true;
2780  }
2781 
2782  args.pop_back();
2783 
2784  // Get a reference to the pointer to make syntax bearable
2785  Option_p &op = *op_ptr;
2787  if(op->get_inject_separator()) {
2788  if(!op->results().empty() && !op->results().back().empty()) {
2789  op->add_result(std::string{});
2790  }
2791  }
2792  if(op->get_trigger_on_parse() && op->current_option_state_ == Option::option_state::callback_run) {
2793  op->clear();
2794  }
2795  int min_num = (std::min)(op->get_type_size_min(), op->get_items_expected_min());
2796  int max_num = op->get_items_expected_max();
2797  // check container like options to limit the argument size to a single type if the allow_extra_flags argument is
2798  // set. 16 is somewhat arbitrary (needs to be at least 4)
2799  if(max_num >= detail::expected_max_vector_size / 16 && !op->get_allow_extra_args()) {
2800  auto tmax = op->get_type_size_max();
2801  max_num = detail::checked_multiply(tmax, op->get_expected_min()) ? tmax : detail::expected_max_vector_size;
2802  }
2803  // Make sure we always eat the minimum for unlimited vectors
2804  int collected = 0; // total number of arguments collected
2805  int result_count = 0; // local variable for number of results in a single arg string
2806  // deal with purely flag like things
2807  if(max_num == 0) {
2808  auto res = op->get_flag_value(arg_name, value);
2809  op->add_result(res);
2810  parse_order_.push_back(op.get());
2811  } else if(!value.empty()) { // --this=value
2812  op->add_result(value, result_count);
2813  parse_order_.push_back(op.get());
2814  collected += result_count;
2815  // -Trest
2816  } else if(!rest.empty()) {
2817  op->add_result(rest, result_count);
2818  parse_order_.push_back(op.get());
2819  rest = "";
2820  collected += result_count;
2821  }
2822 
2823  // gather the minimum number of arguments
2824  while(min_num > collected && !args.empty()) {
2825  std::string current_ = args.back();
2826  args.pop_back();
2827  op->add_result(current_, result_count);
2828  parse_order_.push_back(op.get());
2829  collected += result_count;
2830  }
2831 
2832  if(min_num > collected) { // if we have run out of arguments and the minimum was not met
2833  throw ArgumentMismatch::TypedAtLeast(op->get_name(), min_num, op->get_type_name());
2834  }
2835 
2836  // now check for optional arguments
2837  if(max_num > collected || op->get_allow_extra_args()) { // we allow optional arguments
2838  auto remreqpos = _count_remaining_positionals(true);
2839  // we have met the minimum now optionally check up to the maximum
2840  while((collected < max_num || op->get_allow_extra_args()) && !args.empty() &&
2841  _recognize(args.back(), false) == detail::Classifier::NONE) {
2842  // If any required positionals remain, don't keep eating
2843  if(remreqpos >= args.size()) {
2844  break;
2845  }
2846  if(validate_optional_arguments_) {
2847  std::string optarg = args.back();
2848  optarg = op->_validate(optarg, 0);
2849  if(!optarg.empty()) {
2850  break;
2851  }
2852  }
2853  op->add_result(args.back(), result_count);
2854  parse_order_.push_back(op.get());
2855  args.pop_back();
2856  collected += result_count;
2857  }
2858 
2859  // Allow -- to end an unlimited list and "eat" it
2860  if(!args.empty() && _recognize(args.back()) == detail::Classifier::POSITIONAL_MARK)
2861  args.pop_back();
2862  // optional flag that didn't receive anything now get the default value
2863  if(min_num == 0 && max_num > 0 && collected == 0) {
2864  auto res = op->get_flag_value(arg_name, std::string{});
2865  op->add_result(res);
2866  parse_order_.push_back(op.get());
2867  }
2868  }
2869  // if we only partially completed a type then add an empty string if allowed for later processing
2870  if(min_num > 0 && (collected % op->get_type_size_max()) != 0) {
2871  if(op->get_type_size_max() != op->get_type_size_min()) {
2872  op->add_result(std::string{});
2873  } else {
2874  throw ArgumentMismatch::PartialType(op->get_name(), op->get_type_size_min(), op->get_type_name());
2875  }
2876  }
2877  if(op->get_trigger_on_parse()) {
2878  op->run_callback();
2879  }
2880  if(!rest.empty()) {
2881  rest = "-" + rest;
2882  args.push_back(rest);
2883  }
2884  return true;
2885  }
2886 
2888  void _trigger_pre_parse(std::size_t remaining_args) {
2889  if(!pre_parse_called_) {
2890  pre_parse_called_ = true;
2891  if(pre_parse_callback_) {
2892  pre_parse_callback_(remaining_args);
2893  }
2894  } else if(immediate_callback_) {
2895  if(!name_.empty()) {
2896  auto pcnt = parsed_;
2897  auto extras = std::move(missing_);
2898  clear();
2899  parsed_ = pcnt;
2900  pre_parse_called_ = true;
2901  missing_ = std::move(extras);
2902  }
2903  }
2904  }
2905 
2908  if(parent_ == nullptr) {
2909  throw(HorribleError("No Valid parent"));
2910  }
2911  auto fallthrough_parent = parent_;
2912  while((fallthrough_parent->parent_ != nullptr) && (fallthrough_parent->get_name().empty())) {
2913  fallthrough_parent = fallthrough_parent->parent_;
2914  }
2915  return fallthrough_parent;
2916  }
2917 
2919  const std::string &_compare_subcommand_names(const App &subcom, const App &base) const {
2920  static const std::string estring;
2921  if(subcom.disabled_) {
2922  return estring;
2923  }
2924  for(auto &subc : base.subcommands_) {
2925  if(subc.get() != &subcom) {
2926  if(subc->disabled_) {
2927  continue;
2928  }
2929  if(!subcom.get_name().empty()) {
2930  if(subc->check_name(subcom.get_name())) {
2931  return subcom.get_name();
2932  }
2933  }
2934  if(!subc->get_name().empty()) {
2935  if(subcom.check_name(subc->get_name())) {
2936  return subc->get_name();
2937  }
2938  }
2939  for(const auto &les : subcom.aliases_) {
2940  if(subc->check_name(les)) {
2941  return les;
2942  }
2943  }
2944  // this loop is needed in case of ignore_underscore or ignore_case on one but not the other
2945  for(const auto &les : subc->aliases_) {
2946  if(subcom.check_name(les)) {
2947  return les;
2948  }
2949  }
2950  // if the subcommand is an option group we need to check deeper
2951  if(subc->get_name().empty()) {
2952  auto &cmpres = _compare_subcommand_names(subcom, *subc);
2953  if(!cmpres.empty()) {
2954  return cmpres;
2955  }
2956  }
2957  // if the test subcommand is an option group we need to check deeper
2958  if(subcom.get_name().empty()) {
2959  auto &cmpres = _compare_subcommand_names(*subc, subcom);
2960  if(!cmpres.empty()) {
2961  return cmpres;
2962  }
2963  }
2964  }
2965  }
2966  return estring;
2967  }
2969  void _move_to_missing(detail::Classifier val_type, const std::string &val) {
2970  if(allow_extras_ || subcommands_.empty()) {
2971  missing_.emplace_back(val_type, val);
2972  return;
2973  }
2974  // allow extra arguments to be places in an option group if it is allowed there
2975  for(auto &subc : subcommands_) {
2976  if(subc->name_.empty() && subc->allow_extras_) {
2977  subc->missing_.emplace_back(val_type, val);
2978  return;
2979  }
2980  }
2981  // if we haven't found any place to put them yet put them in missing
2982  missing_.emplace_back(val_type, val);
2983  }
2984 
2985  public:
2987  void _move_option(Option *opt, App *app) {
2988  if(opt == nullptr) {
2989  throw OptionNotFound("the option is NULL");
2990  }
2991  // verify that the give app is actually a subcommand
2992  bool found = false;
2993  for(auto &subc : subcommands_) {
2994  if(app == subc.get()) {
2995  found = true;
2996  }
2997  }
2998  if(!found) {
2999  throw OptionNotFound("The Given app is not a subcommand");
3000  }
3001 
3002  if((help_ptr_ == opt) || (help_all_ptr_ == opt))
3003  throw OptionAlreadyAdded("cannot move help options");
3004 
3005  if(config_ptr_ == opt)
3006  throw OptionAlreadyAdded("cannot move config file options");
3007 
3008  auto iterator =
3009  std::find_if(std::begin(options_), std::end(options_), [opt](const Option_p &v) { return v.get() == opt; });
3010  if(iterator != std::end(options_)) {
3011  const auto &opt_p = *iterator;
3012  if(std::find_if(std::begin(app->options_), std::end(app->options_), [&opt_p](const Option_p &v) {
3013  return (*v == *opt_p);
3014  }) == std::end(app->options_)) {
3015  // only erase after the insertion was successful
3016  app->options_.push_back(std::move(*iterator));
3017  options_.erase(iterator);
3018  } else {
3019  throw OptionAlreadyAdded("option was not located: " + opt->get_name());
3020  }
3021  } else {
3022  throw OptionNotFound("could not locate the given Option");
3023  }
3024  }
3025 }; // namespace CLI
3026 
3028 class Option_group : public App {
3029  public:
3030  Option_group(std::string group_description, std::string group_name, App *parent)
3031  : App(std::move(group_description), "", parent) {
3032  group(group_name);
3033  // option groups should have automatic fallthrough
3034  }
3035  using App::add_option;
3038  if(get_parent() == nullptr) {
3039  throw OptionNotFound("Unable to locate the specified option");
3040  }
3041  get_parent()->_move_option(opt, this);
3042  return opt;
3043  }
3045  void add_options(Option *opt) { add_option(opt); }
3047  template <typename... Args> void add_options(Option *opt, Args... args) {
3048  add_option(opt);
3049  add_options(args...);
3050  }
3051  using App::add_subcommand;
3053  App *add_subcommand(App *subcom) {
3054  App_p subc = subcom->get_parent()->get_subcommand_ptr(subcom);
3055  subc->get_parent()->remove_subcommand(subcom);
3056  add_subcommand(std::move(subc));
3057  return subcom;
3058  }
3059 };
3061 inline void TriggerOn(App *trigger_app, App *app_to_enable) {
3062  app_to_enable->enabled_by_default(false);
3063  app_to_enable->disabled_by_default();
3064  trigger_app->preparse_callback([app_to_enable](std::size_t) { app_to_enable->disabled(false); });
3065 }
3066 
3068 inline void TriggerOn(App *trigger_app, std::vector<App *> apps_to_enable) {
3069  for(auto &app : apps_to_enable) {
3070  app->enabled_by_default(false);
3071  app->disabled_by_default();
3072  }
3073 
3074  trigger_app->preparse_callback([apps_to_enable](std::size_t) {
3075  for(auto &app : apps_to_enable) {
3076  app->disabled(false);
3077  }
3078  });
3079 }
3080 
3082 inline void TriggerOff(App *trigger_app, App *app_to_enable) {
3083  app_to_enable->disabled_by_default(false);
3084  app_to_enable->enabled_by_default();
3085  trigger_app->preparse_callback([app_to_enable](std::size_t) { app_to_enable->disabled(); });
3086 }
3087 
3089 inline void TriggerOff(App *trigger_app, std::vector<App *> apps_to_enable) {
3090  for(auto &app : apps_to_enable) {
3091  app->disabled_by_default(false);
3092  app->enabled_by_default();
3093  }
3094 
3095  trigger_app->preparse_callback([apps_to_enable](std::size_t) {
3096  for(auto &app : apps_to_enable) {
3097  app->disabled();
3098  }
3099  });
3100 }
3101 
3103 inline void deprecate_option(Option *opt, const std::string &replacement = "") {
3104  Validator deprecate_warning{[opt, replacement](std::string &) {
3105  std::cout << opt->get_name() << " is deprecated please use '" << replacement
3106  << "' instead\n";
3107  return std::string();
3108  },
3109  "DEPRECATED"};
3110  deprecate_warning.application_index(0);
3111  opt->check(deprecate_warning);
3112  if(!replacement.empty()) {
3113  opt->description(opt->get_description() + " DEPRECATED: please use '" + replacement + "' instead");
3114  }
3115 }
3116 
3118 inline void deprecate_option(App *app, const std::string &option_name, const std::string &replacement = "") {
3119  auto opt = app->get_option(option_name);
3120  deprecate_option(opt, replacement);
3121 }
3122 
3124 inline void deprecate_option(App &app, const std::string &option_name, const std::string &replacement = "") {
3125  auto opt = app.get_option(option_name);
3126  deprecate_option(opt, replacement);
3127 }
3128 
3130 inline void retire_option(App *app, Option *opt) {
3131  App temp;
3132  auto option_copy = temp.add_option(opt->get_name(false, true))
3134  ->expected(opt->get_expected_min(), opt->get_expected_max())
3136 
3137  app->remove_option(opt);
3138  auto opt2 = app->add_option(option_copy->get_name(false, true), "option has been retired and has no effect")
3139  ->type_name("RETIRED")
3140  ->default_str("RETIRED")
3141  ->type_size(option_copy->get_type_size_min(), option_copy->get_type_size_max())
3142  ->expected(option_copy->get_expected_min(), option_copy->get_expected_max())
3143  ->allow_extra_args(option_copy->get_allow_extra_args());
3144 
3145  Validator retired_warning{[opt2](std::string &) {
3146  std::cout << "WARNING " << opt2->get_name() << " is retired and has no effect\n";
3147  return std::string();
3148  },
3149  ""};
3150  retired_warning.application_index(0);
3151  opt2->check(retired_warning);
3152 }
3153 
3155 inline void retire_option(App &app, Option *opt) { retire_option(&app, opt); }
3156 
3158 inline void retire_option(App *app, const std::string &option_name) {
3159 
3160  auto opt = app->get_option_no_throw(option_name);
3161  if(opt != nullptr) {
3162  retire_option(app, opt);
3163  return;
3164  }
3165  auto opt2 = app->add_option(option_name, "option has been retired and has no effect")
3166  ->type_name("RETIRED")
3167  ->expected(0, 1)
3168  ->default_str("RETIRED");
3169  Validator retired_warning{[opt2](std::string &) {
3170  std::cout << "WARNING " << opt2->get_name() << " is retired and has no effect\n";
3171  return std::string();
3172  },
3173  ""};
3174  retired_warning.application_index(0);
3175  opt2->check(retired_warning);
3176 }
3177 
3179 inline void retire_option(App &app, const std::string &option_name) { retire_option(&app, option_name); }
3180 
3181 namespace FailureMessage {
3182 
3184 inline std::string simple(const App *app, const Error &e) {
3185  std::string header = std::string(e.what()) + "\n";
3186  std::vector<std::string> names;
3187 
3188  // Collect names
3189  if(app->get_help_ptr() != nullptr)
3190  names.push_back(app->get_help_ptr()->get_name());
3191 
3192  if(app->get_help_all_ptr() != nullptr)
3193  names.push_back(app->get_help_all_ptr()->get_name());
3194 
3195  // If any names found, suggest those
3196  if(!names.empty())
3197  header += "Run with " + detail::join(names, " or ") + " for more information.\n";
3198 
3199  return header;
3200 }
3201 
3203 inline std::string help(const App *app, const Error &e) {
3204  std::string header = std::string("ERROR: ") + e.get_name() + ": " + e.what() + "\n";
3205  header += app->help();
3206  return header;
3207 }
3208 
3209 } // namespace FailureMessage
3210 
3211 namespace detail {
3213 struct AppFriend {
3214 #ifdef CLI11_CPP14
3215 
3217  template <typename... Args> static decltype(auto) parse_arg(App *app, Args &&...args) {
3218  return app->_parse_arg(std::forward<Args>(args)...);
3219  }
3220 
3222  template <typename... Args> static decltype(auto) parse_subcommand(App *app, Args &&...args) {
3223  return app->_parse_subcommand(std::forward<Args>(args)...);
3224  }
3225 #else
3227  template <typename... Args>
3228  static auto parse_arg(App *app, Args &&...args) ->
3229  typename std::result_of<decltype (&App::_parse_arg)(App, Args...)>::type {
3230  return app->_parse_arg(std::forward<Args>(args)...);
3231  }
3232 
3234  template <typename... Args>
3235  static auto parse_subcommand(App *app, Args &&...args) ->
3236  typename std::result_of<decltype (&App::_parse_subcommand)(App, Args...)>::type {
3237  return app->_parse_subcommand(std::forward<Args>(args)...);
3238  }
3239 #endif
3241  static App *get_fallthrough_parent(App *app) { return app->_get_fallthrough_parent(); }
3242 };
3243 } // namespace detail
3244 
3245 // [CLI11:app_hpp:end]
3246 } // namespace CLI
Creates a command line program, with very few defaults.
Definition: App.hpp:85
bool _parse_single(std::vector< std::string > &args, bool &positional_only)
Definition: App.hpp:2467
bool get_disabled_by_default() const
Get the status of disabled by default.
Definition: App.hpp:1716
std::vector< std::string > remaining(bool recurse=false) const
This returns the missing options from the current subcommand.
Definition: App.hpp:1831
T * add_option_group(std::string group_name, std::string group_description="")
creates an option group as part of the given app
Definition: App.hpp:954
void _process_env()
Get envname options if not yet passed. Runs on all subcommands.
Definition: App.hpp:2048
Option * add_option(std::string option_name)
Add option with no description or variable assignment.
Definition: App.hpp:701
App * require_option(std::size_t min, std::size_t max)
Definition: App.hpp:1164
void _process()
Process callbacks and such.
Definition: App.hpp:2260
Option * config_ptr_
Pointer to the config option.
Definition: App.hpp:277
void parse(std::string commandline, bool program_name_included=false)
Definition: App.hpp:1230
App * group(std::string group_name)
Changes the group membership.
Definition: App.hpp:1107
const std::vector< std::string > & get_aliases() const
Get the aliases of the current app.
Definition: App.hpp:1759
App * alias(std::string app_name)
Set an alias for the app.
Definition: App.hpp:390
bool remove_excludes(App *app)
Removes a subcommand from the excludes list of this subcommand.
Definition: App.hpp:1453
bool _parse_single_config(const ConfigItem &item, std::size_t level=0)
Fill in a single config option.
Definition: App.hpp:2392
Option * add_option(std::string option_name, callback_t option_callback, std::string option_description="", bool defaulted=false, std::function< std::string()> func={})
Definition: App.hpp:593
App * _get_fallthrough_parent()
Get the appropriate parent to fallthrough to which is the first one that has a name or the main app.
Definition: App.hpp:2907
std::size_t require_option_min_
Minimum required options (not inheritable!)
Definition: App.hpp:258
void _parse(std::vector< std::string > &args)
Internal parse function.
Definition: App.hpp:2323
std::size_t get_require_option_min() const
Get the required min option value.
Definition: App.hpp:1692
void _parse(std::vector< std::string > &&args)
Internal parse function.
Definition: App.hpp:2352
Option * add_flag_callback(std::string flag_name, std::function< void(void)> function, std::string flag_description="")
Add option for callback that is triggered with a true flag and takes no arguments.
Definition: App.hpp:864
bool get_configurable() const
Check the status of the allow windows style options.
Definition: App.hpp:1677
OptionDefaults * option_defaults()
Get the OptionDefault object, to set option defaults.
Definition: App.hpp:573
std::size_t require_subcommand_max_
Max number of subcommands allowed (parsing stops after this number). 0 is unlimited INHERITABLE.
Definition: App.hpp:255
bool _valid_subcommand(const std::string &current, bool ignore_used=true) const
Check to see if a subcommand is valid. Give up immediately if subcommand max has been reached.
Definition: App.hpp:1974
std::vector< App_p > subcommands_
Storage for subcommand list.
Definition: App.hpp:208
std::string help(std::string prev="", AppFormatMode mode=AppFormatMode::Normal) const
Definition: App.hpp:1506
App * fallthrough(bool value=true)
Definition: App.hpp:1172
bool remove_option(Option *opt)
Removes an option from the App. Takes an option pointer. Returns true if found and removed.
Definition: App.hpp:931
std::uint32_t parsed_
Counts the number of times this command/subcommand was parsed.
Definition: App.hpp:249
App * get_parent()
Get the parent of this subcommand (or nullptr if main app)
Definition: App.hpp:1750
bool parsed() const
Check to see if this subcommand was parsed, true only if received on command line.
Definition: App.hpp:570
const Option * get_version_ptr() const
Get a pointer to the version option. (const)
Definition: App.hpp:1747
App * required(bool require=true)
Remove the error when extras are left over on the command line.
Definition: App.hpp:415
std::shared_ptr< FormatterBase > get_formatter() const
Access the formatter.
Definition: App.hpp:1542
OptionDefaults option_defaults_
The default values for options, customizable and changeable INHERITABLE.
Definition: App.hpp:141
bool get_allow_windows_style_options() const
Check the status of the allow windows style options.
Definition: App.hpp:1671
App & operator=(const App &)=delete
App * preparse_callback(std::function< void(std::size_t)> pp_callback)
Definition: App.hpp:366
App * get_subcommand(std::string subcom) const
Check to see if a subcommand is part of this command (text version)
Definition: App.hpp:1031
bool _parse_positional(std::vector< std::string > &args, bool haltOnSubcommand)
Definition: App.hpp:2537
bool check_name(std::string name_to_check) const
Check the name, case insensitive and underscore insensitive if set.
Definition: App.hpp:1785
void _process_help_flags(bool trigger_help=false, bool trigger_all_help=false) const
Definition: App.hpp:2108
bool disabled_
If set to true the subcommand is disabled and cannot be used, ignored for main app.
Definition: App.hpp:118
App * require_subcommand(std::size_t min, std::size_t max)
Definition: App.hpp:1135
bool required_
If set to true the subcommand is required to be processed and used, ignored for main app.
Definition: App.hpp:115
startup_mode
Definition: App.hpp:230
CLI::App_p get_subcommand_ptr(std::string subcom) const
Check to see if a subcommand is part of this command (text version)
Definition: App.hpp:1058
Option * set_help_all_flag(std::string help_name="", const std::string &help_description="")
Set a help all flag, replaced the existing one if present.
Definition: App.hpp:731
std::size_t count_all() const
Definition: App.hpp:1092
Option * add_flag(std::string flag_name, T &flag_result, std::string flag_description="")
Definition: App.hpp:832
App * allow_extras(bool allow=true)
Remove the error when extras are left over on the command line.
Definition: App.hpp:409
CLI::App_p get_subcommand_ptr(int index=0) const
Get an owning pointer to subcommand by index.
Definition: App.hpp:1066
App * excludes(App *app)
Sets excluded subcommands for the subcommand.
Definition: App.hpp:1408
void _process_extras()
Throw an error if anything is left over and should not be.
Definition: App.hpp:2283
void _process_requirements()
Verify required options and cross requirements. Subcommands too (only if selected).
Definition: App.hpp:2131
std::string footer_
Footer to put after all options in the help output INHERITABLE.
Definition: App.hpp:151
config_extras_mode allow_config_extras_
Definition: App.hpp:106
std::vector< std::pair< detail::Classifier, std::string > > missing_t
Definition: App.hpp:175
Option * version_ptr_
A pointer to a version flag if there is one.
Definition: App.hpp:163
App * parent_
A pointer to the parent if this is a subcommand.
Definition: App.hpp:264
std::set< Option * > exclude_options_
Definition: App.hpp:193
std::shared_ptr< ConfigBase > get_config_formatter_base() const
Access the config formatter as a configBase pointer.
Definition: App.hpp:1548
Option * set_config(std::string option_name="", std::string default_filename="", const std::string &help_message="Read an ini file", bool config_required=false)
Set a configuration ini file option, or clear it if no name passed.
Definition: App.hpp:904
Option * add_option(std::string option_name, T &option_description)
Add option with description but with no variable assignment or callback.
Definition: App.hpp:709
void run_callback(bool final_mode=false, bool suppress_final_callback=false)
Internal function to run (App) callback, bottom up.
Definition: App.hpp:1946
std::function< std::string()> footer_callback_
This is a function that generates a footer to put after all other options in help output.
Definition: App.hpp:154
bool get_ignore_case() const
Check the status of ignore_case.
Definition: App.hpp:1662
App(const App &)=delete
bool got_subcommand(std::string subcommand_name) const
Check with name instead of pointer to see if subcommand was selected.
Definition: App.hpp:1396
Option * add_flag(std::string flag_name, std::vector< T > &flag_results, std::string flag_description="")
Vector version to capture multiple flags.
Definition: App.hpp:847
App * description(std::string app_description)
Set the description of the app.
Definition: App.hpp:1561
std::function< void()> parse_complete_callback_
This is a function that runs when parsing has finished.
Definition: App.hpp:131
virtual void pre_callback()
Definition: App.hpp:1188
void parse(int argc, const char *const *argv)
Definition: App.hpp:1212
App * require_option(int value)
Definition: App.hpp:1151
bool get_prefix_command() const
Get the prefix command status.
Definition: App.hpp:1698
std::string name_
Subcommand name or program name (from parser if name is empty)
Definition: App.hpp:96
std::vector< App * > parsed_subcommands_
This is a list of the subcommands collected, in order.
Definition: App.hpp:186
App(std::string app_description="", std::string app_name="")
Create a new program. Pass in the same arguments as main(), along with a help string.
Definition: App.hpp:324
bool ignore_underscore_
If true, the program should ignore underscores INHERITABLE.
Definition: App.hpp:214
CLI::App_p get_subcommand_ptr(App *subcom) const
Check to see if a subcommand is part of this command and get a shared_ptr to it.
Definition: App.hpp:1048
const App * get_parent() const
Get the parent of this subcommand (or nullptr if main app) (const version)
Definition: App.hpp:1753
missing_t missing_
Definition: App.hpp:180
const std::vector< Option * > & parse_order() const
This gets a vector of pointers with the original parse order.
Definition: App.hpp:1828
std::size_t require_subcommand_min_
Minimum required subcommands (not inheritable!)
Definition: App.hpp:252
void clear()
Reset the parsed data.
Definition: App.hpp:1195
std::size_t _count_remaining_positionals(bool required_only=false) const
Count the required remaining positional arguments.
Definition: App.hpp:2510
std::function< std::string(const App *, const Error &e)> failure_message_
The error message printing function INHERITABLE.
Definition: App.hpp:169
bool remove_needs(App *app)
Removes a subcommand from the needs list of this subcommand.
Definition: App.hpp:1475
bool _parse_arg(std::vector< std::string > &args, detail::Classifier current_type)
Definition: App.hpp:2715
App * footer(std::function< std::string()> footer_function)
Set footer.
Definition: App.hpp:1494
bool get_required() const
Get the status of required.
Definition: App.hpp:1704
bool get_validate_positionals() const
Get the status of validating positionals.
Definition: App.hpp:1721
std::vector< const Option * > get_options(const std::function< bool(const Option *)> filter={}) const
Get the list of options (user facing function, so returns raw pointers), has optional filter function...
Definition: App.hpp:1567
void failure_message(std::function< std::string(const App *, const Error &e)> function)
Provide a function to print a help message. The function gets access to the App pointer and error.
Definition: App.hpp:1309
App * clear_aliases()
clear all the aliases of the current App
Definition: App.hpp:1762
App * parse_complete_callback(std::function< void()> pc_callback)
Definition: App.hpp:359
std::size_t get_require_subcommand_max() const
Get the required max subcommand value.
Definition: App.hpp:1689
bool has_automatic_name_
If set to true the name was automatically generated from the command line vs a user set name.
Definition: App.hpp:112
bool get_disabled() const
Get the status of disabled.
Definition: App.hpp:1707
void _process_config_file()
Read and process a configuration file (main app only)
Definition: App.hpp:2015
std::size_t remaining_size(bool recurse=false) const
This returns the number of remaining options, minus the – separator.
Definition: App.hpp:1865
App * add_subcommand(std::string subcommand_name="", std::string subcommand_description="")
Add a subcommand. Inherits INHERITABLE and OptionDefaults, and help flag.
Definition: App.hpp:971
App * needs(Option *opt)
Definition: App.hpp:1423
App * allow_windows_style_options(bool value=true)
Definition: App.hpp:519
void _process_extras(std::vector< std::string > &args)
Definition: App.hpp:2299
virtual ~App()=default
virtual destructor
bool get_allow_extras() const
Get the status of allow extras.
Definition: App.hpp:1701
std::vector< Option_p > options_
The list of options, stored locally.
Definition: App.hpp:144
Option * help_all_ptr_
A pointer to the help all flag if there is one INHERITABLE.
Definition: App.hpp:160
bool validate_optional_arguments_
If set to true optional vector arguments are validated before assigning INHERITABLE.
Definition: App.hpp:242
void parse(std::vector< std::string > &args)
Definition: App.hpp:1259
std::size_t count(std::string option_name) const
Counts the number of times the given option was passed.
Definition: App.hpp:1348
App * disabled_by_default(bool disable=true)
Set the subcommand to be disabled by default, so on clear(), at the start of each parse it is disable...
Definition: App.hpp:433
std::function< void()> final_callback_
This is a function that runs when all processing has completed.
Definition: App.hpp:134
App * final_callback(std::function< void()> app_callback)
Definition: App.hpp:352
Option * add_flag(std::string flag_name)
Add a flag with no description or variable assignment.
Definition: App.hpp:814
void parse(std::vector< std::string > &&args)
The real work is done here. Expects a reversed vector.
Definition: App.hpp:1279
Option * add_option_no_stream(std::string option_name, AssignTo &variable, std::string option_description="")
Add option for assigning to a variable.
Definition: App.hpp:662
App * footer(std::string footer_string)
Set footer.
Definition: App.hpp:1489
const Option * get_option(std::string option_name) const
Get an option by name.
Definition: App.hpp:1638
Option * set_version_flag(std::string flag_name="", const std::string &versionString="", const std::string &version_help="Display program version information and exit")
Set a version flag and version display string, replace the existing one if present.
Definition: App.hpp:748
bool positionals_at_end_
specify that positional arguments come at the end of the argument sequence not inheritable
Definition: App.hpp:228
Option * get_option_no_throw(std::string option_name) noexcept
Get an option by name (noexcept non-const version)
Definition: App.hpp:1600
App * _find_subcommand(const std::string &subc_name, bool ignore_disabled, bool ignore_used) const noexcept
Definition: App.hpp:2663
bool immediate_callback_
Definition: App.hpp:125
Option * add_option_function(std::string option_name, const std::function< void(const ArgType &)> &func, std::string option_description="")
Add option for a callback of a specific type.
Definition: App.hpp:680
App * add_subcommand(CLI::App_p subcom)
Add a previously created app as a subcommand.
Definition: App.hpp:990
const Option * get_help_all_ptr() const
Get a pointer to the help all flag. (const)
Definition: App.hpp:1735
App * require_subcommand()
The argumentless form of require subcommand requires 1 or more subcommands.
Definition: App.hpp:1113
const Option * operator[](const std::string &option_name) const
Shortcut bracket operator for getting a pointer to an option.
Definition: App.hpp:1656
std::vector< App * > get_subcommands(const std::function< bool(App *)> &filter)
Definition: App.hpp:1374
bool remove_excludes(Option *opt)
Removes an option from the excludes list of this subcommand.
Definition: App.hpp:1443
void parse_from_stream(std::istream &input)
Definition: App.hpp:1298
const std::string & get_group() const
Get the group of this subcommand.
Definition: App.hpp:1680
bool configurable_
if set to true the subcommand can be triggered via configuration files INHERITABLE
Definition: App.hpp:236
const Option * get_config_ptr() const
Get a pointer to the config option. (const)
Definition: App.hpp:1741
App * formatter_fn(std::function< std::string(const App *, std::string, AppFormatMode)> fmt)
Set the help formatter.
Definition: App.hpp:558
const std::string & _compare_subcommand_names(const App &subcom, const App &base) const
Helper function to run through all possible comparisons of subcommand names to check there is no over...
Definition: App.hpp:2919
Option * get_config_ptr()
Get a pointer to the config option.
Definition: App.hpp:1738
const Option * operator[](const char *option_name) const
Shortcut bracket operator for getting a pointer to an option.
Definition: App.hpp:1659
Option * set_version_flag(std::string flag_name, std::function< std::string()> vfunc, const std::string &version_help="Display program version information and exit")
Generate the version string through a callback function.
Definition: App.hpp:767
std::string description_
Description of the current program/subcommand.
Definition: App.hpp:99
App * config_formatter(std::shared_ptr< Config > fmt)
Set the config formatter.
Definition: App.hpp:564
std::string get_display_name(bool with_aliases=false) const
Get a display name for an app.
Definition: App.hpp:1768
Option * get_option(std::string option_name)
Get an option by name (non-const version)
Definition: App.hpp:1647
App(std::string app_description, std::string app_name, App *parent)
Special private constructor for subcommand.
Definition: App.hpp:285
bool remove_needs(Option *opt)
Removes an option from the needs list of this subcommand.
Definition: App.hpp:1465
void _move_option(Option *opt, App *app)
function that could be used by subclasses of App to shift options around into subcommands
Definition: App.hpp:2987
int exit(const Error &e, std::ostream &out=std::cout, std::ostream &err=std::cerr) const
Print a nice error message and return the exit code.
Definition: App.hpp:1314
std::vector< std::string > get_groups() const
Get the groups available directly from this option (in order)
Definition: App.hpp:1814
Option * add_option(std::string option_name, AssignTo &variable, std::string option_description="")
Add option for assigning to a variable.
Definition: App.hpp:638
std::size_t require_option_max_
Max number of options allowed. 0 is unlimited (not inheritable)
Definition: App.hpp:261
std::vector< std::string > remaining_for_passthrough(bool recurse=false) const
This returns the missing options in a form ready for processing by another command line program.
Definition: App.hpp:1858
const Option * get_option_no_throw(std::string option_name) const noexcept
Get an option by name (noexcept const version)
Definition: App.hpp:1619
bool get_silent() const
Get the status of silence.
Definition: App.hpp:1710
std::vector< std::string > aliases_
Alias names for the subcommand.
Definition: App.hpp:270
void _parse_stream(std::istream &input)
Internal function to parse a stream.
Definition: App.hpp:2369
std::string get_description() const
Get the app or subcommand description.
Definition: App.hpp:1558
App * callback(std::function< void()> app_callback)
Definition: App.hpp:341
App * allow_config_extras(bool allow=true)
ignore extras in config files
Definition: App.hpp:480
bool get_fallthrough() const
Check the status of fallthrough.
Definition: App.hpp:1668
App * prefix_command(bool allow=true)
Do not parse anything after the first unrecognized option and return.
Definition: App.hpp:497
std::set< App * > exclude_subcommands_
this is a list of subcommands that are exclusionary to this one
Definition: App.hpp:189
App * disabled(bool disable=true)
Disable the subcommand or option group.
Definition: App.hpp:421
App * configurable(bool value=true)
Specify that the subcommand can be triggered by a config file.
Definition: App.hpp:531
App * ignore_case(bool value=true)
Ignore case. Subcommands inherit value.
Definition: App.hpp:503
Option * set_help_flag(std::string flag_name="", const std::string &help_description="")
Set a help flag, replace the existing one if present.
Definition: App.hpp:714
App * validate_optional_arguments(bool validate=true)
Set the subcommand to validate optional vector arguments before assigning.
Definition: App.hpp:474
std::vector< const App * > get_subcommands(const std::function< bool(const App *)> &filter) const
Definition: App.hpp:1356
std::size_t get_require_option_max() const
Get the required max option value.
Definition: App.hpp:1695
App * needs(App *app)
Definition: App.hpp:1431
bool ignore_case_
If true, the program name is not case sensitive INHERITABLE.
Definition: App.hpp:211
bool silent_
Definition: App.hpp:246
std::function< void(std::size_t)> pre_parse_callback_
This is a function that runs prior to the start of parsing.
Definition: App.hpp:128
std::string group_
The group membership INHERITABLE.
Definition: App.hpp:267
std::shared_ptr< Config > get_config_formatter() const
Access the config formatter.
Definition: App.hpp:1545
App * get_subcommand(int index=0) const
Get a pointer to subcommand by index.
Definition: App.hpp:1038
bool pre_parse_called_
Flag indicating that the pre_parse_callback has been triggered.
Definition: App.hpp:121
Option * help_ptr_
A pointer to the help flag if there is one INHERITABLE.
Definition: App.hpp:157
std::size_t count() const
Definition: App.hpp:1088
std::string config_to_str(bool default_also=false, bool write_description=false) const
Definition: App.hpp:1500
std::string version() const
Displays a version string.
Definition: App.hpp:1521
void _configure()
Definition: App.hpp:1925
App * get_subcommand(const App *subcom) const
Definition: App.hpp:1021
App * allow_config_extras(config_extras_mode mode)
ignore extras in config files
Definition: App.hpp:491
bool remove_subcommand(App *subcom)
Removes a subcommand from the App. Takes a subcommand pointer. Returns true if found and removed.
Definition: App.hpp:1004
bool got_subcommand(const App *subcom) const
Check to see if given subcommand was selected.
Definition: App.hpp:1390
App * validate_positionals(bool validate=true)
Set the subcommand to validate positional arguments before assigning.
Definition: App.hpp:468
std::string get_footer() const
Generate and return the footer.
Definition: App.hpp:1683
bool fallthrough_
Allow subcommand fallthrough, so that parent commands can collect commands after subcommand....
Definition: App.hpp:217
std::set< Option * > need_options_
Definition: App.hpp:201
const Option * get_help_ptr() const
Get a pointer to the help flag. (const)
Definition: App.hpp:1732
bool get_ignore_underscore() const
Check the status of ignore_underscore.
Definition: App.hpp:1665
App * require_option()
The argumentless form of require option requires 1 or more options be used.
Definition: App.hpp:1142
std::set< App * > need_subcommands_
Definition: App.hpp:197
bool prefix_command_
If true, return immediately on an unrecognized option (implies allow_extras) INHERITABLE.
Definition: App.hpp:109
void _process_callbacks()
Process callbacks. Runs on all subcommands.
Definition: App.hpp:2081
App * formatter(std::shared_ptr< FormatterBase > fmt)
Set the help formatter.
Definition: App.hpp:552
bool get_validate_optional_arguments() const
Get the status of validating optional vector arguments.
Definition: App.hpp:1723
std::vector< Option * > parse_order_
This is a list of pointers to options with the original parse order.
Definition: App.hpp:183
detail::Classifier _recognize(const std::string &current, bool ignore_used_subcommands=true) const
Selects a Classifier enum based on the type of the current argument.
Definition: App.hpp:1988
void _trigger_pre_parse(std::size_t remaining_args)
Trigger the pre_parse callback if needed.
Definition: App.hpp:2888
std::vector< App * > get_subcommands() const
Definition: App.hpp:1352
bool validate_positionals_
If set to true positional options are validated before assigning INHERITABLE.
Definition: App.hpp:239
const std::string & get_name() const
Get the name of the current app.
Definition: App.hpp:1756
App * require_subcommand(int value)
Definition: App.hpp:1122
App * immediate_callback(bool immediate=true)
Set the subcommand callback to be executed immediately on subcommand completion.
Definition: App.hpp:455
void _validate() const
Definition: App.hpp:1886
Option * get_help_ptr()
Get a pointer to the help flag.
Definition: App.hpp:1729
startup_mode default_startup
Definition: App.hpp:233
App * get_option_group(std::string group_name) const
Check to see if an option group is part of this App.
Definition: App.hpp:1076
void increment_parsed()
Internal function to recursively increment the parsed counter on the current app as well unnamed subc...
Definition: App.hpp:2315
bool allow_extras_
If true, allow extra arguments (ie, don't throw an error). INHERITABLE.
Definition: App.hpp:102
config_extras_mode get_allow_config_extras() const
Get the status of allow extras.
Definition: App.hpp:1726
App * ignore_underscore(bool value=true)
Ignore underscore. Subcommands inherit value.
Definition: App.hpp:537
bool _has_remaining_positionals() const
Count the required remaining positional arguments.
Definition: App.hpp:2524
bool _parse_subcommand(std::vector< std::string > &args)
Definition: App.hpp:2685
bool get_enabled_by_default() const
Get the status of disabled by default.
Definition: App.hpp:1719
void _parse_config(const std::vector< ConfigItem > &args)
Definition: App.hpp:2384
App * positionals_at_end(bool value=true)
Specify that the positional arguments are only at the end of the sequence.
Definition: App.hpp:525
Option * add_flag_function(std::string flag_name, std::function< void(std::int64_t)> function, std::string flag_description="")
Add option for callback with an integer value.
Definition: App.hpp:880
std::shared_ptr< FormatterBase > formatter_
This is the formatter for help printing. Default provided. INHERITABLE (same pointer)
Definition: App.hpp:166
std::vector< Option * > get_options(const std::function< bool(Option *)> filter={})
Non-const version of the above.
Definition: App.hpp:1584
bool get_positionals_at_end() const
Check the status of the allow windows style options.
Definition: App.hpp:1674
App * excludes(Option *opt)
Sets excluded options for the subcommand.
Definition: App.hpp:1399
std::size_t get_require_subcommand_min() const
Get the required min subcommand value.
Definition: App.hpp:1686
Option * add_flag(std::string flag_name, T &flag_description)
Definition: App.hpp:822
App * enabled_by_default(bool enable=true)
Definition: App.hpp:444
bool allow_windows_style_options_
Allow '/' for options for Windows like options. Defaults to true on Windows, false otherwise....
Definition: App.hpp:220
void _move_to_missing(detail::Classifier val_type, const std::string &val)
Helper function to place extra values in the most appropriate position.
Definition: App.hpp:2969
std::shared_ptr< Config > config_formatter_
This is the formatter for help printing. Default provided. INHERITABLE (same pointer)
Definition: App.hpp:280
App * silent(bool silence=true)
silence the subcommand from showing up in the processed list
Definition: App.hpp:427
App * name(std::string app_name="")
Set a name for the app (empty will use parser to set the name)
Definition: App.hpp:372
Option * get_version_ptr()
Get a pointer to the version option.
Definition: App.hpp:1744
bool get_immediate_callback() const
Get the status of disabled.
Definition: App.hpp:1713
Usually something like –help-all on command line.
Definition: Error.hpp:169
-h or –help on command line
Definition: Error.hpp:163
-v or –version on command line
Definition: Error.hpp:176
All errors derive from this one.
Definition: Error.hpp:70
int get_exit_code() const
Definition: Error.hpp:75
std::string get_name() const
Definition: Error.hpp:77
Thrown when an excludes option is present.
Definition: Error.hpp:294
Thrown when too many positionals or options are found.
Definition: Error.hpp:301
Thrown when parsing an INI file and it is missing.
Definition: Error.hpp:189
Definition: FormatterFwd.hpp:116
Definition: Error.hpp:336
Thrown when an option is set to conflicting values (non-vector and multi args, for example)
Definition: Error.hpp:93
Thrown when validation fails before parsing.
Definition: Error.hpp:327
Thrown when an option already exists.
Definition: Error.hpp:135
bool get_configurable() const
The status of configurable.
Definition: Option.hpp:134
const std::string & get_group() const
Get the group of this option.
Definition: Option.hpp:122
CRTP * required(bool value=true)
Set the option as required.
Definition: Option.hpp:106
CRTP * always_capture_default(bool value=true)
Definition: Option.hpp:114
bool get_required() const
True if this is a required option.
Definition: Option.hpp:125
bool required_
True if this is a required option.
Definition: Option.hpp:57
void copy_to(T *other) const
Copy the contents to another similar class (one based on OptionBase)
Definition: Option.hpp:81
CRTP * configurable(bool value=true)
Allow in a configuration file.
Definition: Option.hpp:187
Definition: Option.hpp:201
Thrown when counting a non-existent option.
Definition: Error.hpp:344
Extension of App to better manage groups of options.
Definition: App.hpp:3028
Option_group(std::string group_description, std::string group_name, App *parent)
Definition: App.hpp:3030
void add_options(Option *opt, Args... args)
Add a bunch of options to the group.
Definition: App.hpp:3047
Option * add_option(Option *opt)
Add an existing option to the Option_group.
Definition: App.hpp:3037
App * add_subcommand(App *subcom)
Add an existing subcommand to be a member of an option_group.
Definition: App.hpp:3053
void add_options(Option *opt)
Add an existing option to the Option_group.
Definition: App.hpp:3045
Definition: Option.hpp:238
int get_type_size_max() const
The maximum number of arguments the option expects.
Definition: Option.hpp:690
std::size_t count() const
Count the total number of times an option was passed.
Definition: Option.hpp:364
int get_expected_min() const
The number of times the option expects to be included.
Definition: Option.hpp:735
int get_expected_max() const
The max number of times the option expects to be included.
Definition: Option.hpp:737
@ callback_run
the callback has been executed
option_state current_option_state_
Whether the callback has run (needed for INI parsing)
Definition: Option.hpp:335
bool get_trigger_on_parse() const
The status of trigger on parse.
Definition: Option.hpp:437
int get_type_size_min() const
The minimum number of arguments the option expects.
Definition: Option.hpp:688
std::set< Option * > needs_
A list of options that are required with this option.
Definition: Option.hpp:304
Option * run_callback_for_default(bool value=true)
Definition: Option.hpp:449
Option * default_str(std::string val)
Set the default value string representation (does not change the contained value)
Definition: Option.hpp:1150
Option * type_size(int option_type_size)
Set a custom option size.
Definition: Option.hpp:1089
std::set< Option * > excludes_
A list of options that are excluded with this option.
Definition: Option.hpp:307
std::string get_flag_value(const std::string &name, std::string input_value) const
Definition: Option.hpp:943
std::vector< std::string > fnames_
a list of flag names with specified default values;
Definition: Option.hpp:256
const results_t & results() const
Get the current complete results set.
Definition: Option.hpp:1010
Option * force_callback(bool value=true)
Set the value of force_callback.
Definition: Option.hpp:440
bool check_name(const std::string &name) const
Check a name. Requires "-" or "--" for short / long, supports positional name.
Definition: Option.hpp:894
bool get_allow_extra_args() const
Get the current value of allow extra args.
Definition: Option.hpp:430
Option * add_result(std::string s)
Puts a result at the end.
Definition: Option.hpp:987
const std::string & matching_name(const Option &other) const
If options share any of the same names, find it.
Definition: Option.hpp:870
int get_inject_separator() const
Return the inject_separator flag.
Definition: Option.hpp:693
Option * allow_extra_args(bool value=true)
Definition: Option.hpp:425
Option * multi_option_policy(MultiOptionPolicy value=MultiOptionPolicy::Throw)
Take the last argument if given multiple times (or another policy)
Definition: Option.hpp:662
bool get_callback_run() const
See if the callback has been run already.
Definition: Option.hpp:1070
T as() const
Return the results as the specified type.
Definition: Option.hpp:1063
void run_callback()
Process the callback.
Definition: Option.hpp:843
std::string get_name(bool positional=false, bool all_options=false) const
Gets a comma separated list of names. Will include / prefer the positional name if positional is true...
Definition: Option.hpp:783
void clear()
Clear the parsed results (mostly for testing)
Definition: Option.hpp:373
Option * description(std::string option_description)
Set the description.
Definition: Option.hpp:763
bool get_positional() const
True if the argument can be given directly.
Definition: Option.hpp:751
std::string envname_
If given, check the environment for this option.
Definition: Option.hpp:262
std::vector< std::pair< std::string, std::string > > default_flag_values_
Definition: Option.hpp:253
const std::string & get_description() const
Get the description.
Definition: Option.hpp:760
Option * type_name(std::string typeval)
Set a custom option typestring.
Definition: Option.hpp:1083
Option * check(Validator validator, const std::string &validator_name="")
Adds a Validator with a built in type name.
Definition: Option.hpp:457
bool empty() const
True if the option was not passed.
Definition: Option.hpp:367
Option * expected(int value)
Set the number of expected arguments.
Definition: Option.hpp:383
int get_items_expected_min() const
The total min number of expected string values to be used.
Definition: Option.hpp:740
Thrown when a required option is missing.
Definition: Error.hpp:219
Thrown when a requires option is missing.
Definition: Error.hpp:287
Some validators that are provided.
Definition: Validators.hpp:80
const std::string & get_name() const
Get the name of the Validator.
Definition: Validators.hpp:162
std::string help(const App *app, const Error &e)
Printout the full help string on error (if this fn is set, the old default for CLI11)
Definition: App.hpp:3203
std::string simple(const App *app, const Error &e)
Printout a clean, simple message on error (the default in CLI11 1.5+)
Definition: App.hpp:3184
constexpr enabler dummy
An instance to use in EnableIf.
Definition: TypeTools.hpp:34
bool split_long(const std::string &current, std::string &name, std::string &value)
Definition: Split.hpp:35
auto to_string(T &&value) -> decltype(std::forward< T >(value))
Convert an object to a string (directly forward if this can become a string)
Definition: TypeTools.hpp:270
path_type check_path(const char *file) noexcept
get the type of the path from a file name
Definition: Validators.hpp:327
bool split_short(const std::string &current, std::string &name, std::string &rest)
Definition: Split.hpp:25
std::pair< std::string, std::string > split_program_name(std::string commandline)
Definition: Validators.hpp:1126
bool valid_first_char(T c)
Definition: StringTools.hpp:219
bool valid_name_string(const std::string &str)
Verify an option/subcommand name.
Definition: StringTools.hpp:230
std::vector< std::pair< std::string, std::string > > get_default_flag_values(const std::string &str)
extract default flag values either {def} or starting with a !
Definition: Split.hpp:79
std::string remove_underscore(std::string str)
remove underscores from a string
Definition: StringTools.hpp:267
std::string find_and_modify(std::string str, std::string trigger, Callable modify)
Definition: StringTools.hpp:336
void remove_default_flag_values(std::string &flags)
Definition: StringTools.hpp:290
bool valid_later_char(T c)
Verify following characters of an option.
Definition: StringTools.hpp:222
constexpr int expected_max_vector_size
Definition: StringTools.hpp:43
Option * default_flag_modifiers(Option *opt)
helper functions for adding in appropriate flag modifiers for add_flag
Definition: App.hpp:68
std::vector< std::string > split_up(std::string str, char delimiter='\0')
Definition: StringTools.hpp:346
bool split_windows_style(const std::string &current, std::string &name, std::string &value)
Definition: Split.hpp:51
std::string join(const T &v, std::string delim=",")
Simple function to join a string.
Definition: StringTools.hpp:63
Classifier
Definition: App.hpp:47
std::enable_if< std::is_integral< T >::value, bool >::type checked_multiply(T &a, T b)
Performs a *= b; if it doesn't cause integer overflow. Returns false otherwise.
Definition: Validators.hpp:678
std::size_t escape_detect(std::string &str, std::size_t offset)
Definition: StringTools.hpp:402
bool valid_alias_name_string(const std::string &str)
Verify an app name.
Definition: StringTools.hpp:242
std::string & trim(std::string &str)
Trim whitespace from string.
Definition: StringTools.hpp:138
std::string to_lower(std::string str)
Return a lower case version of a string.
Definition: StringTools.hpp:259
bool has_default_flag_values(const std::string &flags)
check if the flag definitions has possible false flags
Definition: StringTools.hpp:286
enabler
Simple empty scoped class.
Definition: TypeTools.hpp:31
bool lexical_cast(const std::string &input, T &output)
Integer conversion.
Definition: TypeTools.hpp:883
Definition: App.hpp:34
typename std::enable_if< B, T >::type enable_if_t
Definition: TypeTools.hpp:42
ConfigBase ConfigTOML
the default Config is the TOML file format
Definition: ConfigFwd.hpp:170
config_extras_mode
enumeration of modes of how to deal with extras in config files
Definition: App.hpp:58
void deprecate_option(App &app, const std::string &option_name, const std::string &replacement="")
Helper function to mark an option as deprecated.
Definition: App.hpp:3124
void TriggerOn(App *trigger_app, std::vector< App * > apps_to_enable)
Helper function to enable one option group/subcommand when another is used.
Definition: App.hpp:3068
std::unique_ptr< Option > Option_p
Definition: Option.hpp:36
std::vector< std::string > results_t
Definition: Option.hpp:29
void retire_option(App &app, const std::string &option_name)
Helper function to mark an option as retired.
Definition: App.hpp:3179
AppFormatMode
Definition: FormatterFwd.hpp:29
@ Normal
The normal, detailed help.
@ All
A fully expanded help.
@ TakeAll
just get all the passed argument regardless
@ TakeLast
take only the last Expected number of arguments
@ Sum
sum all the arguments together if numerical or concatenate directly without delimiter
std::function< bool(const results_t &)> callback_t
callback function definition
Definition: Option.hpp:31
std::shared_ptr< App > App_p
Definition: App.hpp:62
void TriggerOff(App *trigger_app, std::vector< App * > apps_to_enable)
Helper function to disable one option group/subcommand when another is used.
Definition: App.hpp:3089
Holds values to load into Options.
Definition: ConfigFwd.hpp:26
std::vector< std::string > inputs
Listing of inputs.
Definition: ConfigFwd.hpp:34
std::string name
This is the name.
Definition: ConfigFwd.hpp:31
std::vector< std::string > parents
This is the list of parents.
Definition: ConfigFwd.hpp:28
std::string fullname() const
The list of parents and name joined by ".".
Definition: ConfigFwd.hpp:37
This class is simply to allow tests access to App's protected functions.
Definition: App.hpp:3213
static auto parse_subcommand(App *app, Args &&...args) -> typename std::result_of< decltype(&App::_parse_subcommand)(App, Args...)>::type
Wrap _parse_subcommand, perfectly forward arguments and return.
Definition: App.hpp:3235
static App * get_fallthrough_parent(App *app)
Wrap the fallthrough parent function to make sure that is working correctly.
Definition: App.hpp:3241
static auto parse_arg(App *app, Args &&...args) -> typename std::result_of< decltype(&App::_parse_arg)(App, Args...)>::type
Wrap _parse_short, perfectly forward arguments and return.
Definition: App.hpp:3228
This will only trigger for actual void type.
Definition: TypeTools.hpp:394