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