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