CLI11
C++11 Command Line Interface Parser
App.hpp
1 #pragma once
2 
3 // Distributed under the 3-Clause BSD License. See accompanying
4 // file LICENSE or https://github.com/CLIUtils/CLI11 for details.
5 
6 #include <algorithm>
7 #include <deque>
8 #include <functional>
9 #include <iostream>
10 #include <iterator>
11 #include <memory>
12 #include <numeric>
13 #include <set>
14 #include <sstream>
15 #include <string>
16 #include <utility>
17 #include <vector>
18 
19 // CLI Library includes
20 #include "CLI/ConfigFwd.hpp"
21 #include "CLI/Error.hpp"
22 #include "CLI/FormatterFwd.hpp"
23 #include "CLI/Macros.hpp"
24 #include "CLI/Option.hpp"
25 #include "CLI/Split.hpp"
26 #include "CLI/StringTools.hpp"
27 #include "CLI/TypeTools.hpp"
28 
29 namespace CLI {
30 
31 #ifndef CLI11_PARSE
32 #define CLI11_PARSE(app, argc, argv) \
33  try { \
34  (app).parse((argc), (argv)); \
35  } catch(const CLI::ParseError &e) { \
36  return (app).exit(e); \
37  }
38 #endif
39 
40 namespace detail {
41 enum class Classifier { NONE, POSITIONAL_MARK, SHORT, LONG, WINDOWS, SUBCOMMAND, SUBCOMMAND_TERMINATOR };
42 struct AppFriend;
43 } // namespace detail
44 
45 namespace FailureMessage {
46 std::string simple(const App *app, const Error &e);
47 std::string help(const App *app, const Error &e);
48 } // namespace FailureMessage
49 
50 class App;
51 
52 using App_p = std::shared_ptr<App>;
53 
54 class Option_group;
56 
59 class App {
60  friend Option;
61  friend detail::AppFriend;
62 
63  protected:
64  // This library follows the Google style guide for member names ending in underscores
65 
68 
70  std::string name_;
71 
73  std::string description_;
74 
76  bool allow_extras_{false};
77 
79  bool allow_config_extras_{false};
80 
82  bool prefix_command_{false};
83 
85  bool has_automatic_name_{false};
86 
88  bool required_{false};
89 
91  bool disabled_{false};
92 
94  bool pre_parse_called_{false};
95 
98  bool immediate_callback_{false};
99 
101  std::function<void(size_t)> pre_parse_callback_;
102 
104  std::function<void()> callback_;
105 
109 
112 
114  std::vector<Option_p> options_;
115 
119 
121  std::string footer_;
122 
124  Option *help_ptr_{nullptr};
125 
128 
130  std::shared_ptr<FormatterBase> formatter_{new Formatter()};
131 
133  std::function<std::string(const App *, const Error &e)> failure_message_ = FailureMessage::simple;
134 
138 
139  using missing_t = std::vector<std::pair<detail::Classifier, std::string>>;
140 
144  missing_t missing_;
145 
147  std::vector<Option *> parse_order_;
148 
150  std::vector<App *> parsed_subcommands_;
151 
153  std::set<App *> exclude_subcommands_;
154 
157  std::set<Option *> exclude_options_;
158 
162 
164  std::vector<App_p> subcommands_;
165 
167  bool ignore_case_{false};
168 
170  bool ignore_underscore_{false};
171 
173  bool fallthrough_{false};
174 
177 #ifdef _WIN32
178  true
179 #else
180  false
181 #endif
182  };
184  bool positionals_at_end_{false};
185 
187  bool disabled_by_default_{false};
189  bool enabled_by_default_{false};
193  App *parent_{nullptr};
194 
196  size_t parsed_ = 0;
197 
200 
203 
206 
209 
211  std::string group_{"Subcommands"};
212 
216 
218  std::string config_name_;
219 
221  bool config_required_{false};
222 
224  Option *config_ptr_{nullptr};
225 
227  std::shared_ptr<Config> config_formatter_{new ConfigINI()};
228 
230 
232  App(std::string app_description, std::string app_name, App *parent)
233  : name_(std::move(app_name)), description_(std::move(app_description)), parent_(parent) {
234  // Inherit if not from a nullptr
235  if(parent_ != nullptr) {
236  if(parent_->help_ptr_ != nullptr)
238  if(parent_->help_all_ptr_ != nullptr)
241 
244 
245  // INHERITABLE
256  group_ = parent_->group_;
261  }
262  }
263 
264  public:
267 
269  explicit App(std::string app_description = "", std::string app_name = "")
270  : App(app_description, app_name, nullptr) {
271  set_help_flag("-h,--help", "Print this help message and exit");
272  }
273 
275  virtual ~App() = default;
276 
283  App *callback(std::function<void()> app_callback) {
284  callback_ = std::move(app_callback);
285  return this;
286  }
287 
290  App *preparse_callback(std::function<void(size_t)> pp_callback) {
291  pre_parse_callback_ = std::move(pp_callback);
292  return this;
293  }
294 
296  App *name(std::string app_name = "") {
297  name_ = app_name;
298  has_automatic_name_ = false;
299  return this;
300  }
301 
303  App *allow_extras(bool allow = true) {
304  allow_extras_ = allow;
305  return this;
306  }
307 
309  App *required(bool require = true) {
310  required_ = require;
311  return this;
312  }
313 
315  App *disabled(bool disable = true) {
316  disabled_ = disable;
317  return this;
318  }
319 
321  App *disabled_by_default(bool disable = true) {
322  disabled_by_default_ = disable;
323  return this;
324  }
325 
328  App *enabled_by_default(bool enable = true) {
329  enabled_by_default_ = enable;
330  return this;
331  }
332 
334  App *immediate_callback(bool immediate = true) {
335  immediate_callback_ = immediate;
336  return this;
337  }
338 
340  App *validate_positionals(bool validate = true) {
341  validate_positionals_ = validate;
342  return this;
343  }
344 
347  App *allow_config_extras(bool allow = true) {
348  allow_extras(allow);
349  allow_config_extras_ = allow;
350  return this;
351  }
352 
354  App *prefix_command(bool allow = true) {
355  prefix_command_ = allow;
356  return this;
357  }
358 
360  App *ignore_case(bool value = true) {
361  ignore_case_ = value;
362  if(parent_ != nullptr && !name_.empty()) {
363  for(const auto &subc : parent_->subcommands_) {
364  if(subc.get() != this && (this->check_name(subc->name_) || subc->check_name(this->name_)))
365  throw OptionAlreadyAdded(subc->name_);
366  }
367  }
368  return this;
369  }
370 
372  App *allow_windows_style_options(bool value = true) {
374  return this;
375  }
376 
378  App *positionals_at_end(bool value = true) {
379  positionals_at_end_ = value;
380  return this;
381  }
382 
384  App *ignore_underscore(bool value = true) {
385  ignore_underscore_ = value;
386  if(parent_ != nullptr && !name_.empty()) {
387  for(const auto &subc : parent_->subcommands_) {
388  if(subc.get() != this && (this->check_name(subc->name_) || subc->check_name(this->name_)))
389  throw OptionAlreadyAdded(subc->name_);
390  }
391  }
392  return this;
393  }
394 
396  App *formatter(std::shared_ptr<FormatterBase> fmt) {
397  formatter_ = fmt;
398  return this;
399  }
400 
402  App *formatter_fn(std::function<std::string(const App *, std::string, AppFormatMode)> fmt) {
403  formatter_ = std::make_shared<FormatterLambda>(fmt);
404  return this;
405  }
406 
408  App *config_formatter(std::shared_ptr<Config> fmt) {
409  config_formatter_ = fmt;
410  return this;
411  }
412 
414  bool parsed() const { return parsed_ > 0; }
415 
418 
422 
437  Option *add_option(std::string option_name,
438  callback_t option_callback,
439  std::string option_description = "",
440  bool defaulted = false,
441  std::function<std::string()> func = {}) {
442  Option myopt{option_name, option_description, option_callback, this};
443 
444  if(std::find_if(std::begin(options_), std::end(options_), [&myopt](const Option_p &v) {
445  return *v == myopt;
446  }) == std::end(options_)) {
447  options_.emplace_back();
448  Option_p &option = options_.back();
449  option.reset(new Option(option_name, option_description, option_callback, this));
450 
451  // Set the default string capture function
452  option->default_function(func);
453 
454  // For compatibility with CLI11 1.7 and before, capture the default string here
455  if(defaulted)
456  option->capture_default_str();
457 
458  // Transfer defaults to the new option
459  option_defaults_.copy_to(option.get());
460 
461  // Don't bother to capture if we already did
462  if(!defaulted && option->get_always_capture_default())
463  option->capture_default_str();
464 
465  return option.get();
466 
467  } else
468  throw OptionAlreadyAdded(myopt.get_name());
469  }
470 
472  template <typename T, enable_if_t<!is_vector<T>::value & !std::is_const<T>::value, detail::enabler> = detail::dummy>
473  Option *add_option(std::string option_name,
474  T &variable,
475  std::string option_description = "",
476  bool defaulted = false) {
477 
478  auto fun = [&variable](CLI::results_t res) { return detail::lexical_cast(res[0], variable); };
479 
480  Option *opt = add_option(option_name, fun, option_description, defaulted, [&variable]() {
481  return std::string(CLI::detail::to_string(variable));
482  });
483  opt->type_name(detail::type_name<T>());
484 
485  return opt;
486  }
487 
489  template <typename T, enable_if_t<!is_vector<T>::value, detail::enabler> = detail::dummy>
490  Option *add_option_function(std::string option_name,
491  const std::function<void(const T &)> &func,
492  std::string option_description = "") {
493 
494  auto fun = [func](CLI::results_t res) {
495  T variable;
496  bool result = detail::lexical_cast(res[0], variable);
497  if(result) {
498  func(variable);
499  }
500  return result;
501  };
502 
503  Option *opt = add_option(option_name, std::move(fun), option_description, false);
504  opt->type_name(detail::type_name<T>());
505  return opt;
506  }
507 
509  Option *add_option(std::string option_name) {
510  return add_option(option_name, CLI::callback_t(), std::string{}, false);
511  }
512 
514  template <typename T,
515  enable_if_t<std::is_const<T>::value && std::is_constructible<std::string, T>::value, detail::enabler> =
516  detail::dummy>
517  Option *add_option(std::string option_name, T &option_description) {
518  return add_option(option_name, CLI::callback_t(), option_description, false);
519  }
520 
522  template <typename T>
523  Option *add_option(std::string option_name,
524  std::vector<T> &variable,
525  std::string option_description = "",
526  bool defaulted = false) {
527 
528  auto fun = [&variable](CLI::results_t res) {
529  bool retval = true;
530  variable.clear();
531  variable.reserve(res.size());
532  for(const auto &elem : res) {
533 
534  variable.emplace_back();
535  retval &= detail::lexical_cast(elem, variable.back());
536  }
537  return (!variable.empty()) && retval;
538  };
539 
540  auto default_function = [&variable]() {
541  std::vector<std::string> defaults;
542  defaults.resize(variable.size());
543  std::transform(variable.begin(), variable.end(), defaults.begin(), [](T &val) {
544  return std::string(CLI::detail::to_string(val));
545  });
546  return std::string("[" + detail::join(defaults) + "]");
547  };
548 
549  Option *opt = add_option(option_name, fun, option_description, defaulted, default_function);
550  opt->type_name(detail::type_name<T>())->type_size(-1);
551 
552  return opt;
553  }
554 
556  template <typename T, enable_if_t<is_vector<T>::value, detail::enabler> = detail::dummy>
557  Option *add_option_function(std::string option_name,
558  const std::function<void(const T &)> &func,
559  std::string option_description = "") {
560 
561  CLI::callback_t fun = [func](CLI::results_t res) {
562  T values;
563  bool retval = true;
564  values.reserve(res.size());
565  for(const auto &elem : res) {
566  values.emplace_back();
567  retval &= detail::lexical_cast(elem, values.back());
568  }
569  if(retval) {
570  func(values);
571  }
572  return retval;
573  };
574 
575  Option *opt = add_option(option_name, std::move(fun), std::move(option_description), false);
576  opt->type_name(detail::type_name<T>())->type_size(-1);
577  return opt;
578  }
579 
581  Option *set_help_flag(std::string flag_name = "", const std::string &help_description = "") {
582  // take flag_description by const reference otherwise add_flag tries to assign to help_description
583  if(help_ptr_ != nullptr) {
585  help_ptr_ = nullptr;
586  }
587 
588  // Empty name will simply remove the help flag
589  if(!flag_name.empty()) {
590  help_ptr_ = add_flag(flag_name, help_description);
591  help_ptr_->configurable(false);
592  }
593 
594  return help_ptr_;
595  }
596 
598  Option *set_help_all_flag(std::string help_name = "", const std::string &help_description = "") {
599  // take flag_description by const reference otherwise add_flag tries to assign to flag_description
600  if(help_all_ptr_ != nullptr) {
602  help_all_ptr_ = nullptr;
603  }
604 
605  // Empty name will simply remove the help all flag
606  if(!help_name.empty()) {
607  help_all_ptr_ = add_flag(help_name, help_description);
608  help_all_ptr_->configurable(false);
609  }
610 
611  return help_all_ptr_;
612  }
613 
614  private:
616  Option *_add_flag_internal(std::string flag_name, CLI::callback_t fun, std::string flag_description) {
617  Option *opt;
618  if(detail::has_default_flag_values(flag_name)) {
619  // check for default values and if it has them
620  auto flag_defaults = detail::get_default_flag_values(flag_name);
621  detail::remove_default_flag_values(flag_name);
622  opt = add_option(std::move(flag_name), std::move(fun), std::move(flag_description), false);
623  for(const auto &fname : flag_defaults)
624  opt->fnames_.push_back(fname.first);
625  opt->default_flag_values_ = std::move(flag_defaults);
626  } else {
627  opt = add_option(std::move(flag_name), std::move(fun), std::move(flag_description), false);
628  }
629  // flags cannot have positional values
630  if(opt->get_positional()) {
631  auto pos_name = opt->get_name(true);
632  remove_option(opt);
633  throw IncorrectConstruction::PositionalFlag(pos_name);
634  }
635 
636  opt->type_size(0);
637  return opt;
638  }
639 
640  public:
642  Option *add_flag(std::string flag_name) { return _add_flag_internal(flag_name, CLI::callback_t(), std::string{}); }
643 
647  template <typename T,
648  enable_if_t<std::is_const<T>::value && std::is_constructible<std::string, T>::value, detail::enabler> =
649  detail::dummy>
650  Option *add_flag(std::string flag_name, T &flag_description) {
651  return _add_flag_internal(flag_name, CLI::callback_t(), flag_description);
652  }
653 
656  template <typename T,
657  enable_if_t<std::is_integral<T>::value && !is_bool<T>::value, detail::enabler> = detail::dummy>
658  Option *add_flag(std::string flag_name,
659  T &flag_count,
660  std::string flag_description = "") {
661  flag_count = 0;
662  CLI::callback_t fun = [&flag_count](CLI::results_t res) {
663  try {
664  detail::sum_flag_vector(res, flag_count);
665  } catch(const std::invalid_argument &) {
666  return false;
667  }
668  return true;
669  };
670  return _add_flag_internal(flag_name, std::move(fun), std::move(flag_description));
671  }
672 
675  template <typename T,
676  enable_if_t<!is_vector<T>::value && !std::is_const<T>::value &&
677  (!std::is_integral<T>::value || is_bool<T>::value) &&
678  !std::is_constructible<std::function<void(int)>, T>::value,
679  detail::enabler> = detail::dummy>
680  Option *add_flag(std::string flag_name,
681  T &flag_result,
682  std::string flag_description = "") {
683 
684  CLI::callback_t fun = [&flag_result](CLI::results_t res) {
685  if(res.size() != 1) {
686  return false;
687  }
688  return CLI::detail::lexical_cast(res[0], flag_result);
689  };
690  Option *opt = _add_flag_internal(flag_name, std::move(fun), std::move(flag_description));
691  opt->multi_option_policy(CLI::MultiOptionPolicy::TakeLast);
692  return opt;
693  }
694 
696  template <typename T,
697  enable_if_t<!std::is_assignable<std::function<void(int64_t)>, T>::value, detail::enabler> = detail::dummy>
698  Option *add_flag(std::string flag_name,
699  std::vector<T> &flag_results,
700  std::string flag_description = "") {
701  CLI::callback_t fun = [&flag_results](CLI::results_t res) {
702  bool retval = true;
703  for(const auto &elem : res) {
704  flag_results.emplace_back();
705  retval &= detail::lexical_cast(elem, flag_results.back());
706  }
707  return retval;
708  };
709  return _add_flag_internal(flag_name, std::move(fun), std::move(flag_description));
710  }
711 
713  Option *add_flag_callback(std::string flag_name,
714  std::function<void(void)> function,
715  std::string flag_description = "") {
716 
717  CLI::callback_t fun = [function](CLI::results_t res) {
718  if(res.size() != 1) {
719  return false;
720  }
721  bool trigger;
722  auto result = CLI::detail::lexical_cast(res[0], trigger);
723  if(trigger)
724  function();
725  return result;
726  };
727  Option *opt = _add_flag_internal(flag_name, std::move(fun), std::move(flag_description));
728  opt->multi_option_policy(CLI::MultiOptionPolicy::TakeLast);
729  return opt;
730  }
731 
733  Option *add_flag_function(std::string flag_name,
734  std::function<void(int64_t)> function,
735  std::string flag_description = "") {
736 
737  CLI::callback_t fun = [function](CLI::results_t res) {
738  int64_t flag_count = 0;
739  detail::sum_flag_vector(res, flag_count);
740  function(flag_count);
741  return true;
742  };
743  return _add_flag_internal(flag_name, std::move(fun), std::move(flag_description));
744  }
745 
746 #ifdef CLI11_CPP14
747  Option *add_flag(std::string flag_name,
749  std::function<void(int64_t)> function,
750  std::string flag_description = "") {
751  return add_flag_function(std::move(flag_name), std::move(function), std::move(flag_description));
752  }
753 #endif
754 
756  template <typename T>
757  Option *add_set(std::string option_name,
758  T &member,
759  std::set<T> options,
760  std::string option_description = "") {
761 
762  Option *opt = add_option(option_name, member, std::move(option_description));
763  opt->check(IsMember{options});
764  return opt;
765  }
766 
768  template <typename T>
769  Option *add_mutable_set(std::string option_name,
770  T &member,
771  const std::set<T> &options,
772  std::string option_description = "") {
773 
774  Option *opt = add_option(option_name, member, std::move(option_description));
775  opt->check(IsMember{&options});
776  return opt;
777  }
778 
780  template <typename T>
781  Option *add_set(std::string option_name,
782  T &member,
783  std::set<T> options,
784  std::string option_description,
785  bool defaulted) {
786 
787  Option *opt = add_option(option_name, member, std::move(option_description), defaulted);
788  opt->check(IsMember{options});
789  return opt;
790  }
791 
793  template <typename T>
794  Option *add_mutable_set(std::string option_name,
795  T &member,
796  const std::set<T> &options,
797  std::string option_description,
798  bool defaulted) {
799 
800  Option *opt = add_option(option_name, member, std::move(option_description), defaulted);
801  opt->check(IsMember{&options});
802  return opt;
803  }
804 
806  CLI11_DEPRECATED("Use ->transform(CLI::IsMember(..., CLI::ignore_case)) instead")
807  Option *add_set_ignore_case(std::string option_name,
808  std::string &member,
809  std::set<std::string> options,
810  std::string option_description = "") {
811 
812  Option *opt = add_option(option_name, member, std::move(option_description));
813  opt->transform(IsMember{options, CLI::ignore_case});
814  return opt;
815  }
816 
819  CLI11_DEPRECATED("Use ->transform(CLI::IsMember(..., CLI::ignore_case)) with a (shared) pointer instead")
820  Option *add_mutable_set_ignore_case(std::string option_name,
821  std::string &member,
822  const std::set<std::string> &options,
823  std::string option_description = "") {
824 
825  Option *opt = add_option(option_name, member, std::move(option_description));
826  opt->transform(IsMember{&options, CLI::ignore_case});
827  return opt;
828  }
829 
831  CLI11_DEPRECATED("Use ->transform(CLI::IsMember(..., CLI::ignore_case)) instead")
832  Option *add_set_ignore_case(std::string option_name,
833  std::string &member,
834  std::set<std::string> options,
835  std::string option_description,
836  bool defaulted) {
837 
838  Option *opt = add_option(option_name, member, std::move(option_description), defaulted);
839  opt->transform(IsMember{options, CLI::ignore_case});
840  return opt;
841  }
842 
845  CLI11_DEPRECATED("Use ->transform(CLI::IsMember(...)) with a (shared) pointer instead")
846  Option *add_mutable_set_ignore_case(std::string option_name,
847  std::string &member,
848  const std::set<std::string> &options,
849  std::string option_description,
850  bool defaulted) {
851 
852  Option *opt = add_option(option_name, member, std::move(option_description), defaulted);
853  opt->transform(IsMember{&options, CLI::ignore_case});
854  return opt;
855  }
856 
858  CLI11_DEPRECATED("Use ->transform(CLI::IsMember(..., CLI::ignore_underscore)) instead")
859  Option *add_set_ignore_underscore(std::string option_name,
860  std::string &member,
861  std::set<std::string> options,
862  std::string option_description = "") {
863 
864  Option *opt = add_option(option_name, member, std::move(option_description));
865  opt->transform(IsMember{options, CLI::ignore_underscore});
866  return opt;
867  }
868 
871  CLI11_DEPRECATED("Use ->transform(CLI::IsMember(..., CLI::ignore_underscore)) with a (shared) pointer instead")
872  Option *add_mutable_set_ignore_underscore(std::string option_name,
873  std::string &member,
874  const std::set<std::string> &options,
875  std::string option_description = "") {
876 
877  Option *opt = add_option(option_name, member, std::move(option_description));
878  opt->transform(IsMember{options, CLI::ignore_underscore});
879  return opt;
880  }
881 
883  CLI11_DEPRECATED("Use ->transform(CLI::IsMember(..., CLI::ignore_underscore)) instead")
884  Option *add_set_ignore_underscore(std::string option_name,
885  std::string &member,
886  std::set<std::string> options,
887  std::string option_description,
888  bool defaulted) {
889 
890  Option *opt = add_option(option_name, member, std::move(option_description), defaulted);
891  opt->transform(IsMember{options, CLI::ignore_underscore});
892  return opt;
893  }
894 
897  CLI11_DEPRECATED("Use ->transform(CLI::IsMember(..., CLI::ignore_underscore)) with a (shared) pointer instead")
898  Option *add_mutable_set_ignore_underscore(std::string option_name,
899  std::string &member,
900  const std::set<std::string> &options,
901  std::string option_description,
902  bool defaulted) {
903 
904  Option *opt = add_option(option_name, member, std::move(option_description), defaulted);
905  opt->transform(IsMember{&options, CLI::ignore_underscore});
906  return opt;
907  }
908 
910  CLI11_DEPRECATED("Use ->transform(CLI::IsMember(..., CLI::ignore_case, CLI::ignore_underscore)) instead")
911  Option *add_set_ignore_case_underscore(std::string option_name,
912  std::string &member,
913  std::set<std::string> options,
914  std::string option_description = "") {
915 
916  Option *opt = add_option(option_name, member, std::move(option_description));
917  opt->transform(IsMember{options, CLI::ignore_underscore, CLI::ignore_case});
918  return opt;
919  }
920 
924  "Use ->transform(CLI::IsMember(..., CLI::ignore_case, CLI::ignore_underscore)) with a (shared) pointer instead")
925  Option *add_mutable_set_ignore_case_underscore(std::string option_name,
926  std::string &member,
927  const std::set<std::string> &options,
928  std::string option_description = "") {
929 
930  Option *opt = add_option(option_name, member, std::move(option_description));
931  opt->transform(IsMember{&options, CLI::ignore_underscore, CLI::ignore_case});
932  return opt;
933  }
934 
936  CLI11_DEPRECATED("Use ->transform(CLI::IsMember(..., CLI::ignore_case, CLI::ignore_underscore)) instead")
937  Option *add_set_ignore_case_underscore(std::string option_name,
938  std::string &member,
939  std::set<std::string> options,
940  std::string option_description,
941  bool defaulted) {
942 
943  Option *opt = add_option(option_name, member, std::move(option_description), defaulted);
944  opt->transform(IsMember{options, CLI::ignore_underscore, CLI::ignore_case});
945  return opt;
946  }
947 
951  "Use ->transform(CLI::IsMember(..., CLI::ignore_case, CLI::ignore_underscore)) with a (shared) pointer instead")
952  Option *add_mutable_set_ignore_case_underscore(std::string option_name,
953  std::string &member,
954  const std::set<std::string> &options,
955  std::string option_description,
956  bool defaulted) {
957 
958  Option *opt = add_option(option_name, member, std::move(option_description), defaulted);
959  opt->transform(IsMember{&options, CLI::ignore_underscore, CLI::ignore_case});
960  return opt;
961  }
962 
964  template <typename T>
965  Option *add_complex(std::string option_name,
966  T &variable,
967  std::string option_description = "",
968  bool defaulted = false,
969  std::string label = "COMPLEX") {
970 
971  std::string simple_name = CLI::detail::split(option_name, ',').at(0);
972  CLI::callback_t fun = [&variable, simple_name, label](results_t res) {
973  if(res[1].back() == 'i')
974  res[1].pop_back();
975  double x, y;
976  bool worked = detail::lexical_cast(res[0], x) && detail::lexical_cast(res[1], y);
977  if(worked)
978  variable = T(x, y);
979  return worked;
980  };
981 
982  auto default_function = [&variable]() {
983  std::stringstream out;
984  out << variable;
985  return out.str();
986  };
987 
988  CLI::Option *opt =
989  add_option(option_name, std::move(fun), std::move(option_description), defaulted, default_function);
990 
991  opt->type_name(label)->type_size(2);
992  return opt;
993  }
994 
996  Option *set_config(std::string option_name = "",
997  std::string default_filename = "",
998  std::string help_message = "Read an ini file",
999  bool config_required = false) {
1000 
1001  // Remove existing config if present
1002  if(config_ptr_ != nullptr)
1004 
1005  // Only add config if option passed
1006  if(!option_name.empty()) {
1007  config_name_ = default_filename;
1008  config_required_ = config_required;
1009  config_ptr_ = add_option(option_name, config_name_, help_message, !default_filename.empty());
1010  config_ptr_->configurable(false);
1011  }
1012 
1013  return config_ptr_;
1014  }
1015 
1017  bool remove_option(Option *opt) {
1018  // Make sure no links exist
1019  for(Option_p &op : options_) {
1020  op->remove_needs(opt);
1021  op->remove_excludes(opt);
1022  }
1023 
1024  if(help_ptr_ == opt)
1025  help_ptr_ = nullptr;
1026  if(help_all_ptr_ == opt)
1027  help_all_ptr_ = nullptr;
1028 
1029  auto iterator =
1030  std::find_if(std::begin(options_), std::end(options_), [opt](const Option_p &v) { return v.get() == opt; });
1031  if(iterator != std::end(options_)) {
1032  options_.erase(iterator);
1033  return true;
1034  }
1035  return false;
1036  }
1037 
1039  template <typename T = Option_group>
1040  T *add_option_group(std::string group_name, std::string group_description = "") {
1041  auto option_group = std::make_shared<T>(std::move(group_description), group_name, nullptr);
1042  auto ptr = option_group.get();
1043  // move to App_p for overload resolution on older gcc versions
1044  App_p app_ptr = std::dynamic_pointer_cast<App>(option_group);
1045  add_subcommand(std::move(app_ptr));
1046  return ptr;
1047  }
1048 
1052 
1054  App *add_subcommand(std::string subcommand_name = "", std::string subcommand_description = "") {
1055  CLI::App_p subcom = std::shared_ptr<App>(new App(std::move(subcommand_description), subcommand_name, this));
1056  return add_subcommand(std::move(subcom));
1057  }
1058 
1060  App *add_subcommand(CLI::App_p subcom) {
1061  if(!subcom)
1062  throw IncorrectConstruction("passed App is not valid");
1063  if(!subcom->name_.empty()) {
1064  for(const auto &subc : subcommands_)
1065  if(subc->check_name(subcom->name_) || subcom->check_name(subc->name_))
1066  throw OptionAlreadyAdded(subc->name_);
1067  }
1068  subcom->parent_ = this;
1069  subcommands_.push_back(std::move(subcom));
1070  return subcommands_.back().get();
1071  }
1072 
1074  bool remove_subcommand(App *subcom) {
1075  // Make sure no links exist
1076  for(App_p &sub : subcommands_) {
1077  sub->remove_excludes(subcom);
1078  }
1079 
1080  auto iterator = std::find_if(
1081  std::begin(subcommands_), std::end(subcommands_), [subcom](const App_p &v) { return v.get() == subcom; });
1082  if(iterator != std::end(subcommands_)) {
1083  subcommands_.erase(iterator);
1084  return true;
1085  }
1086  return false;
1087  }
1090  App *get_subcommand(App *subcom) const {
1091  if(subcom == nullptr)
1092  throw OptionNotFound("nullptr passed");
1093  for(const App_p &subcomptr : subcommands_)
1094  if(subcomptr.get() == subcom)
1095  return subcom;
1096  throw OptionNotFound(subcom->get_name());
1097  }
1098 
1100  App *get_subcommand(std::string subcom) const {
1101  auto subc = _find_subcommand(subcom, false, false);
1102  if(subc == nullptr)
1103  throw OptionNotFound(subcom);
1104  return subc;
1105  }
1107  App *get_subcommand(int index = 0) const {
1108  if(index >= 0) {
1109  auto uindex = static_cast<unsigned>(index);
1110  if(uindex < subcommands_.size())
1111  return subcommands_[uindex].get();
1112  }
1113  throw OptionNotFound(std::to_string(index));
1114  }
1115 
1117  CLI::App_p get_subcommand_ptr(App *subcom) const {
1118  if(subcom == nullptr)
1119  throw OptionNotFound("nullptr passed");
1120  for(const App_p &subcomptr : subcommands_)
1121  if(subcomptr.get() == subcom)
1122  return subcomptr;
1123  throw OptionNotFound(subcom->get_name());
1124  }
1125 
1127  CLI::App_p get_subcommand_ptr(std::string subcom) const {
1128  for(const App_p &subcomptr : subcommands_)
1129  if(subcomptr->check_name(subcom))
1130  return subcomptr;
1131  throw OptionNotFound(subcom);
1132  }
1133 
1135  CLI::App_p get_subcommand_ptr(int index = 0) const {
1136  if(index >= 0) {
1137  auto uindex = static_cast<unsigned>(index);
1138  if(uindex < subcommands_.size())
1139  return subcommands_[uindex];
1140  }
1141  throw OptionNotFound(std::to_string(index));
1142  }
1143 
1145  App *get_option_group(std::string group_name) const {
1146  for(const App_p &app : subcommands_) {
1147  if(app->name_.empty() && app->group_ == group_name) {
1148  return app.get();
1149  }
1150  }
1151  throw OptionNotFound(group_name);
1152  }
1153 
1157  size_t count() const { return parsed_; }
1158 
1161  size_t count_all() const {
1162  size_t cnt{0};
1163  for(auto &opt : options_) {
1164  cnt += opt->count();
1165  }
1166  for(auto &sub : subcommands_) {
1167  cnt += sub->count_all();
1168  }
1169  if(!get_name().empty()) { // for named subcommands add the number of times the subcommand was called
1170  cnt += parsed_;
1171  }
1172  return cnt;
1173  }
1174 
1176  App *group(std::string group_name) {
1177  group_ = group_name;
1178  return this;
1179  }
1180 
1185  return this;
1186  }
1187 
1191  App *require_subcommand(int value) {
1192  if(value < 0) {
1194  require_subcommand_max_ = static_cast<size_t>(-value);
1195  } else {
1196  require_subcommand_min_ = static_cast<size_t>(value);
1197  require_subcommand_max_ = static_cast<size_t>(value);
1198  }
1199  return this;
1200  }
1201 
1204  App *require_subcommand(size_t min, size_t max) {
1207  return this;
1208  }
1209 
1212  require_option_min_ = 1;
1213  require_option_max_ = 0;
1214  return this;
1215  }
1216 
1220  App *require_option(int value) {
1221  if(value < 0) {
1222  require_option_min_ = 0;
1223  require_option_max_ = static_cast<size_t>(-value);
1224  } else {
1225  require_option_min_ = static_cast<size_t>(value);
1226  require_option_max_ = static_cast<size_t>(value);
1227  }
1228  return this;
1229  }
1230 
1233  App *require_option(size_t min, size_t max) {
1234  require_option_min_ = min;
1235  require_option_max_ = max;
1236  return this;
1237  }
1238 
1241  App *fallthrough(bool value = true) {
1242  fallthrough_ = value;
1243  return this;
1244  }
1245 
1248  operator bool() const { return parsed_ > 0; }
1249 
1253 
1257  virtual void pre_callback() {}
1258 
1262  //
1264  void clear() {
1265 
1266  parsed_ = 0;
1267  pre_parse_called_ = false;
1268 
1269  missing_.clear();
1270  parsed_subcommands_.clear();
1271  for(const Option_p &opt : options_) {
1272  opt->clear();
1273  }
1274  for(const App_p &subc : subcommands_) {
1275  subc->clear();
1276  }
1277  }
1278 
1281  void parse(int argc, const char *const *argv) {
1282  // If the name is not set, read from command line
1283  if(name_.empty() || has_automatic_name_) {
1284  has_automatic_name_ = true;
1285  name_ = argv[0];
1286  }
1287 
1288  std::vector<std::string> args;
1289  args.reserve(static_cast<size_t>(argc - 1));
1290  for(int i = argc - 1; i > 0; i--)
1291  args.emplace_back(argv[i]);
1292  parse(std::move(args));
1293  }
1294 
1299  void parse(std::string commandline, bool program_name_included = false) {
1300 
1301  if(program_name_included) {
1302  auto nstr = detail::split_program_name(commandline);
1303  if((name_.empty()) || (has_automatic_name_)) {
1304  has_automatic_name_ = true;
1305  name_ = nstr.first;
1306  }
1307  commandline = std::move(nstr.second);
1308  } else
1309  detail::trim(commandline);
1310  // the next section of code is to deal with quoted arguments after an '=' or ':' for windows like operations
1311  if(!commandline.empty()) {
1312  commandline = detail::find_and_modify(commandline, "=", detail::escape_detect);
1314  commandline = detail::find_and_modify(commandline, ":", detail::escape_detect);
1315  }
1316 
1317  auto args = detail::split_up(std::move(commandline));
1318  // remove all empty strings
1319  args.erase(std::remove(args.begin(), args.end(), std::string{}), args.end());
1320  std::reverse(args.begin(), args.end());
1321 
1322  parse(std::move(args));
1323  }
1324 
1327  void parse(std::vector<std::string> &args) {
1328  // Clear if parsed
1329  if(parsed_ > 0)
1330  clear();
1331 
1332  // parsed_ is incremented in commands/subcommands,
1333  // but placed here to make sure this is cleared when
1334  // running parse after an error is thrown, even by _validate or _configure.
1335  parsed_ = 1;
1336  _validate();
1337  _configure();
1338  // set the parent as nullptr as this object should be the top now
1339  parent_ = nullptr;
1340  parsed_ = 0;
1341 
1342  _parse(args);
1343  run_callback();
1344  }
1345 
1347  void parse(std::vector<std::string> &&args) {
1348  // Clear if parsed
1349  if(parsed_ > 0)
1350  clear();
1351 
1352  // parsed_ is incremented in commands/subcommands,
1353  // but placed here to make sure this is cleared when
1354  // running parse after an error is thrown, even by _validate or _configure.
1355  parsed_ = 1;
1356  _validate();
1357  _configure();
1358  // set the parent as nullptr as this object should be the top now
1359  parent_ = nullptr;
1360  parsed_ = 0;
1361 
1362  _parse(std::move(args));
1363  run_callback();
1364  }
1365 
1367  void failure_message(std::function<std::string(const App *, const Error &e)> function) {
1368  failure_message_ = function;
1369  }
1370 
1372  int exit(const Error &e, std::ostream &out = std::cout, std::ostream &err = std::cerr) const {
1373 
1375  if(dynamic_cast<const CLI::RuntimeError *>(&e) != nullptr)
1376  return e.get_exit_code();
1377 
1378  if(dynamic_cast<const CLI::CallForHelp *>(&e) != nullptr) {
1379  out << help();
1380  return e.get_exit_code();
1381  }
1382 
1383  if(dynamic_cast<const CLI::CallForAllHelp *>(&e) != nullptr) {
1384  out << help("", AppFormatMode::All);
1385  return e.get_exit_code();
1386  }
1387 
1388  if(e.get_exit_code() != static_cast<int>(ExitCodes::Success)) {
1389  if(failure_message_)
1390  err << failure_message_(this, e) << std::flush;
1391  }
1392 
1393  return e.get_exit_code();
1394  }
1395 
1399 
1401  size_t count(std::string option_name) const { return get_option(option_name)->count(); }
1402 
1405  std::vector<App *> get_subcommands() const { return parsed_subcommands_; }
1406 
1409  std::vector<const App *> get_subcommands(const std::function<bool(const App *)> &filter) const {
1410  std::vector<const App *> subcomms(subcommands_.size());
1411  std::transform(std::begin(subcommands_), std::end(subcommands_), std::begin(subcomms), [](const App_p &v) {
1412  return v.get();
1413  });
1414 
1415  if(filter) {
1416  subcomms.erase(std::remove_if(std::begin(subcomms),
1417  std::end(subcomms),
1418  [&filter](const App *app) { return !filter(app); }),
1419  std::end(subcomms));
1420  }
1421 
1422  return subcomms;
1423  }
1424 
1427  std::vector<App *> get_subcommands(const std::function<bool(App *)> &filter) {
1428  std::vector<App *> subcomms(subcommands_.size());
1429  std::transform(std::begin(subcommands_), std::end(subcommands_), std::begin(subcomms), [](const App_p &v) {
1430  return v.get();
1431  });
1432 
1433  if(filter) {
1434  subcomms.erase(
1435  std::remove_if(std::begin(subcomms), std::end(subcomms), [&filter](App *app) { return !filter(app); }),
1436  std::end(subcomms));
1437  }
1438 
1439  return subcomms;
1440  }
1441 
1443  bool got_subcommand(App *subcom) const {
1444  // get subcom needed to verify that this was a real subcommand
1445  return get_subcommand(subcom)->parsed_ > 0;
1446  }
1447 
1449  bool got_subcommand(std::string subcommand_name) const { return get_subcommand(subcommand_name)->parsed_ > 0; }
1450 
1453  if(opt == nullptr) {
1454  throw OptionNotFound("nullptr passed");
1455  }
1456  exclude_options_.insert(opt);
1457  return this;
1458  }
1459 
1461  App *excludes(App *app) {
1462  if((app == this) || (app == nullptr)) {
1463  throw OptionNotFound("nullptr passed");
1464  }
1465  auto res = exclude_subcommands_.insert(app);
1466  // subcommand exclusion should be symmetric
1467  if(res.second) {
1468  app->exclude_subcommands_.insert(this);
1469  }
1470  return this;
1471  }
1472 
1475  auto iterator = std::find(std::begin(exclude_options_), std::end(exclude_options_), opt);
1476  if(iterator != std::end(exclude_options_)) {
1477  exclude_options_.erase(iterator);
1478  return true;
1479  } else {
1480  return false;
1481  }
1482  }
1483 
1485  bool remove_excludes(App *app) {
1486  auto iterator = std::find(std::begin(exclude_subcommands_), std::end(exclude_subcommands_), app);
1487  if(iterator != std::end(exclude_subcommands_)) {
1488  auto other_app = *iterator;
1489  exclude_subcommands_.erase(iterator);
1490  other_app->remove_excludes(this);
1491  return true;
1492  } else {
1493  return false;
1494  }
1495  }
1496 
1500 
1502  App *footer(std::string footer_string) {
1503  footer_ = std::move(footer_string);
1504  return this;
1505  }
1506 
1509  std::string config_to_str(bool default_also = false, bool write_description = false) const {
1510  return config_formatter_->to_config(this, default_also, write_description, "");
1511  }
1512 
1515  std::string help(std::string prev = "", AppFormatMode mode = AppFormatMode::Normal) const {
1516  if(prev.empty())
1517  prev = get_name();
1518  else
1519  prev += " " + get_name();
1520 
1521  // Delegate to subcommand if needed
1522  auto selected_subcommands = get_subcommands();
1523  if(!selected_subcommands.empty())
1524  return selected_subcommands.at(0)->help(prev, mode);
1525  else
1526  return formatter_->make_help(this, prev, mode);
1527  }
1528 
1532 
1534  std::shared_ptr<FormatterBase> get_formatter() const { return formatter_; }
1535 
1537  std::shared_ptr<Config> get_config_formatter() const { return config_formatter_; }
1538 
1540  std::string get_description() const { return description_; }
1541 
1543  App *description(std::string app_description) {
1544  description_ = std::move(app_description);
1545  return this;
1546  }
1547 
1549  std::vector<const Option *> get_options(const std::function<bool(const Option *)> filter = {}) const {
1550  std::vector<const Option *> options(options_.size());
1551  std::transform(std::begin(options_), std::end(options_), std::begin(options), [](const Option_p &val) {
1552  return val.get();
1553  });
1554 
1555  if(filter) {
1556  options.erase(std::remove_if(std::begin(options),
1557  std::end(options),
1558  [&filter](const Option *opt) { return !filter(opt); }),
1559  std::end(options));
1560  }
1561 
1562  return options;
1563  }
1564 
1566  Option *get_option_no_throw(std::string option_name) noexcept {
1567  for(Option_p &opt : options_) {
1568  if(opt->check_name(option_name)) {
1569  return opt.get();
1570  }
1571  }
1572  for(auto &subc : subcommands_) {
1573  // also check down into nameless subcommands
1574  if(subc->get_name().empty()) {
1575  auto opt = subc->get_option_no_throw(option_name);
1576  if(opt != nullptr) {
1577  return opt;
1578  }
1579  }
1580  }
1581  return nullptr;
1582  }
1583 
1585  const Option *get_option_no_throw(std::string option_name) const noexcept {
1586  for(const Option_p &opt : options_) {
1587  if(opt->check_name(option_name)) {
1588  return opt.get();
1589  }
1590  }
1591  for(const auto &subc : subcommands_) {
1592  // also check down into nameless subcommands
1593  if(subc->get_name().empty()) {
1594  auto opt = subc->get_option_no_throw(option_name);
1595  if(opt != nullptr) {
1596  return opt;
1597  }
1598  }
1599  }
1600  return nullptr;
1601  }
1602 
1604  const Option *get_option(std::string option_name) const {
1605  auto opt = get_option_no_throw(option_name);
1606  if(opt == nullptr) {
1607  throw OptionNotFound(option_name);
1608  }
1609  return opt;
1610  }
1611 
1613  Option *get_option(std::string option_name) {
1614  auto opt = get_option_no_throw(option_name);
1615  if(opt == nullptr) {
1616  throw OptionNotFound(option_name);
1617  }
1618  return opt;
1619  }
1620 
1622  const Option *operator[](const std::string &option_name) const { return get_option(option_name); }
1623 
1625  const Option *operator[](const char *option_name) const { return get_option(option_name); }
1626 
1628  bool get_ignore_case() const { return ignore_case_; }
1629 
1632 
1634  bool get_fallthrough() const { return fallthrough_; }
1635 
1638 
1641 
1643  const std::string &get_group() const { return group_; }
1644 
1646  const std::string &get_footer() const { return footer_; }
1647 
1650 
1653 
1655  size_t get_require_option_min() const { return require_option_min_; }
1656 
1658  size_t get_require_option_max() const { return require_option_max_; }
1659 
1661  bool get_prefix_command() const { return prefix_command_; }
1662 
1664  bool get_allow_extras() const { return allow_extras_; }
1665 
1667  bool get_required() const { return required_; }
1668 
1670  bool get_disabled() const { return disabled_; }
1671 
1674 
1677 
1682 
1685 
1688 
1690  const Option *get_help_ptr() const { return help_ptr_; }
1691 
1693  const Option *get_help_all_ptr() const { return help_all_ptr_; }
1694 
1697 
1699  const Option *get_config_ptr() const { return config_ptr_; }
1700 
1702  App *get_parent() { return parent_; }
1703 
1705  const App *get_parent() const { return parent_; }
1706 
1708  std::string get_name() const { return name_; }
1709 
1711  std::string get_display_name() const { return (!name_.empty()) ? name_ : "[Option Group: " + get_group() + "]"; }
1712 
1714  bool check_name(std::string name_to_check) const {
1715  std::string local_name = name_;
1716  if(ignore_underscore_) {
1717  local_name = detail::remove_underscore(name_);
1718  name_to_check = detail::remove_underscore(name_to_check);
1719  }
1720  if(ignore_case_) {
1721  local_name = detail::to_lower(name_);
1722  name_to_check = detail::to_lower(name_to_check);
1723  }
1724 
1725  return local_name == name_to_check;
1726  }
1727 
1729  std::vector<std::string> get_groups() const {
1730  std::vector<std::string> groups;
1731 
1732  for(const Option_p &opt : options_) {
1733  // Add group if it is not already in there
1734  if(std::find(groups.begin(), groups.end(), opt->get_group()) == groups.end()) {
1735  groups.push_back(opt->get_group());
1736  }
1737  }
1738 
1739  return groups;
1740  }
1741 
1743  const std::vector<Option *> &parse_order() const { return parse_order_; }
1744 
1746  std::vector<std::string> remaining(bool recurse = false) const {
1747  std::vector<std::string> miss_list;
1748  for(const std::pair<detail::Classifier, std::string> &miss : missing_) {
1749  miss_list.push_back(std::get<1>(miss));
1750  }
1751  // Get from a subcommand that may allow extras
1752  if(recurse) {
1753  if(!allow_extras_) {
1754  for(const auto &sub : subcommands_) {
1755  if(sub->name_.empty() && !sub->missing_.empty()) {
1756  for(const std::pair<detail::Classifier, std::string> &miss : sub->missing_) {
1757  miss_list.push_back(std::get<1>(miss));
1758  }
1759  }
1760  }
1761  }
1762  // Recurse into subcommands
1763 
1764  for(const App *sub : parsed_subcommands_) {
1765  std::vector<std::string> output = sub->remaining(recurse);
1766  std::copy(std::begin(output), std::end(output), std::back_inserter(miss_list));
1767  }
1768  }
1769  return miss_list;
1770  }
1771 
1773  std::vector<std::string> remaining_for_passthrough(bool recurse = false) const {
1774  std::vector<std::string> miss_list = remaining(recurse);
1775  std::reverse(std::begin(miss_list), std::end(miss_list));
1776  return miss_list;
1777  }
1778 
1780  size_t remaining_size(bool recurse = false) const {
1781  auto remaining_options = static_cast<size_t>(std::count_if(
1782  std::begin(missing_), std::end(missing_), [](const std::pair<detail::Classifier, std::string> &val) {
1783  return val.first != detail::Classifier::POSITIONAL_MARK;
1784  }));
1785 
1786  if(recurse) {
1787  for(const App_p &sub : subcommands_) {
1788  remaining_options += sub->remaining_size(recurse);
1789  }
1790  }
1791  return remaining_options;
1792  }
1793 
1795 
1796  protected:
1801  void _validate() const {
1802  auto pcount = std::count_if(std::begin(options_), std::end(options_), [](const Option_p &opt) {
1803  return opt->get_items_expected() < 0 && opt->get_positional();
1804  });
1805  if(pcount > 1)
1806  throw InvalidError(name_);
1807 
1808  size_t nameless_subs{0};
1809  for(const App_p &app : subcommands_) {
1810  app->_validate();
1811  if(app->get_name().empty())
1812  ++nameless_subs;
1813  }
1814 
1815  if(require_option_min_ > 0) {
1816  if(require_option_max_ > 0) {
1818  throw(InvalidError("Required min options greater than required max options",
1819  ExitCodes::InvalidError));
1820  }
1821  }
1822  if(require_option_min_ > (options_.size() + nameless_subs)) {
1823  throw(InvalidError("Required min options greater than number of available options",
1824  ExitCodes::InvalidError));
1825  }
1826  }
1827  }
1828 
1832  void _configure() {
1833  if(disabled_by_default_) {
1834  disabled_ = true;
1835  }
1836  if(enabled_by_default_) {
1837  disabled_ = false;
1838  }
1839  for(const App_p &app : subcommands_) {
1840  if(app->has_automatic_name_) {
1841  app->name_.clear();
1842  }
1843  if(app->name_.empty()) {
1844  app->fallthrough_ = false; // make sure fallthrough_ is false to prevent infinite loop
1845  app->prefix_command_ = false;
1846  }
1847  // make sure the parent is set to be this object in preparation for parse
1848  app->parent_ = this;
1849  app->_configure();
1850  }
1851  }
1853  void run_callback() {
1854  pre_callback();
1855  // run the callbacks for the received subcommands
1856  for(App *subc : get_subcommands()) {
1857  if(!subc->immediate_callback_)
1858  subc->run_callback();
1859  }
1860  // now run callbacks for option_groups
1861  for(auto &subc : subcommands_) {
1862  if(!subc->immediate_callback_ && subc->name_.empty() && subc->count_all() > 0) {
1863  subc->run_callback();
1864  }
1865  }
1866  // finally run the main callback
1867  if(callback_ && (parsed_ > 0)) {
1868  if(!name_.empty() || count_all() > 0) {
1869  callback_();
1870  }
1871  }
1872  }
1873 
1875  bool _valid_subcommand(const std::string &current, bool ignore_used = true) const {
1876  // Don't match if max has been reached - but still check parents
1878  return parent_ != nullptr && parent_->_valid_subcommand(current, ignore_used);
1879  }
1880  auto com = _find_subcommand(current, true, ignore_used);
1881  if(com != nullptr) {
1882  return true;
1883  }
1884  // Check parent if exists, else return false
1885  return parent_ != nullptr && parent_->_valid_subcommand(current, ignore_used);
1886  }
1887 
1889  detail::Classifier _recognize(const std::string &current, bool ignore_used_subcommands = true) const {
1890  std::string dummy1, dummy2;
1891 
1892  if(current == "--")
1893  return detail::Classifier::POSITIONAL_MARK;
1894  if(_valid_subcommand(current, ignore_used_subcommands))
1895  return detail::Classifier::SUBCOMMAND;
1896  if(detail::split_long(current, dummy1, dummy2))
1897  return detail::Classifier::LONG;
1898  if(detail::split_short(current, dummy1, dummy2))
1899  return detail::Classifier::SHORT;
1900  if((allow_windows_style_options_) && (detail::split_windows_style(current, dummy1, dummy2)))
1901  return detail::Classifier::WINDOWS;
1902  if((current == "++") && !name_.empty() && parent_ != nullptr)
1903  return detail::Classifier::SUBCOMMAND_TERMINATOR;
1904  return detail::Classifier::NONE;
1905  }
1906 
1907  // The parse function is now broken into several parts, and part of process
1908 
1910  void _process_ini() {
1911  // Process an INI file
1912  if(config_ptr_ != nullptr) {
1913  if(*config_ptr_) {
1915  config_required_ = true;
1916  }
1917  if(!config_name_.empty()) {
1918  try {
1919  std::vector<ConfigItem> values = config_formatter_->from_file(config_name_);
1920  _parse_config(values);
1921  } catch(const FileError &) {
1922  if(config_required_)
1923  throw;
1924  }
1925  }
1926  }
1927  }
1928 
1930  void _process_env() {
1931  for(const Option_p &opt : options_) {
1932  if(opt->count() == 0 && !opt->envname_.empty()) {
1933  char *buffer = nullptr;
1934  std::string ename_string;
1935 
1936 #ifdef _MSC_VER
1937  // Windows version
1938  size_t sz = 0;
1939  if(_dupenv_s(&buffer, &sz, opt->envname_.c_str()) == 0 && buffer != nullptr) {
1940  ename_string = std::string(buffer);
1941  free(buffer);
1942  }
1943 #else
1944  // This also works on Windows, but gives a warning
1945  buffer = std::getenv(opt->envname_.c_str());
1946  if(buffer != nullptr)
1947  ename_string = std::string(buffer);
1948 #endif
1949 
1950  if(!ename_string.empty()) {
1951  opt->add_result(ename_string);
1952  }
1953  }
1954  }
1955 
1956  for(App_p &sub : subcommands_) {
1957  if(sub->get_name().empty() || !sub->immediate_callback_)
1958  sub->_process_env();
1959  }
1960  }
1961 
1964 
1965  for(App_p &sub : subcommands_) {
1966  // process the priority option_groups first
1967  if(sub->get_name().empty() && sub->immediate_callback_) {
1968  if(sub->count_all() > 0) {
1969  sub->_process_callbacks();
1970  sub->run_callback();
1971  }
1972  }
1973  }
1974 
1975  for(const Option_p &opt : options_) {
1976  if(opt->count() > 0 && !opt->get_callback_run()) {
1977  opt->run_callback();
1978  }
1979  }
1980 
1981  for(App_p &sub : subcommands_) {
1982  if(!sub->immediate_callback_) {
1983  sub->_process_callbacks();
1984  }
1985  }
1986  }
1987 
1991  void _process_help_flags(bool trigger_help = false, bool trigger_all_help = false) const {
1992  const Option *help_ptr = get_help_ptr();
1993  const Option *help_all_ptr = get_help_all_ptr();
1994 
1995  if(help_ptr != nullptr && help_ptr->count() > 0)
1996  trigger_help = true;
1997  if(help_all_ptr != nullptr && help_all_ptr->count() > 0)
1998  trigger_all_help = true;
1999 
2000  // If there were parsed subcommands, call those. First subcommand wins if there are multiple ones.
2001  if(!parsed_subcommands_.empty()) {
2002  for(const App *sub : parsed_subcommands_)
2003  sub->_process_help_flags(trigger_help, trigger_all_help);
2004 
2005  // Only the final subcommand should call for help. All help wins over help.
2006  } else if(trigger_all_help) {
2007  throw CallForAllHelp();
2008  } else if(trigger_help) {
2009  throw CallForHelp();
2010  }
2011  }
2012 
2015  // check excludes
2016  bool excluded{false};
2017  std::string excluder;
2018  for(auto &opt : exclude_options_) {
2019  if(opt->count() > 0) {
2020  excluded = true;
2021  excluder = opt->get_name();
2022  }
2023  }
2024  for(auto &subc : exclude_subcommands_) {
2025  if(subc->count_all() > 0) {
2026  excluded = true;
2027  excluder = subc->get_display_name();
2028  }
2029  }
2030  if(excluded) {
2031  if(count_all() > 0) {
2032  throw ExcludesError(get_display_name(), excluder);
2033  }
2034  // if we are excluded but didn't receive anything, just return
2035  return;
2036  }
2037  size_t used_options = 0;
2038  for(const Option_p &opt : options_) {
2039 
2040  if(opt->count() != 0) {
2041  ++used_options;
2042  }
2043  // Required or partially filled
2044  if(opt->get_required() || opt->count() != 0) {
2045  // Make sure enough -N arguments parsed (+N is already handled in parsing function)
2046  if(opt->get_items_expected() < 0 && opt->count() < static_cast<size_t>(-opt->get_items_expected()))
2047  throw ArgumentMismatch::AtLeast(opt->get_name(), -opt->get_items_expected());
2048 
2049  // Required but empty
2050  if(opt->get_required() && opt->count() == 0)
2051  throw RequiredError(opt->get_name());
2052  }
2053  // Requires
2054  for(const Option *opt_req : opt->needs_)
2055  if(opt->count() > 0 && opt_req->count() == 0)
2056  throw RequiresError(opt->get_name(), opt_req->get_name());
2057  // Excludes
2058  for(const Option *opt_ex : opt->excludes_)
2059  if(opt->count() > 0 && opt_ex->count() != 0)
2060  throw ExcludesError(opt->get_name(), opt_ex->get_name());
2061  }
2062  // check for the required number of subcommands
2063  if(require_subcommand_min_ > 0) {
2064  auto selected_subcommands = get_subcommands();
2065  if(require_subcommand_min_ > selected_subcommands.size())
2066  throw RequiredError::Subcommand(require_subcommand_min_);
2067  }
2068 
2069  // Max error cannot occur, the extra subcommand will parse as an ExtrasError or a remaining item.
2070 
2071  // run this loop to check how many unnamed subcommands were actually used since they are considered options from
2072  // the perspective of an App
2073  for(App_p &sub : subcommands_) {
2074  if(sub->disabled_)
2075  continue;
2076  if(sub->name_.empty() && sub->count_all() > 0) {
2077  ++used_options;
2078  }
2079  }
2080 
2081  if(require_option_min_ > used_options || (require_option_max_ > 0 && require_option_max_ < used_options)) {
2082  auto option_list = detail::join(options_, [](const Option_p &ptr) { return ptr->get_name(false, true); });
2083  if(option_list.compare(0, 10, "-h,--help,") == 0) {
2084  option_list.erase(0, 10);
2085  }
2086  auto subc_list = get_subcommands([](App *app) { return ((app->get_name().empty()) && (!app->disabled_)); });
2087  if(!subc_list.empty()) {
2088  option_list += "," + detail::join(subc_list, [](const App *app) { return app->get_display_name(); });
2089  }
2090  throw RequiredError::Option(require_option_min_, require_option_max_, used_options, option_list);
2091  }
2092 
2093  // now process the requirements for subcommands if needed
2094  for(App_p &sub : subcommands_) {
2095  if(sub->disabled_)
2096  continue;
2097  if(sub->name_.empty() && sub->required_ == false) {
2098  if(sub->count_all() == 0) {
2099  if(require_option_min_ > 0 && require_option_min_ <= used_options) {
2100  continue;
2101  // if we have met the requirement and there is nothing in this option group skip checking
2102  // requirements
2103  }
2104  if(require_option_max_ > 0 && used_options >= require_option_min_) {
2105  continue;
2106  // if we have met the requirement and there is nothing in this option group skip checking
2107  // requirements
2108  }
2109  }
2110  }
2111  if(sub->count() > 0 || sub->name_.empty()) {
2112  sub->_process_requirements();
2113  }
2114 
2115  if(sub->required_ && sub->count_all() == 0) {
2116  throw(CLI::RequiredError(sub->get_display_name()));
2117  }
2118  }
2119  }
2120 
2122  void _process() {
2123  _process_ini();
2124  _process_env();
2128  }
2129 
2132  if(!(allow_extras_ || prefix_command_)) {
2133  size_t num_left_over = remaining_size();
2134  if(num_left_over > 0) {
2135  throw ExtrasError(remaining(false));
2136  }
2137  }
2138 
2139  for(App_p &sub : subcommands_) {
2140  if(sub->count() > 0)
2141  sub->_process_extras();
2142  }
2143  }
2144 
2147  void _process_extras(std::vector<std::string> &args) {
2148  if(!(allow_extras_ || prefix_command_)) {
2149  size_t num_left_over = remaining_size();
2150  if(num_left_over > 0) {
2151  args = remaining(false);
2152  throw ExtrasError(args);
2153  }
2154  }
2155 
2156  for(App_p &sub : subcommands_) {
2157  if(sub->count() > 0)
2158  sub->_process_extras(args);
2159  }
2160  }
2161 
2164  ++parsed_;
2165  for(App_p &sub : subcommands_) {
2166  if(sub->get_name().empty())
2167  sub->increment_parsed();
2168  }
2169  }
2171  void _parse(std::vector<std::string> &args) {
2172  increment_parsed();
2173  _trigger_pre_parse(args.size());
2174  bool positional_only = false;
2175 
2176  while(!args.empty()) {
2177  if(!_parse_single(args, positional_only)) {
2178  break;
2179  }
2180  }
2181 
2182  if(parent_ == nullptr) {
2183  _process();
2184 
2185  // Throw error if any items are left over (depending on settings)
2186  _process_extras(args);
2187 
2188  // Convert missing (pairs) to extras (string only) ready for processing in another app
2189  args = remaining_for_passthrough(false);
2190  } else if(immediate_callback_) {
2191  _process_env();
2195  run_callback();
2196  }
2197  }
2198 
2200  void _parse(std::vector<std::string> &&args) {
2201  // this can only be called by the top level in which case parent == nullptr by definition
2202  // operation is simplified
2203  increment_parsed();
2204  _trigger_pre_parse(args.size());
2205  bool positional_only = false;
2206 
2207  while(!args.empty()) {
2208  _parse_single(args, positional_only);
2209  }
2210  _process();
2211 
2212  // Throw error if any items are left over (depending on settings)
2213  _process_extras();
2214  }
2215 
2220  void _parse_config(std::vector<ConfigItem> &args) {
2221  for(ConfigItem item : args) {
2223  throw ConfigError::Extras(item.fullname());
2224  }
2225  }
2226 
2228  bool _parse_single_config(const ConfigItem &item, size_t level = 0) {
2229  if(level < item.parents.size()) {
2230  try {
2231  auto subcom = get_subcommand(item.parents.at(level));
2232  return subcom->_parse_single_config(item, level + 1);
2233  } catch(const OptionNotFound &) {
2234  return false;
2235  }
2236  }
2237 
2238  Option *op = get_option_no_throw("--" + item.name);
2239  if(op == nullptr) {
2240  // If the option was not present
2242  // Should we worry about classifying the extras properly?
2243  missing_.emplace_back(detail::Classifier::NONE, item.fullname());
2244  return false;
2245  }
2246 
2247  if(!op->get_configurable())
2248  throw ConfigError::NotConfigurable(item.fullname());
2249 
2250  if(op->empty()) {
2251  // Flag parsing
2252  if(op->get_type_size() == 0) {
2253  auto res = config_formatter_->to_flag(item);
2254  res = op->get_flag_value(item.name, res);
2255 
2256  op->add_result(res);
2257 
2258  } else {
2259  op->add_result(item.inputs);
2260  op->run_callback();
2261  }
2262  }
2263 
2264  return true;
2265  }
2266 
2269  bool _parse_single(std::vector<std::string> &args, bool &positional_only) {
2270  bool retval = true;
2271  detail::Classifier classifier = positional_only ? detail::Classifier::NONE : _recognize(args.back());
2272  switch(classifier) {
2273  case detail::Classifier::POSITIONAL_MARK:
2274  args.pop_back();
2275  positional_only = true;
2276  if((!_has_remaining_positionals()) && (parent_ != nullptr)) {
2277  retval = false;
2278  } else {
2279  _move_to_missing(classifier, "--");
2280  }
2281  break;
2282  case detail::Classifier::SUBCOMMAND_TERMINATOR:
2283  // treat this like a positional mark if in the parent app
2284  args.pop_back();
2285  retval = false;
2286  break;
2287  case detail::Classifier::SUBCOMMAND:
2288  retval = _parse_subcommand(args);
2289  break;
2290  case detail::Classifier::LONG:
2291  case detail::Classifier::SHORT:
2292  case detail::Classifier::WINDOWS:
2293  // If already parsed a subcommand, don't accept options_
2294  _parse_arg(args, classifier);
2295  break;
2296  case detail::Classifier::NONE:
2297  // Probably a positional or something for a parent (sub)command
2298  retval = _parse_positional(args);
2299  if(retval && positionals_at_end_) {
2300  positional_only = true;
2301  }
2302  break;
2303 
2304  // LCOV_EXCL_START
2305  default:
2306  HorribleError("unrecognized classifier (you should not see this!)");
2307  // LCOV_EXCL_END
2308  }
2309  return retval;
2310  }
2311 
2313  size_t _count_remaining_positionals(bool required_only = false) const {
2314  size_t retval = 0;
2315  for(const Option_p &opt : options_)
2316  if(opt->get_positional() && (!required_only || opt->get_required()) && opt->get_items_expected() > 0 &&
2317  static_cast<int>(opt->count()) < opt->get_items_expected())
2318  retval = static_cast<size_t>(opt->get_items_expected()) - opt->count();
2319 
2320  return retval;
2321  }
2322 
2325  for(const Option_p &opt : options_)
2326  if(opt->get_positional() &&
2327  ((opt->get_items_expected() < 0) || ((static_cast<int>(opt->count()) < opt->get_items_expected()))))
2328  return true;
2329 
2330  return false;
2331  }
2332 
2335  bool _parse_positional(std::vector<std::string> &args) {
2336 
2337  const std::string &positional = args.back();
2338  for(const Option_p &opt : options_) {
2339  // Eat options, one by one, until done
2340  if(opt->get_positional() &&
2341  (static_cast<int>(opt->count()) < opt->get_items_expected() || opt->get_items_expected() < 0)) {
2342  if(validate_positionals_) {
2343  std::string pos = positional;
2344  pos = opt->_validate(pos);
2345  if(!pos.empty()) {
2346  continue;
2347  }
2348  }
2349  opt->add_result(positional);
2350  parse_order_.push_back(opt.get());
2351  args.pop_back();
2352  return true;
2353  }
2354  }
2355 
2356  for(auto &subc : subcommands_) {
2357  if((subc->name_.empty()) && (!subc->disabled_)) {
2358  if(subc->_parse_positional(args)) {
2359  if(!subc->pre_parse_called_) {
2360  subc->_trigger_pre_parse(args.size());
2361  }
2362  return true;
2363  }
2364  }
2365  }
2366  // let the parent deal with it if possible
2367  if(parent_ != nullptr && fallthrough_)
2369 
2371  auto com = _find_subcommand(args.back(), true, false);
2372  if(com != nullptr && (require_subcommand_max_ == 0 || require_subcommand_max_ > parsed_subcommands_.size())) {
2373  args.pop_back();
2374  com->_parse(args);
2375  return true;
2376  }
2379  auto parent_app = (parent_ != nullptr) ? _get_fallthrough_parent() : this;
2380  com = parent_app->_find_subcommand(args.back(), true, false);
2381  if(com != nullptr && (com->parent_->require_subcommand_max_ == 0 ||
2382  com->parent_->require_subcommand_max_ > com->parent_->parsed_subcommands_.size())) {
2383  return false;
2384  }
2385 
2386  if(positionals_at_end_) {
2387  throw CLI::ExtrasError(args);
2388  }
2390  if(parent_ != nullptr && name_.empty()) {
2391  return false;
2392  }
2394  _move_to_missing(detail::Classifier::NONE, positional);
2395  args.pop_back();
2396  if(prefix_command_) {
2397  while(!args.empty()) {
2398  _move_to_missing(detail::Classifier::NONE, args.back());
2399  args.pop_back();
2400  }
2401  }
2402 
2403  return true;
2404  }
2405 
2408  App *_find_subcommand(const std::string &subc_name, bool ignore_disabled, bool ignore_used) const noexcept {
2409  for(const App_p &com : subcommands_) {
2410  if(com->disabled_ && ignore_disabled)
2411  continue;
2412  if(com->get_name().empty()) {
2413  auto subc = com->_find_subcommand(subc_name, ignore_disabled, ignore_used);
2414  if(subc != nullptr) {
2415  return subc;
2416  }
2417  } else if(com->check_name(subc_name)) {
2418  if((!*com) || !ignore_used)
2419  return com.get();
2420  }
2421  }
2422  return nullptr;
2423  }
2424 
2429  bool _parse_subcommand(std::vector<std::string> &args) {
2430  if(_count_remaining_positionals(/* required */ true) > 0) {
2431  _parse_positional(args);
2432  return true;
2433  }
2434  auto com = _find_subcommand(args.back(), true, true);
2435  if(com != nullptr) {
2436  args.pop_back();
2437  parsed_subcommands_.push_back(com);
2438  com->_parse(args);
2439  auto parent_app = com->parent_;
2440  while(parent_app != this) {
2441  parent_app->_trigger_pre_parse(args.size());
2442  parent_app->parsed_subcommands_.push_back(com);
2443  parent_app = parent_app->parent_;
2444  }
2445  return true;
2446  }
2447 
2448  if(parent_ == nullptr)
2449  throw HorribleError("Subcommand " + args.back() + " missing");
2450  return false;
2451  }
2452 
2455  bool _parse_arg(std::vector<std::string> &args, detail::Classifier current_type) {
2456 
2457  std::string current = args.back();
2458 
2459  std::string arg_name;
2460  std::string value;
2461  std::string rest;
2462 
2463  switch(current_type) {
2464  case detail::Classifier::LONG:
2465  if(!detail::split_long(current, arg_name, value))
2466  throw HorribleError("Long parsed but missing (you should not see this):" + args.back());
2467  break;
2468  case detail::Classifier::SHORT:
2469  if(!detail::split_short(current, arg_name, rest))
2470  throw HorribleError("Short parsed but missing! You should not see this");
2471  break;
2472  case detail::Classifier::WINDOWS:
2473  if(!detail::split_windows_style(current, arg_name, value))
2474  throw HorribleError("windows option parsed but missing! You should not see this");
2475  break;
2476  case detail::Classifier::SUBCOMMAND:
2477  case detail::Classifier::POSITIONAL_MARK:
2478  case detail::Classifier::NONE:
2479  default:
2480  throw HorribleError("parsing got called with invalid option! You should not see this");
2481  }
2482 
2483  auto op_ptr =
2484  std::find_if(std::begin(options_), std::end(options_), [arg_name, current_type](const Option_p &opt) {
2485  if(current_type == detail::Classifier::LONG)
2486  return opt->check_lname(arg_name);
2487  if(current_type == detail::Classifier::SHORT)
2488  return opt->check_sname(arg_name);
2489  // this will only get called for detail::Classifier::WINDOWS
2490  return opt->check_lname(arg_name) || opt->check_sname(arg_name);
2491  });
2492 
2493  // Option not found
2494  if(op_ptr == std::end(options_)) {
2495  for(auto &subc : subcommands_) {
2496  if(subc->name_.empty() && !subc->disabled_) {
2497  if(subc->_parse_arg(args, current_type)) {
2498  if(!subc->pre_parse_called_) {
2499  subc->_trigger_pre_parse(args.size());
2500  }
2501  return true;
2502  }
2503  }
2504  }
2505  // If a subcommand, try the master command
2506  if(parent_ != nullptr && fallthrough_)
2507  return _get_fallthrough_parent()->_parse_arg(args, current_type);
2508  // don't capture missing if this is a nameless subcommand
2509  if(parent_ != nullptr && name_.empty()) {
2510  return false;
2511  }
2512  // Otherwise, add to missing
2513  args.pop_back();
2514  _move_to_missing(current_type, current);
2515  return true;
2516  }
2517 
2518  args.pop_back();
2519 
2520  // Get a reference to the pointer to make syntax bearable
2521  Option_p &op = *op_ptr;
2522 
2523  int num = op->get_items_expected();
2524 
2525  // Make sure we always eat the minimum for unlimited vectors
2526  int collected = 0;
2527  int result_count = 0;
2528  // deal with flag like things
2529  if(num == 0) {
2530  auto res = op->get_flag_value(arg_name, value);
2531  op->add_result(res);
2532  parse_order_.push_back(op.get());
2533  }
2534  // --this=value
2535  else if(!value.empty()) {
2536  op->add_result(value, result_count);
2537  parse_order_.push_back(op.get());
2538  collected += result_count;
2539  // If exact number expected
2540  if(num > 0)
2541  num = (num >= result_count) ? num - result_count : 0;
2542 
2543  // -Trest
2544  } else if(!rest.empty()) {
2545  op->add_result(rest, result_count);
2546  parse_order_.push_back(op.get());
2547  rest = "";
2548  collected += result_count;
2549  // If exact number expected
2550  if(num > 0)
2551  num = (num >= result_count) ? num - result_count : 0;
2552  }
2553 
2554  // Unlimited vector parser
2555  if(num < 0) {
2556  while(!args.empty() && _recognize(args.back(), false) == detail::Classifier::NONE) {
2557  if(collected >= -num) {
2558  // We could break here for allow extras, but we don't
2559 
2560  // If any positionals remain, don't keep eating
2562  break;
2563  }
2564  op->add_result(args.back(), result_count);
2565  parse_order_.push_back(op.get());
2566  args.pop_back();
2567  collected += result_count;
2568  }
2569 
2570  // Allow -- to end an unlimited list and "eat" it
2571  if(!args.empty() && _recognize(args.back()) == detail::Classifier::POSITIONAL_MARK)
2572  args.pop_back();
2573 
2574  } else {
2575  while(num > 0 && !args.empty()) {
2576  std::string current_ = args.back();
2577  args.pop_back();
2578  op->add_result(current_, result_count);
2579  parse_order_.push_back(op.get());
2580  num -= result_count;
2581  }
2582 
2583  if(num > 0) {
2584  throw ArgumentMismatch::TypedAtLeast(op->get_name(), num, op->get_type_name());
2585  }
2586  }
2587 
2588  if(!rest.empty()) {
2589  rest = "-" + rest;
2590  args.push_back(rest);
2591  }
2592  return true;
2593  }
2594 
2596  void _trigger_pre_parse(size_t remaining_args) {
2597  if(!pre_parse_called_) {
2598  pre_parse_called_ = true;
2599  if(pre_parse_callback_) {
2600  pre_parse_callback_(remaining_args);
2601  }
2602  } else if(immediate_callback_) {
2603  if(!name_.empty()) {
2604  auto pcnt = parsed_;
2605  auto extras = std::move(missing_);
2606  clear();
2607  parsed_ = pcnt;
2608  pre_parse_called_ = true;
2609  missing_ = std::move(extras);
2610  }
2611  }
2612  }
2613 
2616  if(parent_ == nullptr) {
2617  throw(HorribleError("No Valid parent"));
2618  }
2619  auto fallthrough_parent = parent_;
2620  while((fallthrough_parent->parent_ != nullptr) && (fallthrough_parent->get_name().empty())) {
2621  fallthrough_parent = fallthrough_parent->parent_;
2622  }
2623  return fallthrough_parent;
2624  }
2625 
2627  void _move_to_missing(detail::Classifier val_type, const std::string &val) {
2628  if(allow_extras_ || subcommands_.empty()) {
2629  missing_.emplace_back(val_type, val);
2630  return;
2631  }
2632  // allow extra arguments to be places in an option group if it is allowed there
2633  for(auto &subc : subcommands_) {
2634  if(subc->name_.empty() && subc->allow_extras_) {
2635  subc->missing_.emplace_back(val_type, val);
2636  return;
2637  }
2638  }
2639  // if we haven't found any place to put them yet put them in missing
2640  missing_.emplace_back(val_type, val);
2641  }
2642 
2643  public:
2645  void _move_option(Option *opt, App *app) {
2646  if(opt == nullptr) {
2647  throw OptionNotFound("the option is NULL");
2648  }
2649  // verify that the give app is actually a subcommand
2650  bool found = false;
2651  for(auto &subc : subcommands_) {
2652  if(app == subc.get()) {
2653  found = true;
2654  }
2655  }
2656  if(!found) {
2657  throw OptionNotFound("The Given app is not a subcommand");
2658  }
2659 
2660  if((help_ptr_ == opt) || (help_all_ptr_ == opt))
2661  throw OptionAlreadyAdded("cannot move help options");
2662 
2663  if(config_ptr_ == opt)
2664  throw OptionAlreadyAdded("cannot move config file options");
2665 
2666  auto iterator =
2667  std::find_if(std::begin(options_), std::end(options_), [opt](const Option_p &v) { return v.get() == opt; });
2668  if(iterator != std::end(options_)) {
2669  const auto &opt_p = *iterator;
2670  if(std::find_if(std::begin(app->options_), std::end(app->options_), [&opt_p](const Option_p &v) {
2671  return (*v == *opt_p);
2672  }) == std::end(app->options_)) {
2673  // only erase after the insertion was successful
2674  app->options_.push_back(std::move(*iterator));
2675  options_.erase(iterator);
2676  } else {
2677  throw OptionAlreadyAdded(opt->get_name());
2678  }
2679  } else {
2680  throw OptionNotFound("could not locate the given App");
2681  }
2682  }
2683 };
2684 
2686 class Option_group : public App {
2687  public:
2688  Option_group(std::string group_description, std::string group_name, App *parent)
2689  : App(std::move(group_description), "", parent) {
2690  group(group_name);
2691  // option groups should have automatic fallthrough
2692  }
2693  using App::add_option;
2696  if(get_parent() == nullptr) {
2697  throw OptionNotFound("Unable to locate the specified option");
2698  }
2699  get_parent()->_move_option(opt, this);
2700  return opt;
2701  }
2703  void add_options(Option *opt) { add_option(opt); }
2705  template <typename... Args> void add_options(Option *opt, Args... args) {
2706  add_option(opt);
2707  add_options(args...);
2708  }
2709  using App::add_subcommand;
2711  App *add_subcommand(App *subcom) {
2712  App_p subc = subcom->get_parent()->get_subcommand_ptr(subcom);
2713  subc->get_parent()->remove_subcommand(subcom);
2714  add_subcommand(std::move(subc));
2715  return subcom;
2716  }
2717 };
2719 inline void TriggerOn(App *trigger_app, App *app_to_enable) {
2720  app_to_enable->enabled_by_default(false);
2721  app_to_enable->disabled_by_default();
2722  trigger_app->preparse_callback([app_to_enable](size_t) { app_to_enable->disabled(false); });
2723 }
2724 
2726 inline void TriggerOn(App *trigger_app, std::vector<App *> apps_to_enable) {
2727  for(auto &app : apps_to_enable) {
2728  app->enabled_by_default(false);
2729  app->disabled_by_default();
2730  }
2731 
2732  trigger_app->preparse_callback([apps_to_enable](size_t) {
2733  for(auto &app : apps_to_enable) {
2734  app->disabled(false);
2735  }
2736  });
2737 }
2738 
2740 inline void TriggerOff(App *trigger_app, App *app_to_enable) {
2741  app_to_enable->disabled_by_default(false);
2742  app_to_enable->enabled_by_default();
2743  trigger_app->preparse_callback([app_to_enable](size_t) { app_to_enable->disabled(); });
2744 }
2745 
2747 inline void TriggerOff(App *trigger_app, std::vector<App *> apps_to_enable) {
2748  for(auto &app : apps_to_enable) {
2749  app->disabled_by_default(false);
2750  app->enabled_by_default();
2751  }
2752 
2753  trigger_app->preparse_callback([apps_to_enable](size_t) {
2754  for(auto &app : apps_to_enable) {
2755  app->disabled();
2756  }
2757  });
2758 }
2759 
2760 namespace FailureMessage {
2761 
2763 inline std::string simple(const App *app, const Error &e) {
2764  std::string header = std::string(e.what()) + "\n";
2765  std::vector<std::string> names;
2766 
2767  // Collect names
2768  if(app->get_help_ptr() != nullptr)
2769  names.push_back(app->get_help_ptr()->get_name());
2770 
2771  if(app->get_help_all_ptr() != nullptr)
2772  names.push_back(app->get_help_all_ptr()->get_name());
2773 
2774  // If any names found, suggest those
2775  if(!names.empty())
2776  header += "Run with " + detail::join(names, " or ") + " for more information.\n";
2777 
2778  return header;
2779 }
2780 
2782 inline std::string help(const App *app, const Error &e) {
2783  std::string header = std::string("ERROR: ") + e.get_name() + ": " + e.what() + "\n";
2784  header += app->help();
2785  return header;
2786 }
2787 
2788 } // namespace FailureMessage
2789 
2790 namespace detail {
2792 struct AppFriend {
2793 
2795  template <typename... Args>
2796  static auto parse_arg(App *app, Args &&... args) ->
2797  typename std::result_of<decltype (&App::_parse_arg)(App, Args...)>::type {
2798  return app->_parse_arg(std::forward<Args>(args)...);
2799  }
2800 
2802  template <typename... Args>
2803  static auto parse_subcommand(App *app, Args &&... args) ->
2804  typename std::result_of<decltype (&App::_parse_subcommand)(App, Args...)>::type {
2805  return app->_parse_subcommand(std::forward<Args>(args)...);
2806  }
2808  static App *get_fallthrough_parent(App *app) { return app->_get_fallthrough_parent(); }
2809 };
2810 } // namespace detail
2811 
2812 } // namespace CLI
int get_type_size() const
The number of arguments the option expects.
Definition: Option.hpp:540
size_t parsed_
Counts the number of times this command/subcommand was parsed.
Definition: App.hpp:196
size_t count() const
Definition: App.hpp:1157
std::string description_
Description of the current program/subcommand.
Definition: App.hpp:73
bool ignore_case_
If true, the program name is not case sensitive INHERITABLE.
Definition: App.hpp:167
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:437
Definition: App.hpp:29
All errors derive from this one.
Definition: Error.hpp:63
App * add_subcommand(std::string subcommand_name="", std::string subcommand_description="")
Add a subcommand. Inherits INHERITABLE and OptionDefaults, and help flag.
Definition: App.hpp:1054
App * callback(std::function< void()> app_callback)
Definition: App.hpp:283
std::vector< const App * > get_subcommands(const std::function< bool(const App *)> &filter) const
Definition: App.hpp:1409
App * require_option(size_t min, size_t max)
Definition: App.hpp:1233
void _process_help_flags(bool trigger_help=false, bool trigger_all_help=false) const
Definition: App.hpp:1991
std::vector< std::string > inputs
Listing of inputs.
Definition: ConfigFwd.hpp:50
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:2627
int get_items_expected() const
The total number of expected values (including the type) This is positive if exactly this number is e...
Definition: Option.hpp:589
bool get_positionals_at_end() const
Check the status of the allow windows style options.
Definition: App.hpp:1640
std::vector< std::string > parents
This is the list of parents.
Definition: ConfigFwd.hpp:44
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:1773
size_t count(std::string option_name) const
Counts the number of times the given option was passed.
Definition: App.hpp:1401
CLI11_DEPRECATED("Use ->transform(CLI::IsMember(..., CLI::ignore_case)) with a (shared) pointer instead") Option *add_mutable_set_ignore_case(std
Definition: App.hpp:819
size_t get_require_subcommand_min() const
Get the required min subcommand value.
Definition: App.hpp:1649
This converter works with INI files.
Definition: ConfigFwd.hpp:94
void parse(std::vector< std::string > &args)
Definition: App.hpp:1327
Definition: FormatterFwd.hpp:109
bool get_disabled() const
Get the status of disabled.
Definition: App.hpp:1670
void _process_requirements()
Verify required options and cross requirements. Subcommands too (only if selected).
Definition: App.hpp:2014
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:2645
bool get_enabled_by_default() const
Get the status of disabled by default.
Definition: App.hpp:1679
App * immediate_callback(bool immediate=true)
Set the subcommand callback to be executed immediately on subcommand completion.
Definition: App.hpp:334
bool _parse_positional(std::vector< std::string > &args)
Definition: App.hpp:2335
const Option * get_option(std::string option_name) const
Get an option by name.
Definition: App.hpp:1604
Option * add_option(std::string option_name, std::vector< T > &variable, std::string option_description="", bool defaulted=false)
Add option for vectors.
Definition: App.hpp:523
-h or –help on command line
Definition: Error.hpp:156
App * add_subcommand(CLI::App_p subcom)
Add a previously created app as a subcommand.
Definition: App.hpp:1060
Option * add_flag(std::string flag_name, T &flag_result, std::string flag_description="")
Definition: App.hpp:680
void _process_extras(std::vector< std::string > &args)
Definition: App.hpp:2147
static App * get_fallthrough_parent(App *app)
Wrap the fallthrough parent function to make sure that is working correctly.
Definition: App.hpp:2808
Option * add_option(Option *opt)
Add an existing option to the Option_group.
Definition: App.hpp:2695
void _process_callbacks()
Process callbacks. Runs on all subcommands.
Definition: App.hpp:1963
This class is simply to allow tests access to App&#39;s protected functions.
Definition: App.hpp:2792
bool prefix_command_
If true, return immediately on an unrecognized option (implies allow_extras) INHERITABLE.
Definition: App.hpp:82
Option * get_config_ptr()
Get a pointer to the config option.
Definition: App.hpp:1696
void _validate() const
Definition: App.hpp:1801
missing_t missing_
Definition: App.hpp:144
App * add_subcommand(App *subcom)
Add an existing subcommand to be a member of an option_group.
Definition: App.hpp:2711
Option * get_option(std::string option_name)
Get an option by name (non-const version)
Definition: App.hpp:1613
bool _parse_single_config(const ConfigItem &item, size_t level=0)
Fill in a single config option.
Definition: App.hpp:2228
std::string name
This is the name.
Definition: ConfigFwd.hpp:47
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:1127
bool get_positional() const
True if the argument can be given directly.
Definition: Option.hpp:595
App * allow_extras(bool allow=true)
Remove the error when extras are left over on the command line.
Definition: App.hpp:303
Option * add_option(std::string option_name, T &option_description)
Add option with description but with no variable assignment or callback.
Definition: App.hpp:517
std::string group_
The group membership INHERITABLE.
Definition: App.hpp:211
bool get_ignore_case() const
Check the status of ignore_case.
Definition: App.hpp:1628
Option * add_set(std::string option_name, T &member, std::set< T > options, std::string option_description="")
Add set of options (No default, temp reference, such as an inline set) DEPRECATED.
Definition: App.hpp:757
Definition: Error.hpp:304
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:1117
void _configure()
Definition: App.hpp:1832
Option * add_mutable_set(std::string option_name, T &member, const std::set< T > &options, std::string option_description, bool defaulted)
Add set of options (with default, set can be changed afterwards - do not destroy the set) DEPRECATED...
Definition: App.hpp:794
size_t get_require_option_min() const
Get the required min option value.
Definition: App.hpp:1655
std::function< std::string(const App *, const Error &e)> failure_message_
The error message printing function INHERITABLE.
Definition: App.hpp:133
void parse(std::string commandline, bool program_name_included=false)
Definition: App.hpp:1299
bool required_
If set to true the subcommand is required to be processed and used, ignored for main app...
Definition: App.hpp:88
bool immediate_callback_
Definition: App.hpp:98
App * name(std::string app_name="")
Set a name for the app (empty will use parser to set the name)
Definition: App.hpp:296
void run_callback()
Process the callback.
Definition: Option.hpp:680
Thrown when an excludes option is present.
Definition: Error.hpp:268
std::shared_ptr< Config > get_config_formatter() const
Access the config formatter.
Definition: App.hpp:1537
std::string envname_
If given, check the environment for this option.
Definition: Option.hpp:230
size_t require_option_min_
Minimum required options (not inheritable!)
Definition: App.hpp:205
bool get_ignore_underscore() const
Check the status of ignore_underscore.
Definition: App.hpp:1631
std::vector< App * > parsed_subcommands_
This is a list of the subcommands collected, in order.
Definition: App.hpp:150
const std::string & get_group() const
Get the group of this option.
Definition: Option.hpp:105
size_t remaining_size(bool recurse=false) const
This returns the number of remaining options, minus the – separator.
Definition: App.hpp:1780
bool positionals_at_end_
specify that positional arguments come at the end of the argument sequence not inheritable ...
Definition: App.hpp:184
const std::string & get_group() const
Get the group of this subcommand.
Definition: App.hpp:1643
Extension of App to better manage groups of options.
Definition: App.hpp:2686
bool got_subcommand(App *subcom) const
Check to see if given subcommand was selected.
Definition: App.hpp:1443
size_t _count_remaining_positionals(bool required_only=false) const
Count the required remaining positional arguments.
Definition: App.hpp:2313
Option * add_result(std::string s)
Puts a result at the end.
Definition: Option.hpp:833
bool get_disabled_by_default() const
Get the status of disabled by default.
Definition: App.hpp:1676
App * fallthrough(bool value=true)
Definition: App.hpp:1241
virtual void pre_callback()
Definition: App.hpp:1257
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:1875
std::shared_ptr< Config > config_formatter_
This is the formatter for help printing. Default provided. INHERITABLE (same pointer) ...
Definition: App.hpp:227
void add_options(Option *opt, Args... args)
Add a bunch of options to the group.
Definition: App.hpp:2705
Option * add_option(std::string option_name, T &variable, std::string option_description="", bool defaulted=false)
Add option for non-vectors (duplicate copy needed without defaulted to avoid iostream << value) ...
Definition: App.hpp:473
App * require_subcommand(size_t min, size_t max)
Definition: App.hpp:1204
Option * add_option(std::string option_name)
Add option with no description or variable assignment.
Definition: App.hpp:509
App * footer(std::string footer_string)
Set footer.
Definition: App.hpp:1502
Holds values to load into Options.
Definition: ConfigFwd.hpp:42
std::shared_ptr< FormatterBase > formatter_
This is the formatter for help printing. Default provided. INHERITABLE (same pointer) ...
Definition: App.hpp:130
CLI11_DEPRECATED("Use ->transform(CLI::IsMember(..., CLI::ignore_case, CLI::ignore_underscore)) with a (shared) pointer instead") Option *add_mutable_set_ignore_case_underscore(std
Definition: App.hpp:923
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:1040
void clear()
Clear the parsed results (mostly for testing)
Definition: Option.hpp:316
App * disabled(bool disable=true)
Disable the subcommand or option group.
Definition: App.hpp:315
size_t get_require_option_max() const
Get the required max option value.
Definition: App.hpp:1658
bool remove_option(Option *opt)
Removes an option from the App. Takes an option pointer. Returns true if found and removed...
Definition: App.hpp:1017
Verify items are in a set.
Definition: Validators.hpp:540
const Option * get_option_no_throw(std::string option_name) const noexcept
Get an option by name (noexcept const version)
Definition: App.hpp:1585
bool check_name(std::string name) const
Check a name. Requires "-" or "--" for short / long, supports positional name.
Definition: Option.hpp:757
App * ignore_underscore(bool value=true)
Ignore underscore. Subcommands inherit value.
Definition: App.hpp:384
App * get_parent()
Get the parent of this subcommand (or nullptr if master app)
Definition: App.hpp:1702
std::string get_name() const
Get the name of the current app.
Definition: App.hpp:1708
bool remove_excludes(App *app)
Removes a subcommand from this excludes list of this subcommand.
Definition: App.hpp:1485
App * require_subcommand(int value)
Definition: App.hpp:1191
const std::vector< Option * > & parse_order() const
This gets a vector of pointers with the original parse order.
Definition: App.hpp:1743
Thrown when an option is set to conflicting values (non-vector and multi args, for example) ...
Definition: Error.hpp:86
void _parse(std::vector< std::string > &&args)
Internal parse function.
Definition: App.hpp:2200
void add_options(Option *opt)
Add an existing option to the Option_group.
Definition: App.hpp:2703
bool parsed() const
Check to see if this subcommand was parsed, true only if received on command line.
Definition: App.hpp:414
App * _find_subcommand(const std::string &subc_name, bool ignore_disabled, bool ignore_used) const noexcept
Definition: App.hpp:2408
CLI11_DEPRECATED("Use ->transform(CLI::IsMember(..., CLI::ignore_case, CLI::ignore_underscore)) instead") Option *add_set_ignore_case_underscore(std
Add set of options, string only, ignore underscore and case (no default, static set) DEPRECATED...
Definition: App.hpp:910
bool allow_config_extras_
If true, allow extra arguments in the ini file (ie, don&#39;t throw an error). INHERITABLE.
Definition: App.hpp:79
App * description(std::string app_description)
Set the description of the app.
Definition: App.hpp:1543
bool got_subcommand(std::string subcommand_name) const
Check with name instead of pointer to see if subcommand was selected.
Definition: App.hpp:1449
std::vector< App * > get_subcommands() const
Definition: App.hpp:1405
const std::string & get_footer() const
Get footer.
Definition: App.hpp:1646
bool get_allow_windows_style_options() const
Check the status of the allow windows style options.
Definition: App.hpp:1637
bool check_name(std::string name_to_check) const
Check the name, case insensitive and underscore insensitive if set.
Definition: App.hpp:1714
void increment_parsed()
Internal function to recursively increment the parsed counter on the current app as well unnamed subc...
Definition: App.hpp:2163
std::vector< Option * > parse_order_
This is a list of pointers to options with the original parse order.
Definition: App.hpp:147
Thrown when too many positionals or options are found.
Definition: Error.hpp:275
const Option * get_help_ptr() const
Get a pointer to the help flag. (const)
Definition: App.hpp:1690
CLI11_DEPRECATED("Use ->transform(CLI::IsMember(..., CLI::ignore_underscore)) instead") Option *add_set_ignore_underscore(std
Add set of options, string only, ignore underscore (no default, static set) DEPRECATED.
Definition: App.hpp:858
CLI::App_p get_subcommand_ptr(int index=0) const
Get an owning pointer to subcommand by index.
Definition: App.hpp:1135
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:1889
App * allow_config_extras(bool allow=true)
Definition: App.hpp:347
App * formatter_fn(std::function< std::string(const App *, std::string, AppFormatMode)> fmt)
Set the help formatter.
Definition: App.hpp:402
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:581
Option * add_flag(std::string flag_name, T &flag_count, std::string flag_description="")
Definition: App.hpp:658
std::vector< std::string > remaining(bool recurse=false) const
This returns the missing options from the current subcommand.
Definition: App.hpp:1746
Creates a command line program, with very few defaults.
Definition: App.hpp:59
App * allow_windows_style_options(bool value=true)
Allow windows style options, such as /opt. First matching short or long name used. Subcommands inherit value.
Definition: App.hpp:372
OptionDefaults option_defaults_
The default values for options, customizable and changeable INHERITABLE.
Definition: App.hpp:111
bool get_required() const
True if this is a required option.
Definition: Option.hpp:108
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:1372
Option * type_size(int option_type_size)
Set a custom option size.
Definition: Option.hpp:929
std::set< Option * > exclude_options_
Definition: App.hpp:157
bool get_callback_run() const
See if the callback has been run already.
Definition: Option.hpp:910
std::vector< std::string > fnames_
a list of flag names with specified default values;
Definition: Option.hpp:224
void _process()
Process callbacks and such.
Definition: App.hpp:2122
Thrown when a requires option is missing.
Definition: Error.hpp:261
size_t count_all() const
Definition: App.hpp:1161
std::string help(std::string prev="", AppFormatMode mode=AppFormatMode::Normal) const
Definition: App.hpp:1515
std::function< void(size_t)> pre_parse_callback_
This is a function that runs prior to the start of parsing.
Definition: App.hpp:101
std::set< Option * > excludes_
A list of options that are excluded with this option.
Definition: Option.hpp:269
Option * get_option_no_throw(std::string option_name) noexcept
Get an option by name (noexcept non-const version)
Definition: App.hpp:1566
bool _parse_subcommand(std::vector< std::string > &args)
Definition: App.hpp:2429
bool get_configurable() const
The status of configurable.
Definition: Option.hpp:117
const Option * get_config_ptr() const
Get a pointer to the config option. (const)
Definition: App.hpp:1699
bool get_allow_extras() const
Get the status of allow extras.
Definition: App.hpp:1664
std::string footer_
Footer to put after all options in the help output INHERITABLE.
Definition: App.hpp:121
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:1367
App * positionals_at_end(bool value=true)
Specify that the positional arguments are only at the end of the sequence.
Definition: App.hpp:378
size_t empty() const
True if the option was not passed.
Definition: Option.hpp:310
Usually something like –help-all on command line.
Definition: Error.hpp:162
App * get_subcommand(std::string subcom) const
Check to see if a subcommand is part of this command (text version)
Definition: App.hpp:1100
App * get_subcommand(int index=0) const
Get a pointer to subcommand by index.
Definition: App.hpp:1107
App * get_option_group(std::string group_name) const
Check to see if an option group is part of this App.
Definition: App.hpp:1145
bool allow_extras_
If true, allow extra arguments (ie, don&#39;t throw an error). INHERITABLE.
Definition: App.hpp:76
Thrown when validation fails before parsing.
Definition: Error.hpp:295
App * excludes(Option *opt)
Sets excluded options for the subcommand.
Definition: App.hpp:1452
App(std::string app_description, std::string app_name, App *parent)
Special private constructor for subcommand.
Definition: App.hpp:232
std::vector< App * > get_subcommands(const std::function< bool(App *)> &filter)
Definition: App.hpp:1427
Definition: Option.hpp:169
Thrown when parsing an INI file and it is missing.
Definition: Error.hpp:175
Option * help_all_ptr_
A pointer to the help all flag if there is one INHERITABLE.
Definition: App.hpp:127
Option * config_ptr_
Pointer to the config option.
Definition: App.hpp:224
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:713
bool config_required_
True if ini is required (throws if not present), if false simply keep going.
Definition: App.hpp:221
void _process_extras()
Throw an error if anything is left over and should not be.
Definition: App.hpp:2131
App * formatter(std::shared_ptr< FormatterBase > fmt)
Set the help formatter.
Definition: App.hpp:396
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:2615
std::string config_name_
The name of the connected config file.
Definition: App.hpp:218
void clear()
Reset the parsed data.
Definition: App.hpp:1264
void run_callback()
Internal function to run (App) callback, bottom up.
Definition: App.hpp:1853
Check to see if something is bool (fail check by default)
Definition: TypeTools.hpp:50
void _process_env()
Get envname options if not yet passed. Runs on all subcommands.
Definition: App.hpp:1930
std::string config_to_str(bool default_also=false, bool write_description=false) const
Definition: App.hpp:1509
CLI11_DEPRECATED("Use ->transform(CLI::IsMember(..., CLI::ignore_underscore)) with a (shared) pointer instead") Option *add_mutable_set_ignore_underscore(std
Definition: App.hpp:871
size_t require_subcommand_min_
Minimum required subcommands (not inheritable!)
Definition: App.hpp:199
bool get_validate_positionals() const
Get the status of validating positionals.
Definition: App.hpp:1681
bool disabled_
If set to true the subcommand is disabled and cannot be used, ignored for main app.
Definition: App.hpp:91
const Option * operator[](const char *option_name) const
Shortcut bracket operator for getting a pointer to an option.
Definition: App.hpp:1625
size_t require_subcommand_max_
Max number of subcommands allowed (parsing stops after this number). 0 is unlimited INHERITABLE...
Definition: App.hpp:202
const App * get_parent() const
Get the parent of this subcommand (or nullptr if master app) (const version)
Definition: App.hpp:1705
std::string name_
Subcommand name or program name (from parser if name is empty)
Definition: App.hpp:70
Option * add_flag(std::string flag_name, T &flag_description)
Definition: App.hpp:650
Option * add_option_function(std::string option_name, const std::function< void(const T &)> &func, std::string option_description="")
Add option for a callback of a specific type.
Definition: App.hpp:490
bool pre_parse_called_
Flag indicating that the pre_parse_callback has been triggered.
Definition: App.hpp:94
std::shared_ptr< FormatterBase > get_formatter() const
Access the formatter.
Definition: App.hpp:1534
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:1549
bool enabled_by_default_
If set to true the subcommand will be reenabled at the start of each parse.
Definition: App.hpp:189
bool _has_remaining_positionals() const
Count the required remaining positional arguments.
Definition: App.hpp:2324
Option * get_help_ptr()
Get a pointer to the help flag.
Definition: App.hpp:1687
Thrown when an option already exists.
Definition: Error.hpp:128
Thrown when counting a non-existent option.
Definition: Error.hpp:312
bool _parse_arg(std::vector< std::string > &args, detail::Classifier current_type)
Definition: App.hpp:2455
bool allow_windows_style_options_
Allow &#39;/&#39; for options for Windows like options. Defaults to true on Windows, false otherwise...
Definition: App.hpp:176
void parse(std::vector< std::string > &&args)
The real work is done here. Expects a reversed vector.
Definition: App.hpp:1347
const Option * operator[](const std::string &option_name) const
Shortcut bracket operator for getting a pointer to an option.
Definition: App.hpp:1622
bool get_prefix_command() const
Get the prefix command status.
Definition: App.hpp:1661
void _process_ini()
Read and process an ini file (main app only)
Definition: App.hpp:1910
size_t require_option_max_
Max number of options allowed. 0 is unlimited (not inheritable)
Definition: App.hpp:208
CLI11_DEPRECATED("Use ->transform(CLI::IsMember(...)) with a (shared) pointer instead") Option *add_mutable_set_ignore_case(std
Definition: App.hpp:845
std::string get_description() const
Get the app or subcommand description.
Definition: App.hpp:1540
std::string fullname() const
The list of parents and name joined by ".".
Definition: ConfigFwd.hpp:53
bool disabled_by_default_
If set to true the subcommand will start each parse disabled.
Definition: App.hpp:187
App * prefix_command(bool allow=true)
Do not parse anything after the first unrecognized option and return.
Definition: App.hpp:354
Option * add_mutable_set(std::string option_name, T &member, const std::set< T > &options, std::string option_description="")
Add set of options (No default, set can be changed afterwards - do not destroy the set) DEPRECATED...
Definition: App.hpp:769
App * require_subcommand()
The argumentless form of require subcommand requires 1 or more subcommands.
Definition: App.hpp:1182
std::vector< std::pair< std::string, std::string > > default_flag_values_
Definition: Option.hpp:221
Option * add_set(std::string option_name, T &member, std::set< T > options, std::string option_description, bool defaulted)
Add set of options (with default, static set, such as an inline set) DEPRECATED.
Definition: App.hpp:781
bool remove_subcommand(App *subcom)
Removes a subcommand from the App. Takes a subcommand pointer. Returns true if found and removed...
Definition: App.hpp:1074
App * enabled_by_default(bool enable=true)
Definition: App.hpp:328
bool remove_excludes(Option *opt)
Removes an option from the excludes list of this subcommand.
Definition: App.hpp:1474
size_t get_require_subcommand_max() const
Get the required max subcommand value.
Definition: App.hpp:1652
std::vector< Option_p > options_
The list of options, stored locally.
Definition: App.hpp:114
std::set< App * > exclude_subcommands_
this is a list of subcommands that are exclusionary to this one
Definition: App.hpp:153
void _parse_config(std::vector< ConfigItem > &args)
Definition: App.hpp:2220
App * require_option()
The argumentless form of require option requires 1 or more options be used.
Definition: App.hpp:1211
App * required(bool require=true)
Remove the error when extras are left over on the command line.
Definition: App.hpp:309
std::string get_display_name() const
Get a display name for an app.
Definition: App.hpp:1711
App * get_subcommand(App *subcom) const
Definition: App.hpp:1090
const Option * get_help_all_ptr() const
Get a pointer to the help all flag. (const)
Definition: App.hpp:1693
App * validate_positionals(bool validate=true)
Set the subcommand to validate positional arguments before assigning.
Definition: App.hpp:340
Option * type_name(std::string typeval)
Set a custom option typestring.
Definition: Option.hpp:923
void _trigger_pre_parse(size_t remaining_args)
Trigger the pre_parse callback if needed.
Definition: App.hpp:2596
bool get_immediate_callback() const
Get the status of disabled.
Definition: App.hpp:1673
bool ignore_underscore_
If true, the program should ignore underscores INHERITABLE.
Definition: App.hpp:170
App * preparse_callback(std::function< void(size_t)> pp_callback)
Definition: App.hpp:290
bool get_required() const
Get the status of required.
Definition: App.hpp:1667
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:2803
Option * add_flag_function(std::string flag_name, std::function< void(int64_t)> function, std::string flag_description="")
Add option for callback with an integer value.
Definition: App.hpp:733
Option * transform(Validator validator, std::string validator_name="")
Adds a transforming validator with a built in type name.
Definition: Option.hpp:368
App * excludes(App *app)
Sets excluded subcommands for the subcommand.
Definition: App.hpp:1461
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:598
const std::string & get_description() const
Get the description.
Definition: Option.hpp:604
void _parse(std::vector< std::string > &args)
Internal parse function.
Definition: App.hpp:2171
App * config_formatter(std::shared_ptr< Config > fmt)
Set the config formatter.
Definition: App.hpp:408
bool fallthrough_
Allow subcommand fallthrough, so that parent commands can collect commands after subcommand. INHERITABLE.
Definition: App.hpp:173
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:620
Option * add_complex(std::string option_name, T &variable, std::string option_description="", bool defaulted=false, std::string label="COMPLEX")
Add a complex number.
Definition: App.hpp:965
Option * multi_option_policy(MultiOptionPolicy value=MultiOptionPolicy::Throw)
Take the last argument if given multiple times (or another policy)
Definition: Option.hpp:522
bool _parse_single(std::vector< std::string > &args, bool &positional_only)
Definition: App.hpp:2269
size_t count() const
Count the total number of times an option was passed.
Definition: Option.hpp:307
void parse(int argc, const char *const *argv)
Definition: App.hpp:1281
Option * set_config(std::string option_name="", std::string default_filename="", 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:996
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:85
Definition: Option.hpp:206
std::function< void()> callback_
This is a function that runs when complete. Great for subcommands. Can throw.
Definition: App.hpp:104
void copy_to(T *other) const
Copy the contents to another similar class (one based on OptionBase)
Definition: Option.hpp:67
bool get_allow_config_extras() const
Get the status of allow extras.
Definition: App.hpp:1684
std::vector< App_p > subcommands_
Storage for subcommand list.
Definition: App.hpp:164
bool validate_positionals_
If set to true positional options are validated before assigning INHERITABLE.
Definition: App.hpp:191
virtual ~App()=default
virtual destructor
Option * add_flag(std::string flag_name)
Add a flag with no description or variable assignment.
Definition: App.hpp:642
App * require_option(int value)
Definition: App.hpp:1220
OptionDefaults * option_defaults()
Get the OptionDefault object, to set option defaults.
Definition: App.hpp:417
App * group(std::string group_name)
Changes the group membership.
Definition: App.hpp:1176
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:2796
App * parent_
A pointer to the parent if this is a subcommand.
Definition: App.hpp:193
Option * check(Validator validator, std::string validator_name="")
Adds a Validator with a built in type name.
Definition: Option.hpp:350
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:698
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:269
App * ignore_case(bool value=true)
Ignore case. Subcommands inherit value.
Definition: App.hpp:360
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:321
std::set< Option * > needs_
A list of options that are required with this option.
Definition: Option.hpp:266
Thrown when a required option is missing.
Definition: Error.hpp:205
CRTP * configurable(bool value=true)
Allow in a configuration file.
Definition: Option.hpp:155
Option * help_ptr_
A pointer to the help flag if there is one INHERITABLE.
Definition: App.hpp:124
std::vector< std::string > get_groups() const
Get the groups available directly from this option (in order)
Definition: App.hpp:1729
CLI11_DEPRECATED("Use ->transform(CLI::IsMember(..., CLI::ignore_case)) instead") Option *add_set_ignore_case(std
Add set of options, string only, ignore case (no default, static set) DEPRECATED. ...
Definition: App.hpp:806
bool get_fallthrough() const
Check the status of fallthrough.
Definition: App.hpp:1634