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