timemory 3.3.0
Modular C++ Toolkit for Performance Analysis and Logging. Profiling API and Tools for C, C++, CUDA, Fortran, and Python. The C++ template API is essentially a framework to creating tools: it is designed to provide a unifying interface for recording various performance measurements alongside data logging and interfaces to other tools.
tim::argparse::argument_parser Struct Reference

#include "timemory/utility/argparse.hpp"

+ Collaboration diagram for tim::argparse::argument_parser:

Classes

struct  arg_result
 
struct  argument
 

Public Types

using this_type = argument_parser
 
using result_type = arg_result
 
using bool_func_t = std::function< bool(this_type &)>
 
using action_func_t = std::function< void(this_type &)>
 
using action_pair_t = std::pair< bool_func_t, action_func_t >
 
using error_func_t = std::function< void(this_type &, arg_result &)>
 
using known_args_t = std::tuple< arg_result, int, char ** >
 
using strvec_t = std::vector< std::string >
 
using strset_t = std::set< std::string >
 

Public Member Functions

 argument_parser (std::string desc)
 
argumentadd_argument ()
 
argumentadd_argument (const std::initializer_list< std::string > &_names, const std::string &desc, bool req=false)
 
argumentadd_argument (const std::vector< std::string > &_names, const std::string &desc, bool req=false)
 
argumentadd_positional_argument (const std::string &_name)
 
template<typename Tp >
arg_result get (size_t _idx, Tp &_value)
 
template<typename Tp >
arg_result get (const std::string &_name, Tp &_value)
 
template<typename BoolFuncT , typename ActionFuncT >
this_typeadd_action (BoolFuncT &&_b, ActionFuncT &_act)
 
template<typename ActionFuncT >
this_typeadd_action (const std::string &_name, ActionFuncT &_act)
 
void print_help (const std::string &_extra="")
 
known_args_t parse_known_args (int argc, char **argv, const std::string &_delim="--", int verbose_level=0)
 Basic variant of parse_known_args which does not replace argc/argv and does not provide an array of strings that it processed. More...
 
arg_result parse_known_args (int *argc, char ***argv, const std::string &_delim="--", int verbose_level=0)
 This variant calls parse_known_args and replaces argc and argv with the argv[0] + anything after delimiter (if the delimiter is provided). If the delimiter does not exist, argc and argv are unchanged. More...
 
arg_result parse_known_args (int *argc, char ***argv, strvec_t &_args, const std::string &_delim="--", int verbose_level=0)
 
known_args_t parse_known_args (int argc, char **argv, strvec_t &_args, const std::string &_delim="--", int verbose_level=0)
 Parses all options until argv[argc-1] or delimiter is found. Returns a tuple containing an argument error object (operator bool will return true if there was an error) and the new argc and argv after the known arguments have been processed. This is slightly different from the Python argparse.ArgumentParser.parse_known_args: if the delimiter is not found, it will not remove the arguments that it recognizes. To distinguish this parsers options from user arguments, use the syntax: More...
 
template<typename... Args>
arg_result parse_args (Args &&... args)
 
arg_result parse (int argc, char **argv, int verbose_level=0)
 
arg_result parse (const std::vector< std::string > &_args, int verbose_level=0)
 This is the primary function for parsing the command line arguments. This is where the map of the options is built and the loop over the arguments is performed. More...
 
argumentenable_help ()
 Add a help command. More...
 
bool exists (const std::string &name) const
 Returns whether or not an option was found in the arguments. Only useful after a call to parse or parse_known_args. More...
 
template<typename T >
get (const std::string &name)
 Get the value(s) associated with an argument. If option, it should be used in conjunction with exists(name). Only useful after a call to parse or parse_known_args. More...
 
int64_t get_count (const std::string &name)
 
int64_t get_positional_count () const
 
template<typename ErrorFuncT >
void on_error (ErrorFuncT &&_func)
 
void set_help_width (int _v)
 

Static Public Member Functions

static int64_t get_count (argument &a)
 

Detailed Description

Definition at line 323 of file argparse.hpp.

Member Typedef Documentation

◆ action_func_t

Definition at line 330 of file argparse.hpp.

◆ action_pair_t

◆ bool_func_t

Definition at line 329 of file argparse.hpp.

◆ error_func_t

Definition at line 332 of file argparse.hpp.

◆ known_args_t

using tim::argparse::argument_parser::known_args_t = std::tuple<arg_result, int, char**>

Definition at line 333 of file argparse.hpp.

◆ result_type

◆ strset_t

using tim::argparse::argument_parser::strset_t = std::set<std::string>

Definition at line 335 of file argparse.hpp.

◆ strvec_t

using tim::argparse::argument_parser::strvec_t = std::vector<std::string>

Definition at line 334 of file argparse.hpp.

◆ this_type

Constructor & Destructor Documentation

◆ argument_parser()

tim::argparse::argument_parser::argument_parser ( std::string  desc)
inline

Definition at line 630 of file argparse.hpp.

631 : m_desc(std::move(desc))
632 {}

Member Function Documentation

◆ add_action() [1/2]

template<typename BoolFuncT , typename ActionFuncT >
this_type & tim::argparse::argument_parser::add_action ( BoolFuncT &&  _b,
ActionFuncT &  _act 
)
inline

Definition at line 731 of file argparse.hpp.

732 {
733 m_actions.push_back(
734 { std::forward<BoolFuncT>(_b), std::forward<ActionFuncT>(_act) });
735 return *this;
736 }

◆ add_action() [2/2]

template<typename ActionFuncT >
this_type & tim::argparse::argument_parser::add_action ( const std::string &  _name,
ActionFuncT &  _act 
)
inline

Definition at line 741 of file argparse.hpp.

742 {
743 auto _b = [=](this_type& p) { return p.exists(_name); };
744 m_actions.push_back({ _b, std::forward<ActionFuncT>(_act) });
745 return *this;
746 }

References exists().

◆ add_argument() [1/3]

argument & tim::argparse::argument_parser::add_argument ( )
inline

Definition at line 636 of file argparse.hpp.

637 {
638 m_arguments.push_back({});
639 m_arguments.back().m_index = static_cast<int>(m_arguments.size()) - 1;
640 return m_arguments.back();
641 }

Referenced by tim::tsettings< Tp, Vp >::add_argument(), add_argument(), enable_help(), and tim::for().

◆ add_argument() [2/3]

argument & tim::argparse::argument_parser::add_argument ( const std::initializer_list< std::string > &  _names,
const std::string &  desc,
bool  req = false 
)
inline

Definition at line 645 of file argparse.hpp.

647 {
648 return add_argument().names(_names).description(desc).required(req);
649 }
argument & description(const std::string &description)
Definition: argparse.hpp:390
argument & names(const std::vector< std::string > &names)
Definition: argparse.hpp:383

References add_argument(), tim::argparse::argument_parser::argument::description(), tim::argparse::argument_parser::argument::names(), and tim::argparse::argument_parser::argument::required().

◆ add_argument() [3/3]

argument & tim::argparse::argument_parser::add_argument ( const std::vector< std::string > &  _names,
const std::string &  desc,
bool  req = false 
)
inline

◆ add_positional_argument()

argument & tim::argparse::argument_parser::add_positional_argument ( const std::string &  _name)
inline

Definition at line 661 of file argparse.hpp.

662 {
663 m_positional_arguments.push_back({});
664 auto& _entry = m_positional_arguments.back();
665 _entry.name(_name);
666 _entry.count(1);
667 _entry.m_index = m_positional_arguments.size();
668 return _entry;
669 }

◆ enable_help()

argument & tim::argparse::argument_parser::enable_help ( )
inline

Add a help command.

Definition at line 871 of file argparse.hpp.

872 {
873 m_help_enabled = true;
874 return add_argument()
875 .names({ "-h", "-?", "--help" })
876 .description("Shows this page")
877 .count(0);
878 }
description("A generic option for any setting. Each argument MUST be passed in " "form: 'NAME=VALUE'. E.g. --timemory-args " "\"papi_events=PAPI_TOT_INS,PAPI_TOT_CYC\" text_output=off") .action([&](parser_t &p)
Definition: config.cpp:312

References add_argument(), tim::description(), and tim::argparse::argument_parser::argument::names().

◆ exists()

bool tim::argparse::argument_parser::exists ( const std::string &  name) const
inline

Returns whether or not an option was found in the arguments. Only useful after a call to parse or parse_known_args.

int main(int argc, char** argv)
{
p.add_argument()
.names({ "-h", "--help"})
.description("Help message")
.count(0);
auto ec = p.parse(argc, argv);
if(ec)
{
std::cerr << "Error: " << ec << std::endl;
exit(EXIT_FAILURE);
}
if(p.exists("help"))
{
p.print_help();
exit(EXIT_FAILURE);
}
// ...
}
auto ec
char ** argv
Definition: config.cpp:55
argument_parser(std::string desc)
Definition: argparse.hpp:630

Definition at line 912 of file argparse.hpp.

913 {
914 std::string n = helpers::ltrim(
915 name, [](int c) -> bool { return c != static_cast<int>('-'); });
916 auto itr = m_name_map.find(n);
917 if(itr != m_name_map.end())
918 return m_arguments[static_cast<size_t>(itr->second)].m_found;
919 return false;
920 }
tim::mpl::apply< std::string > string
Definition: macros.hpp:53

Referenced by add_action(), and parse_known_args().

◆ get() [1/3]

template<typename Tp >
arg_result tim::argparse::argument_parser::get ( const std::string &  _name,
Tp &  _value 
)
inline

Definition at line 689 of file argparse.hpp.

690 {
691 // loop over parsed positional args
692 for(size_t i = 0; i < m_positional_values.size(); ++i)
693 {
694 if(i >= m_positional_arguments.size())
695 break;
696
697 // loop over added positional args
698 auto& itr = m_positional_arguments.at(i);
699 for(auto& nitr : itr.m_names)
700 {
701 if(nitr == _name)
702 return get(i, _value);
703 }
704 }
705
706 // not found, check if required
707 for(auto& itr : m_positional_arguments)
708 {
709 for(auto& nitr : itr.m_names)
710 {
711 if(nitr == _name)
712 {
713 if(itr.m_default &&
714 itr.m_default_tidx == std::type_index{ typeid(decay_t<Tp>) })
715 _value = (*static_cast<Tp*>(itr.m_default));
716 else if(itr.m_required)
717 return arg_result{
718 _name + " not parsed from the command line (required)"
719 };
720 return arg_result{};
721 }
722 }
723 }
724
725 return arg_result{ _name + " is not a named positional argument" };
726 }
arg_result get(size_t _idx, Tp &_value)
Definition: argparse.hpp:674

References get().

◆ get() [2/3]

template<typename T >
T tim::argparse::argument_parser::get ( const std::string &  name)
inline

Get the value(s) associated with an argument. If option, it should be used in conjunction with exists(name). Only useful after a call to parse or parse_known_args.

Template Parameters
TData type to convert the argument into
Parameters
[in]nameAn identifier of the option
int main(int argc, char** argv)
{
p.add_argument()
.names({ "-n", "--iterations"})
.description("Number of iterations")
.count(1);
// ... etc.
auto nitr = p.get<size_t>("iteration");
// ... etc.
}

Definition at line 950 of file argparse.hpp.

951 {
952 auto itr = m_name_map.find(name);
953 if(itr != m_name_map.end())
954 return m_arguments[static_cast<size_t>(itr->second)].get<T>();
955 return T{};
956 }

◆ get() [3/3]

template<typename Tp >
arg_result tim::argparse::argument_parser::get ( size_t  _idx,
Tp &  _value 
)
inline

Definition at line 674 of file argparse.hpp.

675 {
676 if(m_positional_values.find(_idx) == m_positional_values.end())
677 return arg_result{ "Positional value not found at index " +
678 std::to_string(_idx) };
679 if(_idx >= m_positional_arguments.size())
680 return arg_result{ "No positional argument was specified for index " +
681 std::to_string(_idx) };
682 _value = m_positional_arguments.at(_idx).get<Tp>();
683 return arg_result{};
684 }

Referenced by tim::description(), get(), tim::component::network_stats::get_interfaces(), and tim::settings::parse().

◆ get_count() [1/2]

static int64_t tim::argparse::argument_parser::get_count ( argument a)
inlinestatic

Definition at line 974 of file argparse.hpp.

974{ return a.m_values.size(); }

◆ get_count() [2/2]

int64_t tim::argparse::argument_parser::get_count ( const std::string &  name)
inline

Definition at line 960 of file argparse.hpp.

961 {
962 auto itr = m_name_map.find(name);
963 if(itr != m_name_map.end())
964 return m_arguments[static_cast<size_t>(itr->second)].size();
965 return 0;
966 }

◆ get_positional_count()

int64_t tim::argparse::argument_parser::get_positional_count ( ) const
inline

Definition at line 970 of file argparse.hpp.

970{ return m_positional_values.size(); }

◆ on_error()

template<typename ErrorFuncT >
void tim::argparse::argument_parser::on_error ( ErrorFuncT &&  _func)
inline

Definition at line 979 of file argparse.hpp.

980 {
981 on_error_sfinae(std::forward<ErrorFuncT>(_func), 0);
982 }

◆ parse() [1/2]

arg_result tim::argparse::argument_parser::parse ( const std::vector< std::string > &  args,
int  verb = 0 
)

This is the primary function for parsing the command line arguments. This is where the map of the options is built and the loop over the arguments is performed.

Parameters
[in]argsArray of strings (i.e. command-line arguments)
[in]verbVerbosity

Definition at line 375 of file argparse.cpp.

376{
377 if(verbose_level > 0)
378 {
379 std::cerr << "[argparse::parse]> parsing '";
380 for(const auto& itr : _args)
381 std::cerr << itr << " ";
382 std::cerr << "'" << '\n';
383 }
384
385 for(auto& a : m_arguments)
386 a.m_callback(a.m_default);
387 for(auto& a : m_positional_arguments)
388 a.m_callback(a.m_default);
389
390 using argmap_t = std::map<std::string, argument*>;
391
392 argmap_t m_arg_map = {};
393 arg_result err;
394 int argc = _args.size();
395 // the set of options which use a single leading dash but are longer than
396 // one character, e.g. -LS ...
397 std::set<std::string> long_short_opts;
398 if(_args.size() > 1)
399 {
400 auto is_leading_dash = [](int c) -> bool { return c != static_cast<int>('-'); };
401 // build name map
402 for(auto& a : m_arguments)
403 {
404 for(auto& n : a.m_names)
405 {
406 auto nleading_dash = helpers::lcount(n, is_leading_dash);
407 std::string name = helpers::ltrim(n, is_leading_dash);
408 if(name.empty())
409 continue;
410 if(m_name_map.find(name) != m_name_map.end())
411 return arg_result("Duplicate of argument name: " + n);
412 m_name_map[name] = a.m_index;
413 m_arg_map[name] = &a;
414 if(nleading_dash == 1 && name.length() > 1)
415 long_short_opts.insert(name);
416 }
417 if(a.m_position >= 0 || a.m_position == argument::Position::LastArgument)
418 m_positional_map.at(a.m_position) = a.m_index;
419 }
420
421 m_bin = _args.at(0);
422
423 // parse
424 std::string current_arg;
425 size_t arg_len;
426 for(int argv_index = 1; argv_index < argc; ++argv_index)
427 {
428 current_arg = _args.at(argv_index);
429 arg_len = current_arg.length();
430 if(arg_len == 0)
431 continue;
432 if(argv_index == argc - 1 &&
433 m_positional_map.find(argument::Position::LastArgument) !=
434 m_positional_map.end())
435 {
436 err = end_argument();
437 arg_result b = err;
438 err = add_value(current_arg, argument::Position::LastArgument);
439 if(b)
440 return b;
441 // return (m_error_func(*this, b), b);
442 if(err)
443 return (m_error_func(*this, err), err);
444 continue;
445 }
446
447 // count number of leading dashes
448 auto nleading_dash = helpers::lcount(current_arg, is_leading_dash);
449 // ignores the case if the arg is just a '-'
450 // look for -a (short) or --arg (long) args
451 bool is_arg = (nleading_dash > 0 && arg_len > 1 && arg_len != nleading_dash)
452 ? true
453 : false;
454
455 if(is_arg && !helpers::is_numeric(current_arg))
456 {
457 err = end_argument();
458 if(err)
459 return (m_error_func(*this, err), err);
460
461 auto name = current_arg.substr(nleading_dash);
462 auto islong = (nleading_dash > 1 || long_short_opts.count(name) > 0);
463 err = begin_argument(name, islong, argv_index);
464 if(err)
465 return (m_error_func(*this, err), err);
466 }
467 else if(current_arg.length() > 0)
468 {
469 // argument value
470 err = add_value(current_arg, argv_index);
471 if(err)
472 return (m_error_func(*this, err), err);
473 }
474 }
475 }
476
477 // return the help
478 if(m_help_enabled && exists("help"))
479 return arg_result("help requested");
480
481 err = end_argument();
482 if(err)
483 return (m_error_func(*this, err), err);
484
485 // check requirements
486 for(auto& a : m_arguments)
487 {
488 if(a.m_required && !a.m_found)
489 {
490 return arg_result("Required argument not found: " + a.m_names.at(0));
491 }
492 if(a.m_position >= 0 && argc >= a.m_position && !a.m_found)
493 {
494 return arg_result("argument " + a.m_names.at(0) + " expected in position " +
495 std::to_string(a.m_position));
496 }
497 }
498
499 // check requirements
500 for(auto& a : m_positional_arguments)
501 {
502 if(a.m_required && !a.m_found)
503 return arg_result("Required argument not found: " + a.m_names.at(0));
504 }
505
506 // check all the counts have been satisfied
507 for(auto& a : m_arguments)
508 {
509 if(a.m_found && a.m_default == nullptr)
510 {
511 auto cnt_err = check_count(a);
512 if(cnt_err)
513 return cnt_err;
514 }
515 }
516
517 // execute the global actions
518 for(auto& itr : m_actions)
519 {
520 if(itr.first(*this))
521 itr.second(*this);
522 }
523
524 // execute the argument-specific actions
525 for(auto& itr : m_arg_map)
526 {
527 if(exists(itr.first))
528 itr.second->execute_actions(*this);
529 }
530
531 return arg_result{};
532}
std::array< char *, 4 > _args
bool exists(const std::string &name) const
Returns whether or not an option was found in the arguments. Only useful after a call to parse or par...
Definition: argparse.hpp:912

References tim::_args.

◆ parse() [2/2]

arg_result tim::argparse::argument_parser::parse ( int  argc,
char **  argv,
int  verbose_level = 0 
)
inline

Definition at line 847 of file argparse.hpp.

848 {
849 std::vector<std::string> _args;
850 _args.reserve(argc);
851 for(int i = 0; i < argc; ++i)
852 _args.emplace_back((const char*) argv[i]);
853 return parse(_args, verbose_level);
854 }
arg_result parse(int argc, char **argv, int verbose_level=0)
Definition: argparse.hpp:847

References tim::_args, tim::argv, and parse().

Referenced by parse(), parse_args(), and parse_known_args().

◆ parse_args()

template<typename... Args>
arg_result tim::argparse::argument_parser::parse_args ( Args &&...  args)
inline

Definition at line 840 of file argparse.hpp.

841 {
842 return parse(std::forward<Args>(args)...);
843 }

References parse().

◆ parse_known_args() [1/4]

arg_result tim::argparse::argument_parser::parse_known_args ( int *  argc,
char ***  argv,
const std::string &  delim = "--",
int  verb = 0 
)
inline

This variant calls parse_known_args and replaces argc and argv with the argv[0] + anything after delimiter (if the delimiter is provided). If the delimiter does not exist, argc and argv are unchanged.

Parameters
[in,out]argcPointer to number of arguments (i.e. # of command-line args)
[in,out]argvPointer to array of strings (i.e. command-line)
[in]delimDelimiter which separates this argparser's opts from user's arguments
[in]verbverbosity

Definition at line 774 of file argparse.hpp.

776 {
777 strvec_t args{};
778 return parse_known_args(argc, argv, args, _delim, verbose_level);
779 }
known_args_t parse_known_args(int argc, char **argv, const std::string &_delim="--", int verbose_level=0)
Basic variant of parse_known_args which does not replace argc/argv and does not provide an array of s...
Definition: argparse.hpp:765
std::vector< std::string > strvec_t
Definition: argparse.hpp:334

References tim::argv, and parse_known_args().

◆ parse_known_args() [2/4]

TIMEMORY_UTILITY_INLINE argument_parser::arg_result tim::argparse::argument_parser::parse_known_args ( int *  argc,
char ***  argv,
strvec_t _args,
const std::string &  _delim = "--",
int  verbose_level = 0 
)

Definition at line 269 of file argparse.cpp.

271{
272 // check for help flag
273 auto help_check = [&](int _argc, char** _argv) {
274 strset_t help_args = { "-h", "--help", "-?" };
275 auto _help_req = (exists("help") ||
276 (_argc > 1 && help_args.find(_argv[1]) != help_args.end()));
277 if(_help_req && !exists("help"))
278 {
279 for(auto hitr : help_args)
280 {
281 auto hstr = hitr.substr(hitr.find_first_not_of('-'));
282 auto itr = m_name_map.find(hstr);
283 if(itr != m_name_map.end())
284 m_arguments[static_cast<size_t>(itr->second)].m_found = true;
285 }
286 }
287 return _help_req;
288 };
289
290 // check for a dash in th command line
291 bool _pdash = false;
292 for(int i = 1; i < *argc; ++i)
293 {
294 if((*argv)[i] == std::string("--"))
295 _pdash = true;
296 }
297
298 // parse the known args and get the remaining argc/argv
299 auto _pargs = parse_known_args(*argc, *argv, _args, _delim, verbose_level);
300 auto _perrc = std::get<0>(_pargs);
301 auto _pargc = std::get<1>(_pargs);
302 auto _pargv = std::get<2>(_pargs);
303
304 // check if help was requested before the dash (if dash exists)
305 if(help_check((_pdash) ? 0 : _pargc, _pargv))
306 return arg_result{ "help requested" };
307
308 // assign the argc and argv
309 *argc = _pargc;
310 *argv = _pargv;
311
312 return _perrc;
313}
std::set< std::string > strset_t
Definition: argparse.hpp:335

References tim::_args, tim::argv, exists(), and parse_known_args().

◆ parse_known_args() [3/4]

arg_result tim::argparse::argument_parser::parse_known_args ( int  argc,
char **  argv,
const std::string &  delim = "--",
int  verb = 0 
)
inline

Basic variant of parse_known_args which does not replace argc/argv and does not provide an array of strings that it processed.

Parameters
[in,out]argcNumber of arguments (i.e. # of command-line args)
[in,out]argvArray of strings (i.e. command-line)
[in]delimDelimiter which separates this argparser's opts from user's arguments
[in]verbverbosity

Definition at line 765 of file argparse.hpp.

767 {
768 strvec_t _args{};
769 return parse_known_args(argc, argv, _args, _delim, verbose_level);
770 }

References tim::_args, tim::argv, and parse_known_args().

Referenced by parse_known_args().

◆ parse_known_args() [4/4]

arg_result tim::argparse::argument_parser::parse_known_args ( int  argc,
char **  argv,
strvec_t args,
const std::string &  delim = "--",
int  verb = 0 
)

Parses all options until argv[argc-1] or delimiter is found. Returns a tuple containing an argument error object (operator bool will return true if there was an error) and the new argc and argv after the known arguments have been processed. This is slightly different from the Python argparse.ArgumentParser.parse_known_args: if the delimiter is not found, it will not remove the arguments that it recognizes. To distinguish this parsers options from user arguments, use the syntax:

Parameters
[in,out]argcNumber of arguments (i.e. # of command-line args)
[in,out]argvArray of strings (i.e. command-line)
[in,out]argsArray of strings processed by this parser
[in]delimDelimiter which separates this argparser's opts from user's arguments
[in]verbverbosity

./<CMD> <PARSER_OPTIONS> – <USER_ARGS>

And std::get<1>(...) on the return value will be the new argc. and std::get<2>(...) on the return value will be the new argv. Other valid usages:

./<CMD> –help (will report this parser's help message) ./<CMD> – –help (will report the applications help message, if supported) ./<CMD> <USER_ARGS> ./<CMD> <PARSER_OPTIONS> ./<CMD> <PARSER_OPTIONS> <USER_ARGS> (intermixed)

will not remove any of the known options. In other words, this will remove all arguments after <CMD> until the first "--" if reached and everything after the "--" will be placed in argv[1:]

Definition at line 316 of file argparse.cpp.

318{
319 int _cmdc = argc; // the argc after known args removed
320 char** _cmdv = argv; // the argv after known args removed
321 // _cmdv and argv are same pointer unless delimiter is found
322
323 if(argc > 0)
324 {
325 m_bin = std::string((const char*) argv[0]);
326 _args.push_back(std::string((const char*) argv[0]));
327 }
328
329 for(int i = 1; i < argc; ++i)
330 {
331 std::string _arg = argv[i];
332 if(_arg == _delim)
333 {
334 _cmdc = argc - i;
335 _cmdv = new char*[_cmdc + 1];
336 _cmdv[_cmdc] = nullptr;
337 _cmdv[0] = helpers::strdup(argv[0]);
338 int k = 1;
339 for(int j = i + 1; j < argc; ++j, ++k)
340 _cmdv[k] = helpers::strdup(argv[j]);
341 break;
342 }
343 else
344 {
345 _args.push_back(std::string((const char*) argv[i]));
346 }
347 }
348
349 auto cmd_string = [](int _ac, char** _av) {
350 std::stringstream ss;
351 for(int i = 0; i < _ac; ++i)
352 ss << _av[i] << " ";
353 return ss.str();
354 };
355
356 if((_cmdc > 0 && verbose_level > 0) || verbose_level > 1)
357 std::cerr << "\n";
358
359 if(verbose_level > 1)
360 {
361 std::cerr << "[original]> " << cmd_string(argc, argv) << std::endl;
362 std::cerr << "[cfg-args]> ";
363 for(auto& itr : _args)
364 std::cerr << itr << " ";
365 std::cerr << std::endl;
366 }
367
368 if(_cmdc > 0 && verbose_level > 0)
369 std::cerr << "[command]> " << cmd_string(_cmdc, _cmdv) << "\n\n";
370
371 return known_args_t{ parse(_args, verbose_level), _cmdc, _cmdv };
372}
std::tuple< arg_result, int, char ** > known_args_t
Definition: argparse.hpp:333
char * strdup(const char *s)
Definition: timemory_c.c:41

References tim::_args, tim::argv, parse(), and strdup().

◆ print_help()

TIMEMORY_UTILITY_INLINE void tim::argparse::argument_parser::print_help ( const std::string &  _extra = "")

Definition at line 109 of file argparse.cpp.

110{
111 std::stringstream _usage;
112 if(!m_desc.empty())
113 _usage << "[" << m_desc << "] ";
114 _usage << "Usage: " << m_bin;
115
116 std::cerr << _usage.str();
117
118 std::stringstream _sshort_desc;
119 auto _indent = _usage.str().length() + 2;
120 size_t _ncnt = 0;
121 for(auto& a : m_arguments)
122 {
123 std::string name = a.m_names.at(0);
124 if(name.empty() || name.find_first_of('-') > name.find_first_not_of(" -"))
125 continue;
126 // select the first long option
127 for(size_t n = 1; n < a.m_names.size(); ++n)
128 {
129 if(name.find("--") == 0)
130 break;
131 else if(a.m_names.at(n).find("--") == 0)
132 {
133 name = a.m_names.at(n);
134 break;
135 }
136 }
137 if(name.length() > 0)
138 {
139 if(_ncnt++ > 0)
140 _sshort_desc << "\n " << std::setw(_indent) << " " << name;
141 else
142 _sshort_desc << " " << name;
143
144 _sshort_desc << " (";
145 if(a.m_count != argument::Count::ANY)
146 _sshort_desc << "count: " << a.m_count;
147 else if(a.m_min_count != argument::Count::ANY)
148 _sshort_desc << "min: " << a.m_min_count;
149 else if(a.m_max_count != argument::Count::ANY)
150 _sshort_desc << "max: " << a.m_max_count;
151 else
152 _sshort_desc << "count: unlimited";
153 if(!a.m_dtype.empty())
154 _sshort_desc << ", dtype: " << a.m_dtype;
155 else if(a.m_count == 0 ||
156 (a.m_count == argument::Count::ANY && a.m_max_count == 1))
157 _sshort_desc << ", dtype: bool" << a.m_dtype;
158 _sshort_desc << ")";
159 }
160 }
161
162 std::string _short_desc;
163 if(!_sshort_desc.str().empty())
164 {
165 _short_desc.append("[" + _sshort_desc.str());
166 std::stringstream _tmp;
167 _tmp << "\n" << std::setw(_indent) << "]";
168 _short_desc.append(_tmp.str());
169 }
170
171 if(m_positional_arguments.empty())
172 {
173 std::cerr << " " << _short_desc << " " << _extra << std::endl;
174 }
175 else
176 {
177 std::cerr << " " << _short_desc;
178 if(!_short_desc.empty())
179 std::cerr << "\n" << std::setw(_indent - 2) << " ";
180 for(auto& itr : m_positional_arguments)
181 {
182 std::cerr << " " << helpers::ltrim(itr.m_names.at(0), [](int c) -> bool {
183 return c != static_cast<int>('-');
184 });
185 }
186
187 int current = 0;
188 for(auto& v : m_positional_map)
189 {
190 if(v.first != argument::Position::LastArgument)
191 {
192 for(; current < v.first; ++current)
193 std::cerr << " [" << current << "]";
194 std::cerr << " ["
195 << helpers::ltrim(
196 m_arguments[static_cast<size_t>(v.second)].m_names.at(0),
197 [](int c) -> bool { return c != static_cast<int>('-'); })
198 << "]";
199 }
200 else
201 {
202 std::cerr << " ... ["
203 << helpers::ltrim(
204 m_arguments[static_cast<size_t>(v.second)].m_names.at(0),
205 [](int c) -> bool { return c != static_cast<int>('-'); })
206 << "]";
207 }
208 }
209 std::cerr << " " << _extra << std::endl;
210 }
211
212 std::cerr << "\nOptions:" << std::endl;
213 for(auto& a : m_arguments)
214 {
215 std::string name = a.m_names.at(0);
216 for(size_t n = 1; n < a.m_names.size(); ++n)
217 name.append(", " + a.m_names[n]);
218 std::stringstream ss;
219 ss << name;
220 if(a.m_choices.size() > 0)
221 {
222 ss << " [";
223 auto itr = a.m_choices.begin();
224 ss << " " << *itr++;
225 for(; itr != a.m_choices.end(); ++itr)
226 ss << " | " << *itr;
227 ss << " ] ";
228 }
229 std::stringstream prefix;
230 prefix << " " << std::setw(m_width) << std::left << ss.str();
231 std::cerr << std::left << prefix.str();
232
233 auto desc = a.m_desc;
234 if(ss.str().length() >= static_cast<size_t>(m_width))
235 desc = std::string("\n%{NEWLINE}%") + desc;
236
237 {
238 // replace %{INDENT}% with indentation
239 const std::string indent_key = "%{INDENT}%";
240 const auto npos = std::string::npos;
241 auto pos = npos;
242 std::stringstream indent;
243 indent << std::setw(prefix.str().length()) << "";
244 while((pos = desc.find(indent_key)) != npos)
245 desc = desc.replace(pos, indent_key.length(), indent.str());
246 }
247
248 {
249 // replace %{NEWLINE}% with indentation
250 const std::string indent_key = "%{NEWLINE}%";
251 const auto npos = std::string::npos;
252 auto pos = npos;
253 std::stringstream indent;
254 indent << std::setw(m_width + 5) << "";
255 while((pos = desc.find(indent_key)) != npos)
256 desc = desc.replace(pos, indent_key.length(), indent.str());
257 }
258
259 std::cerr << " " << std::setw(m_width) << desc;
260
261 if(a.m_required)
262 std::cerr << " (Required)";
263 std::cerr << std::endl;
264 }
265 std::cerr << '\n';
266}
size_t pos
Definition: config.cpp:102

Referenced by tim::on_error().

◆ set_help_width()

void tim::argparse::argument_parser::set_help_width ( int  _v)
inline

Definition at line 986 of file argparse.hpp.

986{ m_width = _v; }

The documentation for this struct was generated from the following files: