27 #ifndef LBANN_UTILS_ARGUMENT_PARSER_HPP_INCLUDED 28 #define LBANN_UTILS_ARGUMENT_PARSER_HPP_INCLUDED 36 #include <initializer_list> 41 #include <unordered_map> 42 #include <unordered_set> 58 parse_error(T&& what_arg) : std::runtime_error{std::forward<T>(what_arg)}
69 void handle_error(clara::detail::InternalParseResult result,
70 clara::Parser& parser,
71 std::vector<char const*>& argv);
82 void handle_error(clara::detail::InternalParseResult result,
83 clara::Parser& parser,
84 std::vector<char const*>& argv);
159 template <
typename ErrorHandler>
174 template <
typename T>
179 T
const&
get()
const noexcept {
return ref_; }
180 operator T
const&()
const noexcept {
return this->
get(); }
182 template <
typename S>
185 return this->
get() == y;
201 template <
typename T>
202 parse_error(T&& what_arg) : std::runtime_error{std::forward<T>(what_arg)}
218 template <
typename Container>
220 : std::runtime_error{build_what_string_(missing_args)}
224 template <
typename Container>
227 std::ostringstream oss;
228 oss <<
"The following required arguments are missing: {";
229 for (
auto const& x : missing_args)
230 oss <<
" \"" << x <<
"\"";
291 add_flag(std::string
const& name,
292 std::initializer_list<std::string> cli_flags,
316 template <
typename AccessPolicy>
319 std::initializer_list<std::string> cli_flags,
321 std::string
const& description)
323 if (env.
exists() && env.template value<bool>())
324 return add_flag_impl_(name,
325 std::move(cli_flags),
326 description +
"\nENV: {" + env.
name() +
"}",
329 return add_flag(name,
330 std::move(cli_flags),
331 description +
"\nENV: {" + env.
name() +
"}");
356 template <
typename T>
358 std::initializer_list<std::string> cli_flags,
359 std::string
const& description,
360 T default_value = T());
388 template <
typename T,
typename AccessPolicy>
390 std::initializer_list<std::string> cli_flags,
392 std::string
const& description,
393 T default_value = T())
396 return add_option(name,
397 std::move(cli_flags),
398 description +
"\nENV: {" + env.
name() +
"}",
399 env.template value<T>());
401 return add_option(name,
402 std::move(cli_flags),
403 description +
"\nENV: {" + env.
name() +
"}",
404 std::move(default_value));
426 std::initializer_list<std::string> cli_flags,
427 std::string
const& description,
428 char const* default_value)
430 return add_option(name,
431 std::move(cli_flags),
433 std::string(default_value));
455 template <
typename AccessPolicy>
458 std::initializer_list<std::string> cli_flags,
460 std::string
const& description,
461 char const* default_value)
463 return add_option(name,
466 description +
"\nENV: {" + env.
name() +
"}",
467 std::string(default_value));
489 template <
typename T>
491 std::string
const& description,
492 T default_value = T());
509 std::string
const& description,
510 char const* default_value)
512 return add_argument(name, description, std::string(default_value));
526 template <
typename T>
528 std::string
const& description);
535 void clear() noexcept;
552 void parse(
int argc,
char const*
const argv[]);
567 void parse_no_finalize(
int argc,
char const*
const argv[]);
591 std::string get_exe_name()
const noexcept;
600 bool option_is_defined(std::string
const& option_name)
const;
603 bool help_requested()
const;
610 template <
typename T>
611 T
const&
get(std::string
const& option_name)
const;
620 void print_help(std::ostream& stream)
const;
626 void init() noexcept;
630 add_flag_impl_(std::string
const& name,
631 std::initializer_list<std::string> cli_flags,
632 std::string
const& description,
637 std::unordered_map<std::string, std::any>
params_;
644 template <
typename ErrorHandler>
646 std::string
const& option_name)
const 648 return params_.count(option_name);
651 template <
typename ErrorHandler>
652 template <
typename T>
656 if (!option_is_defined(option_name)) {
659 return std::any_cast<T
const&>(params_.at(option_name));
662 template <
typename ErrorHandler>
663 template <
typename T>
665 std::string
const& name,
666 std::initializer_list<std::string> cli_flags,
667 std::string
const& description,
670 params_[name] = std::move(default_value);
671 auto& param_ref = std::any_cast<T&>(params_[name]);
672 clara::Opt option(param_ref, name);
673 for (
auto const& f : cli_flags)
675 parser_ |= option(description).optional();
679 template <
typename ErrorHandler>
680 template <
typename T>
683 std::string
const& description,
687 params_[name] = std::move(default_value);
688 auto& param_ref = std::any_cast<T&>(params_[name]);
689 parser_ |= clara::Arg(param_ref, name)(description).optional();
693 template <
typename ErrorHandler>
694 template <
typename T>
696 std::string
const& name,
701 auto& param_any = params_[name];
702 auto& param_ref = std::any_cast<T&>(param_any);
704 required_.insert(name);
707 auto iter = parser_.m_args.cbegin(),
invalid = parser_.m_args.cend();
708 while (iter !=
invalid && !iter->isOptional())
712 auto ret = parser_.m_args.emplace(
714 [name, ¶m_ref,
this](std::string
const& value) {
715 auto result = clara::detail::convertInto(value, param_ref);
717 required_.erase(name);
721 ret->operator()(description).required();
725 template <
typename ErrorHandler>
731 template <
typename ErrorHandler>
734 std::unordered_map<std::string, std::any>{}.swap(params_);
735 std::unordered_set<std::string>{}.swap(required_);
736 parser_ = clara::Parser{};
740 template <
typename ErrorHandler>
743 params_[
"print help"] =
false;
744 parser_ |= clara::ExeName();
745 parser_ |= clara::Help(std::any_cast<bool&>(params_[
"print help"]));
748 template <
typename ErrorHandler>
751 parse_no_finalize(argc, argv);
755 template <
typename ErrorHandler>
757 char const*
const argv[])
759 std::vector<char const*> newargv(argv, argv + argc);
761 parser_.parse(clara::Args(newargv.size(), newargv.data()));
764 this->handle_error(parse_result, parser_, newargv);
767 template <
typename ErrorHandler>
770 if (!help_requested() && required_.size())
774 template <
typename ErrorHandler>
776 std::string
const& name,
777 std::initializer_list<std::string> cli_flags,
780 return add_flag_impl_(name, std::move(cli_flags), description,
false);
783 template <
typename ErrorHandler>
786 return parser_.m_exeName.name();
789 template <
typename ErrorHandler>
792 return std::any_cast<
bool>(params_.at(
"print help"));
795 template <
typename ErrorHandler>
798 out << parser_ << std::endl;
801 template <
typename ErrorHandler>
803 std::string
const& name,
804 std::initializer_list<std::string> cli_flags,
805 std::string
const& description,
808 params_[name] = default_value;
809 auto& param_ref = std::any_cast<
bool&>(params_[name]);
810 clara::Opt option(param_ref);
811 for (
auto const& f : cli_flags)
813 parser_ |= option(description).optional();
826 template <
typename ErrorHandler>
std::string get_exe_name() const noexcept
Get the executable name.
Basic argument parsing with automatic help messages.
bool exists() const
Test if the variable exists in the environment.
readonly_reference< bool > add_flag(std::string const &name, std::initializer_list< std::string > cli_flags, EnvVariable< AccessPolicy > env, std::string const &description)
Add a flag with environment variable override.
void parse_no_finalize(int argc, char const *const argv[])
Parse the command line arguments but do not finalize the parser.
argument_parser()
Create the parser.
readonly_reference< T > add_option(std::string const &name, std::initializer_list< std::string > cli_flags, std::string const &description, T default_value=T())
Add an additional named option.
std::exception subclass that is thrown if the parser can not parse the arguments. ...
readonly_reference< T > add_option(std::string const &name, std::initializer_list< std::string > cli_flags, EnvVariable< AccessPolicy > env, std::string const &description, T default_value=T())
Add an additional named option.
readonly_reference< bool > add_flag_impl_(std::string const &name, std::initializer_list< std::string > cli_flags, std::string const &description, bool default_value)
Implementation of add_flag.
readonly_reference< T > add_argument(std::string const &name, std::string const &description, T default_value=T())
Add an optional positional argument.
std::string build_what_string_(Container const &missing_args)
Generates nicely formatted description messages.
T const & get(std::string const &option_name) const
Get the requested value from the argument list.
std::string const & name() const noexcept
Get the name of the environment variable.
void parse(int argc, char const *const argv[])
Parse the command line arguments and finalize the arguments.
std::unordered_set< std::string > required_
Patch around in-progress clara limitation.
readonly_reference< bool > add_flag(std::string const &name, std::initializer_list< std::string > cli_flags, std::string const &description)
Add a flag (i.e. a boolean parameter that is "true" if given and "false" if not given).
parse_error(T &&what_arg)
Construct the exception with the string to be return by what()
readonly_reference< std::string > add_option(std::string const &name, std::initializer_list< std::string > cli_flags, EnvVariable< AccessPolicy > env, std::string const &description, char const *default_value)
Add an additional named option; overloaded for "char const*" parameters.
bool operator==(S const &y) const noexcept
std::exception subclass that is thrown if the parser can not parse the arguments. ...
parse_error(T &&what_arg)
Construct the exception with the string to be return by what()
void clear() noexcept
Clear all state in the parser.
bool help_requested() const
Test if help has been requested.
std::ostream & operator<<(std::ostream &os, const ParallelStrategy &ps)
clara::Parser parser_
The underlying clara object.
readonly_reference< std::string > add_option(std::string const &name, std::initializer_list< std::string > cli_flags, std::string const &description, char const *default_value)
Add an additional named option; overloaded for "char const*" parameters.
std::exception subclass that is thrown if a required argument is not found.
void print_help(std::ostream &stream) const
Print a help string to a stream.
std::unordered_map< std::string, std::any > params_
Dictionary of arguments to their values.
void finalize() const
Assert that all required components are set properly.
bool option_is_defined(std::string const &option_name) const
Test if an option exists in the parser.
default_arg_parser_type & global_argument_parser()
void init() noexcept
Reinitialize the parser.
readonly_reference< std::string > add_argument(std::string const &name, std::string const &description, char const *default_value)
Add a positional argument; char const* overload.
void finalize(lbann_comm *comm=nullptr)
readonly_reference< T > add_required_argument(std::string const &name, std::string const &description)
Add a "required" positional argument.
A proxy class representing the current value associated with an option.
missing_required_arguments(Container const &missing_args)
Construct the exception with a list of the missing argument names.
readonly_reference(T &val) noexcept