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