CLI11
C++11 Command Line Interface Parser
Option.hpp
1 #pragma once
2 
3 // Distributed under the 3-Clause BSD License. See accompanying
4 // file LICENSE or https://github.com/CLIUtils/CLI11 for details.
5 
6 #include <algorithm>
7 #include <functional>
8 #include <memory>
9 #include <set>
10 #include <string>
11 #include <tuple>
12 #include <utility>
13 #include <vector>
14 
15 #include "CLI/Error.hpp"
16 #include "CLI/Macros.hpp"
17 #include "CLI/Split.hpp"
18 #include "CLI/StringTools.hpp"
19 #include "CLI/Validators.hpp"
20 
21 namespace CLI {
22 
23 using results_t = std::vector<std::string>;
24 using callback_t = std::function<bool(results_t)>;
25 
26 class Option;
27 class App;
28 
29 using Option_p = std::unique_ptr<Option>;
30 
31 enum class MultiOptionPolicy : char { Throw, TakeLast, TakeFirst, Join };
32 
35 template <typename CRTP> class OptionBase {
36  friend App;
37 
38  protected:
40  std::string group_ = std::string("Options");
41 
43  bool required_{false};
44 
46  bool ignore_case_{false};
47 
49  bool ignore_underscore_{false};
50 
52  bool configurable_{true};
53 
56 
58  char delimiter_{'\0'};
59 
62 
64  MultiOptionPolicy multi_option_policy_{MultiOptionPolicy::Throw};
65 
67  template <typename T> void copy_to(T *other) const {
68  other->group(group_);
69  other->required(required_);
70  other->ignore_case(ignore_case_);
71  other->ignore_underscore(ignore_underscore_);
72  other->configurable(configurable_);
73  other->disable_flag_override(disable_flag_override_);
74  other->delimiter(delimiter_);
75  other->always_capture_default(always_capture_default_);
76  other->multi_option_policy(multi_option_policy_);
77  }
78 
79  public:
80  // setters
81 
83  CRTP *group(std::string name) {
84  group_ = name;
85  return static_cast<CRTP *>(this);
86  }
87 
89  CRTP *required(bool value = true) {
90  required_ = value;
91  return static_cast<CRTP *>(this);
92  }
93 
95  CRTP *mandatory(bool value = true) { return required(value); }
96 
97  CRTP *always_capture_default(bool value = true) {
99  return static_cast<CRTP *>(this);
100  }
101 
102  // Getters
103 
105  const std::string &get_group() const { return group_; }
106 
108  bool get_required() const { return required_; }
109 
111  bool get_ignore_case() const { return ignore_case_; }
112 
114  bool get_ignore_underscore() const { return ignore_underscore_; }
115 
117  bool get_configurable() const { return configurable_; }
118 
121 
123  char get_delimiter() const { return delimiter_; }
124 
127 
129  MultiOptionPolicy get_multi_option_policy() const { return multi_option_policy_; }
130 
131  // Shortcuts for multi option policy
132 
134  CRTP *take_last() {
135  auto self = static_cast<CRTP *>(this);
136  self->multi_option_policy(MultiOptionPolicy::TakeLast);
137  return self;
138  }
139 
141  CRTP *take_first() {
142  auto self = static_cast<CRTP *>(this);
143  self->multi_option_policy(MultiOptionPolicy::TakeFirst);
144  return self;
145  }
146 
148  CRTP *join() {
149  auto self = static_cast<CRTP *>(this);
150  self->multi_option_policy(MultiOptionPolicy::Join);
151  return self;
152  }
153 
155  CRTP *configurable(bool value = true) {
156  configurable_ = value;
157  return static_cast<CRTP *>(this);
158  }
159 
161  CRTP *delimiter(char value = '\0') {
162  delimiter_ = value;
163  return static_cast<CRTP *>(this);
164  }
165 };
166 
169 class OptionDefaults : public OptionBase<OptionDefaults> {
170  public:
171  OptionDefaults() = default;
172 
173  // Methods here need a different implementation if they are Option vs. OptionDefault
174 
176  OptionDefaults *multi_option_policy(MultiOptionPolicy value = MultiOptionPolicy::Throw) {
177  multi_option_policy_ = value;
178  return this;
179  }
180 
182  OptionDefaults *ignore_case(bool value = true) {
183  ignore_case_ = value;
184  return this;
185  }
186 
188  OptionDefaults *ignore_underscore(bool value = true) {
189  ignore_underscore_ = value;
190  return this;
191  }
192 
194  OptionDefaults *disable_flag_override(bool value = true) {
195  disable_flag_override_ = value;
196  return this;
197  }
198 
200  OptionDefaults *delimiter(char value = '\0') {
201  delimiter_ = value;
202  return this;
203  }
204 };
205 
206 class Option : public OptionBase<Option> {
207  friend App;
208 
209  protected:
212 
214  std::vector<std::string> snames_;
215 
217  std::vector<std::string> lnames_;
218 
221  std::vector<std::pair<std::string, std::string>> default_flag_values_;
222 
224  std::vector<std::string> fnames_;
225 
227  std::string pname_;
228 
230  std::string envname_;
231 
235 
237  std::string description_;
238 
240  std::string default_str_;
241 
245  std::function<std::string()> type_name_{[]() { return std::string(); }};
246 
248  std::function<std::string()> default_function_;
249 
253 
257  int type_size_{1};
258 
260  int expected_{1};
261 
263  std::vector<Validator> validators_;
264 
266  std::set<Option *> needs_;
267 
269  std::set<Option *> excludes_;
270 
274 
277 
279  callback_t callback_;
280 
284 
286  results_t results_;
287 
289  bool callback_run_{false};
290 
292 
294  Option(std::string option_name,
295  std::string option_description,
296  std::function<bool(results_t)> callback,
297  App *parent)
298  : description_(std::move(option_description)), parent_(parent), callback_(std::move(callback)) {
299  std::tie(snames_, lnames_, pname_) = detail::get_names(detail::split_names(option_name));
300  }
301 
302  public:
305 
307  size_t count() const { return results_.size(); }
308 
310  size_t empty() const { return results_.empty(); }
311 
313  operator bool() const { return !empty(); }
314 
316  void clear() { results_.clear(); }
317 
321 
323  Option *expected(int value) {
324 
325  // Break if this is a flag
326  if(type_size_ == 0)
327  throw IncorrectConstruction::SetFlag(get_name(true, true));
328 
329  // Setting 0 is not allowed
330  else if(value == 0)
331  throw IncorrectConstruction::Set0Opt(get_name());
332 
333  // No change is okay, quit now
334  else if(expected_ == value)
335  return this;
336 
337  // Type must be a vector
338  else if(type_size_ >= 0)
339  throw IncorrectConstruction::ChangeNotVector(get_name());
340 
341  // TODO: Can support multioption for non-1 values (except for join)
342  else if(value != 1 && multi_option_policy_ != MultiOptionPolicy::Throw)
343  throw IncorrectConstruction::AfterMultiOpt(get_name());
344 
345  expected_ = value;
346  return this;
347  }
348 
350  Option *check(Validator validator, std::string validator_name = "") {
351  validator.non_modifying();
352  validators_.push_back(std::move(validator));
353  if(!validator_name.empty())
354  validators_.front().name(validator_name);
355  return this;
356  }
357 
359  Option *check(std::function<std::string(const std::string &)> validator,
360  std::string validator_description = "",
361  std::string validator_name = "") {
362  validators_.emplace_back(validator, std::move(validator_description), std::move(validator_name));
363  validators_.back().non_modifying();
364  return this;
365  }
366 
368  Option *transform(Validator validator, std::string validator_name = "") {
369  validators_.insert(validators_.begin(), std::move(validator));
370  if(!validator_name.empty())
371  validators_.front().name(validator_name);
372  return this;
373  }
374 
376  Option *transform(std::function<std::string(std::string)> func,
377  std::string transform_description = "",
378  std::string transform_name = "") {
379  validators_.insert(validators_.begin(),
380  Validator(
381  [func](std::string &val) {
382  val = func(val);
383  return std::string{};
384  },
385  std::move(transform_description),
386  std::move(transform_name)));
387 
388  return this;
389  }
390 
392  Option *each(std::function<void(std::string)> func) {
393  validators_.emplace_back(
394  [func](std::string &inout) {
395  func(inout);
396  return std::string{};
397  },
398  std::string{});
399  return this;
400  }
402  Validator *get_validator(const std::string &validator_name = "") {
403  for(auto &validator : validators_) {
404  if(validator_name == validator.get_name()) {
405  return &validator;
406  }
407  }
408  if((validator_name.empty()) && (!validators_.empty())) {
409  return &(validators_.front());
410  }
411  throw OptionNotFound(std::string("Validator ") + validator_name + " Not Found");
412  }
414  Option *needs(Option *opt) {
415  auto tup = needs_.insert(opt);
416  if(!tup.second)
417  throw OptionAlreadyAdded::Requires(get_name(), opt->get_name());
418  return this;
419  }
420 
422  template <typename T = App> Option *needs(std::string opt_name) {
423  for(const Option_p &opt : dynamic_cast<T *>(parent_)->options_)
424  if(opt.get() != this && opt->check_name(opt_name))
425  return needs(opt.get());
426  throw IncorrectConstruction::MissingOption(opt_name);
427  }
428 
430  template <typename A, typename B, typename... ARG> Option *needs(A opt, B opt1, ARG... args) {
431  needs(opt);
432  return needs(opt1, args...);
433  }
434 
436  bool remove_needs(Option *opt) {
437  auto iterator = std::find(std::begin(needs_), std::end(needs_), opt);
438 
439  if(iterator != std::end(needs_)) {
440  needs_.erase(iterator);
441  return true;
442  } else {
443  return false;
444  }
445  }
446 
449  excludes_.insert(opt);
450 
451  // Help text should be symmetric - excluding a should exclude b
452  opt->excludes_.insert(this);
453 
454  // Ignoring the insert return value, excluding twice is now allowed.
455  // (Mostly to allow both directions to be excluded by user, even though the library does it for you.)
456 
457  return this;
458  }
459 
461  template <typename T = App> Option *excludes(std::string opt_name) {
462  for(const Option_p &opt : dynamic_cast<T *>(parent_)->options_)
463  if(opt.get() != this && opt->check_name(opt_name))
464  return excludes(opt.get());
465  throw IncorrectConstruction::MissingOption(opt_name);
466  }
467 
469  template <typename A, typename B, typename... ARG> Option *excludes(A opt, B opt1, ARG... args) {
470  excludes(opt);
471  return excludes(opt1, args...);
472  }
473 
475  bool remove_excludes(Option *opt) {
476  auto iterator = std::find(std::begin(excludes_), std::end(excludes_), opt);
477 
478  if(iterator != std::end(excludes_)) {
479  excludes_.erase(iterator);
480  return true;
481  } else {
482  return false;
483  }
484  }
485 
487  Option *envname(std::string name) {
488  envname_ = name;
489  return this;
490  }
491 
496  template <typename T = App> Option *ignore_case(bool value = true) {
497  ignore_case_ = value;
498  auto *parent = dynamic_cast<T *>(parent_);
499 
500  for(const Option_p &opt : parent->options_)
501  if(opt.get() != this && *opt == *this)
502  throw OptionAlreadyAdded(opt->get_name(true, true));
503 
504  return this;
505  }
506 
511  template <typename T = App> Option *ignore_underscore(bool value = true) {
512  ignore_underscore_ = value;
513  auto *parent = dynamic_cast<T *>(parent_);
514  for(const Option_p &opt : parent->options_)
515  if(opt.get() != this && *opt == *this)
516  throw OptionAlreadyAdded(opt->get_name(true, true));
517 
518  return this;
519  }
520 
522  Option *multi_option_policy(MultiOptionPolicy value = MultiOptionPolicy::Throw) {
523 
524  if(get_items_expected() < 0)
525  throw IncorrectConstruction::MultiOptionPolicy(get_name());
526  multi_option_policy_ = value;
527  return this;
528  }
529 
531  Option *disable_flag_override(bool value = true) {
532  disable_flag_override_ = value;
533  return this;
534  }
538 
540  int get_type_size() const { return type_size_; }
541 
543  std::string get_envname() const { return envname_; }
544 
546  std::set<Option *> get_needs() const { return needs_; }
547 
549  std::set<Option *> get_excludes() const { return excludes_; }
550 
552  CLI11_DEPRECATED("Use get_default_str() instead")
553  std::string get_defaultval() const { return default_str_; }
554 
556  std::string get_default_str() const { return default_str_; }
557 
559  callback_t get_callback() const { return callback_; }
560 
562  const std::vector<std::string> get_lnames() const { return lnames_; }
563 
565  const std::vector<std::string> get_snames() const { return snames_; }
566 
568  const std::vector<std::string> get_fnames() const { return fnames_; }
569 
571  int get_expected() const { return expected_; }
572 
589  int get_items_expected() const {
590  return std::abs(type_size_ * expected_) *
591  ((multi_option_policy_ != MultiOptionPolicy::Throw || (expected_ < 0 && type_size_ < 0) ? -1 : 1));
592  }
593 
595  bool get_positional() const { return pname_.length() > 0; }
596 
598  bool nonpositional() const { return (snames_.size() + lnames_.size()) > 0; }
599 
601  bool has_description() const { return description_.length() > 0; }
602 
604  const std::string &get_description() const { return description_; }
605 
607  Option *description(std::string option_description) {
608  description_ = std::move(option_description);
609  return this;
610  }
611 
615 
620  std::string get_name(bool positional = false, //<[input] Show the positional name
621  bool all_options = false //<[input] Show every option
622  ) const {
623 
624  if(all_options) {
625 
626  std::vector<std::string> name_list;
627 
629  if((positional && pname_.length()) || (snames_.empty() && lnames_.empty()))
630  name_list.push_back(pname_);
631  if((get_items_expected() == 0) && (!fnames_.empty())) {
632  for(const std::string &sname : snames_) {
633  name_list.push_back("-" + sname);
634  if(check_fname(sname)) {
635  name_list.back() += "{" + get_flag_value(sname, "") + "}";
636  }
637  }
638 
639  for(const std::string &lname : lnames_) {
640  name_list.push_back("--" + lname);
641  if(check_fname(lname)) {
642  name_list.back() += "{" + get_flag_value(lname, "") + "}";
643  }
644  }
645  } else {
646  for(const std::string &sname : snames_)
647  name_list.push_back("-" + sname);
648 
649  for(const std::string &lname : lnames_)
650  name_list.push_back("--" + lname);
651  }
652 
653  return detail::join(name_list);
654 
655  } else {
656 
657  // This returns the positional name no matter what
658  if(positional)
659  return pname_;
660 
661  // Prefer long name
662  else if(!lnames_.empty())
663  return std::string("--") + lnames_[0];
664 
665  // Or short name if no long name
666  else if(!snames_.empty())
667  return std::string("-") + snames_[0];
668 
669  // If positional is the only name, it's okay to use that
670  else
671  return pname_;
672  }
673  }
674 
678 
680  void run_callback() {
681 
682  callback_run_ = true;
683 
684  // Run the validators (can change the string)
685  if(!validators_.empty()) {
686  for(std::string &result : results_) {
687  auto err_msg = _validate(result);
688  if(!err_msg.empty())
689  throw ValidationError(get_name(), err_msg);
690  }
691  }
692  if(!(callback_)) {
693  return;
694  }
695  bool local_result;
696 
697  // Num items expected or length of vector, always at least 1
698  // Only valid for a trimming policy
699  int trim_size =
700  std::min<int>(std::max<int>(std::abs(get_items_expected()), 1), static_cast<int>(results_.size()));
701 
702  // Operation depends on the policy setting
703  if(multi_option_policy_ == MultiOptionPolicy::TakeLast) {
704  // Allow multi-option sizes (including 0)
705  results_t partial_result{results_.end() - trim_size, results_.end()};
706  local_result = !callback_(partial_result);
707 
708  } else if(multi_option_policy_ == MultiOptionPolicy::TakeFirst) {
709  results_t partial_result{results_.begin(), results_.begin() + trim_size};
710  local_result = !callback_(partial_result);
711 
712  } else if(multi_option_policy_ == MultiOptionPolicy::Join) {
713  results_t partial_result = {detail::join(results_, "\n")};
714  local_result = !callback_(partial_result);
715 
716  } else {
717  // Exact number required
718  if(get_items_expected() > 0) {
719  if(results_.size() != static_cast<size_t>(get_items_expected()))
721  // Variable length list
722  } else if(get_items_expected() < 0) {
723  // Require that this be a multiple of expected size and at least as many as expected
724  if(results_.size() < static_cast<size_t>(-get_items_expected()) ||
725  results_.size() % static_cast<size_t>(std::abs(get_type_size())) != 0u)
727  }
728  local_result = !callback_(results_);
729  }
730 
731  if(local_result)
733  }
734 
736  bool operator==(const Option &other) const {
737  for(const std::string &sname : snames_)
738  if(other.check_sname(sname))
739  return true;
740  for(const std::string &lname : lnames_)
741  if(other.check_lname(lname))
742  return true;
743 
744  if(ignore_case_ ||
745  ignore_underscore_) { // We need to do the inverse, in case we are ignore_case or ignore underscore
746  for(const std::string &sname : other.snames_)
747  if(check_sname(sname))
748  return true;
749  for(const std::string &lname : other.lnames_)
750  if(check_lname(lname))
751  return true;
752  }
753  return false;
754  }
755 
757  bool check_name(std::string name) const {
758 
759  if(name.length() > 2 && name[0] == '-' && name[1] == '-')
760  return check_lname(name.substr(2));
761  else if(name.length() > 1 && name.front() == '-')
762  return check_sname(name.substr(1));
763  else {
764  std::string local_pname = pname_;
765  if(ignore_underscore_) {
766  local_pname = detail::remove_underscore(local_pname);
767  name = detail::remove_underscore(name);
768  }
769  if(ignore_case_) {
770  local_pname = detail::to_lower(local_pname);
771  name = detail::to_lower(name);
772  }
773  return name == local_pname;
774  }
775  }
776 
778  bool check_sname(std::string name) const { return (detail::find_member(name, snames_, ignore_case_) >= 0); }
779 
781  bool check_lname(std::string name) const {
782  return (detail::find_member(name, lnames_, ignore_case_, ignore_underscore_) >= 0);
783  }
784 
786  bool check_fname(std::string name) const {
787  if(fnames_.empty()) {
788  return false;
789  }
790  return (detail::find_member(name, fnames_, ignore_case_, ignore_underscore_) >= 0);
791  }
792 
793  std::string get_flag_value(std::string name, std::string input_value) const {
794  static const std::string trueString{"true"};
795  static const std::string falseString{"false"};
796  static const std::string emptyString{"{}"};
797  // check for disable flag override_
799  if(!((input_value.empty()) || (input_value == emptyString))) {
800  auto default_ind = detail::find_member(name, fnames_, ignore_case_, ignore_underscore_);
801  if(default_ind >= 0) {
802  // We can static cast this to size_t because it is more than 0 in this block
803  if(default_flag_values_[static_cast<size_t>(default_ind)].second != input_value) {
804  throw(ArgumentMismatch::FlagOverride(name));
805  }
806  } else {
807  if(input_value != trueString) {
808  throw(ArgumentMismatch::FlagOverride(name));
809  }
810  }
811  }
812  }
813  auto ind = detail::find_member(name, fnames_, ignore_case_, ignore_underscore_);
814  if((input_value.empty()) || (input_value == emptyString)) {
815  return (ind < 0) ? trueString : default_flag_values_[static_cast<size_t>(ind)].second;
816  }
817  if(ind < 0) {
818  return input_value;
819  }
820  if(default_flag_values_[static_cast<size_t>(ind)].second == falseString) {
821  try {
822  auto val = detail::to_flag_value(input_value);
823  return (val == 1) ? falseString : (val == (-1) ? trueString : std::to_string(-val));
824  } catch(const std::invalid_argument &) {
825  return input_value;
826  }
827  } else {
828  return input_value;
829  }
830  }
831 
833  Option *add_result(std::string s) {
834  _add_result(std::move(s));
835  callback_run_ = false;
836  return this;
837  }
838 
840  Option *add_result(std::string s, int &results_added) {
841  results_added = _add_result(std::move(s));
842  callback_run_ = false;
843  return this;
844  }
845 
847  Option *add_result(std::vector<std::string> s) {
848  for(auto &str : s) {
849  _add_result(std::move(str));
850  }
851  callback_run_ = false;
852  return this;
853  }
854 
856  std::vector<std::string> results() const { return results_; }
857 
859  template <typename T,
860  enable_if_t<!is_vector<T>::value && !std::is_const<T>::value, detail::enabler> = detail::dummy>
861  void results(T &output) const {
862  bool retval;
863  if(results_.empty()) {
864  retval = detail::lexical_cast(default_str_, output);
865  } else if(results_.size() == 1) {
866  retval = detail::lexical_cast(results_[0], output);
867  } else {
868  switch(multi_option_policy_) {
869  case MultiOptionPolicy::TakeFirst:
870  retval = detail::lexical_cast(results_.front(), output);
871  break;
872  case MultiOptionPolicy::TakeLast:
873  default:
874  retval = detail::lexical_cast(results_.back(), output);
875  break;
876  case MultiOptionPolicy::Throw:
878  case MultiOptionPolicy::Join:
879  retval = detail::lexical_cast(detail::join(results_), output);
880  break;
881  }
882  }
883  if(!retval) {
885  }
886  }
888  template <typename T> void results(std::vector<T> &output) const {
889  output.clear();
890  bool retval = true;
891 
892  for(const auto &elem : results_) {
893  output.emplace_back();
894  retval &= detail::lexical_cast(elem, output.back());
895  }
896 
897  if(!retval) {
899  }
900  }
901 
903  template <typename T> T as() const {
904  T output;
905  results(output);
906  return output;
907  }
908 
910  bool get_callback_run() const { return callback_run_; }
911 
915 
917  Option *type_name_fn(std::function<std::string()> typefun) {
918  type_name_ = typefun;
919  return this;
920  }
921 
923  Option *type_name(std::string typeval) {
924  type_name_fn([typeval]() { return typeval; });
925  return this;
926  }
927 
929  Option *type_size(int option_type_size) {
930  type_size_ = option_type_size;
931  if(type_size_ == 0)
932  required_ = false;
933  if(option_type_size < 0)
934  expected_ = -1;
935  return this;
936  }
937 
939  Option *default_function(const std::function<std::string()> &func) {
940  default_function_ = func;
941  return this;
942  }
943 
946  if(default_function_) {
948  }
949  return this;
950  }
951 
953  Option *default_str(std::string val) {
954  default_str_ = val;
955  return this;
956  }
957 
959  Option *default_val(std::string val) {
960  default_str(val);
961  auto old_results = results_;
962  results_ = {val};
963  run_callback();
964  results_ = std::move(old_results);
965  return this;
966  }
967 
969  std::string get_type_name() const {
970  std::string full_type_name = type_name_();
971  if(!validators_.empty()) {
972  for(auto &validator : validators_) {
973  std::string vtype = validator.get_description();
974  if(!vtype.empty()) {
975  full_type_name += ":" + vtype;
976  }
977  }
978  }
979  return full_type_name;
980  }
981 
982  private:
983  // run through the validators
984  std::string _validate(std::string &result) {
985  std::string err_msg;
986  for(const auto &vali : validators_) {
987  try {
988  err_msg = vali(result);
989  } catch(const ValidationError &err) {
990  err_msg = err.what();
991  }
992  if(!err_msg.empty())
993  break;
994  }
995  return err_msg;
996  }
997 
998  int _add_result(std::string &&result) {
999  int result_count = 0;
1000  if(delimiter_ == '\0') {
1001  results_.push_back(std::move(result));
1002  ++result_count;
1003  } else {
1004  if((result.find_first_of(delimiter_) != std::string::npos)) {
1005  for(const auto &var : CLI::detail::split(result, delimiter_)) {
1006  if(!var.empty()) {
1007  results_.push_back(var);
1008  ++result_count;
1009  }
1010  }
1011  } else {
1012  results_.push_back(std::move(result));
1013  ++result_count;
1014  }
1015  }
1016  return result_count;
1017  }
1018 };
1019 
1020 } // namespace CLI
bool required_
True if this is a required option.
Definition: Option.hpp:43
int get_type_size() const
The number of arguments the option expects.
Definition: Option.hpp:540
bool get_ignore_underscore() const
The status of ignore_underscore.
Definition: Option.hpp:114
std::vector< std::string > results() const
Get a copy of the results.
Definition: Option.hpp:856
void results(T &output) const
get the results as a particular type
Definition: Option.hpp:861
Option * expected(int value)
Set the number of expected arguments (Flags don't use this)
Definition: Option.hpp:323
bool ignore_underscore_
Ignore underscores when matching (option, not value)
Definition: Option.hpp:49
std::string get_type_name() const
Get the full typename for this option.
Definition: Option.hpp:969
int get_items_expected() const
The total number of expected values (including the type) This is positive if exactly this number is e...
Definition: Option.hpp:589
Validator * get_validator(const std::string &validator_name="")
Get a named Validator.
Definition: Option.hpp:402
results_t results_
Results of parsing.
Definition: Option.hpp:286
Option(std::string option_name, std::string option_description, std::function< bool(results_t)> callback, App *parent)
Making an option by hand is not defined, it must be made by the App class.
Definition: Option.hpp:294
void results(std::vector< T > &output) const
get the results as a vector of a particular type
Definition: Option.hpp:888
std::string pname_
A positional name.
Definition: Option.hpp:227
CRTP * mandatory(bool value=true)
Support Plumbum term.
Definition: Option.hpp:95
OptionDefaults * disable_flag_override(bool value=true)
Disable overriding flag values with an '=' segment.
Definition: Option.hpp:194
Option * needs(std::string opt_name)
Can find a string if needed.
Definition: Option.hpp:422
Option * ignore_underscore(bool value=true)
Definition: Option.hpp:511
Option * add_result(std::vector< std::string > s)
Puts a result at the end.
Definition: Option.hpp:847
std::set< Option * > get_needs() const
The set of options needed.
Definition: Option.hpp:546
Option * transform(std::function< std::string(std::string)> func, std::string transform_description="", std::string transform_name="")
Adds a validator-like function that can change result.
Definition: Option.hpp:376
bool get_positional() const
True if the argument can be given directly.
Definition: Option.hpp:595
OptionDefaults * multi_option_policy(MultiOptionPolicy value=MultiOptionPolicy::Throw)
Take the last argument if given multiple times.
Definition: Option.hpp:176
bool remove_needs(Option *opt)
Remove needs link from an option. Returns true if the option really was in the needs list.
Definition: Option.hpp:436
bool nonpositional() const
True if option has at least one non-positional name.
Definition: Option.hpp:598
Option * default_str(std::string val)
Set the default value string representation (does not change the contained value)
Definition: Option.hpp:953
App * parent_
Remember the parent app.
Definition: Option.hpp:276
void run_callback()
Process the callback.
Definition: Option.hpp:680
std::string envname_
If given, check the environment for this option.
Definition: Option.hpp:230
int get_expected() const
The number of times the option expects to be included.
Definition: Option.hpp:571
OptionDefaults * delimiter(char value='\0')
set a delimiter character to split up single arguments to treat as multiple inputs
Definition: Option.hpp:200
const std::vector< std::string > get_fnames() const
get the flag names with specified default values
Definition: Option.hpp:568
Option * default_function(const std::function< std::string()> &func)
Set a capture function for the default. Mostly used by App.
Definition: Option.hpp:939
const std::string & get_group() const
Get the group of this option.
Definition: Option.hpp:105
Option * needs(A opt, B opt1, ARG... args)
Any number supported, any mix of string and Opt.
Definition: Option.hpp:430
Some validators that are provided.
Definition: Validators.hpp:36
bool ignore_case_
Ignore the case when matching (option, not value)
Definition: Option.hpp:46
Option * needs(Option *opt)
Sets required options.
Definition: Option.hpp:414
Option * add_result(std::string s)
Puts a result at the end.
Definition: Option.hpp:833
std::vector< Validator > validators_
A list of validators to run on each value parsed.
Definition: Option.hpp:263
int expected_
The number of expected values, type_size_ must be < 0. Ignored for flag. N < 0 means at least -N valu...
Definition: Option.hpp:260
void clear()
Clear the parsed results (mostly for testing)
Definition: Option.hpp:316
bool check_fname(std::string name) const
Requires "--" to be removed from string.
Definition: Option.hpp:786
std::string group_
The group membership.
Definition: Option.hpp:40
Option * excludes(Option *opt)
Sets excluded options.
Definition: Option.hpp:448
bool get_always_capture_default() const
Return true if this will automatically capture the default value for help printing.
Definition: Option.hpp:126
bool check_name(std::string name) const
Check a name. Requires "-" or "--" for short / long, supports positional name.
Definition: Option.hpp:757
bool always_capture_default_
Automatically capture default value.
Definition: Option.hpp:61
const std::vector< std::string > get_lnames() const
Get the long names.
Definition: Option.hpp:562
CRTP * join()
Set the multi option policy to take last.
Definition: Option.hpp:148
std::set< Option * > get_excludes() const
The set of options excluded.
Definition: Option.hpp:549
Option * type_name_fn(std::function< std::string()> typefun)
Set the type function to run when displayed on this option.
Definition: Option.hpp:917
Option * check(std::function< std::string(const std::string &)> validator, std::string validator_description="", std::string validator_name="")
Adds a Validator. Takes a const string& and returns an error message (empty if conversion/check is ok...
Definition: Option.hpp:359
std::string description_
The description for help strings.
Definition: Option.hpp:237
bool get_disable_flag_override() const
The status of configurable.
Definition: Option.hpp:120
T as() const
return the results as a particular type
Definition: Option.hpp:903
MultiOptionPolicy multi_option_policy_
Policy for multiple arguments when expected_ == 1 (can be set on bool flags, too)
Definition: Option.hpp:64
callback_t callback_
Options store a callback to do all the work.
Definition: Option.hpp:279
MultiOptionPolicy get_multi_option_policy() const
The status of the multi option policy.
Definition: Option.hpp:129
bool operator==(const Option &other) const
If options share any of the same names, they are equal (not counting positional)
Definition: Option.hpp:736
std::string get_default_str() const
The default value (for help printing)
Definition: Option.hpp:556
bool disable_flag_override_
Disable overriding flag values with '=value'.
Definition: Option.hpp:55
Creates a command line program, with very few defaults.
Definition: App.hpp:59
std::vector< std::string > lnames_
A list of the long names (--a) without the leading dashes.
Definition: Option.hpp:217
bool get_required() const
True if this is a required option.
Definition: Option.hpp:108
Option * type_size(int option_type_size)
Set a custom option size.
Definition: Option.hpp:929
bool get_callback_run() const
See if the callback has been run already.
Definition: Option.hpp:910
Option * envname(std::string name)
Sets environment variable to read if no option given.
Definition: Option.hpp:487
Option * excludes(std::string opt_name)
Can find a string if needed.
Definition: Option.hpp:461
std::vector< std::string > fnames_
a list of flag names with specified default values;
Definition: Option.hpp:224
std::set< Option * > excludes_
A list of options that are excluded with this option.
Definition: Option.hpp:269
bool get_configurable() const
The status of configurable.
Definition: Option.hpp:117
Option * add_result(std::string s, int &results_added)
Puts a result at the end and get a count of the number of arguments actually added.
Definition: Option.hpp:840
size_t empty() const
True if the option was not passed.
Definition: Option.hpp:310
std::string default_str_
A human readable default value, either manually set, captured, or captured by default.
Definition: Option.hpp:240
Option * disable_flag_override(bool value=true)
disable flag overrides
Definition: Option.hpp:531
bool get_ignore_case() const
The status of ignore case.
Definition: Option.hpp:111
Option * each(std::function< void(std::string)> func)
Adds a user supplied function to run on each item passed in (communicate though lambda capture)
Definition: Option.hpp:392
int type_size_
Definition: Option.hpp:257
Definition: Option.hpp:169
CRTP * required(bool value=true)
Set the option as required.
Definition: Option.hpp:89
CRTP * group(std::string name)
Changes the group membership.
Definition: Option.hpp:83
Option * description(std::string option_description)
Set the description.
Definition: Option.hpp:607
const std::vector< std::string > get_snames() const
Get the short names.
Definition: Option.hpp:565
OptionDefaults * ignore_underscore(bool value=true)
Ignore underscores in the option name.
Definition: Option.hpp:188
bool callback_run_
Whether the callback has run (needed for INI parsing)
Definition: Option.hpp:289
char delimiter_
Specify a delimiter character for vector arguments.
Definition: Option.hpp:58
OptionDefaults * ignore_case(bool value=true)
Ignore the case of the option name.
Definition: Option.hpp:182
Definition: Option.hpp:35
Option * ignore_case(bool value=true)
Definition: Option.hpp:496
Thrown when an option already exists.
Definition: Error.hpp:128
Thrown when counting a non-existent option.
Definition: Error.hpp:312
bool check_sname(std::string name) const
Requires "-" to be removed from string.
Definition: Option.hpp:778
std::function< std::string()> type_name_
Definition: Option.hpp:245
Option * capture_default_str()
Capture the default value from the original value (if it can be captured)
Definition: Option.hpp:945
std::vector< std::pair< std::string, std::string > > default_flag_values_
Definition: Option.hpp:221
bool has_description() const
True if option has description.
Definition: Option.hpp:601
std::function< std::string()> default_function_
Run this function to capture a default (ignore if empty)
Definition: Option.hpp:248
bool configurable_
Allow this option to be given in a configuration file.
Definition: Option.hpp:52
std::vector< std::string > snames_
A list of the short names (-a) without the leading dashes.
Definition: Option.hpp:214
std::string get_defaultval() const
The default value (for help printing) DEPRECATED Use get_default_str() instead.
Definition: Option.hpp:553
callback_t get_callback() const
Get the callback function.
Definition: Option.hpp:559
Option * type_name(std::string typeval)
Set a custom option typestring.
Definition: Option.hpp:923
CRTP * take_last()
Set the multi option policy to take last.
Definition: Option.hpp:134
CRTP * delimiter(char value='\0')
Allow in a configuration file.
Definition: Option.hpp:161
bool check_lname(std::string name) const
Requires "--" to be removed from string.
Definition: Option.hpp:781
Option * transform(Validator validator, std::string validator_name="")
Adds a transforming validator with a built in type name.
Definition: Option.hpp:368
const std::string & get_description() const
Get the description.
Definition: Option.hpp:604
std::string get_name(bool positional=false, bool all_options=false) const
Gets a comma separated list of names. Will include / prefer the positional name if positional is true...
Definition: Option.hpp:620
Option * multi_option_policy(MultiOptionPolicy value=MultiOptionPolicy::Throw)
Take the last argument if given multiple times (or another policy)
Definition: Option.hpp:522
size_t count() const
Count the total number of times an option was passed.
Definition: Option.hpp:307
Definition: Option.hpp:206
Thrown when the wrong number of arguments has been received.
Definition: Error.hpp:239
Thrown when conversion call back fails, such as when an int fails to coerce to a string.
Definition: Error.hpp:182
void copy_to(T *other) const
Copy the contents to another similar class (one based on OptionBase)
Definition: Option.hpp:67
CRTP * take_first()
Set the multi option policy to take last.
Definition: Option.hpp:141
Validator & non_modifying(bool no_modify=true)
Specify whether the Validator can be modifying or not.
Definition: Validators.hpp:112
Option * default_val(std::string val)
Set the default value string representation and evaluate into the bound value.
Definition: Option.hpp:959
Option * check(Validator validator, std::string validator_name="")
Adds a Validator with a built in type name.
Definition: Option.hpp:350
char get_delimiter() const
Get the current delimeter char.
Definition: Option.hpp:123
std::set< Option * > needs_
A list of options that are required with this option.
Definition: Option.hpp:266
std::string get_envname() const
The environment variable associated to this value.
Definition: Option.hpp:543
CRTP * configurable(bool value=true)
Allow in a configuration file.
Definition: Option.hpp:155
bool remove_excludes(Option *opt)
Remove needs link from an option. Returns true if the option really was in the needs list.
Definition: Option.hpp:475
Option * excludes(A opt, B opt1, ARG... args)
Any number supported, any mix of string and Opt.
Definition: Option.hpp:469
Thrown when validation of results fails.
Definition: Error.hpp:198