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