Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-09-28 07:02:17

0001 // Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
0002 // under NSF AWARD 1414736 and by the respective contributors.
0003 // All rights reserved.
0004 //
0005 // SPDX-License-Identifier: BSD-3-Clause
0006 
0007 #pragma once
0008 
0009 // [CLI11:public_includes:set]
0010 #include <algorithm>
0011 #include <cstdint>
0012 #include <functional>
0013 #include <iostream>
0014 #include <iterator>
0015 #include <memory>
0016 #include <numeric>
0017 #include <set>
0018 #include <sstream>
0019 #include <string>
0020 #include <utility>
0021 #include <vector>
0022 // [CLI11:public_includes:end]
0023 
0024 // CLI Library includes
0025 #include "ConfigFwd.hpp"
0026 #include "Error.hpp"
0027 #include "FormatterFwd.hpp"
0028 #include "Macros.hpp"
0029 #include "Option.hpp"
0030 #include "Split.hpp"
0031 #include "StringTools.hpp"
0032 #include "TypeTools.hpp"
0033 
0034 namespace CLI {
0035 // [CLI11:app_hpp:verbatim]
0036 
0037 #ifndef CLI11_PARSE
0038 #define CLI11_PARSE(app, argc, argv)                                                                                   \
0039     try {                                                                                                              \
0040         (app).parse((argc), (argv));                                                                                   \
0041     } catch(const CLI::ParseError &e) {                                                                                \
0042         return (app).exit(e);                                                                                          \
0043     }
0044 #endif
0045 
0046 namespace detail {
0047 enum class Classifier { NONE, POSITIONAL_MARK, SHORT, LONG, WINDOWS_STYLE, SUBCOMMAND, SUBCOMMAND_TERMINATOR };
0048 struct AppFriend;
0049 }  // namespace detail
0050 
0051 namespace FailureMessage {
0052 std::string simple(const App *app, const Error &e);
0053 std::string help(const App *app, const Error &e);
0054 }  // namespace FailureMessage
0055 
0056 /// enumeration of modes of how to deal with extras in config files
0057 
0058 enum class config_extras_mode : char { error = 0, ignore, capture };
0059 
0060 class App;
0061 
0062 using App_p = std::shared_ptr<App>;
0063 
0064 class Option_group;
0065 /// Creates a command line program, with very few defaults.
0066 /** To use, create a new `Program()` instance with `argc`, `argv`, and a help description. The templated
0067  *  add_option methods make it easy to prepare options. Remember to call `.start` before starting your
0068  * program, so that the options can be evaluated and the help option doesn't accidentally run your program. */
0069 class App {
0070     friend Option;
0071     friend detail::AppFriend;
0072 
0073   protected:
0074     // This library follows the Google style guide for member names ending in underscores
0075 
0076     /// @name Basics
0077     ///@{
0078 
0079     /// Subcommand name or program name (from parser if name is empty)
0080     std::string name_{};
0081 
0082     /// Description of the current program/subcommand
0083     std::string description_{};
0084 
0085     /// If true, allow extra arguments (ie, don't throw an error). INHERITABLE
0086     bool allow_extras_{false};
0087 
0088     /// If ignore, allow extra arguments in the ini file (ie, don't throw an error). INHERITABLE
0089     /// if error error on an extra argument, and if capture feed it to the app
0090     config_extras_mode allow_config_extras_{config_extras_mode::ignore};
0091 
0092     ///  If true, return immediately on an unrecognized option (implies allow_extras) INHERITABLE
0093     bool prefix_command_{false};
0094 
0095     /// If set to true the name was automatically generated from the command line vs a user set name
0096     bool has_automatic_name_{false};
0097 
0098     /// If set to true the subcommand is required to be processed and used, ignored for main app
0099     bool required_{false};
0100 
0101     /// If set to true the subcommand is disabled and cannot be used, ignored for main app
0102     bool disabled_{false};
0103 
0104     /// Flag indicating that the pre_parse_callback has been triggered
0105     bool pre_parse_called_{false};
0106 
0107     /// Flag indicating that the callback for the subcommand should be executed immediately on parse completion which is
0108     /// before help or ini files are processed. INHERITABLE
0109     bool immediate_callback_{false};
0110 
0111     /// This is a function that runs prior to the start of parsing
0112     std::function<void(std::size_t)> pre_parse_callback_{};
0113 
0114     /// This is a function that runs when parsing has finished.
0115     std::function<void()> parse_complete_callback_{};
0116 
0117     /// This is a function that runs when all processing has completed
0118     std::function<void()> final_callback_{};
0119 
0120     ///@}
0121     /// @name Options
0122     ///@{
0123 
0124     /// The default values for options, customizable and changeable INHERITABLE
0125     OptionDefaults option_defaults_{};
0126 
0127     /// The list of options, stored locally
0128     std::vector<Option_p> options_{};
0129 
0130     ///@}
0131     /// @name Help
0132     ///@{
0133 
0134     /// Footer to put after all options in the help output INHERITABLE
0135     std::string footer_{};
0136 
0137     /// This is a function that generates a footer to put after all other options in help output
0138     std::function<std::string()> footer_callback_{};
0139 
0140     /// A pointer to the help flag if there is one INHERITABLE
0141     Option *help_ptr_{nullptr};
0142 
0143     /// A pointer to the help all flag if there is one INHERITABLE
0144     Option *help_all_ptr_{nullptr};
0145 
0146     /// A pointer to a version flag if there is one
0147     Option *version_ptr_{nullptr};
0148 
0149     /// This is the formatter for help printing. Default provided. INHERITABLE (same pointer)
0150     std::shared_ptr<FormatterBase> formatter_{new Formatter()};
0151 
0152     /// The error message printing function INHERITABLE
0153     std::function<std::string(const App *, const Error &e)> failure_message_{FailureMessage::simple};
0154 
0155     ///@}
0156     /// @name Parsing
0157     ///@{
0158 
0159     using missing_t = std::vector<std::pair<detail::Classifier, std::string>>;
0160 
0161     /// Pair of classifier, string for missing options. (extra detail is removed on returning from parse)
0162     ///
0163     /// This is faster and cleaner than storing just a list of strings and reparsing. This may contain the -- separator.
0164     missing_t missing_{};
0165 
0166     /// This is a list of pointers to options with the original parse order
0167     std::vector<Option *> parse_order_{};
0168 
0169     /// This is a list of the subcommands collected, in order
0170     std::vector<App *> parsed_subcommands_{};
0171 
0172     /// this is a list of subcommands that are exclusionary to this one
0173     std::set<App *> exclude_subcommands_{};
0174 
0175     /// This is a list of options which are exclusionary to this App, if the options were used this subcommand should
0176     /// not be
0177     std::set<Option *> exclude_options_{};
0178 
0179     /// this is a list of subcommands or option groups that are required by this one, the list is not mutual,  the
0180     /// listed subcommands do not require this one
0181     std::set<App *> need_subcommands_{};
0182 
0183     /// This is a list of options which are required by this app, the list is not mutual, listed options do not need the
0184     /// subcommand not be
0185     std::set<Option *> need_options_{};
0186 
0187     ///@}
0188     /// @name Subcommands
0189     ///@{
0190 
0191     /// Storage for subcommand list
0192     std::vector<App_p> subcommands_{};
0193 
0194     /// If true, the program name is not case sensitive INHERITABLE
0195     bool ignore_case_{false};
0196 
0197     /// If true, the program should ignore underscores INHERITABLE
0198     bool ignore_underscore_{false};
0199 
0200     /// Allow subcommand fallthrough, so that parent commands can collect commands after subcommand.  INHERITABLE
0201     bool fallthrough_{false};
0202 
0203     /// Allow '/' for options for Windows like options. Defaults to true on Windows, false otherwise. INHERITABLE
0204     bool allow_windows_style_options_{
0205 #ifdef _WIN32
0206         true
0207 #else
0208         false
0209 #endif
0210     };
0211     /// specify that positional arguments come at the end of the argument sequence not inheritable
0212     bool positionals_at_end_{false};
0213 
0214     enum class startup_mode : char { stable, enabled, disabled };
0215     /// specify the startup mode for the app
0216     /// stable=no change, enabled= startup enabled, disabled=startup disabled
0217     startup_mode default_startup{startup_mode::stable};
0218 
0219     /// if set to true the subcommand can be triggered via configuration files INHERITABLE
0220     bool configurable_{false};
0221 
0222     /// If set to true positional options are validated before assigning INHERITABLE
0223     bool validate_positionals_{false};
0224 
0225     /// indicator that the subcommand is silent and won't show up in subcommands list
0226     /// This is potentially useful as a modifier subcommand
0227     bool silent_{false};
0228 
0229     /// Counts the number of times this command/subcommand was parsed
0230     std::uint32_t parsed_{0U};
0231 
0232     /// Minimum required subcommands (not inheritable!)
0233     std::size_t require_subcommand_min_{0};
0234 
0235     /// Max number of subcommands allowed (parsing stops after this number). 0 is unlimited INHERITABLE
0236     std::size_t require_subcommand_max_{0};
0237 
0238     /// Minimum required options (not inheritable!)
0239     std::size_t require_option_min_{0};
0240 
0241     /// Max number of options allowed. 0 is unlimited (not inheritable)
0242     std::size_t require_option_max_{0};
0243 
0244     /// A pointer to the parent if this is a subcommand
0245     App *parent_{nullptr};
0246 
0247     /// The group membership INHERITABLE
0248     std::string group_{"Subcommands"};
0249 
0250     /// Alias names for the subcommand
0251     std::vector<std::string> aliases_{};
0252 
0253     ///@}
0254     /// @name Config
0255     ///@{
0256 
0257     /// Pointer to the config option
0258     Option *config_ptr_{nullptr};
0259 
0260     /// This is the formatter for help printing. Default provided. INHERITABLE (same pointer)
0261     std::shared_ptr<Config> config_formatter_{new ConfigTOML()};
0262 
0263     ///@}
0264 
0265     /// Special private constructor for subcommand
0266     App(std::string app_description, std::string app_name, App *parent)
0267         : name_(std::move(app_name)), description_(std::move(app_description)), parent_(parent) {
0268         // Inherit if not from a nullptr
0269         if(parent_ != nullptr) {
0270             if(parent_->help_ptr_ != nullptr)
0271                 set_help_flag(parent_->help_ptr_->get_name(false, true), parent_->help_ptr_->get_description());
0272             if(parent_->help_all_ptr_ != nullptr)
0273                 set_help_all_flag(parent_->help_all_ptr_->get_name(false, true),
0274                                   parent_->help_all_ptr_->get_description());
0275 
0276             /// OptionDefaults
0277             option_defaults_ = parent_->option_defaults_;
0278 
0279             // INHERITABLE
0280             failure_message_ = parent_->failure_message_;
0281             allow_extras_ = parent_->allow_extras_;
0282             allow_config_extras_ = parent_->allow_config_extras_;
0283             prefix_command_ = parent_->prefix_command_;
0284             immediate_callback_ = parent_->immediate_callback_;
0285             ignore_case_ = parent_->ignore_case_;
0286             ignore_underscore_ = parent_->ignore_underscore_;
0287             fallthrough_ = parent_->fallthrough_;
0288             validate_positionals_ = parent_->validate_positionals_;
0289             configurable_ = parent_->configurable_;
0290             allow_windows_style_options_ = parent_->allow_windows_style_options_;
0291             group_ = parent_->group_;
0292             footer_ = parent_->footer_;
0293             formatter_ = parent_->formatter_;
0294             config_formatter_ = parent_->config_formatter_;
0295             require_subcommand_max_ = parent_->require_subcommand_max_;
0296         }
0297     }
0298 
0299   public:
0300     /// @name Basic
0301     ///@{
0302 
0303     /// Create a new program. Pass in the same arguments as main(), along with a help string.
0304     explicit App(std::string app_description = "", std::string app_name = "")
0305         : App(app_description, app_name, nullptr) {
0306         set_help_flag("-h,--help", "Print this help message and exit");
0307     }
0308 
0309     App(const App &) = delete;
0310     App &operator=(const App &) = delete;
0311 
0312     /// virtual destructor
0313     virtual ~App() = default;
0314 
0315     /// Set a callback for execution when all parsing and processing has completed
0316     ///
0317     /// Due to a bug in c++11,
0318     /// it is not possible to overload on std::function (fixed in c++14
0319     /// and backported to c++11 on newer compilers). Use capture by reference
0320     /// to get a pointer to App if needed.
0321     App *callback(std::function<void()> app_callback) {
0322         if(immediate_callback_) {
0323             parse_complete_callback_ = std::move(app_callback);
0324         } else {
0325             final_callback_ = std::move(app_callback);
0326         }
0327         return this;
0328     }
0329 
0330     /// Set a callback for execution when all parsing and processing has completed
0331     /// aliased as callback
0332     App *final_callback(std::function<void()> app_callback) {
0333         final_callback_ = std::move(app_callback);
0334         return this;
0335     }
0336 
0337     /// Set a callback to execute when parsing has completed for the app
0338     ///
0339     App *parse_complete_callback(std::function<void()> pc_callback) {
0340         parse_complete_callback_ = std::move(pc_callback);
0341         return this;
0342     }
0343 
0344     /// Set a callback to execute prior to parsing.
0345     ///
0346     App *preparse_callback(std::function<void(std::size_t)> pp_callback) {
0347         pre_parse_callback_ = std::move(pp_callback);
0348         return this;
0349     }
0350 
0351     /// Set a name for the app (empty will use parser to set the name)
0352     App *name(std::string app_name = "") {
0353 
0354         if(parent_ != nullptr) {
0355             auto oname = name_;
0356             name_ = app_name;
0357             auto &res = _compare_subcommand_names(*this, *_get_fallthrough_parent());
0358             if(!res.empty()) {
0359                 name_ = oname;
0360                 throw(OptionAlreadyAdded(app_name + " conflicts with existing subcommand names"));
0361             }
0362         } else {
0363             name_ = app_name;
0364         }
0365         has_automatic_name_ = false;
0366         return this;
0367     }
0368 
0369     /// Set an alias for the app
0370     App *alias(std::string app_name) {
0371         if(!detail::valid_name_string(app_name)) {
0372             if(app_name.empty()) {
0373                 throw IncorrectConstruction("Empty aliases are not allowed");
0374             }
0375             if(!detail::valid_first_char(app_name[0])) {
0376                 throw IncorrectConstruction(
0377                     "Alias starts with invalid character, allowed characters are [a-zA-z0-9]+'_','?','@' ");
0378             }
0379             for(auto c : app_name) {
0380                 if(!detail::valid_later_char(c)) {
0381                     throw IncorrectConstruction(std::string("Alias contains invalid character ('") + c +
0382                                                 "'), allowed characters are "
0383                                                 "[a-zA-z0-9]+'_','?','@','.','-' ");
0384                 }
0385             }
0386         }
0387 
0388         if(parent_ != nullptr) {
0389             aliases_.push_back(app_name);
0390             auto &res = _compare_subcommand_names(*this, *_get_fallthrough_parent());
0391             if(!res.empty()) {
0392                 aliases_.pop_back();
0393                 throw(OptionAlreadyAdded("alias already matches an existing subcommand: " + app_name));
0394             }
0395         } else {
0396             aliases_.push_back(app_name);
0397         }
0398 
0399         return this;
0400     }
0401 
0402     /// Remove the error when extras are left over on the command line.
0403     App *allow_extras(bool allow = true) {
0404         allow_extras_ = allow;
0405         return this;
0406     }
0407 
0408     /// Remove the error when extras are left over on the command line.
0409     App *required(bool require = true) {
0410         required_ = require;
0411         return this;
0412     }
0413 
0414     /// Disable the subcommand or option group
0415     App *disabled(bool disable = true) {
0416         disabled_ = disable;
0417         return this;
0418     }
0419 
0420     /// silence the subcommand from showing up in the processed list
0421     App *silent(bool silence = true) {
0422         silent_ = silence;
0423         return this;
0424     }
0425 
0426     /// Set the subcommand to be disabled by default, so on clear(), at the start of each parse it is disabled
0427     App *disabled_by_default(bool disable = true) {
0428         if(disable) {
0429             default_startup = startup_mode::disabled;
0430         } else {
0431             default_startup = (default_startup == startup_mode::enabled) ? startup_mode::enabled : startup_mode::stable;
0432         }
0433         return this;
0434     }
0435 
0436     /// Set the subcommand to be enabled by default, so on clear(), at the start of each parse it is enabled (not
0437     /// disabled)
0438     App *enabled_by_default(bool enable = true) {
0439         if(enable) {
0440             default_startup = startup_mode::enabled;
0441         } else {
0442             default_startup =
0443                 (default_startup == startup_mode::disabled) ? startup_mode::disabled : startup_mode::stable;
0444         }
0445         return this;
0446     }
0447 
0448     /// Set the subcommand callback to be executed immediately on subcommand completion
0449     App *immediate_callback(bool immediate = true) {
0450         immediate_callback_ = immediate;
0451         if(immediate_callback_) {
0452             if(final_callback_ && !(parse_complete_callback_)) {
0453                 std::swap(final_callback_, parse_complete_callback_);
0454             }
0455         } else if(!(final_callback_) && parse_complete_callback_) {
0456             std::swap(final_callback_, parse_complete_callback_);
0457         }
0458         return this;
0459     }
0460 
0461     /// Set the subcommand to validate positional arguments before assigning
0462     App *validate_positionals(bool validate = true) {
0463         validate_positionals_ = validate;
0464         return this;
0465     }
0466 
0467     /// ignore extras in config files
0468     App *allow_config_extras(bool allow = true) {
0469         if(allow) {
0470             allow_config_extras_ = config_extras_mode::capture;
0471             allow_extras_ = true;
0472         } else {
0473             allow_config_extras_ = config_extras_mode::error;
0474         }
0475         return this;
0476     }
0477 
0478     /// ignore extras in config files
0479     App *allow_config_extras(config_extras_mode mode) {
0480         allow_config_extras_ = mode;
0481         return this;
0482     }
0483 
0484     /// Do not parse anything after the first unrecognized option and return
0485     App *prefix_command(bool allow = true) {
0486         prefix_command_ = allow;
0487         return this;
0488     }
0489 
0490     /// Ignore case. Subcommands inherit value.
0491     App *ignore_case(bool value = true) {
0492         if(value && !ignore_case_) {
0493             ignore_case_ = true;
0494             auto *p = (parent_ != nullptr) ? _get_fallthrough_parent() : this;
0495             auto &match = _compare_subcommand_names(*this, *p);
0496             if(!match.empty()) {
0497                 ignore_case_ = false;  // we are throwing so need to be exception invariant
0498                 throw OptionAlreadyAdded("ignore case would cause subcommand name conflicts: " + match);
0499             }
0500         }
0501         ignore_case_ = value;
0502         return this;
0503     }
0504 
0505     /// Allow windows style options, such as `/opt`. First matching short or long name used. Subcommands inherit
0506     /// value.
0507     App *allow_windows_style_options(bool value = true) {
0508         allow_windows_style_options_ = value;
0509         return this;
0510     }
0511 
0512     /// Specify that the positional arguments are only at the end of the sequence
0513     App *positionals_at_end(bool value = true) {
0514         positionals_at_end_ = value;
0515         return this;
0516     }
0517 
0518     /// Specify that the subcommand can be triggered by a config file
0519     App *configurable(bool value = true) {
0520         configurable_ = value;
0521         return this;
0522     }
0523 
0524     /// Ignore underscore. Subcommands inherit value.
0525     App *ignore_underscore(bool value = true) {
0526         if(value && !ignore_underscore_) {
0527             ignore_underscore_ = true;
0528             auto *p = (parent_ != nullptr) ? _get_fallthrough_parent() : this;
0529             auto &match = _compare_subcommand_names(*this, *p);
0530             if(!match.empty()) {
0531                 ignore_underscore_ = false;
0532                 throw OptionAlreadyAdded("ignore underscore would cause subcommand name conflicts: " + match);
0533             }
0534         }
0535         ignore_underscore_ = value;
0536         return this;
0537     }
0538 
0539     /// Set the help formatter
0540     App *formatter(std::shared_ptr<FormatterBase> fmt) {
0541         formatter_ = fmt;
0542         return this;
0543     }
0544 
0545     /// Set the help formatter
0546     App *formatter_fn(std::function<std::string(const App *, std::string, AppFormatMode)> fmt) {
0547         formatter_ = std::make_shared<FormatterLambda>(fmt);
0548         return this;
0549     }
0550 
0551     /// Set the config formatter
0552     App *config_formatter(std::shared_ptr<Config> fmt) {
0553         config_formatter_ = fmt;
0554         return this;
0555     }
0556 
0557     /// Check to see if this subcommand was parsed, true only if received on command line.
0558     bool parsed() const { return parsed_ > 0; }
0559 
0560     /// Get the OptionDefault object, to set option defaults
0561     OptionDefaults *option_defaults() { return &option_defaults_; }
0562 
0563     ///@}
0564     /// @name Adding options
0565     ///@{
0566 
0567     /// Add an option, will automatically understand the type for common types.
0568     ///
0569     /// To use, create a variable with the expected type, and pass it in after the name.
0570     /// After start is called, you can use count to see if the value was passed, and
0571     /// the value will be initialized properly. Numbers, vectors, and strings are supported.
0572     ///
0573     /// ->required(), ->default, and the validators are options,
0574     /// The positional options take an optional number of arguments.
0575     ///
0576     /// For example,
0577     ///
0578     ///     std::string filename;
0579     ///     program.add_option("filename", filename, "description of filename");
0580     ///
0581     Option *add_option(std::string option_name,
0582                        callback_t option_callback,
0583                        std::string option_description = "",
0584                        bool defaulted = false,
0585                        std::function<std::string()> func = {}) {
0586         Option myopt{option_name, option_description, option_callback, this};
0587 
0588         if(std::find_if(std::begin(options_), std::end(options_), [&myopt](const Option_p &v) {
0589                return *v == myopt;
0590            }) == std::end(options_)) {
0591             options_.emplace_back();
0592             Option_p &option = options_.back();
0593             option.reset(new Option(option_name, option_description, option_callback, this));
0594 
0595             // Set the default string capture function
0596             option->default_function(func);
0597 
0598             // For compatibility with CLI11 1.7 and before, capture the default string here
0599             if(defaulted)
0600                 option->capture_default_str();
0601 
0602             // Transfer defaults to the new option
0603             option_defaults_.copy_to(option.get());
0604 
0605             // Don't bother to capture if we already did
0606             if(!defaulted && option->get_always_capture_default())
0607                 option->capture_default_str();
0608 
0609             return option.get();
0610         }
0611         // we know something matches now find what it is so we can produce more error information
0612         for(auto &opt : options_) {
0613             auto &matchname = opt->matching_name(myopt);
0614             if(!matchname.empty()) {
0615                 throw(OptionAlreadyAdded("added option matched existing option name: " + matchname));
0616             }
0617         }
0618         // this line should not be reached the above loop should trigger the throw
0619         throw(OptionAlreadyAdded("added option matched existing option name"));  // LCOV_EXCL_LINE
0620     }
0621 
0622     /// Add option for assigning to a variable
0623     template <typename AssignTo,
0624               typename ConvertTo = AssignTo,
0625               enable_if_t<!std::is_const<ConvertTo>::value, detail::enabler> = detail::dummy>
0626     Option *add_option(std::string option_name,
0627                        AssignTo &variable,  ///< The variable to set
0628                        std::string option_description = "") {
0629 
0630         auto fun = [&variable](const CLI::results_t &res) {  // comment for spacing
0631             return detail::lexical_conversion<AssignTo, ConvertTo>(res, variable);
0632         };
0633 
0634         Option *opt = add_option(option_name, fun, option_description, false, [&variable]() {
0635             return CLI::detail::checked_to_string<AssignTo, ConvertTo>(variable);
0636         });
0637         opt->type_name(detail::type_name<ConvertTo>());
0638         // these must be actual lvalues since (std::max) sometimes is defined in terms of references and references
0639         // to structs used in the evaluation can be temporary so that would cause issues.
0640         auto Tcount = detail::type_count<AssignTo>::value;
0641         auto XCcount = detail::type_count<ConvertTo>::value;
0642         opt->type_size(detail::type_count_min<ConvertTo>::value, (std::max)(Tcount, XCcount));
0643         opt->expected(detail::expected_count<ConvertTo>::value);
0644         opt->run_callback_for_default();
0645         return opt;
0646     }
0647 
0648     /// Add option for assigning to a variable
0649     template <typename AssignTo, enable_if_t<!std::is_const<AssignTo>::value, detail::enabler> = detail::dummy>
0650     Option *add_option_no_stream(std::string option_name,
0651                                  AssignTo &variable,  ///< The variable to set
0652                                  std::string option_description = "") {
0653 
0654         auto fun = [&variable](const CLI::results_t &res) {  // comment for spacing
0655             return detail::lexical_conversion<AssignTo, AssignTo>(res, variable);
0656         };
0657 
0658         Option *opt = add_option(option_name, fun, option_description, false, []() { return std::string{}; });
0659         opt->type_name(detail::type_name<AssignTo>());
0660         opt->type_size(detail::type_count_min<AssignTo>::value, detail::type_count<AssignTo>::value);
0661         opt->expected(detail::expected_count<AssignTo>::value);
0662         opt->run_callback_for_default();
0663         return opt;
0664     }
0665 
0666     /// Add option for a callback of a specific type
0667     template <typename ArgType>
0668     Option *add_option_function(std::string option_name,
0669                                 const std::function<void(const ArgType &)> &func,  ///< the callback to execute
0670                                 std::string option_description = "") {
0671 
0672         auto fun = [func](const CLI::results_t &res) {
0673             ArgType variable;
0674             bool result = detail::lexical_conversion<ArgType, ArgType>(res, variable);
0675             if(result) {
0676                 func(variable);
0677             }
0678             return result;
0679         };
0680 
0681         Option *opt = add_option(option_name, std::move(fun), option_description, false);
0682         opt->type_name(detail::type_name<ArgType>());
0683         opt->type_size(detail::type_count_min<ArgType>::value, detail::type_count<ArgType>::value);
0684         opt->expected(detail::expected_count<ArgType>::value);
0685         return opt;
0686     }
0687 
0688     /// Add option with no description or variable assignment
0689     Option *add_option(std::string option_name) {
0690         return add_option(option_name, CLI::callback_t{}, std::string{}, false);
0691     }
0692 
0693     /// Add option with description but with no variable assignment or callback
0694     template <typename T,
0695               enable_if_t<std::is_const<T>::value && std::is_constructible<std::string, T>::value, detail::enabler> =
0696                   detail::dummy>
0697     Option *add_option(std::string option_name, T &option_description) {
0698         return add_option(option_name, CLI::callback_t(), option_description, false);
0699     }
0700 
0701     /// Set a help flag, replace the existing one if present
0702     Option *set_help_flag(std::string flag_name = "", const std::string &help_description = "") {
0703         // take flag_description by const reference otherwise add_flag tries to assign to help_description
0704         if(help_ptr_ != nullptr) {
0705             remove_option(help_ptr_);
0706             help_ptr_ = nullptr;
0707         }
0708 
0709         // Empty name will simply remove the help flag
0710         if(!flag_name.empty()) {
0711             help_ptr_ = add_flag(flag_name, help_description);
0712             help_ptr_->configurable(false);
0713         }
0714 
0715         return help_ptr_;
0716     }
0717 
0718     /// Set a help all flag, replaced the existing one if present
0719     Option *set_help_all_flag(std::string help_name = "", const std::string &help_description = "") {
0720         // take flag_description by const reference otherwise add_flag tries to assign to flag_description
0721         if(help_all_ptr_ != nullptr) {
0722             remove_option(help_all_ptr_);
0723             help_all_ptr_ = nullptr;
0724         }
0725 
0726         // Empty name will simply remove the help all flag
0727         if(!help_name.empty()) {
0728             help_all_ptr_ = add_flag(help_name, help_description);
0729             help_all_ptr_->configurable(false);
0730         }
0731 
0732         return help_all_ptr_;
0733     }
0734 
0735     /// Set a version flag and version display string, replace the existing one if present
0736     Option *set_version_flag(std::string flag_name = "",
0737                              const std::string &versionString = "",
0738                              const std::string &version_help = "Display program version information and exit") {
0739         // take flag_description by const reference otherwise add_flag tries to assign to version_description
0740         if(version_ptr_ != nullptr) {
0741             remove_option(version_ptr_);
0742             version_ptr_ = nullptr;
0743         }
0744 
0745         // Empty name will simply remove the version flag
0746         if(!flag_name.empty()) {
0747             version_ptr_ = add_flag_callback(
0748                 flag_name, [versionString]() { throw(CLI::CallForVersion(versionString, 0)); }, version_help);
0749             version_ptr_->configurable(false);
0750         }
0751 
0752         return version_ptr_;
0753     }
0754     /// Generate the version string through a callback function
0755     Option *set_version_flag(std::string flag_name,
0756                              std::function<std::string()> vfunc,
0757                              const std::string &version_help = "Display program version information and exit") {
0758         if(version_ptr_ != nullptr) {
0759             remove_option(version_ptr_);
0760             version_ptr_ = nullptr;
0761         }
0762 
0763         // Empty name will simply remove the version flag
0764         if(!flag_name.empty()) {
0765             version_ptr_ = add_flag_callback(
0766                 flag_name, [vfunc]() { throw(CLI::CallForVersion(vfunc(), 0)); }, version_help);
0767             version_ptr_->configurable(false);
0768         }
0769 
0770         return version_ptr_;
0771     }
0772 
0773   private:
0774     /// Internal function for adding a flag
0775     Option *_add_flag_internal(std::string flag_name, CLI::callback_t fun, std::string flag_description) {
0776         Option *opt;
0777         if(detail::has_default_flag_values(flag_name)) {
0778             // check for default values and if it has them
0779             auto flag_defaults = detail::get_default_flag_values(flag_name);
0780             detail::remove_default_flag_values(flag_name);
0781             opt = add_option(std::move(flag_name), std::move(fun), std::move(flag_description), false);
0782             for(const auto &fname : flag_defaults)
0783                 opt->fnames_.push_back(fname.first);
0784             opt->default_flag_values_ = std::move(flag_defaults);
0785         } else {
0786             opt = add_option(std::move(flag_name), std::move(fun), std::move(flag_description), false);
0787         }
0788         // flags cannot have positional values
0789         if(opt->get_positional()) {
0790             auto pos_name = opt->get_name(true);
0791             remove_option(opt);
0792             throw IncorrectConstruction::PositionalFlag(pos_name);
0793         }
0794         opt->multi_option_policy(MultiOptionPolicy::TakeLast);
0795         opt->expected(0);
0796         opt->required(false);
0797         return opt;
0798     }
0799 
0800   public:
0801     /// Add a flag with no description or variable assignment
0802     Option *add_flag(std::string flag_name) { return _add_flag_internal(flag_name, CLI::callback_t(), std::string{}); }
0803 
0804     /// Add flag with description but with no variable assignment or callback
0805     /// takes a constant string,  if a variable string is passed that variable will be assigned the results from the
0806     /// flag
0807     template <typename T,
0808               enable_if_t<std::is_const<T>::value && std::is_constructible<std::string, T>::value, detail::enabler> =
0809                   detail::dummy>
0810     Option *add_flag(std::string flag_name, T &flag_description) {
0811         return _add_flag_internal(flag_name, CLI::callback_t(), flag_description);
0812     }
0813 
0814     /// Add option for flag with integer result - defaults to allowing multiple passings, but can be forced to one
0815     /// if `multi_option_policy(CLI::MultiOptionPolicy::Throw)` is used.
0816     template <typename T,
0817               enable_if_t<std::is_constructible<T, std::int64_t>::value && !is_bool<T>::value, detail::enabler> =
0818                   detail::dummy>
0819     Option *add_flag(std::string flag_name,
0820                      T &flag_count,  ///< A variable holding the count
0821                      std::string flag_description = "") {
0822         flag_count = 0;
0823         CLI::callback_t fun = [&flag_count](const CLI::results_t &res) {
0824             try {
0825                 detail::sum_flag_vector(res, flag_count);
0826             } catch(const std::invalid_argument &) {
0827                 return false;
0828             }
0829             return true;
0830         };
0831         return _add_flag_internal(flag_name, std::move(fun), std::move(flag_description))
0832             ->multi_option_policy(MultiOptionPolicy::TakeAll);
0833     }
0834 
0835     /// Other type version accepts all other types that are not vectors such as bool, enum, string or other classes
0836     /// that can be converted from a string
0837     template <typename T,
0838               enable_if_t<!detail::is_mutable_container<T>::value && !std::is_const<T>::value &&
0839                               (!std::is_constructible<T, std::int64_t>::value || is_bool<T>::value) &&
0840                               !std::is_constructible<std::function<void(int)>, T>::value,
0841                           detail::enabler> = detail::dummy>
0842     Option *add_flag(std::string flag_name,
0843                      T &flag_result,  ///< A variable holding true if passed
0844                      std::string flag_description = "") {
0845 
0846         CLI::callback_t fun = [&flag_result](const CLI::results_t &res) {
0847             return CLI::detail::lexical_cast(res[0], flag_result);
0848         };
0849         return _add_flag_internal(flag_name, std::move(fun), std::move(flag_description))->run_callback_for_default();
0850     }
0851 
0852     /// Vector version to capture multiple flags.
0853     template <typename T,
0854               enable_if_t<!std::is_assignable<std::function<void(std::int64_t)> &, T>::value, detail::enabler> =
0855                   detail::dummy>
0856     Option *add_flag(std::string flag_name,
0857                      std::vector<T> &flag_results,  ///< A vector of values with the flag results
0858                      std::string flag_description = "") {
0859         CLI::callback_t fun = [&flag_results](const CLI::results_t &res) {
0860             bool retval = true;
0861             for(const auto &elem : res) {
0862                 flag_results.emplace_back();
0863                 retval &= detail::lexical_cast(elem, flag_results.back());
0864             }
0865             return retval;
0866         };
0867         return _add_flag_internal(flag_name, std::move(fun), std::move(flag_description))
0868             ->multi_option_policy(MultiOptionPolicy::TakeAll)
0869             ->run_callback_for_default();
0870     }
0871 
0872     /// Add option for callback that is triggered with a true flag and takes no arguments
0873     Option *add_flag_callback(std::string flag_name,
0874                               std::function<void(void)> function,  ///< A function to call, void(void)
0875                               std::string flag_description = "") {
0876 
0877         CLI::callback_t fun = [function](const CLI::results_t &res) {
0878             bool trigger{false};
0879             auto result = CLI::detail::lexical_cast(res[0], trigger);
0880             if(result && trigger) {
0881                 function();
0882             }
0883             return result;
0884         };
0885         return _add_flag_internal(flag_name, std::move(fun), std::move(flag_description));
0886     }
0887 
0888     /// Add option for callback with an integer value
0889     Option *add_flag_function(std::string flag_name,
0890                               std::function<void(std::int64_t)> function,  ///< A function to call, void(int)
0891                               std::string flag_description = "") {
0892 
0893         CLI::callback_t fun = [function](const CLI::results_t &res) {
0894             std::int64_t flag_count = 0;
0895             detail::sum_flag_vector(res, flag_count);
0896             function(flag_count);
0897             return true;
0898         };
0899         return _add_flag_internal(flag_name, std::move(fun), std::move(flag_description))
0900             ->multi_option_policy(MultiOptionPolicy::TakeAll);
0901     }
0902 
0903 #ifdef CLI11_CPP14
0904     /// Add option for callback (C++14 or better only)
0905     Option *add_flag(std::string flag_name,
0906                      std::function<void(std::int64_t)> function,  ///< A function to call, void(std::int64_t)
0907                      std::string flag_description = "") {
0908         return add_flag_function(std::move(flag_name), std::move(function), std::move(flag_description));
0909     }
0910 #endif
0911 
0912     /// Set a configuration ini file option, or clear it if no name passed
0913     Option *set_config(std::string option_name = "",
0914                        std::string default_filename = "",
0915                        const std::string &help_message = "Read an ini file",
0916                        bool config_required = false) {
0917 
0918         // Remove existing config if present
0919         if(config_ptr_ != nullptr) {
0920             remove_option(config_ptr_);
0921             config_ptr_ = nullptr;  // need to remove the config_ptr completely
0922         }
0923 
0924         // Only add config if option passed
0925         if(!option_name.empty()) {
0926             config_ptr_ = add_option(option_name, help_message);
0927             if(config_required) {
0928                 config_ptr_->required();
0929             }
0930             if(!default_filename.empty()) {
0931                 config_ptr_->default_str(std::move(default_filename));
0932             }
0933             config_ptr_->configurable(false);
0934         }
0935 
0936         return config_ptr_;
0937     }
0938 
0939     /// Removes an option from the App. Takes an option pointer. Returns true if found and removed.
0940     bool remove_option(Option *opt) {
0941         // Make sure no links exist
0942         for(Option_p &op : options_) {
0943             op->remove_needs(opt);
0944             op->remove_excludes(opt);
0945         }
0946 
0947         if(help_ptr_ == opt)
0948             help_ptr_ = nullptr;
0949         if(help_all_ptr_ == opt)
0950             help_all_ptr_ = nullptr;
0951 
0952         auto iterator =
0953             std::find_if(std::begin(options_), std::end(options_), [opt](const Option_p &v) { return v.get() == opt; });
0954         if(iterator != std::end(options_)) {
0955             options_.erase(iterator);
0956             return true;
0957         }
0958         return false;
0959     }
0960 
0961     /// creates an option group as part of the given app
0962     template <typename T = Option_group>
0963     T *add_option_group(std::string group_name, std::string group_description = "") {
0964         auto option_group = std::make_shared<T>(std::move(group_description), group_name, this);
0965         auto ptr = option_group.get();
0966         // move to App_p for overload resolution on older gcc versions
0967         App_p app_ptr = std::dynamic_pointer_cast<App>(option_group);
0968         add_subcommand(std::move(app_ptr));
0969         return ptr;
0970     }
0971 
0972     ///@}
0973     /// @name Subcommands
0974     ///@{
0975 
0976     /// Add a subcommand. Inherits INHERITABLE and OptionDefaults, and help flag
0977     App *add_subcommand(std::string subcommand_name = "", std::string subcommand_description = "") {
0978         if(!subcommand_name.empty() && !detail::valid_name_string(subcommand_name)) {
0979             if(!detail::valid_first_char(subcommand_name[0])) {
0980                 throw IncorrectConstruction(
0981                     "Subcommand name starts with invalid character, allowed characters are [a-zA-z0-9]+'_','?','@' ");
0982             }
0983             for(auto c : subcommand_name) {
0984                 if(!detail::valid_later_char(c)) {
0985                     throw IncorrectConstruction(std::string("Subcommand name contains invalid character ('") + c +
0986                                                 "'), allowed characters are "
0987                                                 "[a-zA-z0-9]+'_','?','@','.','-' ");
0988                 }
0989             }
0990         }
0991         CLI::App_p subcom = std::shared_ptr<App>(new App(std::move(subcommand_description), subcommand_name, this));
0992         return add_subcommand(std::move(subcom));
0993     }
0994 
0995     /// Add a previously created app as a subcommand
0996     App *add_subcommand(CLI::App_p subcom) {
0997         if(!subcom)
0998             throw IncorrectConstruction("passed App is not valid");
0999         auto ckapp = (name_.empty() && parent_ != nullptr) ? _get_fallthrough_parent() : this;
1000         auto &mstrg = _compare_subcommand_names(*subcom, *ckapp);
1001         if(!mstrg.empty()) {
1002             throw(OptionAlreadyAdded("subcommand name or alias matches existing subcommand: " + mstrg));
1003         }
1004         subcom->parent_ = this;
1005         subcommands_.push_back(std::move(subcom));
1006         return subcommands_.back().get();
1007     }
1008 
1009     /// Removes a subcommand from the App. Takes a subcommand pointer. Returns true if found and removed.
1010     bool remove_subcommand(App *subcom) {
1011         // Make sure no links exist
1012         for(App_p &sub : subcommands_) {
1013             sub->remove_excludes(subcom);
1014             sub->remove_needs(subcom);
1015         }
1016 
1017         auto iterator = std::find_if(
1018             std::begin(subcommands_), std::end(subcommands_), [subcom](const App_p &v) { return v.get() == subcom; });
1019         if(iterator != std::end(subcommands_)) {
1020             subcommands_.erase(iterator);
1021             return true;
1022         }
1023         return false;
1024     }
1025     /// Check to see if a subcommand is part of this command (doesn't have to be in command line)
1026     /// returns the first subcommand if passed a nullptr
1027     App *get_subcommand(const App *subcom) const {
1028         if(subcom == nullptr)
1029             throw OptionNotFound("nullptr passed");
1030         for(const App_p &subcomptr : subcommands_)
1031             if(subcomptr.get() == subcom)
1032                 return subcomptr.get();
1033         throw OptionNotFound(subcom->get_name());
1034     }
1035 
1036     /// Check to see if a subcommand is part of this command (text version)
1037     App *get_subcommand(std::string subcom) const {
1038         auto subc = _find_subcommand(subcom, false, false);
1039         if(subc == nullptr)
1040             throw OptionNotFound(subcom);
1041         return subc;
1042     }
1043     /// Get a pointer to subcommand by index
1044     App *get_subcommand(int index = 0) const {
1045         if(index >= 0) {
1046             auto uindex = static_cast<unsigned>(index);
1047             if(uindex < subcommands_.size())
1048                 return subcommands_[uindex].get();
1049         }
1050         throw OptionNotFound(std::to_string(index));
1051     }
1052 
1053     /// Check to see if a subcommand is part of this command and get a shared_ptr to it
1054     CLI::App_p get_subcommand_ptr(App *subcom) const {
1055         if(subcom == nullptr)
1056             throw OptionNotFound("nullptr passed");
1057         for(const App_p &subcomptr : subcommands_)
1058             if(subcomptr.get() == subcom)
1059                 return subcomptr;
1060         throw OptionNotFound(subcom->get_name());
1061     }
1062 
1063     /// Check to see if a subcommand is part of this command (text version)
1064     CLI::App_p get_subcommand_ptr(std::string subcom) const {
1065         for(const App_p &subcomptr : subcommands_)
1066             if(subcomptr->check_name(subcom))
1067                 return subcomptr;
1068         throw OptionNotFound(subcom);
1069     }
1070 
1071     /// Get an owning pointer to subcommand by index
1072     CLI::App_p get_subcommand_ptr(int index = 0) const {
1073         if(index >= 0) {
1074             auto uindex = static_cast<unsigned>(index);
1075             if(uindex < subcommands_.size())
1076                 return subcommands_[uindex];
1077         }
1078         throw OptionNotFound(std::to_string(index));
1079     }
1080 
1081     /// Check to see if an option group is part of this App
1082     App *get_option_group(std::string group_name) const {
1083         for(const App_p &app : subcommands_) {
1084             if(app->name_.empty() && app->group_ == group_name) {
1085                 return app.get();
1086             }
1087         }
1088         throw OptionNotFound(group_name);
1089     }
1090 
1091     /// No argument version of count counts the number of times this subcommand was
1092     /// passed in. The main app will return 1. Unnamed subcommands will also return 1 unless
1093     /// otherwise modified in a callback
1094     std::size_t count() const { return parsed_; }
1095 
1096     /// Get a count of all the arguments processed in options and subcommands, this excludes arguments which were
1097     /// treated as extras.
1098     std::size_t count_all() const {
1099         std::size_t cnt{0};
1100         for(auto &opt : options_) {
1101             cnt += opt->count();
1102         }
1103         for(auto &sub : subcommands_) {
1104             cnt += sub->count_all();
1105         }
1106         if(!get_name().empty()) {  // for named subcommands add the number of times the subcommand was called
1107             cnt += parsed_;
1108         }
1109         return cnt;
1110     }
1111 
1112     /// Changes the group membership
1113     App *group(std::string group_name) {
1114         group_ = group_name;
1115         return this;
1116     }
1117 
1118     /// The argumentless form of require subcommand requires 1 or more subcommands
1119     App *require_subcommand() {
1120         require_subcommand_min_ = 1;
1121         require_subcommand_max_ = 0;
1122         return this;
1123     }
1124 
1125     /// Require a subcommand to be given (does not affect help call)
1126     /// The number required can be given. Negative values indicate maximum
1127     /// number allowed (0 for any number). Max number inheritable.
1128     App *require_subcommand(int value) {
1129         if(value < 0) {
1130             require_subcommand_min_ = 0;
1131             require_subcommand_max_ = static_cast<std::size_t>(-value);
1132         } else {
1133             require_subcommand_min_ = static_cast<std::size_t>(value);
1134             require_subcommand_max_ = static_cast<std::size_t>(value);
1135         }
1136         return this;
1137     }
1138 
1139     /// Explicitly control the number of subcommands required. Setting 0
1140     /// for the max means unlimited number allowed. Max number inheritable.
1141     App *require_subcommand(std::size_t min, std::size_t max) {
1142         require_subcommand_min_ = min;
1143         require_subcommand_max_ = max;
1144         return this;
1145     }
1146 
1147     /// The argumentless form of require option requires 1 or more options be used
1148     App *require_option() {
1149         require_option_min_ = 1;
1150         require_option_max_ = 0;
1151         return this;
1152     }
1153 
1154     /// Require an option to be given (does not affect help call)
1155     /// The number required can be given. Negative values indicate maximum
1156     /// number allowed (0 for any number).
1157     App *require_option(int value) {
1158         if(value < 0) {
1159             require_option_min_ = 0;
1160             require_option_max_ = static_cast<std::size_t>(-value);
1161         } else {
1162             require_option_min_ = static_cast<std::size_t>(value);
1163             require_option_max_ = static_cast<std::size_t>(value);
1164         }
1165         return this;
1166     }
1167 
1168     /// Explicitly control the number of options required. Setting 0
1169     /// for the max means unlimited number allowed. Max number inheritable.
1170     App *require_option(std::size_t min, std::size_t max) {
1171         require_option_min_ = min;
1172         require_option_max_ = max;
1173         return this;
1174     }
1175 
1176     /// Stop subcommand fallthrough, so that parent commands cannot collect commands after subcommand.
1177     /// Default from parent, usually set on parent.
1178     App *fallthrough(bool value = true) {
1179         fallthrough_ = value;
1180         return this;
1181     }
1182 
1183     /// Check to see if this subcommand was parsed, true only if received on command line.
1184     /// This allows the subcommand to be directly checked.
1185     explicit operator bool() const { return parsed_ > 0; }
1186 
1187     ///@}
1188     /// @name Extras for subclassing
1189     ///@{
1190 
1191     /// This allows subclasses to inject code before callbacks but after parse.
1192     ///
1193     /// This does not run if any errors or help is thrown.
1194     virtual void pre_callback() {}
1195 
1196     ///@}
1197     /// @name Parsing
1198     ///@{
1199     //
1200     /// Reset the parsed data
1201     void clear() {
1202 
1203         parsed_ = 0;
1204         pre_parse_called_ = false;
1205 
1206         missing_.clear();
1207         parsed_subcommands_.clear();
1208         for(const Option_p &opt : options_) {
1209             opt->clear();
1210         }
1211         for(const App_p &subc : subcommands_) {
1212             subc->clear();
1213         }
1214     }
1215 
1216     /// Parses the command line - throws errors.
1217     /// This must be called after the options are in but before the rest of the program.
1218     void parse(int argc, const char *const *argv) {
1219         // If the name is not set, read from command line
1220         if(name_.empty() || has_automatic_name_) {
1221             has_automatic_name_ = true;
1222             name_ = argv[0];
1223         }
1224 
1225         std::vector<std::string> args;
1226         args.reserve(static_cast<std::size_t>(argc) - 1);
1227         for(int i = argc - 1; i > 0; i--)
1228             args.emplace_back(argv[i]);
1229         parse(std::move(args));
1230     }
1231 
1232     /// Parse a single string as if it contained command line arguments.
1233     /// This function splits the string into arguments then calls parse(std::vector<std::string> &)
1234     /// the function takes an optional boolean argument specifying if the programName is included in the string to
1235     /// process
1236     void parse(std::string commandline, bool program_name_included = false) {
1237 
1238         if(program_name_included) {
1239             auto nstr = detail::split_program_name(commandline);
1240             if((name_.empty()) || (has_automatic_name_)) {
1241                 has_automatic_name_ = true;
1242                 name_ = nstr.first;
1243             }
1244             commandline = std::move(nstr.second);
1245         } else {
1246             detail::trim(commandline);
1247         }
1248         // the next section of code is to deal with quoted arguments after an '=' or ':' for windows like operations
1249         if(!commandline.empty()) {
1250             commandline = detail::find_and_modify(commandline, "=", detail::escape_detect);
1251             if(allow_windows_style_options_)
1252                 commandline = detail::find_and_modify(commandline, ":", detail::escape_detect);
1253         }
1254 
1255         auto args = detail::split_up(std::move(commandline));
1256         // remove all empty strings
1257         args.erase(std::remove(args.begin(), args.end(), std::string{}), args.end());
1258         std::reverse(args.begin(), args.end());
1259 
1260         parse(std::move(args));
1261     }
1262 
1263     /// The real work is done here. Expects a reversed vector.
1264     /// Changes the vector to the remaining options.
1265     void parse(std::vector<std::string> &args) {
1266         // Clear if parsed
1267         if(parsed_ > 0)
1268             clear();
1269 
1270         // parsed_ is incremented in commands/subcommands,
1271         // but placed here to make sure this is cleared when
1272         // running parse after an error is thrown, even by _validate or _configure.
1273         parsed_ = 1;
1274         _validate();
1275         _configure();
1276         // set the parent as nullptr as this object should be the top now
1277         parent_ = nullptr;
1278         parsed_ = 0;
1279 
1280         _parse(args);
1281         run_callback();
1282     }
1283 
1284     /// The real work is done here. Expects a reversed vector.
1285     void parse(std::vector<std::string> &&args) {
1286         // Clear if parsed
1287         if(parsed_ > 0)
1288             clear();
1289 
1290         // parsed_ is incremented in commands/subcommands,
1291         // but placed here to make sure this is cleared when
1292         // running parse after an error is thrown, even by _validate or _configure.
1293         parsed_ = 1;
1294         _validate();
1295         _configure();
1296         // set the parent as nullptr as this object should be the top now
1297         parent_ = nullptr;
1298         parsed_ = 0;
1299 
1300         _parse(std::move(args));
1301         run_callback();
1302     }
1303 
1304     /// Provide a function to print a help message. The function gets access to the App pointer and error.
1305     void failure_message(std::function<std::string(const App *, const Error &e)> function) {
1306         failure_message_ = function;
1307     }
1308 
1309     /// Print a nice error message and return the exit code
1310     int exit(const Error &e, std::ostream &out = std::cout, std::ostream &err = std::cerr) const {
1311 
1312         /// Avoid printing anything if this is a CLI::RuntimeError
1313         if(e.get_name() == "RuntimeError")
1314             return e.get_exit_code();
1315 
1316         if(e.get_name() == "CallForHelp") {
1317             out << help();
1318             return e.get_exit_code();
1319         }
1320 
1321         if(e.get_name() == "CallForAllHelp") {
1322             out << help("", AppFormatMode::All);
1323             return e.get_exit_code();
1324         }
1325 
1326         if(e.get_name() == "CallForVersion") {
1327             out << e.what() << std::endl;
1328             return e.get_exit_code();
1329         }
1330 
1331         if(e.get_exit_code() != static_cast<int>(ExitCodes::Success)) {
1332             if(failure_message_)
1333                 err << failure_message_(this, e) << std::flush;
1334         }
1335 
1336         return e.get_exit_code();
1337     }
1338 
1339     ///@}
1340     /// @name Post parsing
1341     ///@{
1342 
1343     /// Counts the number of times the given option was passed.
1344     std::size_t count(std::string option_name) const { return get_option(option_name)->count(); }
1345 
1346     /// Get a subcommand pointer list to the currently selected subcommands (after parsing by default, in command
1347     /// line order; use parsed = false to get the original definition list.)
1348     std::vector<App *> get_subcommands() const { return parsed_subcommands_; }
1349 
1350     /// Get a filtered subcommand pointer list from the original definition list. An empty function will provide all
1351     /// subcommands (const)
1352     std::vector<const App *> get_subcommands(const std::function<bool(const App *)> &filter) const {
1353         std::vector<const App *> subcomms(subcommands_.size());
1354         std::transform(std::begin(subcommands_), std::end(subcommands_), std::begin(subcomms), [](const App_p &v) {
1355             return v.get();
1356         });
1357 
1358         if(filter) {
1359             subcomms.erase(std::remove_if(std::begin(subcomms),
1360                                           std::end(subcomms),
1361                                           [&filter](const App *app) { return !filter(app); }),
1362                            std::end(subcomms));
1363         }
1364 
1365         return subcomms;
1366     }
1367 
1368     /// Get a filtered subcommand pointer list from the original definition list. An empty function will provide all
1369     /// subcommands
1370     std::vector<App *> get_subcommands(const std::function<bool(App *)> &filter) {
1371         std::vector<App *> subcomms(subcommands_.size());
1372         std::transform(std::begin(subcommands_), std::end(subcommands_), std::begin(subcomms), [](const App_p &v) {
1373             return v.get();
1374         });
1375 
1376         if(filter) {
1377             subcomms.erase(
1378                 std::remove_if(std::begin(subcomms), std::end(subcomms), [&filter](App *app) { return !filter(app); }),
1379                 std::end(subcomms));
1380         }
1381 
1382         return subcomms;
1383     }
1384 
1385     /// Check to see if given subcommand was selected
1386     bool got_subcommand(const App *subcom) const {
1387         // get subcom needed to verify that this was a real subcommand
1388         return get_subcommand(subcom)->parsed_ > 0;
1389     }
1390 
1391     /// Check with name instead of pointer to see if subcommand was selected
1392     bool got_subcommand(std::string subcommand_name) const { return get_subcommand(subcommand_name)->parsed_ > 0; }
1393 
1394     /// Sets excluded options for the subcommand
1395     App *excludes(Option *opt) {
1396         if(opt == nullptr) {
1397             throw OptionNotFound("nullptr passed");
1398         }
1399         exclude_options_.insert(opt);
1400         return this;
1401     }
1402 
1403     /// Sets excluded subcommands for the subcommand
1404     App *excludes(App *app) {
1405         if(app == nullptr) {
1406             throw OptionNotFound("nullptr passed");
1407         }
1408         if(app == this) {
1409             throw OptionNotFound("cannot self reference in needs");
1410         }
1411         auto res = exclude_subcommands_.insert(app);
1412         // subcommand exclusion should be symmetric
1413         if(res.second) {
1414             app->exclude_subcommands_.insert(this);
1415         }
1416         return this;
1417     }
1418 
1419     App *needs(Option *opt) {
1420         if(opt == nullptr) {
1421             throw OptionNotFound("nullptr passed");
1422         }
1423         need_options_.insert(opt);
1424         return this;
1425     }
1426 
1427     App *needs(App *app) {
1428         if(app == nullptr) {
1429             throw OptionNotFound("nullptr passed");
1430         }
1431         if(app == this) {
1432             throw OptionNotFound("cannot self reference in needs");
1433         }
1434         need_subcommands_.insert(app);
1435         return this;
1436     }
1437 
1438     /// Removes an option from the excludes list of this subcommand
1439     bool remove_excludes(Option *opt) {
1440         auto iterator = std::find(std::begin(exclude_options_), std::end(exclude_options_), opt);
1441         if(iterator == std::end(exclude_options_)) {
1442             return false;
1443         }
1444         exclude_options_.erase(iterator);
1445         return true;
1446     }
1447 
1448     /// Removes a subcommand from the excludes list of this subcommand
1449     bool remove_excludes(App *app) {
1450         auto iterator = std::find(std::begin(exclude_subcommands_), std::end(exclude_subcommands_), app);
1451         if(iterator == std::end(exclude_subcommands_)) {
1452             return false;
1453         }
1454         auto other_app = *iterator;
1455         exclude_subcommands_.erase(iterator);
1456         other_app->remove_excludes(this);
1457         return true;
1458     }
1459 
1460     /// Removes an option from the needs list of this subcommand
1461     bool remove_needs(Option *opt) {
1462         auto iterator = std::find(std::begin(need_options_), std::end(need_options_), opt);
1463         if(iterator == std::end(need_options_)) {
1464             return false;
1465         }
1466         need_options_.erase(iterator);
1467         return true;
1468     }
1469 
1470     /// Removes a subcommand from the needs list of this subcommand
1471     bool remove_needs(App *app) {
1472         auto iterator = std::find(std::begin(need_subcommands_), std::end(need_subcommands_), app);
1473         if(iterator == std::end(need_subcommands_)) {
1474             return false;
1475         }
1476         need_subcommands_.erase(iterator);
1477         return true;
1478     }
1479 
1480     ///@}
1481     /// @name Help
1482     ///@{
1483 
1484     /// Set footer.
1485     App *footer(std::string footer_string) {
1486         footer_ = std::move(footer_string);
1487         return this;
1488     }
1489     /// Set footer.
1490     App *footer(std::function<std::string()> footer_function) {
1491         footer_callback_ = std::move(footer_function);
1492         return this;
1493     }
1494     /// Produce a string that could be read in as a config of the current values of the App. Set default_also to
1495     /// include default arguments. write_descriptions will print a description for the App and for each option.
1496     std::string config_to_str(bool default_also = false, bool write_description = false) const {
1497         return config_formatter_->to_config(this, default_also, write_description, "");
1498     }
1499 
1500     /// Makes a help message, using the currently configured formatter
1501     /// Will only do one subcommand at a time
1502     std::string help(std::string prev = "", AppFormatMode mode = AppFormatMode::Normal) const {
1503         if(prev.empty())
1504             prev = get_name();
1505         else
1506             prev += " " + get_name();
1507 
1508         // Delegate to subcommand if needed
1509         auto selected_subcommands = get_subcommands();
1510         if(!selected_subcommands.empty()) {
1511             return selected_subcommands.at(0)->help(prev, mode);
1512         }
1513         return formatter_->make_help(this, prev, mode);
1514     }
1515 
1516     /// Displays a version string
1517     std::string version() const {
1518         std::string val;
1519         if(version_ptr_ != nullptr) {
1520             auto rv = version_ptr_->results();
1521             version_ptr_->clear();
1522             version_ptr_->add_result("true");
1523             try {
1524                 version_ptr_->run_callback();
1525             } catch(const CLI::CallForVersion &cfv) {
1526                 val = cfv.what();
1527             }
1528             version_ptr_->clear();
1529             version_ptr_->add_result(rv);
1530         }
1531         return val;
1532     }
1533     ///@}
1534     /// @name Getters
1535     ///@{
1536 
1537     /// Access the formatter
1538     std::shared_ptr<FormatterBase> get_formatter() const { return formatter_; }
1539 
1540     /// Access the config formatter
1541     std::shared_ptr<Config> get_config_formatter() const { return config_formatter_; }
1542 
1543     /// Access the config formatter as a configBase pointer
1544     std::shared_ptr<ConfigBase> get_config_formatter_base() const {
1545         // This is safer as a dynamic_cast if we have RTTI, as Config -> ConfigBase
1546 #if defined(__cpp_rtti) || (defined(__GXX_RTTI) && __GXX_RTTI) || (defined(_HAS_STATIC_RTTI) && (_HAS_STATIC_RTTI == 0))
1547         return std::dynamic_pointer_cast<ConfigBase>(config_formatter_);
1548 #else
1549         return std::static_pointer_cast<ConfigBase>(config_formatter_);
1550 #endif
1551     }
1552 
1553     /// Get the app or subcommand description
1554     std::string get_description() const { return description_; }
1555 
1556     /// Set the description of the app
1557     App *description(std::string app_description) {
1558         description_ = std::move(app_description);
1559         return this;
1560     }
1561 
1562     /// Get the list of options (user facing function, so returns raw pointers), has optional filter function
1563     std::vector<const Option *> get_options(const std::function<bool(const Option *)> filter = {}) const {
1564         std::vector<const Option *> options(options_.size());
1565         std::transform(std::begin(options_), std::end(options_), std::begin(options), [](const Option_p &val) {
1566             return val.get();
1567         });
1568 
1569         if(filter) {
1570             options.erase(std::remove_if(std::begin(options),
1571                                          std::end(options),
1572                                          [&filter](const Option *opt) { return !filter(opt); }),
1573                           std::end(options));
1574         }
1575 
1576         return options;
1577     }
1578 
1579     /// Non-const version of the above
1580     std::vector<Option *> get_options(const std::function<bool(Option *)> filter = {}) {
1581         std::vector<Option *> options(options_.size());
1582         std::transform(std::begin(options_), std::end(options_), std::begin(options), [](const Option_p &val) {
1583             return val.get();
1584         });
1585 
1586         if(filter) {
1587             options.erase(
1588                 std::remove_if(std::begin(options), std::end(options), [&filter](Option *opt) { return !filter(opt); }),
1589                 std::end(options));
1590         }
1591 
1592         return options;
1593     }
1594 
1595     /// Get an option by name (noexcept non-const version)
1596     Option *get_option_no_throw(std::string option_name) noexcept {
1597         for(Option_p &opt : options_) {
1598             if(opt->check_name(option_name)) {
1599                 return opt.get();
1600             }
1601         }
1602         for(auto &subc : subcommands_) {
1603             // also check down into nameless subcommands
1604             if(subc->get_name().empty()) {
1605                 auto opt = subc->get_option_no_throw(option_name);
1606                 if(opt != nullptr) {
1607                     return opt;
1608                 }
1609             }
1610         }
1611         return nullptr;
1612     }
1613 
1614     /// Get an option by name (noexcept const version)
1615     const Option *get_option_no_throw(std::string option_name) const noexcept {
1616         for(const Option_p &opt : options_) {
1617             if(opt->check_name(option_name)) {
1618                 return opt.get();
1619             }
1620         }
1621         for(const auto &subc : subcommands_) {
1622             // also check down into nameless subcommands
1623             if(subc->get_name().empty()) {
1624                 auto opt = subc->get_option_no_throw(option_name);
1625                 if(opt != nullptr) {
1626                     return opt;
1627                 }
1628             }
1629         }
1630         return nullptr;
1631     }
1632 
1633     /// Get an option by name
1634     const Option *get_option(std::string option_name) const {
1635         auto opt = get_option_no_throw(option_name);
1636         if(opt == nullptr) {
1637             throw OptionNotFound(option_name);
1638         }
1639         return opt;
1640     }
1641 
1642     /// Get an option by name (non-const version)
1643     Option *get_option(std::string option_name) {
1644         auto opt = get_option_no_throw(option_name);
1645         if(opt == nullptr) {
1646             throw OptionNotFound(option_name);
1647         }
1648         return opt;
1649     }
1650 
1651     /// Shortcut bracket operator for getting a pointer to an option
1652     const Option *operator[](const std::string &option_name) const { return get_option(option_name); }
1653 
1654     /// Shortcut bracket operator for getting a pointer to an option
1655     const Option *operator[](const char *option_name) const { return get_option(option_name); }
1656 
1657     /// Check the status of ignore_case
1658     bool get_ignore_case() const { return ignore_case_; }
1659 
1660     /// Check the status of ignore_underscore
1661     bool get_ignore_underscore() const { return ignore_underscore_; }
1662 
1663     /// Check the status of fallthrough
1664     bool get_fallthrough() const { return fallthrough_; }
1665 
1666     /// Check the status of the allow windows style options
1667     bool get_allow_windows_style_options() const { return allow_windows_style_options_; }
1668 
1669     /// Check the status of the allow windows style options
1670     bool get_positionals_at_end() const { return positionals_at_end_; }
1671 
1672     /// Check the status of the allow windows style options
1673     bool get_configurable() const { return configurable_; }
1674 
1675     /// Get the group of this subcommand
1676     const std::string &get_group() const { return group_; }
1677 
1678     /// Generate and return the footer.
1679     std::string get_footer() const { return (footer_callback_) ? footer_callback_() + '\n' + footer_ : footer_; }
1680 
1681     /// Get the required min subcommand value
1682     std::size_t get_require_subcommand_min() const { return require_subcommand_min_; }
1683 
1684     /// Get the required max subcommand value
1685     std::size_t get_require_subcommand_max() const { return require_subcommand_max_; }
1686 
1687     /// Get the required min option value
1688     std::size_t get_require_option_min() const { return require_option_min_; }
1689 
1690     /// Get the required max option value
1691     std::size_t get_require_option_max() const { return require_option_max_; }
1692 
1693     /// Get the prefix command status
1694     bool get_prefix_command() const { return prefix_command_; }
1695 
1696     /// Get the status of allow extras
1697     bool get_allow_extras() const { return allow_extras_; }
1698 
1699     /// Get the status of required
1700     bool get_required() const { return required_; }
1701 
1702     /// Get the status of disabled
1703     bool get_disabled() const { return disabled_; }
1704 
1705     /// Get the status of silence
1706     bool get_silent() const { return silent_; }
1707 
1708     /// Get the status of disabled
1709     bool get_immediate_callback() const { return immediate_callback_; }
1710 
1711     /// Get the status of disabled by default
1712     bool get_disabled_by_default() const { return (default_startup == startup_mode::disabled); }
1713 
1714     /// Get the status of disabled by default
1715     bool get_enabled_by_default() const { return (default_startup == startup_mode::enabled); }
1716     /// Get the status of validating positionals
1717     bool get_validate_positionals() const { return validate_positionals_; }
1718 
1719     /// Get the status of allow extras
1720     config_extras_mode get_allow_config_extras() const { return allow_config_extras_; }
1721 
1722     /// Get a pointer to the help flag.
1723     Option *get_help_ptr() { return help_ptr_; }
1724 
1725     /// Get a pointer to the help flag. (const)
1726     const Option *get_help_ptr() const { return help_ptr_; }
1727 
1728     /// Get a pointer to the help all flag. (const)
1729     const Option *get_help_all_ptr() const { return help_all_ptr_; }
1730 
1731     /// Get a pointer to the config option.
1732     Option *get_config_ptr() { return config_ptr_; }
1733 
1734     /// Get a pointer to the config option. (const)
1735     const Option *get_config_ptr() const { return config_ptr_; }
1736 
1737     /// Get a pointer to the version option.
1738     Option *get_version_ptr() { return version_ptr_; }
1739 
1740     /// Get a pointer to the version option. (const)
1741     const Option *get_version_ptr() const { return version_ptr_; }
1742 
1743     /// Get the parent of this subcommand (or nullptr if master app)
1744     App *get_parent() { return parent_; }
1745 
1746     /// Get the parent of this subcommand (or nullptr if master app) (const version)
1747     const App *get_parent() const { return parent_; }
1748 
1749     /// Get the name of the current app
1750     const std::string &get_name() const { return name_; }
1751 
1752     /// Get the aliases of the current app
1753     const std::vector<std::string> &get_aliases() const { return aliases_; }
1754 
1755     /// clear all the aliases of the current App
1756     App *clear_aliases() {
1757         aliases_.clear();
1758         return this;
1759     }
1760 
1761     /// Get a display name for an app
1762     std::string get_display_name(bool with_aliases = false) const {
1763         if(name_.empty()) {
1764             return std::string("[Option Group: ") + get_group() + "]";
1765         }
1766         if(aliases_.empty() || !with_aliases || aliases_.empty()) {
1767             return name_;
1768         }
1769         std::string dispname = name_;
1770         for(const auto &lalias : aliases_) {
1771             dispname.push_back(',');
1772             dispname.push_back(' ');
1773             dispname.append(lalias);
1774         }
1775         return dispname;
1776     }
1777 
1778     /// Check the name, case insensitive and underscore insensitive if set
1779     bool check_name(std::string name_to_check) const {
1780         std::string local_name = name_;
1781         if(ignore_underscore_) {
1782             local_name = detail::remove_underscore(name_);
1783             name_to_check = detail::remove_underscore(name_to_check);
1784         }
1785         if(ignore_case_) {
1786             local_name = detail::to_lower(name_);
1787             name_to_check = detail::to_lower(name_to_check);
1788         }
1789 
1790         if(local_name == name_to_check) {
1791             return true;
1792         }
1793         for(auto les : aliases_) {
1794             if(ignore_underscore_) {
1795                 les = detail::remove_underscore(les);
1796             }
1797             if(ignore_case_) {
1798                 les = detail::to_lower(les);
1799             }
1800             if(les == name_to_check) {
1801                 return true;
1802             }
1803         }
1804         return false;
1805     }
1806 
1807     /// Get the groups available directly from this option (in order)
1808     std::vector<std::string> get_groups() const {
1809         std::vector<std::string> groups;
1810 
1811         for(const Option_p &opt : options_) {
1812             // Add group if it is not already in there
1813             if(std::find(groups.begin(), groups.end(), opt->get_group()) == groups.end()) {
1814                 groups.push_back(opt->get_group());
1815             }
1816         }
1817 
1818         return groups;
1819     }
1820 
1821     /// This gets a vector of pointers with the original parse order
1822     const std::vector<Option *> &parse_order() const { return parse_order_; }
1823 
1824     /// This returns the missing options from the current subcommand
1825     std::vector<std::string> remaining(bool recurse = false) const {
1826         std::vector<std::string> miss_list;
1827         for(const std::pair<detail::Classifier, std::string> &miss : missing_) {
1828             miss_list.push_back(std::get<1>(miss));
1829         }
1830         // Get from a subcommand that may allow extras
1831         if(recurse) {
1832             if(!allow_extras_) {
1833                 for(const auto &sub : subcommands_) {
1834                     if(sub->name_.empty() && !sub->missing_.empty()) {
1835                         for(const std::pair<detail::Classifier, std::string> &miss : sub->missing_) {
1836                             miss_list.push_back(std::get<1>(miss));
1837                         }
1838                     }
1839                 }
1840             }
1841             // Recurse into subcommands
1842 
1843             for(const App *sub : parsed_subcommands_) {
1844                 std::vector<std::string> output = sub->remaining(recurse);
1845                 std::copy(std::begin(output), std::end(output), std::back_inserter(miss_list));
1846             }
1847         }
1848         return miss_list;
1849     }
1850 
1851     /// This returns the missing options in a form ready for processing by another command line program
1852     std::vector<std::string> remaining_for_passthrough(bool recurse = false) const {
1853         std::vector<std::string> miss_list = remaining(recurse);
1854         std::reverse(std::begin(miss_list), std::end(miss_list));
1855         return miss_list;
1856     }
1857 
1858     /// This returns the number of remaining options, minus the -- separator
1859     std::size_t remaining_size(bool recurse = false) const {
1860         auto remaining_options = static_cast<std::size_t>(std::count_if(
1861             std::begin(missing_), std::end(missing_), [](const std::pair<detail::Classifier, std::string> &val) {
1862                 return val.first != detail::Classifier::POSITIONAL_MARK;
1863             }));
1864 
1865         if(recurse) {
1866             for(const App_p &sub : subcommands_) {
1867                 remaining_options += sub->remaining_size(recurse);
1868             }
1869         }
1870         return remaining_options;
1871     }
1872 
1873     ///@}
1874 
1875   protected:
1876     /// Check the options to make sure there are no conflicts.
1877     ///
1878     /// Currently checks to see if multiple positionals exist with unlimited args and checks if the min and max options
1879     /// are feasible
1880     void _validate() const {
1881         // count the number of positional only args
1882         auto pcount = std::count_if(std::begin(options_), std::end(options_), [](const Option_p &opt) {
1883             return opt->get_items_expected_max() >= detail::expected_max_vector_size && !opt->nonpositional();
1884         });
1885         if(pcount > 1) {
1886             auto pcount_req = std::count_if(std::begin(options_), std::end(options_), [](const Option_p &opt) {
1887                 return opt->get_items_expected_max() >= detail::expected_max_vector_size && !opt->nonpositional() &&
1888                        opt->get_required();
1889             });
1890             if(pcount - pcount_req > 1) {
1891                 throw InvalidError(name_);
1892             }
1893         }
1894 
1895         std::size_t nameless_subs{0};
1896         for(const App_p &app : subcommands_) {
1897             app->_validate();
1898             if(app->get_name().empty())
1899                 ++nameless_subs;
1900         }
1901 
1902         if(require_option_min_ > 0) {
1903             if(require_option_max_ > 0) {
1904                 if(require_option_max_ < require_option_min_) {
1905                     throw(InvalidError("Required min options greater than required max options",
1906                                        ExitCodes::InvalidError));
1907                 }
1908             }
1909             if(require_option_min_ > (options_.size() + nameless_subs)) {
1910                 throw(InvalidError("Required min options greater than number of available options",
1911                                    ExitCodes::InvalidError));
1912             }
1913         }
1914     }
1915 
1916     /// configure subcommands to enable parsing through the current object
1917     /// set the correct fallthrough and prefix for nameless subcommands and manage the automatic enable or disable
1918     /// makes sure parent is set correctly
1919     void _configure() {
1920         if(default_startup == startup_mode::enabled) {
1921             disabled_ = false;
1922         } else if(default_startup == startup_mode::disabled) {
1923             disabled_ = true;
1924         }
1925         for(const App_p &app : subcommands_) {
1926             if(app->has_automatic_name_) {
1927                 app->name_.clear();
1928             }
1929             if(app->name_.empty()) {
1930                 app->fallthrough_ = false;  // make sure fallthrough_ is false to prevent infinite loop
1931                 app->prefix_command_ = false;
1932             }
1933             // make sure the parent is set to be this object in preparation for parse
1934             app->parent_ = this;
1935             app->_configure();
1936         }
1937     }
1938 
1939     /// Internal function to run (App) callback, bottom up
1940     void run_callback(bool final_mode = false, bool suppress_final_callback = false) {
1941         pre_callback();
1942         // in the main app if immediate_callback_ is set it runs the main callback before the used subcommands
1943         if(!final_mode && parse_complete_callback_) {
1944             parse_complete_callback_();
1945         }
1946         // run the callbacks for the received subcommands
1947         for(App *subc : get_subcommands()) {
1948             subc->run_callback(true, suppress_final_callback);
1949         }
1950         // now run callbacks for option_groups
1951         for(auto &subc : subcommands_) {
1952             if(subc->name_.empty() && subc->count_all() > 0) {
1953                 subc->run_callback(true, suppress_final_callback);
1954             }
1955         }
1956 
1957         // finally run the main callback
1958         if(final_callback_ && (parsed_ > 0) && (!suppress_final_callback)) {
1959             if(!name_.empty() || count_all() > 0 || parent_ == nullptr) {
1960                 final_callback_();
1961             }
1962         }
1963     }
1964 
1965     /// Check to see if a subcommand is valid. Give up immediately if subcommand max has been reached.
1966     bool _valid_subcommand(const std::string &current, bool ignore_used = true) const {
1967         // Don't match if max has been reached - but still check parents
1968         if(require_subcommand_max_ != 0 && parsed_subcommands_.size() >= require_subcommand_max_) {
1969             return parent_ != nullptr && parent_->_valid_subcommand(current, ignore_used);
1970         }
1971         auto com = _find_subcommand(current, true, ignore_used);
1972         if(com != nullptr) {
1973             return true;
1974         }
1975         // Check parent if exists, else return false
1976         return parent_ != nullptr && parent_->_valid_subcommand(current, ignore_used);
1977     }
1978 
1979     /// Selects a Classifier enum based on the type of the current argument
1980     detail::Classifier _recognize(const std::string &current, bool ignore_used_subcommands = true) const {
1981         std::string dummy1, dummy2;
1982 
1983         if(current == "--")
1984             return detail::Classifier::POSITIONAL_MARK;
1985         if(_valid_subcommand(current, ignore_used_subcommands))
1986             return detail::Classifier::SUBCOMMAND;
1987         if(detail::split_long(current, dummy1, dummy2))
1988             return detail::Classifier::LONG;
1989         if(detail::split_short(current, dummy1, dummy2)) {
1990             if(dummy1[0] >= '0' && dummy1[0] <= '9') {
1991                 if(get_option_no_throw(std::string{'-', dummy1[0]}) == nullptr) {
1992                     return detail::Classifier::NONE;
1993                 }
1994             }
1995             return detail::Classifier::SHORT;
1996         }
1997         if((allow_windows_style_options_) && (detail::split_windows_style(current, dummy1, dummy2)))
1998             return detail::Classifier::WINDOWS_STYLE;
1999         if((current == "++") && !name_.empty() && parent_ != nullptr)
2000             return detail::Classifier::SUBCOMMAND_TERMINATOR;
2001         return detail::Classifier::NONE;
2002     }
2003 
2004     // The parse function is now broken into several parts, and part of process
2005 
2006     /// Read and process a configuration file (main app only)
2007     void _process_config_file() {
2008         if(config_ptr_ != nullptr) {
2009             bool config_required = config_ptr_->get_required();
2010             auto file_given = config_ptr_->count() > 0;
2011             auto config_files = config_ptr_->as<std::vector<std::string>>();
2012             if(config_files.empty() || config_files.front().empty()) {
2013                 if(config_required) {
2014                     throw FileError::Missing("no specified config file");
2015                 }
2016                 return;
2017             }
2018             for(auto rit = config_files.rbegin(); rit != config_files.rend(); ++rit) {
2019                 const auto &config_file = *rit;
2020                 auto path_result = detail::check_path(config_file.c_str());
2021                 if(path_result == detail::path_type::file) {
2022                     try {
2023                         std::vector<ConfigItem> values = config_formatter_->from_file(config_file);
2024                         _parse_config(values);
2025                         if(!file_given) {
2026                             config_ptr_->add_result(config_file);
2027                         }
2028                     } catch(const FileError &) {
2029                         if(config_required || file_given)
2030                             throw;
2031                     }
2032                 } else if(config_required || file_given) {
2033                     throw FileError::Missing(config_file);
2034                 }
2035             }
2036         }
2037     }
2038 
2039     /// Get envname options if not yet passed. Runs on *all* subcommands.
2040     void _process_env() {
2041         for(const Option_p &opt : options_) {
2042             if(opt->count() == 0 && !opt->envname_.empty()) {
2043                 char *buffer = nullptr;
2044                 std::string ename_string;
2045 
2046 #ifdef _MSC_VER
2047                 // Windows version
2048                 std::size_t sz = 0;
2049                 if(_dupenv_s(&buffer, &sz, opt->envname_.c_str()) == 0 && buffer != nullptr) {
2050                     ename_string = std::string(buffer);
2051                     free(buffer);
2052                 }
2053 #else
2054                 // This also works on Windows, but gives a warning
2055                 buffer = std::getenv(opt->envname_.c_str());
2056                 if(buffer != nullptr)
2057                     ename_string = std::string(buffer);
2058 #endif
2059 
2060                 if(!ename_string.empty()) {
2061                     opt->add_result(ename_string);
2062                 }
2063             }
2064         }
2065 
2066         for(App_p &sub : subcommands_) {
2067             if(sub->get_name().empty() || !sub->parse_complete_callback_)
2068                 sub->_process_env();
2069         }
2070     }
2071 
2072     /// Process callbacks. Runs on *all* subcommands.
2073     void _process_callbacks() {
2074 
2075         for(App_p &sub : subcommands_) {
2076             // process the priority option_groups first
2077             if(sub->get_name().empty() && sub->parse_complete_callback_) {
2078                 if(sub->count_all() > 0) {
2079                     sub->_process_callbacks();
2080                     sub->run_callback();
2081                 }
2082             }
2083         }
2084 
2085         for(const Option_p &opt : options_) {
2086             if(opt->count() > 0 && !opt->get_callback_run()) {
2087                 opt->run_callback();
2088             }
2089         }
2090         for(App_p &sub : subcommands_) {
2091             if(!sub->parse_complete_callback_) {
2092                 sub->_process_callbacks();
2093             }
2094         }
2095     }
2096 
2097     /// Run help flag processing if any are found.
2098     ///
2099     /// The flags allow recursive calls to remember if there was a help flag on a parent.
2100     void _process_help_flags(bool trigger_help = false, bool trigger_all_help = false) const {
2101         const Option *help_ptr = get_help_ptr();
2102         const Option *help_all_ptr = get_help_all_ptr();
2103 
2104         if(help_ptr != nullptr && help_ptr->count() > 0)
2105             trigger_help = true;
2106         if(help_all_ptr != nullptr && help_all_ptr->count() > 0)
2107             trigger_all_help = true;
2108 
2109         // If there were parsed subcommands, call those. First subcommand wins if there are multiple ones.
2110         if(!parsed_subcommands_.empty()) {
2111             for(const App *sub : parsed_subcommands_)
2112                 sub->_process_help_flags(trigger_help, trigger_all_help);
2113 
2114             // Only the final subcommand should call for help. All help wins over help.
2115         } else if(trigger_all_help) {
2116             throw CallForAllHelp();
2117         } else if(trigger_help) {
2118             throw CallForHelp();
2119         }
2120     }
2121 
2122     /// Verify required options and cross requirements. Subcommands too (only if selected).
2123     void _process_requirements() {
2124         // check excludes
2125         bool excluded{false};
2126         std::string excluder;
2127         for(auto &opt : exclude_options_) {
2128             if(opt->count() > 0) {
2129                 excluded = true;
2130                 excluder = opt->get_name();
2131             }
2132         }
2133         for(auto &subc : exclude_subcommands_) {
2134             if(subc->count_all() > 0) {
2135                 excluded = true;
2136                 excluder = subc->get_display_name();
2137             }
2138         }
2139         if(excluded) {
2140             if(count_all() > 0) {
2141                 throw ExcludesError(get_display_name(), excluder);
2142             }
2143             // if we are excluded but didn't receive anything, just return
2144             return;
2145         }
2146 
2147         // check excludes
2148         bool missing_needed{false};
2149         std::string missing_need;
2150         for(auto &opt : need_options_) {
2151             if(opt->count() == 0) {
2152                 missing_needed = true;
2153                 missing_need = opt->get_name();
2154             }
2155         }
2156         for(auto &subc : need_subcommands_) {
2157             if(subc->count_all() == 0) {
2158                 missing_needed = true;
2159                 missing_need = subc->get_display_name();
2160             }
2161         }
2162         if(missing_needed) {
2163             if(count_all() > 0) {
2164                 throw RequiresError(get_display_name(), missing_need);
2165             }
2166             // if we missing something but didn't have any options, just return
2167             return;
2168         }
2169 
2170         std::size_t used_options = 0;
2171         for(const Option_p &opt : options_) {
2172 
2173             if(opt->count() != 0) {
2174                 ++used_options;
2175             }
2176             // Required but empty
2177             if(opt->get_required() && opt->count() == 0) {
2178                 throw RequiredError(opt->get_name());
2179             }
2180             // Requires
2181             for(const Option *opt_req : opt->needs_)
2182                 if(opt->count() > 0 && opt_req->count() == 0)
2183                     throw RequiresError(opt->get_name(), opt_req->get_name());
2184             // Excludes
2185             for(const Option *opt_ex : opt->excludes_)
2186                 if(opt->count() > 0 && opt_ex->count() != 0)
2187                     throw ExcludesError(opt->get_name(), opt_ex->get_name());
2188         }
2189         // check for the required number of subcommands
2190         if(require_subcommand_min_ > 0) {
2191             auto selected_subcommands = get_subcommands();
2192             if(require_subcommand_min_ > selected_subcommands.size())
2193                 throw RequiredError::Subcommand(require_subcommand_min_);
2194         }
2195 
2196         // Max error cannot occur, the extra subcommand will parse as an ExtrasError or a remaining item.
2197 
2198         // run this loop to check how many unnamed subcommands were actually used since they are considered options
2199         // from the perspective of an App
2200         for(App_p &sub : subcommands_) {
2201             if(sub->disabled_)
2202                 continue;
2203             if(sub->name_.empty() && sub->count_all() > 0) {
2204                 ++used_options;
2205             }
2206         }
2207 
2208         if(require_option_min_ > used_options || (require_option_max_ > 0 && require_option_max_ < used_options)) {
2209             auto option_list = detail::join(options_, [this](const Option_p &ptr) {
2210                 if(ptr.get() == help_ptr_ || ptr.get() == help_all_ptr_) {
2211                     return std::string{};
2212                 }
2213                 return ptr->get_name(false, true);
2214             });
2215 
2216             auto subc_list = get_subcommands([](App *app) { return ((app->get_name().empty()) && (!app->disabled_)); });
2217             if(!subc_list.empty()) {
2218                 option_list += "," + detail::join(subc_list, [](const App *app) { return app->get_display_name(); });
2219             }
2220             throw RequiredError::Option(require_option_min_, require_option_max_, used_options, option_list);
2221         }
2222 
2223         // now process the requirements for subcommands if needed
2224         for(App_p &sub : subcommands_) {
2225             if(sub->disabled_)
2226                 continue;
2227             if(sub->name_.empty() && sub->required_ == false) {
2228                 if(sub->count_all() == 0) {
2229                     if(require_option_min_ > 0 && require_option_min_ <= used_options) {
2230                         continue;
2231                         // if we have met the requirement and there is nothing in this option group skip checking
2232                         // requirements
2233                     }
2234                     if(require_option_max_ > 0 && used_options >= require_option_min_) {
2235                         continue;
2236                         // if we have met the requirement and there is nothing in this option group skip checking
2237                         // requirements
2238                     }
2239                 }
2240             }
2241             if(sub->count() > 0 || sub->name_.empty()) {
2242                 sub->_process_requirements();
2243             }
2244 
2245             if(sub->required_ && sub->count_all() == 0) {
2246                 throw(CLI::RequiredError(sub->get_display_name()));
2247             }
2248         }
2249     }
2250 
2251     /// Process callbacks and such.
2252     void _process() {
2253         CLI::FileError fe("ne");
2254         bool caught_error{false};
2255         try {
2256             // the config file might generate a FileError but that should not be processed until later in the process
2257             // to allow for help, version and other errors to generate first.
2258             _process_config_file();
2259             // process env shouldn't throw but no reason to process it if config generated an error
2260             _process_env();
2261         } catch(const CLI::FileError &fe2) {
2262             fe = fe2;
2263             caught_error = true;
2264         }
2265         // callbacks and help_flags can generate exceptions which should take priority over the config file error if one
2266         // exists
2267         _process_callbacks();
2268         _process_help_flags();
2269 
2270         if(caught_error) {
2271             throw CLI::FileError(std::move(fe));
2272         }
2273 
2274         _process_requirements();
2275     }
2276 
2277     /// Throw an error if anything is left over and should not be.
2278     void _process_extras() {
2279         if(!(allow_extras_ || prefix_command_)) {
2280             std::size_t num_left_over = remaining_size();
2281             if(num_left_over > 0) {
2282                 throw ExtrasError(name_, remaining(false));
2283             }
2284         }
2285 
2286         for(App_p &sub : subcommands_) {
2287             if(sub->count() > 0)
2288                 sub->_process_extras();
2289         }
2290     }
2291 
2292     /// Throw an error if anything is left over and should not be.
2293     /// Modifies the args to fill in the missing items before throwing.
2294     void _process_extras(std::vector<std::string> &args) {
2295         if(!(allow_extras_ || prefix_command_)) {
2296             std::size_t num_left_over = remaining_size();
2297             if(num_left_over > 0) {
2298                 args = remaining(false);
2299                 throw ExtrasError(name_, args);
2300             }
2301         }
2302 
2303         for(App_p &sub : subcommands_) {
2304             if(sub->count() > 0)
2305                 sub->_process_extras(args);
2306         }
2307     }
2308 
2309     /// Internal function to recursively increment the parsed counter on the current app as well unnamed subcommands
2310     void increment_parsed() {
2311         ++parsed_;
2312         for(App_p &sub : subcommands_) {
2313             if(sub->get_name().empty())
2314                 sub->increment_parsed();
2315         }
2316     }
2317     /// Internal parse function
2318     void _parse(std::vector<std::string> &args) {
2319         increment_parsed();
2320         _trigger_pre_parse(args.size());
2321         bool positional_only = false;
2322 
2323         while(!args.empty()) {
2324             if(!_parse_single(args, positional_only)) {
2325                 break;
2326             }
2327         }
2328 
2329         if(parent_ == nullptr) {
2330             _process();
2331 
2332             // Throw error if any items are left over (depending on settings)
2333             _process_extras(args);
2334 
2335             // Convert missing (pairs) to extras (string only) ready for processing in another app
2336             args = remaining_for_passthrough(false);
2337         } else if(parse_complete_callback_) {
2338             _process_env();
2339             _process_callbacks();
2340             _process_help_flags();
2341             _process_requirements();
2342             run_callback(false, true);
2343         }
2344     }
2345 
2346     /// Internal parse function
2347     void _parse(std::vector<std::string> &&args) {
2348         // this can only be called by the top level in which case parent == nullptr by definition
2349         // operation is simplified
2350         increment_parsed();
2351         _trigger_pre_parse(args.size());
2352         bool positional_only = false;
2353 
2354         while(!args.empty()) {
2355             _parse_single(args, positional_only);
2356         }
2357         _process();
2358 
2359         // Throw error if any items are left over (depending on settings)
2360         _process_extras();
2361     }
2362 
2363     /// Parse one config param, return false if not found in any subcommand, remove if it is
2364     ///
2365     /// If this has more than one dot.separated.name, go into the subcommand matching it
2366     /// Returns true if it managed to find the option, if false you'll need to remove the arg manually.
2367     void _parse_config(const std::vector<ConfigItem> &args) {
2368         for(const ConfigItem &item : args) {
2369             if(!_parse_single_config(item) && allow_config_extras_ == config_extras_mode::error)
2370                 throw ConfigError::Extras(item.fullname());
2371         }
2372     }
2373 
2374     /// Fill in a single config option
2375     bool _parse_single_config(const ConfigItem &item, std::size_t level = 0) {
2376         if(level < item.parents.size()) {
2377             try {
2378                 auto subcom = get_subcommand(item.parents.at(level));
2379                 auto result = subcom->_parse_single_config(item, level + 1);
2380 
2381                 return result;
2382             } catch(const OptionNotFound &) {
2383                 return false;
2384             }
2385         }
2386         // check for section open
2387         if(item.name == "++") {
2388             if(configurable_) {
2389                 increment_parsed();
2390                 _trigger_pre_parse(2);
2391                 if(parent_ != nullptr) {
2392                     parent_->parsed_subcommands_.push_back(this);
2393                 }
2394             }
2395             return true;
2396         }
2397         // check for section close
2398         if(item.name == "--") {
2399             if(configurable_) {
2400                 _process_callbacks();
2401                 _process_requirements();
2402                 run_callback();
2403             }
2404             return true;
2405         }
2406         Option *op = get_option_no_throw("--" + item.name);
2407         if(op == nullptr) {
2408             if(item.name.size() == 1) {
2409                 op = get_option_no_throw("-" + item.name);
2410             }
2411         }
2412         if(op == nullptr) {
2413             op = get_option_no_throw(item.name);
2414         }
2415         if(op == nullptr) {
2416             // If the option was not present
2417             if(get_allow_config_extras() == config_extras_mode::capture)
2418                 // Should we worry about classifying the extras properly?
2419                 missing_.emplace_back(detail::Classifier::NONE, item.fullname());
2420             return false;
2421         }
2422 
2423         if(!op->get_configurable())
2424             throw ConfigError::NotConfigurable(item.fullname());
2425 
2426         if(op->empty()) {
2427             // Flag parsing
2428             if(op->get_expected_min() == 0) {
2429                 auto res = config_formatter_->to_flag(item);
2430                 res = op->get_flag_value(item.name, res);
2431 
2432                 op->add_result(res);
2433 
2434             } else {
2435                 op->add_result(item.inputs);
2436                 op->run_callback();
2437             }
2438         }
2439 
2440         return true;
2441     }
2442 
2443     /// Parse "one" argument (some may eat more than one), delegate to parent if fails, add to missing if missing
2444     /// from master return false if the parse has failed and needs to return to parent
2445     bool _parse_single(std::vector<std::string> &args, bool &positional_only) {
2446         bool retval = true;
2447         detail::Classifier classifier = positional_only ? detail::Classifier::NONE : _recognize(args.back());
2448         switch(classifier) {
2449         case detail::Classifier::POSITIONAL_MARK:
2450             args.pop_back();
2451             positional_only = true;
2452             if((!_has_remaining_positionals()) && (parent_ != nullptr)) {
2453                 retval = false;
2454             } else {
2455                 _move_to_missing(classifier, "--");
2456             }
2457             break;
2458         case detail::Classifier::SUBCOMMAND_TERMINATOR:
2459             // treat this like a positional mark if in the parent app
2460             args.pop_back();
2461             retval = false;
2462             break;
2463         case detail::Classifier::SUBCOMMAND:
2464             retval = _parse_subcommand(args);
2465             break;
2466         case detail::Classifier::LONG:
2467         case detail::Classifier::SHORT:
2468         case detail::Classifier::WINDOWS_STYLE:
2469             // If already parsed a subcommand, don't accept options_
2470             _parse_arg(args, classifier);
2471             break;
2472         case detail::Classifier::NONE:
2473             // Probably a positional or something for a parent (sub)command
2474             retval = _parse_positional(args, false);
2475             if(retval && positionals_at_end_) {
2476                 positional_only = true;
2477             }
2478             break;
2479             // LCOV_EXCL_START
2480         default:
2481             throw HorribleError("unrecognized classifier (you should not see this!)");
2482             // LCOV_EXCL_STOP
2483         }
2484         return retval;
2485     }
2486 
2487     /// Count the required remaining positional arguments
2488     std::size_t _count_remaining_positionals(bool required_only = false) const {
2489         std::size_t retval = 0;
2490         for(const Option_p &opt : options_) {
2491             if(opt->get_positional() && (!required_only || opt->get_required())) {
2492                 if(opt->get_items_expected_min() > 0 &&
2493                    static_cast<int>(opt->count()) < opt->get_items_expected_min()) {
2494                     retval += static_cast<std::size_t>(opt->get_items_expected_min()) - opt->count();
2495                 }
2496             }
2497         }
2498         return retval;
2499     }
2500 
2501     /// Count the required remaining positional arguments
2502     bool _has_remaining_positionals() const {
2503         for(const Option_p &opt : options_) {
2504             if(opt->get_positional() && ((static_cast<int>(opt->count()) < opt->get_items_expected_min()))) {
2505                 return true;
2506             }
2507         }
2508 
2509         return false;
2510     }
2511 
2512     /// Parse a positional, go up the tree to check
2513     /// @param haltOnSubcommand if set to true the operation will not process subcommands merely return false
2514     /// Return true if the positional was used false otherwise
2515     bool _parse_positional(std::vector<std::string> &args, bool haltOnSubcommand) {
2516 
2517         const std::string &positional = args.back();
2518 
2519         if(positionals_at_end_) {
2520             // deal with the case of required arguments at the end which should take precedence over other arguments
2521             auto arg_rem = args.size();
2522             auto remreq = _count_remaining_positionals(true);
2523             if(arg_rem <= remreq) {
2524                 for(const Option_p &opt : options_) {
2525                     if(opt->get_positional() && opt->required_) {
2526                         if(static_cast<int>(opt->count()) < opt->get_items_expected_min()) {
2527                             if(validate_positionals_) {
2528                                 std::string pos = positional;
2529                                 pos = opt->_validate(pos, 0);
2530                                 if(!pos.empty()) {
2531                                     continue;
2532                                 }
2533                             }
2534                             opt->add_result(positional);
2535                             parse_order_.push_back(opt.get());
2536                             args.pop_back();
2537                             return true;
2538                         }
2539                     }
2540                 }
2541             }
2542         }
2543         for(const Option_p &opt : options_) {
2544             // Eat options, one by one, until done
2545             if(opt->get_positional() &&
2546                (static_cast<int>(opt->count()) < opt->get_items_expected_min() || opt->get_allow_extra_args())) {
2547                 if(validate_positionals_) {
2548                     std::string pos = positional;
2549                     pos = opt->_validate(pos, 0);
2550                     if(!pos.empty()) {
2551                         continue;
2552                     }
2553                 }
2554                 opt->add_result(positional);
2555                 parse_order_.push_back(opt.get());
2556                 args.pop_back();
2557                 return true;
2558             }
2559         }
2560 
2561         for(auto &subc : subcommands_) {
2562             if((subc->name_.empty()) && (!subc->disabled_)) {
2563                 if(subc->_parse_positional(args, false)) {
2564                     if(!subc->pre_parse_called_) {
2565                         subc->_trigger_pre_parse(args.size());
2566                     }
2567                     return true;
2568                 }
2569             }
2570         }
2571         // let the parent deal with it if possible
2572         if(parent_ != nullptr && fallthrough_)
2573             return _get_fallthrough_parent()->_parse_positional(args, static_cast<bool>(parse_complete_callback_));
2574 
2575         /// Try to find a local subcommand that is repeated
2576         auto com = _find_subcommand(args.back(), true, false);
2577         if(com != nullptr && (require_subcommand_max_ == 0 || require_subcommand_max_ > parsed_subcommands_.size())) {
2578             if(haltOnSubcommand) {
2579                 return false;
2580             }
2581             args.pop_back();
2582             com->_parse(args);
2583             return true;
2584         }
2585         /// now try one last gasp at subcommands that have been executed before, go to root app and try to find a
2586         /// subcommand in a broader way, if one exists let the parent deal with it
2587         auto parent_app = (parent_ != nullptr) ? _get_fallthrough_parent() : this;
2588         com = parent_app->_find_subcommand(args.back(), true, false);
2589         if(com != nullptr && (com->parent_->require_subcommand_max_ == 0 ||
2590                               com->parent_->require_subcommand_max_ > com->parent_->parsed_subcommands_.size())) {
2591             return false;
2592         }
2593 
2594         if(positionals_at_end_) {
2595             throw CLI::ExtrasError(name_, args);
2596         }
2597         /// If this is an option group don't deal with it
2598         if(parent_ != nullptr && name_.empty()) {
2599             return false;
2600         }
2601         /// We are out of other options this goes to missing
2602         _move_to_missing(detail::Classifier::NONE, positional);
2603         args.pop_back();
2604         if(prefix_command_) {
2605             while(!args.empty()) {
2606                 _move_to_missing(detail::Classifier::NONE, args.back());
2607                 args.pop_back();
2608             }
2609         }
2610 
2611         return true;
2612     }
2613 
2614     /// Locate a subcommand by name with two conditions, should disabled subcommands be ignored, and should used
2615     /// subcommands be ignored
2616     App *_find_subcommand(const std::string &subc_name, bool ignore_disabled, bool ignore_used) const noexcept {
2617         for(const App_p &com : subcommands_) {
2618             if(com->disabled_ && ignore_disabled)
2619                 continue;
2620             if(com->get_name().empty()) {
2621                 auto subc = com->_find_subcommand(subc_name, ignore_disabled, ignore_used);
2622                 if(subc != nullptr) {
2623                     return subc;
2624                 }
2625             }
2626             if(com->check_name(subc_name)) {
2627                 if((!*com) || !ignore_used)
2628                     return com.get();
2629             }
2630         }
2631         return nullptr;
2632     }
2633 
2634     /// Parse a subcommand, modify args and continue
2635     ///
2636     /// Unlike the others, this one will always allow fallthrough
2637     /// return true if the subcommand was processed false otherwise
2638     bool _parse_subcommand(std::vector<std::string> &args) {
2639         if(_count_remaining_positionals(/* required */ true) > 0) {
2640             _parse_positional(args, false);
2641             return true;
2642         }
2643         auto com = _find_subcommand(args.back(), true, true);
2644         if(com != nullptr) {
2645             args.pop_back();
2646             if(!com->silent_) {
2647                 parsed_subcommands_.push_back(com);
2648             }
2649             com->_parse(args);
2650             auto parent_app = com->parent_;
2651             while(parent_app != this) {
2652                 parent_app->_trigger_pre_parse(args.size());
2653                 if(!com->silent_) {
2654                     parent_app->parsed_subcommands_.push_back(com);
2655                 }
2656                 parent_app = parent_app->parent_;
2657             }
2658             return true;
2659         }
2660 
2661         if(parent_ == nullptr)
2662             throw HorribleError("Subcommand " + args.back() + " missing");
2663         return false;
2664     }
2665 
2666     /// Parse a short (false) or long (true) argument, must be at the top of the list
2667     /// return true if the argument was processed or false if nothing was done
2668     bool _parse_arg(std::vector<std::string> &args, detail::Classifier current_type) {
2669 
2670         std::string current = args.back();
2671 
2672         std::string arg_name;
2673         std::string value;
2674         std::string rest;
2675 
2676         switch(current_type) {
2677         case detail::Classifier::LONG:
2678             if(!detail::split_long(current, arg_name, value))
2679                 throw HorribleError("Long parsed but missing (you should not see this):" + args.back());
2680             break;
2681         case detail::Classifier::SHORT:
2682             if(!detail::split_short(current, arg_name, rest))
2683                 throw HorribleError("Short parsed but missing! You should not see this");
2684             break;
2685         case detail::Classifier::WINDOWS_STYLE:
2686             if(!detail::split_windows_style(current, arg_name, value))
2687                 throw HorribleError("windows option parsed but missing! You should not see this");
2688             break;
2689         case detail::Classifier::SUBCOMMAND:
2690         case detail::Classifier::SUBCOMMAND_TERMINATOR:
2691         case detail::Classifier::POSITIONAL_MARK:
2692         case detail::Classifier::NONE:
2693         default:
2694             throw HorribleError("parsing got called with invalid option! You should not see this");
2695         }
2696 
2697         auto op_ptr =
2698             std::find_if(std::begin(options_), std::end(options_), [arg_name, current_type](const Option_p &opt) {
2699                 if(current_type == detail::Classifier::LONG)
2700                     return opt->check_lname(arg_name);
2701                 if(current_type == detail::Classifier::SHORT)
2702                     return opt->check_sname(arg_name);
2703                 // this will only get called for detail::Classifier::WINDOWS_STYLE
2704                 return opt->check_lname(arg_name) || opt->check_sname(arg_name);
2705             });
2706 
2707         // Option not found
2708         if(op_ptr == std::end(options_)) {
2709             for(auto &subc : subcommands_) {
2710                 if(subc->name_.empty() && !subc->disabled_) {
2711                     if(subc->_parse_arg(args, current_type)) {
2712                         if(!subc->pre_parse_called_) {
2713                             subc->_trigger_pre_parse(args.size());
2714                         }
2715                         return true;
2716                     }
2717                 }
2718             }
2719             // If a subcommand, try the master command
2720             if(parent_ != nullptr && fallthrough_)
2721                 return _get_fallthrough_parent()->_parse_arg(args, current_type);
2722             // don't capture missing if this is a nameless subcommand
2723             if(parent_ != nullptr && name_.empty()) {
2724                 return false;
2725             }
2726             // Otherwise, add to missing
2727             args.pop_back();
2728             _move_to_missing(current_type, current);
2729             return true;
2730         }
2731 
2732         args.pop_back();
2733 
2734         // Get a reference to the pointer to make syntax bearable
2735         Option_p &op = *op_ptr;
2736         /// if we require a separator add it here
2737         if(op->get_inject_separator()) {
2738             if(!op->results().empty() && !op->results().back().empty()) {
2739                 op->add_result(std::string{});
2740             }
2741         }
2742         int min_num = (std::min)(op->get_type_size_min(), op->get_items_expected_min());
2743         int max_num = op->get_items_expected_max();
2744         // check container like options to limit the argument size to a single type if the allow_extra_flags argument is
2745         // set. 16 is somewhat arbitrary (needs to be at least 4)
2746         if(max_num >= detail::expected_max_vector_size / 16 && !op->get_allow_extra_args()) {
2747             auto tmax = op->get_type_size_max();
2748             max_num = detail::checked_multiply(tmax, op->get_expected_min()) ? tmax : detail::expected_max_vector_size;
2749         }
2750         // Make sure we always eat the minimum for unlimited vectors
2751         int collected = 0;     // total number of arguments collected
2752         int result_count = 0;  // local variable for number of results in a single arg string
2753         // deal with purely flag like things
2754         if(max_num == 0) {
2755             auto res = op->get_flag_value(arg_name, value);
2756             op->add_result(res);
2757             parse_order_.push_back(op.get());
2758         } else if(!value.empty()) {  // --this=value
2759             op->add_result(value, result_count);
2760             parse_order_.push_back(op.get());
2761             collected += result_count;
2762             // -Trest
2763         } else if(!rest.empty()) {
2764             op->add_result(rest, result_count);
2765             parse_order_.push_back(op.get());
2766             rest = "";
2767             collected += result_count;
2768         }
2769 
2770         // gather the minimum number of arguments
2771         while(min_num > collected && !args.empty()) {
2772             std::string current_ = args.back();
2773             args.pop_back();
2774             op->add_result(current_, result_count);
2775             parse_order_.push_back(op.get());
2776             collected += result_count;
2777         }
2778 
2779         if(min_num > collected) {  // if we have run out of arguments and the minimum was not met
2780             throw ArgumentMismatch::TypedAtLeast(op->get_name(), min_num, op->get_type_name());
2781         }
2782 
2783         if(max_num > collected || op->get_allow_extra_args()) {  // we allow optional arguments
2784             auto remreqpos = _count_remaining_positionals(true);
2785             // we have met the minimum now optionally check up to the maximum
2786             while((collected < max_num || op->get_allow_extra_args()) && !args.empty() &&
2787                   _recognize(args.back(), false) == detail::Classifier::NONE) {
2788                 // If any required positionals remain, don't keep eating
2789                 if(remreqpos >= args.size()) {
2790                     break;
2791                 }
2792 
2793                 op->add_result(args.back(), result_count);
2794                 parse_order_.push_back(op.get());
2795                 args.pop_back();
2796                 collected += result_count;
2797             }
2798 
2799             // Allow -- to end an unlimited list and "eat" it
2800             if(!args.empty() && _recognize(args.back()) == detail::Classifier::POSITIONAL_MARK)
2801                 args.pop_back();
2802             // optional flag that didn't receive anything now get the default value
2803             if(min_num == 0 && max_num > 0 && collected == 0) {
2804                 auto res = op->get_flag_value(arg_name, std::string{});
2805                 op->add_result(res);
2806                 parse_order_.push_back(op.get());
2807             }
2808         }
2809 
2810         // if we only partially completed a type then add an empty string for later processing
2811         if(min_num > 0 && op->get_type_size_max() != min_num && (collected % op->get_type_size_max()) != 0) {
2812             op->add_result(std::string{});
2813         }
2814 
2815         if(!rest.empty()) {
2816             rest = "-" + rest;
2817             args.push_back(rest);
2818         }
2819         return true;
2820     }
2821 
2822     /// Trigger the pre_parse callback if needed
2823     void _trigger_pre_parse(std::size_t remaining_args) {
2824         if(!pre_parse_called_) {
2825             pre_parse_called_ = true;
2826             if(pre_parse_callback_) {
2827                 pre_parse_callback_(remaining_args);
2828             }
2829         } else if(immediate_callback_) {
2830             if(!name_.empty()) {
2831                 auto pcnt = parsed_;
2832                 auto extras = std::move(missing_);
2833                 clear();
2834                 parsed_ = pcnt;
2835                 pre_parse_called_ = true;
2836                 missing_ = std::move(extras);
2837             }
2838         }
2839     }
2840 
2841     /// Get the appropriate parent to fallthrough to which is the first one that has a name or the main app
2842     App *_get_fallthrough_parent() {
2843         if(parent_ == nullptr) {
2844             throw(HorribleError("No Valid parent"));
2845         }
2846         auto fallthrough_parent = parent_;
2847         while((fallthrough_parent->parent_ != nullptr) && (fallthrough_parent->get_name().empty())) {
2848             fallthrough_parent = fallthrough_parent->parent_;
2849         }
2850         return fallthrough_parent;
2851     }
2852 
2853     /// Helper function to run through all possible comparisons of subcommand names to check there is no overlap
2854     const std::string &_compare_subcommand_names(const App &subcom, const App &base) const {
2855         static const std::string estring;
2856         if(subcom.disabled_) {
2857             return estring;
2858         }
2859         for(auto &subc : base.subcommands_) {
2860             if(subc.get() != &subcom) {
2861                 if(subc->disabled_) {
2862                     continue;
2863                 }
2864                 if(!subcom.get_name().empty()) {
2865                     if(subc->check_name(subcom.get_name())) {
2866                         return subcom.get_name();
2867                     }
2868                 }
2869                 if(!subc->get_name().empty()) {
2870                     if(subcom.check_name(subc->get_name())) {
2871                         return subc->get_name();
2872                     }
2873                 }
2874                 for(const auto &les : subcom.aliases_) {
2875                     if(subc->check_name(les)) {
2876                         return les;
2877                     }
2878                 }
2879                 // this loop is needed in case of ignore_underscore or ignore_case on one but not the other
2880                 for(const auto &les : subc->aliases_) {
2881                     if(subcom.check_name(les)) {
2882                         return les;
2883                     }
2884                 }
2885                 // if the subcommand is an option group we need to check deeper
2886                 if(subc->get_name().empty()) {
2887                     auto &cmpres = _compare_subcommand_names(subcom, *subc);
2888                     if(!cmpres.empty()) {
2889                         return cmpres;
2890                     }
2891                 }
2892                 // if the test subcommand is an option group we need to check deeper
2893                 if(subcom.get_name().empty()) {
2894                     auto &cmpres = _compare_subcommand_names(*subc, subcom);
2895                     if(!cmpres.empty()) {
2896                         return cmpres;
2897                     }
2898                 }
2899             }
2900         }
2901         return estring;
2902     }
2903     /// Helper function to place extra values in the most appropriate position
2904     void _move_to_missing(detail::Classifier val_type, const std::string &val) {
2905         if(allow_extras_ || subcommands_.empty()) {
2906             missing_.emplace_back(val_type, val);
2907             return;
2908         }
2909         // allow extra arguments to be places in an option group if it is allowed there
2910         for(auto &subc : subcommands_) {
2911             if(subc->name_.empty() && subc->allow_extras_) {
2912                 subc->missing_.emplace_back(val_type, val);
2913                 return;
2914             }
2915         }
2916         // if we haven't found any place to put them yet put them in missing
2917         missing_.emplace_back(val_type, val);
2918     }
2919 
2920   public:
2921     /// function that could be used by subclasses of App to shift options around into subcommands
2922     void _move_option(Option *opt, App *app) {
2923         if(opt == nullptr) {
2924             throw OptionNotFound("the option is NULL");
2925         }
2926         // verify that the give app is actually a subcommand
2927         bool found = false;
2928         for(auto &subc : subcommands_) {
2929             if(app == subc.get()) {
2930                 found = true;
2931             }
2932         }
2933         if(!found) {
2934             throw OptionNotFound("The Given app is not a subcommand");
2935         }
2936 
2937         if((help_ptr_ == opt) || (help_all_ptr_ == opt))
2938             throw OptionAlreadyAdded("cannot move help options");
2939 
2940         if(config_ptr_ == opt)
2941             throw OptionAlreadyAdded("cannot move config file options");
2942 
2943         auto iterator =
2944             std::find_if(std::begin(options_), std::end(options_), [opt](const Option_p &v) { return v.get() == opt; });
2945         if(iterator != std::end(options_)) {
2946             const auto &opt_p = *iterator;
2947             if(std::find_if(std::begin(app->options_), std::end(app->options_), [&opt_p](const Option_p &v) {
2948                    return (*v == *opt_p);
2949                }) == std::end(app->options_)) {
2950                 // only erase after the insertion was successful
2951                 app->options_.push_back(std::move(*iterator));
2952                 options_.erase(iterator);
2953             } else {
2954                 throw OptionAlreadyAdded("option was not located: " + opt->get_name());
2955             }
2956         } else {
2957             throw OptionNotFound("could not locate the given Option");
2958         }
2959     }
2960 };  // namespace CLI
2961 
2962 /// Extension of App to better manage groups of options
2963 class Option_group : public App {
2964   public:
2965     Option_group(std::string group_description, std::string group_name, App *parent)
2966         : App(std::move(group_description), "", parent) {
2967         group(group_name);
2968         // option groups should have automatic fallthrough
2969     }
2970     using App::add_option;
2971     /// Add an existing option to the Option_group
2972     Option *add_option(Option *opt) {
2973         if(get_parent() == nullptr) {
2974             throw OptionNotFound("Unable to locate the specified option");
2975         }
2976         get_parent()->_move_option(opt, this);
2977         return opt;
2978     }
2979     /// Add an existing option to the Option_group
2980     void add_options(Option *opt) { add_option(opt); }
2981     /// Add a bunch of options to the group
2982     template <typename... Args> void add_options(Option *opt, Args... args) {
2983         add_option(opt);
2984         add_options(args...);
2985     }
2986     using App::add_subcommand;
2987     /// Add an existing subcommand to be a member of an option_group
2988     App *add_subcommand(App *subcom) {
2989         App_p subc = subcom->get_parent()->get_subcommand_ptr(subcom);
2990         subc->get_parent()->remove_subcommand(subcom);
2991         add_subcommand(std::move(subc));
2992         return subcom;
2993     }
2994 };
2995 /// Helper function to enable one option group/subcommand when another is used
2996 inline void TriggerOn(App *trigger_app, App *app_to_enable) {
2997     app_to_enable->enabled_by_default(false);
2998     app_to_enable->disabled_by_default();
2999     trigger_app->preparse_callback([app_to_enable](std::size_t) { app_to_enable->disabled(false); });
3000 }
3001 
3002 /// Helper function to enable one option group/subcommand when another is used
3003 inline void TriggerOn(App *trigger_app, std::vector<App *> apps_to_enable) {
3004     for(auto &app : apps_to_enable) {
3005         app->enabled_by_default(false);
3006         app->disabled_by_default();
3007     }
3008 
3009     trigger_app->preparse_callback([apps_to_enable](std::size_t) {
3010         for(auto &app : apps_to_enable) {
3011             app->disabled(false);
3012         }
3013     });
3014 }
3015 
3016 /// Helper function to disable one option group/subcommand when another is used
3017 inline void TriggerOff(App *trigger_app, App *app_to_enable) {
3018     app_to_enable->disabled_by_default(false);
3019     app_to_enable->enabled_by_default();
3020     trigger_app->preparse_callback([app_to_enable](std::size_t) { app_to_enable->disabled(); });
3021 }
3022 
3023 /// Helper function to disable one option group/subcommand when another is used
3024 inline void TriggerOff(App *trigger_app, std::vector<App *> apps_to_enable) {
3025     for(auto &app : apps_to_enable) {
3026         app->disabled_by_default(false);
3027         app->enabled_by_default();
3028     }
3029 
3030     trigger_app->preparse_callback([apps_to_enable](std::size_t) {
3031         for(auto &app : apps_to_enable) {
3032             app->disabled();
3033         }
3034     });
3035 }
3036 
3037 /// Helper function to mark an option as deprecated
3038 inline void deprecate_option(Option *opt, const std::string &replacement = "") {
3039     Validator deprecate_warning{[opt, replacement](std::string &) {
3040                                     std::cout << opt->get_name() << " is deprecated please use '" << replacement
3041                                               << "' instead\n";
3042                                     return std::string();
3043                                 },
3044                                 "DEPRECATED"};
3045     deprecate_warning.application_index(0);
3046     opt->check(deprecate_warning);
3047     if(!replacement.empty()) {
3048         opt->description(opt->get_description() + " DEPRECATED: please use '" + replacement + "' instead");
3049     }
3050 }
3051 
3052 /// Helper function to mark an option as deprecated
3053 inline void deprecate_option(App *app, const std::string &option_name, const std::string &replacement = "") {
3054     auto opt = app->get_option(option_name);
3055     deprecate_option(opt, replacement);
3056 }
3057 
3058 /// Helper function to mark an option as deprecated
3059 inline void deprecate_option(App &app, const std::string &option_name, const std::string &replacement = "") {
3060     auto opt = app.get_option(option_name);
3061     deprecate_option(opt, replacement);
3062 }
3063 
3064 /// Helper function to mark an option as retired
3065 inline void retire_option(App *app, Option *opt) {
3066     App temp;
3067     auto option_copy = temp.add_option(opt->get_name(false, true))
3068                            ->type_size(opt->get_type_size_min(), opt->get_type_size_max())
3069                            ->expected(opt->get_expected_min(), opt->get_expected_max())
3070                            ->allow_extra_args(opt->get_allow_extra_args());
3071 
3072     app->remove_option(opt);
3073     auto opt2 = app->add_option(option_copy->get_name(false, true), "option has been retired and has no effect")
3074                     ->type_name("RETIRED")
3075                     ->default_str("RETIRED")
3076                     ->type_size(option_copy->get_type_size_min(), option_copy->get_type_size_max())
3077                     ->expected(option_copy->get_expected_min(), option_copy->get_expected_max())
3078                     ->allow_extra_args(option_copy->get_allow_extra_args());
3079 
3080     Validator retired_warning{[opt2](std::string &) {
3081                                   std::cout << "WARNING " << opt2->get_name() << " is retired and has no effect\n";
3082                                   return std::string();
3083                               },
3084                               ""};
3085     retired_warning.application_index(0);
3086     opt2->check(retired_warning);
3087 }
3088 
3089 /// Helper function to mark an option as retired
3090 inline void retire_option(App &app, Option *opt) { retire_option(&app, opt); }
3091 
3092 /// Helper function to mark an option as retired
3093 inline void retire_option(App *app, const std::string &option_name) {
3094 
3095     auto opt = app->get_option_no_throw(option_name);
3096     if(opt != nullptr) {
3097         retire_option(app, opt);
3098         return;
3099     }
3100     auto opt2 = app->add_option(option_name, "option has been retired and has no effect")
3101                     ->type_name("RETIRED")
3102                     ->expected(0, 1)
3103                     ->default_str("RETIRED");
3104     Validator retired_warning{[opt2](std::string &) {
3105                                   std::cout << "WARNING " << opt2->get_name() << " is retired and has no effect\n";
3106                                   return std::string();
3107                               },
3108                               ""};
3109     retired_warning.application_index(0);
3110     opt2->check(retired_warning);
3111 }
3112 
3113 /// Helper function to mark an option as retired
3114 inline void retire_option(App &app, const std::string &option_name) { retire_option(&app, option_name); }
3115 
3116 namespace FailureMessage {
3117 
3118 /// Printout a clean, simple message on error (the default in CLI11 1.5+)
3119 inline std::string simple(const App *app, const Error &e) {
3120     std::string header = std::string(e.what()) + "\n";
3121     std::vector<std::string> names;
3122 
3123     // Collect names
3124     if(app->get_help_ptr() != nullptr)
3125         names.push_back(app->get_help_ptr()->get_name());
3126 
3127     if(app->get_help_all_ptr() != nullptr)
3128         names.push_back(app->get_help_all_ptr()->get_name());
3129 
3130     // If any names found, suggest those
3131     if(!names.empty())
3132         header += "Run with " + detail::join(names, " or ") + " for more information.\n";
3133 
3134     return header;
3135 }
3136 
3137 /// Printout the full help string on error (if this fn is set, the old default for CLI11)
3138 inline std::string help(const App *app, const Error &e) {
3139     std::string header = std::string("ERROR: ") + e.get_name() + ": " + e.what() + "\n";
3140     header += app->help();
3141     return header;
3142 }
3143 
3144 }  // namespace FailureMessage
3145 
3146 namespace detail {
3147 /// This class is simply to allow tests access to App's protected functions
3148 struct AppFriend {
3149 #ifdef CLI11_CPP14
3150 
3151     /// Wrap _parse_short, perfectly forward arguments and return
3152     template <typename... Args> static decltype(auto) parse_arg(App *app, Args &&... args) {
3153         return app->_parse_arg(std::forward<Args>(args)...);
3154     }
3155 
3156     /// Wrap _parse_subcommand, perfectly forward arguments and return
3157     template <typename... Args> static decltype(auto) parse_subcommand(App *app, Args &&... args) {
3158         return app->_parse_subcommand(std::forward<Args>(args)...);
3159     }
3160 #else
3161     /// Wrap _parse_short, perfectly forward arguments and return
3162     template <typename... Args>
3163     static auto parse_arg(App *app, Args &&... args) ->
3164         typename std::result_of<decltype (&App::_parse_arg)(App, Args...)>::type {
3165         return app->_parse_arg(std::forward<Args>(args)...);
3166     }
3167 
3168     /// Wrap _parse_subcommand, perfectly forward arguments and return
3169     template <typename... Args>
3170     static auto parse_subcommand(App *app, Args &&... args) ->
3171         typename std::result_of<decltype (&App::_parse_subcommand)(App, Args...)>::type {
3172         return app->_parse_subcommand(std::forward<Args>(args)...);
3173     }
3174 #endif
3175     /// Wrap the fallthrough parent function to make sure that is working correctly
3176     static App *get_fallthrough_parent(App *app) { return app->_get_fallthrough_parent(); }
3177 };
3178 }  // namespace detail
3179 
3180 // [CLI11:app_hpp:end]
3181 }  // namespace CLI