File indexing completed on 2025-07-01 08:34:30
0001
0002
0003
0004
0005
0006
0007 #pragma once
0008
0009
0010
0011
0012 #include <algorithm>
0013 #include <cstdint>
0014 #include <functional>
0015 #include <iostream>
0016 #include <iterator>
0017 #include <memory>
0018 #include <numeric>
0019 #include <set>
0020 #include <sstream>
0021 #include <string>
0022 #include <utility>
0023 #include <vector>
0024
0025
0026
0027 #include "ConfigFwd.hpp"
0028 #include "Error.hpp"
0029 #include "FormatterFwd.hpp"
0030 #include "Macros.hpp"
0031 #include "Option.hpp"
0032 #include "Split.hpp"
0033 #include "StringTools.hpp"
0034 #include "TypeTools.hpp"
0035
0036 namespace CLI {
0037
0038
0039 #ifndef CLI11_PARSE
0040 #define CLI11_PARSE(app, ...) \
0041 try { \
0042 (app).parse(__VA_ARGS__); \
0043 } catch(const CLI::ParseError &e) { \
0044 return (app).exit(e); \
0045 }
0046 #endif
0047
0048 namespace detail {
0049 enum class Classifier { NONE, POSITIONAL_MARK, SHORT, LONG, WINDOWS_STYLE, SUBCOMMAND, SUBCOMMAND_TERMINATOR };
0050 struct AppFriend;
0051 }
0052
0053 namespace FailureMessage {
0054
0055 CLI11_INLINE std::string simple(const App *app, const Error &e);
0056
0057
0058 CLI11_INLINE std::string help(const App *app, const Error &e);
0059 }
0060
0061
0062
0063 enum class config_extras_mode : char { error = 0, ignore, ignore_all, capture };
0064
0065 class App;
0066
0067 using App_p = std::shared_ptr<App>;
0068
0069 namespace detail {
0070
0071
0072 template <typename T, enable_if_t<!std::is_integral<T>::value || (sizeof(T) <= 1U), detail::enabler> = detail::dummy>
0073 Option *default_flag_modifiers(Option *opt) {
0074 return opt->always_capture_default();
0075 }
0076
0077
0078 template <typename T, enable_if_t<std::is_integral<T>::value && (sizeof(T) > 1U), detail::enabler> = detail::dummy>
0079 Option *default_flag_modifiers(Option *opt) {
0080 return opt->multi_option_policy(MultiOptionPolicy::Sum)->default_str("0")->force_callback();
0081 }
0082
0083 }
0084
0085 class Option_group;
0086
0087
0088
0089
0090 class App {
0091 friend Option;
0092 friend detail::AppFriend;
0093
0094 protected:
0095
0096
0097
0098
0099
0100
0101 std::string name_{};
0102
0103
0104 std::string description_{};
0105
0106
0107 bool allow_extras_{false};
0108
0109
0110
0111 config_extras_mode allow_config_extras_{config_extras_mode::ignore};
0112
0113
0114 bool prefix_command_{false};
0115
0116
0117 bool has_automatic_name_{false};
0118
0119
0120 bool required_{false};
0121
0122
0123 bool disabled_{false};
0124
0125
0126 bool pre_parse_called_{false};
0127
0128
0129
0130 bool immediate_callback_{false};
0131
0132
0133 std::function<void(std::size_t)> pre_parse_callback_{};
0134
0135
0136 std::function<void()> parse_complete_callback_{};
0137
0138
0139 std::function<void()> final_callback_{};
0140
0141
0142
0143
0144
0145
0146 OptionDefaults option_defaults_{};
0147
0148
0149 std::vector<Option_p> options_{};
0150
0151
0152
0153
0154
0155
0156 std::string usage_{};
0157
0158
0159 std::function<std::string()> usage_callback_{};
0160
0161
0162 std::string footer_{};
0163
0164
0165 std::function<std::string()> footer_callback_{};
0166
0167
0168 Option *help_ptr_{nullptr};
0169
0170
0171 Option *help_all_ptr_{nullptr};
0172
0173
0174 Option *version_ptr_{nullptr};
0175
0176
0177 std::shared_ptr<FormatterBase> formatter_{new Formatter()};
0178
0179
0180 std::function<std::string(const App *, const Error &e)> failure_message_{FailureMessage::simple};
0181
0182
0183
0184
0185
0186 using missing_t = std::vector<std::pair<detail::Classifier, std::string>>;
0187
0188
0189
0190
0191 missing_t missing_{};
0192
0193
0194 std::vector<Option *> parse_order_{};
0195
0196
0197 std::vector<App *> parsed_subcommands_{};
0198
0199
0200 std::set<App *> exclude_subcommands_{};
0201
0202
0203
0204 std::set<Option *> exclude_options_{};
0205
0206
0207
0208 std::set<App *> need_subcommands_{};
0209
0210
0211
0212 std::set<Option *> need_options_{};
0213
0214
0215
0216
0217
0218
0219 std::vector<App_p> subcommands_{};
0220
0221
0222 bool ignore_case_{false};
0223
0224
0225 bool ignore_underscore_{false};
0226
0227
0228 bool fallthrough_{false};
0229
0230
0231 bool allow_windows_style_options_{
0232 #ifdef _WIN32
0233 true
0234 #else
0235 false
0236 #endif
0237 };
0238
0239 bool positionals_at_end_{false};
0240
0241 enum class startup_mode : char { stable, enabled, disabled };
0242
0243
0244 startup_mode default_startup{startup_mode::stable};
0245
0246
0247 bool configurable_{false};
0248
0249
0250 bool validate_positionals_{false};
0251
0252
0253 bool validate_optional_arguments_{false};
0254
0255
0256
0257 bool silent_{false};
0258
0259
0260 std::uint32_t parsed_{0U};
0261
0262
0263 std::size_t require_subcommand_min_{0};
0264
0265
0266 std::size_t require_subcommand_max_{0};
0267
0268
0269 std::size_t require_option_min_{0};
0270
0271
0272 std::size_t require_option_max_{0};
0273
0274
0275 App *parent_{nullptr};
0276
0277
0278 std::string group_{"Subcommands"};
0279
0280
0281 std::vector<std::string> aliases_{};
0282
0283
0284
0285
0286
0287
0288 Option *config_ptr_{nullptr};
0289
0290
0291 std::shared_ptr<Config> config_formatter_{new ConfigTOML()};
0292
0293
0294
0295 #ifdef _WIN32
0296
0297 std::vector<std::string> normalized_argv_{};
0298
0299
0300 std::vector<char *> normalized_argv_view_{};
0301 #endif
0302
0303
0304 App(std::string app_description, std::string app_name, App *parent);
0305
0306 public:
0307
0308
0309
0310
0311 explicit App(std::string app_description = "", std::string app_name = "")
0312 : App(app_description, app_name, nullptr) {
0313 set_help_flag("-h,--help", "Print this help message and exit");
0314 }
0315
0316 App(const App &) = delete;
0317 App &operator=(const App &) = delete;
0318
0319
0320 virtual ~App() = default;
0321
0322
0323 CLI11_NODISCARD char **ensure_utf8(char **argv);
0324
0325
0326
0327
0328
0329
0330
0331 App *callback(std::function<void()> app_callback) {
0332 if(immediate_callback_) {
0333 parse_complete_callback_ = std::move(app_callback);
0334 } else {
0335 final_callback_ = std::move(app_callback);
0336 }
0337 return this;
0338 }
0339
0340
0341
0342 App *final_callback(std::function<void()> app_callback) {
0343 final_callback_ = std::move(app_callback);
0344 return this;
0345 }
0346
0347
0348
0349 App *parse_complete_callback(std::function<void()> pc_callback) {
0350 parse_complete_callback_ = std::move(pc_callback);
0351 return this;
0352 }
0353
0354
0355
0356 App *preparse_callback(std::function<void(std::size_t)> pp_callback) {
0357 pre_parse_callback_ = std::move(pp_callback);
0358 return this;
0359 }
0360
0361
0362 App *name(std::string app_name = "");
0363
0364
0365 App *alias(std::string app_name);
0366
0367
0368 App *allow_extras(bool allow = true) {
0369 allow_extras_ = allow;
0370 return this;
0371 }
0372
0373
0374 App *required(bool require = true) {
0375 required_ = require;
0376 return this;
0377 }
0378
0379
0380 App *disabled(bool disable = true) {
0381 disabled_ = disable;
0382 return this;
0383 }
0384
0385
0386 App *silent(bool silence = true) {
0387 silent_ = silence;
0388 return this;
0389 }
0390
0391
0392 App *disabled_by_default(bool disable = true) {
0393 if(disable) {
0394 default_startup = startup_mode::disabled;
0395 } else {
0396 default_startup = (default_startup == startup_mode::enabled) ? startup_mode::enabled : startup_mode::stable;
0397 }
0398 return this;
0399 }
0400
0401
0402
0403 App *enabled_by_default(bool enable = true) {
0404 if(enable) {
0405 default_startup = startup_mode::enabled;
0406 } else {
0407 default_startup =
0408 (default_startup == startup_mode::disabled) ? startup_mode::disabled : startup_mode::stable;
0409 }
0410 return this;
0411 }
0412
0413
0414 App *immediate_callback(bool immediate = true);
0415
0416
0417 App *validate_positionals(bool validate = true) {
0418 validate_positionals_ = validate;
0419 return this;
0420 }
0421
0422
0423 App *validate_optional_arguments(bool validate = true) {
0424 validate_optional_arguments_ = validate;
0425 return this;
0426 }
0427
0428
0429 App *allow_config_extras(bool allow = true) {
0430 if(allow) {
0431 allow_config_extras_ = config_extras_mode::capture;
0432 allow_extras_ = true;
0433 } else {
0434 allow_config_extras_ = config_extras_mode::error;
0435 }
0436 return this;
0437 }
0438
0439
0440 App *allow_config_extras(config_extras_mode mode) {
0441 allow_config_extras_ = mode;
0442 return this;
0443 }
0444
0445
0446 App *prefix_command(bool allow = true) {
0447 prefix_command_ = allow;
0448 return this;
0449 }
0450
0451
0452 App *ignore_case(bool value = true);
0453
0454
0455
0456 App *allow_windows_style_options(bool value = true) {
0457 allow_windows_style_options_ = value;
0458 return this;
0459 }
0460
0461
0462 App *positionals_at_end(bool value = true) {
0463 positionals_at_end_ = value;
0464 return this;
0465 }
0466
0467
0468 App *configurable(bool value = true) {
0469 configurable_ = value;
0470 return this;
0471 }
0472
0473
0474 App *ignore_underscore(bool value = true);
0475
0476
0477 App *formatter(std::shared_ptr<FormatterBase> fmt) {
0478 formatter_ = fmt;
0479 return this;
0480 }
0481
0482
0483 App *formatter_fn(std::function<std::string(const App *, std::string, AppFormatMode)> fmt) {
0484 formatter_ = std::make_shared<FormatterLambda>(fmt);
0485 return this;
0486 }
0487
0488
0489 App *config_formatter(std::shared_ptr<Config> fmt) {
0490 config_formatter_ = fmt;
0491 return this;
0492 }
0493
0494
0495 CLI11_NODISCARD bool parsed() const { return parsed_ > 0; }
0496
0497
0498 OptionDefaults *option_defaults() { return &option_defaults_; }
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508
0509
0510
0511
0512
0513
0514
0515
0516
0517
0518 Option *add_option(std::string option_name,
0519 callback_t option_callback,
0520 std::string option_description = "",
0521 bool defaulted = false,
0522 std::function<std::string()> func = {});
0523
0524
0525 template <typename AssignTo,
0526 typename ConvertTo = AssignTo,
0527 enable_if_t<!std::is_const<ConvertTo>::value, detail::enabler> = detail::dummy>
0528 Option *add_option(std::string option_name,
0529 AssignTo &variable,
0530 std::string option_description = "") {
0531
0532 auto fun = [&variable](const CLI::results_t &res) {
0533 return detail::lexical_conversion<AssignTo, ConvertTo>(res, variable);
0534 };
0535
0536 Option *opt = add_option(option_name, fun, option_description, false, [&variable]() {
0537 return CLI::detail::checked_to_string<AssignTo, ConvertTo>(variable);
0538 });
0539 opt->type_name(detail::type_name<ConvertTo>());
0540
0541
0542 auto Tcount = detail::type_count<AssignTo>::value;
0543 auto XCcount = detail::type_count<ConvertTo>::value;
0544 opt->type_size(detail::type_count_min<ConvertTo>::value, (std::max)(Tcount, XCcount));
0545 opt->expected(detail::expected_count<ConvertTo>::value);
0546 opt->run_callback_for_default();
0547 return opt;
0548 }
0549
0550
0551 template <typename AssignTo, enable_if_t<!std::is_const<AssignTo>::value, detail::enabler> = detail::dummy>
0552 Option *add_option_no_stream(std::string option_name,
0553 AssignTo &variable,
0554 std::string option_description = "") {
0555
0556 auto fun = [&variable](const CLI::results_t &res) {
0557 return detail::lexical_conversion<AssignTo, AssignTo>(res, variable);
0558 };
0559
0560 Option *opt = add_option(option_name, fun, option_description, false, []() { return std::string{}; });
0561 opt->type_name(detail::type_name<AssignTo>());
0562 opt->type_size(detail::type_count_min<AssignTo>::value, detail::type_count<AssignTo>::value);
0563 opt->expected(detail::expected_count<AssignTo>::value);
0564 opt->run_callback_for_default();
0565 return opt;
0566 }
0567
0568
0569 template <typename ArgType>
0570 Option *add_option_function(std::string option_name,
0571 const std::function<void(const ArgType &)> &func,
0572 std::string option_description = "") {
0573
0574 auto fun = [func](const CLI::results_t &res) {
0575 ArgType variable;
0576 bool result = detail::lexical_conversion<ArgType, ArgType>(res, variable);
0577 if(result) {
0578 func(variable);
0579 }
0580 return result;
0581 };
0582
0583 Option *opt = add_option(option_name, std::move(fun), option_description, false);
0584 opt->type_name(detail::type_name<ArgType>());
0585 opt->type_size(detail::type_count_min<ArgType>::value, detail::type_count<ArgType>::value);
0586 opt->expected(detail::expected_count<ArgType>::value);
0587 return opt;
0588 }
0589
0590
0591 Option *add_option(std::string option_name) {
0592 return add_option(option_name, CLI::callback_t{}, std::string{}, false);
0593 }
0594
0595
0596 template <typename T,
0597 enable_if_t<std::is_const<T>::value && std::is_constructible<std::string, T>::value, detail::enabler> =
0598 detail::dummy>
0599 Option *add_option(std::string option_name, T &option_description) {
0600 return add_option(option_name, CLI::callback_t(), option_description, false);
0601 }
0602
0603
0604 Option *set_help_flag(std::string flag_name = "", const std::string &help_description = "");
0605
0606
0607 Option *set_help_all_flag(std::string help_name = "", const std::string &help_description = "");
0608
0609
0610 Option *set_version_flag(std::string flag_name = "",
0611 const std::string &versionString = "",
0612 const std::string &version_help = "Display program version information and exit");
0613
0614
0615 Option *set_version_flag(std::string flag_name,
0616 std::function<std::string()> vfunc,
0617 const std::string &version_help = "Display program version information and exit");
0618
0619 private:
0620
0621 Option *_add_flag_internal(std::string flag_name, CLI::callback_t fun, std::string flag_description);
0622
0623 public:
0624
0625 Option *add_flag(std::string flag_name) { return _add_flag_internal(flag_name, CLI::callback_t(), std::string{}); }
0626
0627
0628
0629
0630 template <typename T,
0631 enable_if_t<std::is_const<T>::value && std::is_constructible<std::string, T>::value, detail::enabler> =
0632 detail::dummy>
0633 Option *add_flag(std::string flag_name, T &flag_description) {
0634 return _add_flag_internal(flag_name, CLI::callback_t(), flag_description);
0635 }
0636
0637
0638
0639 template <typename T,
0640 enable_if_t<!detail::is_mutable_container<T>::value && !std::is_const<T>::value &&
0641 !std::is_constructible<std::function<void(int)>, T>::value,
0642 detail::enabler> = detail::dummy>
0643 Option *add_flag(std::string flag_name,
0644 T &flag_result,
0645 std::string flag_description = "") {
0646
0647 CLI::callback_t fun = [&flag_result](const CLI::results_t &res) {
0648 using CLI::detail::lexical_cast;
0649 return lexical_cast(res[0], flag_result);
0650 };
0651 auto *opt = _add_flag_internal(flag_name, std::move(fun), std::move(flag_description));
0652 return detail::default_flag_modifiers<T>(opt);
0653 }
0654
0655
0656 template <typename T,
0657 enable_if_t<!std::is_assignable<std::function<void(std::int64_t)> &, T>::value, detail::enabler> =
0658 detail::dummy>
0659 Option *add_flag(std::string flag_name,
0660 std::vector<T> &flag_results,
0661 std::string flag_description = "") {
0662 CLI::callback_t fun = [&flag_results](const CLI::results_t &res) {
0663 bool retval = true;
0664 for(const auto &elem : res) {
0665 using CLI::detail::lexical_cast;
0666 flag_results.emplace_back();
0667 retval &= lexical_cast(elem, flag_results.back());
0668 }
0669 return retval;
0670 };
0671 return _add_flag_internal(flag_name, std::move(fun), std::move(flag_description))
0672 ->multi_option_policy(MultiOptionPolicy::TakeAll)
0673 ->run_callback_for_default();
0674 }
0675
0676
0677 Option *add_flag_callback(std::string flag_name,
0678 std::function<void(void)> function,
0679 std::string flag_description = "");
0680
0681
0682 Option *add_flag_function(std::string flag_name,
0683 std::function<void(std::int64_t)> function,
0684 std::string flag_description = "");
0685
0686 #ifdef CLI11_CPP14
0687
0688 Option *add_flag(std::string flag_name,
0689 std::function<void(std::int64_t)> function,
0690 std::string flag_description = "") {
0691 return add_flag_function(std::move(flag_name), std::move(function), std::move(flag_description));
0692 }
0693 #endif
0694
0695
0696 Option *set_config(std::string option_name = "",
0697 std::string default_filename = "",
0698 const std::string &help_message = "Read an ini file",
0699 bool config_required = false);
0700
0701
0702 bool remove_option(Option *opt);
0703
0704
0705 template <typename T = Option_group>
0706 T *add_option_group(std::string group_name, std::string group_description = "") {
0707 if(!detail::valid_alias_name_string(group_name)) {
0708 throw IncorrectConstruction("option group names may not contain newlines or null characters");
0709 }
0710 auto option_group = std::make_shared<T>(std::move(group_description), group_name, this);
0711 auto *ptr = option_group.get();
0712
0713 App_p app_ptr = std::dynamic_pointer_cast<App>(option_group);
0714 add_subcommand(std::move(app_ptr));
0715 return ptr;
0716 }
0717
0718
0719
0720
0721
0722
0723 App *add_subcommand(std::string subcommand_name = "", std::string subcommand_description = "");
0724
0725
0726 App *add_subcommand(CLI::App_p subcom);
0727
0728
0729 bool remove_subcommand(App *subcom);
0730
0731
0732
0733 App *get_subcommand(const App *subcom) const;
0734
0735
0736 CLI11_NODISCARD App *get_subcommand(std::string subcom) const;
0737
0738
0739
0740 CLI11_NODISCARD App *get_subcommand_no_throw(std::string subcom) const noexcept;
0741
0742
0743 CLI11_NODISCARD App *get_subcommand(int index = 0) const;
0744
0745
0746 CLI::App_p get_subcommand_ptr(App *subcom) const;
0747
0748
0749 CLI11_NODISCARD CLI::App_p get_subcommand_ptr(std::string subcom) const;
0750
0751
0752 CLI11_NODISCARD CLI::App_p get_subcommand_ptr(int index = 0) const;
0753
0754
0755 CLI11_NODISCARD App *get_option_group(std::string group_name) const;
0756
0757
0758
0759
0760 CLI11_NODISCARD std::size_t count() const { return parsed_; }
0761
0762
0763
0764 CLI11_NODISCARD std::size_t count_all() const;
0765
0766
0767 App *group(std::string group_name) {
0768 group_ = group_name;
0769 return this;
0770 }
0771
0772
0773 App *require_subcommand() {
0774 require_subcommand_min_ = 1;
0775 require_subcommand_max_ = 0;
0776 return this;
0777 }
0778
0779
0780
0781
0782 App *require_subcommand(int value) {
0783 if(value < 0) {
0784 require_subcommand_min_ = 0;
0785 require_subcommand_max_ = static_cast<std::size_t>(-value);
0786 } else {
0787 require_subcommand_min_ = static_cast<std::size_t>(value);
0788 require_subcommand_max_ = static_cast<std::size_t>(value);
0789 }
0790 return this;
0791 }
0792
0793
0794
0795 App *require_subcommand(std::size_t min, std::size_t max) {
0796 require_subcommand_min_ = min;
0797 require_subcommand_max_ = max;
0798 return this;
0799 }
0800
0801
0802 App *require_option() {
0803 require_option_min_ = 1;
0804 require_option_max_ = 0;
0805 return this;
0806 }
0807
0808
0809
0810
0811 App *require_option(int value) {
0812 if(value < 0) {
0813 require_option_min_ = 0;
0814 require_option_max_ = static_cast<std::size_t>(-value);
0815 } else {
0816 require_option_min_ = static_cast<std::size_t>(value);
0817 require_option_max_ = static_cast<std::size_t>(value);
0818 }
0819 return this;
0820 }
0821
0822
0823
0824 App *require_option(std::size_t min, std::size_t max) {
0825 require_option_min_ = min;
0826 require_option_max_ = max;
0827 return this;
0828 }
0829
0830
0831
0832 App *fallthrough(bool value = true) {
0833 fallthrough_ = value;
0834 return this;
0835 }
0836
0837
0838
0839 explicit operator bool() const { return parsed_ > 0; }
0840
0841
0842
0843
0844
0845
0846
0847
0848 virtual void pre_callback() {}
0849
0850
0851
0852
0853
0854
0855 void clear();
0856
0857
0858
0859 void parse(int argc, const char *const *argv);
0860 void parse(int argc, const wchar_t *const *argv);
0861
0862 private:
0863 template <class CharT> void parse_char_t(int argc, const CharT *const *argv);
0864
0865 public:
0866
0867
0868
0869
0870 void parse(std::string commandline, bool program_name_included = false);
0871 void parse(std::wstring commandline, bool program_name_included = false);
0872
0873
0874
0875 void parse(std::vector<std::string> &args);
0876
0877
0878 void parse(std::vector<std::string> &&args);
0879
0880 void parse_from_stream(std::istream &input);
0881
0882
0883 void failure_message(std::function<std::string(const App *, const Error &e)> function) {
0884 failure_message_ = function;
0885 }
0886
0887
0888 int exit(const Error &e, std::ostream &out = std::cout, std::ostream &err = std::cerr) const;
0889
0890
0891
0892
0893
0894
0895 CLI11_NODISCARD std::size_t count(std::string option_name) const { return get_option(option_name)->count(); }
0896
0897
0898
0899 CLI11_NODISCARD std::vector<App *> get_subcommands() const { return parsed_subcommands_; }
0900
0901
0902
0903 std::vector<const App *> get_subcommands(const std::function<bool(const App *)> &filter) const;
0904
0905
0906
0907 std::vector<App *> get_subcommands(const std::function<bool(App *)> &filter);
0908
0909
0910 bool got_subcommand(const App *subcom) const {
0911
0912 return get_subcommand(subcom)->parsed_ > 0;
0913 }
0914
0915
0916 CLI11_NODISCARD bool got_subcommand(std::string subcommand_name) const noexcept {
0917 App *sub = get_subcommand_no_throw(subcommand_name);
0918 return (sub != nullptr) ? (sub->parsed_ > 0) : false;
0919 }
0920
0921
0922 App *excludes(Option *opt) {
0923 if(opt == nullptr) {
0924 throw OptionNotFound("nullptr passed");
0925 }
0926 exclude_options_.insert(opt);
0927 return this;
0928 }
0929
0930
0931 App *excludes(App *app) {
0932 if(app == nullptr) {
0933 throw OptionNotFound("nullptr passed");
0934 }
0935 if(app == this) {
0936 throw OptionNotFound("cannot self reference in needs");
0937 }
0938 auto res = exclude_subcommands_.insert(app);
0939
0940 if(res.second) {
0941 app->exclude_subcommands_.insert(this);
0942 }
0943 return this;
0944 }
0945
0946 App *needs(Option *opt) {
0947 if(opt == nullptr) {
0948 throw OptionNotFound("nullptr passed");
0949 }
0950 need_options_.insert(opt);
0951 return this;
0952 }
0953
0954 App *needs(App *app) {
0955 if(app == nullptr) {
0956 throw OptionNotFound("nullptr passed");
0957 }
0958 if(app == this) {
0959 throw OptionNotFound("cannot self reference in needs");
0960 }
0961 need_subcommands_.insert(app);
0962 return this;
0963 }
0964
0965
0966 bool remove_excludes(Option *opt);
0967
0968
0969 bool remove_excludes(App *app);
0970
0971
0972 bool remove_needs(Option *opt);
0973
0974
0975 bool remove_needs(App *app);
0976
0977
0978
0979
0980
0981 App *usage(std::string usage_string) {
0982 usage_ = std::move(usage_string);
0983 return this;
0984 }
0985
0986 App *usage(std::function<std::string()> usage_function) {
0987 usage_callback_ = std::move(usage_function);
0988 return this;
0989 }
0990
0991 App *footer(std::string footer_string) {
0992 footer_ = std::move(footer_string);
0993 return this;
0994 }
0995
0996 App *footer(std::function<std::string()> footer_function) {
0997 footer_callback_ = std::move(footer_function);
0998 return this;
0999 }
1000
1001
1002 CLI11_NODISCARD std::string config_to_str(bool default_also = false, bool write_description = false) const {
1003 return config_formatter_->to_config(this, default_also, write_description, "");
1004 }
1005
1006
1007
1008 CLI11_NODISCARD std::string help(std::string prev = "", AppFormatMode mode = AppFormatMode::Normal) const;
1009
1010
1011 CLI11_NODISCARD std::string version() const;
1012
1013
1014
1015
1016
1017 CLI11_NODISCARD std::shared_ptr<FormatterBase> get_formatter() const { return formatter_; }
1018
1019
1020 CLI11_NODISCARD std::shared_ptr<Config> get_config_formatter() const { return config_formatter_; }
1021
1022
1023 CLI11_NODISCARD std::shared_ptr<ConfigBase> get_config_formatter_base() const {
1024
1025 #if CLI11_USE_STATIC_RTTI == 0
1026 return std::dynamic_pointer_cast<ConfigBase>(config_formatter_);
1027 #else
1028 return std::static_pointer_cast<ConfigBase>(config_formatter_);
1029 #endif
1030 }
1031
1032
1033 CLI11_NODISCARD std::string get_description() const { return description_; }
1034
1035
1036 App *description(std::string app_description) {
1037 description_ = std::move(app_description);
1038 return this;
1039 }
1040
1041
1042 std::vector<const Option *> get_options(const std::function<bool(const Option *)> filter = {}) const;
1043
1044
1045 std::vector<Option *> get_options(const std::function<bool(Option *)> filter = {});
1046
1047
1048 CLI11_NODISCARD Option *get_option_no_throw(std::string option_name) noexcept;
1049
1050
1051 CLI11_NODISCARD const Option *get_option_no_throw(std::string option_name) const noexcept;
1052
1053
1054 CLI11_NODISCARD const Option *get_option(std::string option_name) const {
1055 const auto *opt = get_option_no_throw(option_name);
1056 if(opt == nullptr) {
1057 throw OptionNotFound(option_name);
1058 }
1059 return opt;
1060 }
1061
1062
1063 Option *get_option(std::string option_name) {
1064 auto *opt = get_option_no_throw(option_name);
1065 if(opt == nullptr) {
1066 throw OptionNotFound(option_name);
1067 }
1068 return opt;
1069 }
1070
1071
1072 const Option *operator[](const std::string &option_name) const { return get_option(option_name); }
1073
1074
1075 const Option *operator[](const char *option_name) const { return get_option(option_name); }
1076
1077
1078 CLI11_NODISCARD bool get_ignore_case() const { return ignore_case_; }
1079
1080
1081 CLI11_NODISCARD bool get_ignore_underscore() const { return ignore_underscore_; }
1082
1083
1084 CLI11_NODISCARD bool get_fallthrough() const { return fallthrough_; }
1085
1086
1087 CLI11_NODISCARD bool get_allow_windows_style_options() const { return allow_windows_style_options_; }
1088
1089
1090 CLI11_NODISCARD bool get_positionals_at_end() const { return positionals_at_end_; }
1091
1092
1093 CLI11_NODISCARD bool get_configurable() const { return configurable_; }
1094
1095
1096 CLI11_NODISCARD const std::string &get_group() const { return group_; }
1097
1098
1099 CLI11_NODISCARD std::string get_usage() const {
1100 return (usage_callback_) ? usage_callback_() + '\n' + usage_ : usage_;
1101 }
1102
1103
1104 CLI11_NODISCARD std::string get_footer() const {
1105 return (footer_callback_) ? footer_callback_() + '\n' + footer_ : footer_;
1106 }
1107
1108
1109 CLI11_NODISCARD std::size_t get_require_subcommand_min() const { return require_subcommand_min_; }
1110
1111
1112 CLI11_NODISCARD std::size_t get_require_subcommand_max() const { return require_subcommand_max_; }
1113
1114
1115 CLI11_NODISCARD std::size_t get_require_option_min() const { return require_option_min_; }
1116
1117
1118 CLI11_NODISCARD std::size_t get_require_option_max() const { return require_option_max_; }
1119
1120
1121 CLI11_NODISCARD bool get_prefix_command() const { return prefix_command_; }
1122
1123
1124 CLI11_NODISCARD bool get_allow_extras() const { return allow_extras_; }
1125
1126
1127 CLI11_NODISCARD bool get_required() const { return required_; }
1128
1129
1130 CLI11_NODISCARD bool get_disabled() const { return disabled_; }
1131
1132
1133 CLI11_NODISCARD bool get_silent() const { return silent_; }
1134
1135
1136 CLI11_NODISCARD bool get_immediate_callback() const { return immediate_callback_; }
1137
1138
1139 CLI11_NODISCARD bool get_disabled_by_default() const { return (default_startup == startup_mode::disabled); }
1140
1141
1142 CLI11_NODISCARD bool get_enabled_by_default() const { return (default_startup == startup_mode::enabled); }
1143
1144 CLI11_NODISCARD bool get_validate_positionals() const { return validate_positionals_; }
1145
1146 CLI11_NODISCARD bool get_validate_optional_arguments() const { return validate_optional_arguments_; }
1147
1148
1149 CLI11_NODISCARD config_extras_mode get_allow_config_extras() const { return allow_config_extras_; }
1150
1151
1152 Option *get_help_ptr() { return help_ptr_; }
1153
1154
1155 CLI11_NODISCARD const Option *get_help_ptr() const { return help_ptr_; }
1156
1157
1158 CLI11_NODISCARD const Option *get_help_all_ptr() const { return help_all_ptr_; }
1159
1160
1161 Option *get_config_ptr() { return config_ptr_; }
1162
1163
1164 CLI11_NODISCARD const Option *get_config_ptr() const { return config_ptr_; }
1165
1166
1167 Option *get_version_ptr() { return version_ptr_; }
1168
1169
1170 CLI11_NODISCARD const Option *get_version_ptr() const { return version_ptr_; }
1171
1172
1173 App *get_parent() { return parent_; }
1174
1175
1176 CLI11_NODISCARD const App *get_parent() const { return parent_; }
1177
1178
1179 CLI11_NODISCARD const std::string &get_name() const { return name_; }
1180
1181
1182 CLI11_NODISCARD const std::vector<std::string> &get_aliases() const { return aliases_; }
1183
1184
1185 App *clear_aliases() {
1186 aliases_.clear();
1187 return this;
1188 }
1189
1190
1191 CLI11_NODISCARD std::string get_display_name(bool with_aliases = false) const;
1192
1193
1194 CLI11_NODISCARD bool check_name(std::string name_to_check) const;
1195
1196
1197 CLI11_NODISCARD std::vector<std::string> get_groups() const;
1198
1199
1200 CLI11_NODISCARD const std::vector<Option *> &parse_order() const { return parse_order_; }
1201
1202
1203 CLI11_NODISCARD std::vector<std::string> remaining(bool recurse = false) const;
1204
1205
1206 CLI11_NODISCARD std::vector<std::string> remaining_for_passthrough(bool recurse = false) const;
1207
1208
1209 CLI11_NODISCARD std::size_t remaining_size(bool recurse = false) const;
1210
1211
1212
1213 protected:
1214
1215
1216
1217
1218 void _validate() const;
1219
1220
1221
1222
1223 void _configure();
1224
1225
1226 void run_callback(bool final_mode = false, bool suppress_final_callback = false);
1227
1228
1229 CLI11_NODISCARD bool _valid_subcommand(const std::string ¤t, bool ignore_used = true) const;
1230
1231
1232 CLI11_NODISCARD detail::Classifier _recognize(const std::string ¤t,
1233 bool ignore_used_subcommands = true) const;
1234
1235
1236
1237
1238 void _process_config_file();
1239
1240
1241 bool _process_config_file(const std::string &config_file, bool throw_error);
1242
1243
1244 void _process_env();
1245
1246
1247 void _process_callbacks();
1248
1249
1250
1251
1252 void _process_help_flags(bool trigger_help = false, bool trigger_all_help = false) const;
1253
1254
1255 void _process_requirements();
1256
1257
1258 void _process();
1259
1260
1261 void _process_extras();
1262
1263
1264
1265 void _process_extras(std::vector<std::string> &args);
1266
1267
1268 void increment_parsed();
1269
1270
1271 void _parse(std::vector<std::string> &args);
1272
1273
1274 void _parse(std::vector<std::string> &&args);
1275
1276
1277 void _parse_stream(std::istream &input);
1278
1279
1280
1281
1282
1283 void _parse_config(const std::vector<ConfigItem> &args);
1284
1285
1286 bool _parse_single_config(const ConfigItem &item, std::size_t level = 0);
1287
1288
1289
1290 bool _parse_single(std::vector<std::string> &args, bool &positional_only);
1291
1292
1293 CLI11_NODISCARD std::size_t _count_remaining_positionals(bool required_only = false) const;
1294
1295
1296 CLI11_NODISCARD bool _has_remaining_positionals() const;
1297
1298
1299
1300
1301 bool _parse_positional(std::vector<std::string> &args, bool haltOnSubcommand);
1302
1303
1304
1305 CLI11_NODISCARD App *
1306 _find_subcommand(const std::string &subc_name, bool ignore_disabled, bool ignore_used) const noexcept;
1307
1308
1309
1310
1311
1312 bool _parse_subcommand(std::vector<std::string> &args);
1313
1314
1315
1316
1317 bool _parse_arg(std::vector<std::string> &args, detail::Classifier current_type, bool local_processing_only);
1318
1319
1320 void _trigger_pre_parse(std::size_t remaining_args);
1321
1322
1323 App *_get_fallthrough_parent();
1324
1325
1326 CLI11_NODISCARD const std::string &_compare_subcommand_names(const App &subcom, const App &base) const;
1327
1328
1329 void _move_to_missing(detail::Classifier val_type, const std::string &val);
1330
1331 public:
1332
1333 void _move_option(Option *opt, App *app);
1334 };
1335
1336
1337 class Option_group : public App {
1338 public:
1339 Option_group(std::string group_description, std::string group_name, App *parent)
1340 : App(std::move(group_description), "", parent) {
1341 group(group_name);
1342
1343 }
1344 using App::add_option;
1345
1346 Option *add_option(Option *opt) {
1347 if(get_parent() == nullptr) {
1348 throw OptionNotFound("Unable to locate the specified option");
1349 }
1350 get_parent()->_move_option(opt, this);
1351 return opt;
1352 }
1353
1354 void add_options(Option *opt) { add_option(opt); }
1355
1356 template <typename... Args> void add_options(Option *opt, Args... args) {
1357 add_option(opt);
1358 add_options(args...);
1359 }
1360 using App::add_subcommand;
1361
1362 App *add_subcommand(App *subcom) {
1363 App_p subc = subcom->get_parent()->get_subcommand_ptr(subcom);
1364 subc->get_parent()->remove_subcommand(subcom);
1365 add_subcommand(std::move(subc));
1366 return subcom;
1367 }
1368 };
1369
1370
1371 CLI11_INLINE void TriggerOn(App *trigger_app, App *app_to_enable);
1372
1373
1374 CLI11_INLINE void TriggerOn(App *trigger_app, std::vector<App *> apps_to_enable);
1375
1376
1377 CLI11_INLINE void TriggerOff(App *trigger_app, App *app_to_enable);
1378
1379
1380 CLI11_INLINE void TriggerOff(App *trigger_app, std::vector<App *> apps_to_enable);
1381
1382
1383 CLI11_INLINE void deprecate_option(Option *opt, const std::string &replacement = "");
1384
1385
1386 inline void deprecate_option(App *app, const std::string &option_name, const std::string &replacement = "") {
1387 auto *opt = app->get_option(option_name);
1388 deprecate_option(opt, replacement);
1389 }
1390
1391
1392 inline void deprecate_option(App &app, const std::string &option_name, const std::string &replacement = "") {
1393 auto *opt = app.get_option(option_name);
1394 deprecate_option(opt, replacement);
1395 }
1396
1397
1398 CLI11_INLINE void retire_option(App *app, Option *opt);
1399
1400
1401 CLI11_INLINE void retire_option(App &app, Option *opt);
1402
1403
1404 CLI11_INLINE void retire_option(App *app, const std::string &option_name);
1405
1406
1407 CLI11_INLINE void retire_option(App &app, const std::string &option_name);
1408
1409 namespace detail {
1410
1411 struct AppFriend {
1412 #ifdef CLI11_CPP14
1413
1414
1415 template <typename... Args> static decltype(auto) parse_arg(App *app, Args &&...args) {
1416 return app->_parse_arg(std::forward<Args>(args)...);
1417 }
1418
1419
1420 template <typename... Args> static decltype(auto) parse_subcommand(App *app, Args &&...args) {
1421 return app->_parse_subcommand(std::forward<Args>(args)...);
1422 }
1423 #else
1424
1425 template <typename... Args>
1426 static auto parse_arg(App *app, Args &&...args) ->
1427 typename std::result_of<decltype (&App::_parse_arg)(App, Args...)>::type {
1428 return app->_parse_arg(std::forward<Args>(args)...);
1429 }
1430
1431
1432 template <typename... Args>
1433 static auto parse_subcommand(App *app, Args &&...args) ->
1434 typename std::result_of<decltype (&App::_parse_subcommand)(App, Args...)>::type {
1435 return app->_parse_subcommand(std::forward<Args>(args)...);
1436 }
1437 #endif
1438
1439 static App *get_fallthrough_parent(App *app) { return app->_get_fallthrough_parent(); }
1440 };
1441 }
1442
1443
1444 }
1445
1446 #ifndef CLI11_COMPILE
1447 #include "impl/App_inl.hpp" // IWYU pragma: export
1448 #endif