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