ONE - On-device Neural Engine
Loading...
Searching...
No Matches
arser::Arser Class Reference

#include <arser.h>

Public Member Functions

 Arser (const std::string &program_description={})
 
Argumentadd_argument (const std::string &arg_name)
 
Argumentadd_argument (const std::vector< std::string > &arg_name_vec)
 
template<typename... Ts>
Argumentadd_argument (const std::string &arg_name, Ts... arg_names)
 
void validate_arguments (void)
 
void parse (int argc, char **argv)
 
bool operator[] (const std::string &arg_name)
 
template<typename T >
get_impl (const std::string &arg_name, T *)
 
template<typename T >
std::vector< T > get_impl (const std::string &arg_name, std::vector< T > *)
 
template<typename T >
std::vector< std::vector< T > > get_impl (const std::string &arg_name, std::vector< std::vector< T > > *)
 
template<typename T >
get (const std::string &arg_name)
 
 Arser (const std::string &program_description={})
 
Argumentadd_argument (const std::string &arg_name)
 
Argumentadd_argument (const std::vector< std::string > &arg_name_vec)
 
template<typename... Ts>
Argumentadd_argument (const std::string &arg_name, Ts... arg_names)
 
void validate_arguments (void)
 
void parse (int argc, char **argv)
 
bool operator[] (const std::string &arg_name)
 
template<typename T >
get_impl (const std::string &arg_name, T *)
 
template<typename T >
std::vector< T > get_impl (const std::string &arg_name, std::vector< T > *)
 
template<typename T >
std::vector< std::vector< T > > get_impl (const std::string &arg_name, std::vector< std::vector< T > > *)
 
template<typename T >
get (const std::string &arg_name)
 

Friends

std::ostream & operator<< (std::ostream &stream, const Arser &parser)
 
std::ostream & operator<< (std::ostream &stream, const Arser &parser)
 

Detailed Description

Definition at line 331 of file arser.h.

Constructor & Destructor Documentation

◆ Arser() [1/2]

arser::Arser::Arser ( const std::string &  program_description = {})
inlineexplicit

Definition at line 334 of file arser.h.

334 {})
335 : _program_description{program_description}
336 {
337 add_argument("-h", "--help").help("Show help message and exit").nargs(0);
338 }
Argument & nargs(uint32_t num)
Definition arser.h:191
Argument & help(std::string help_message)
Definition arser.h:256
Argument & add_argument(const std::string &arg_name)
Definition arser.h:340

◆ Arser() [2/2]

arser::Arser::Arser ( const std::string &  program_description = {})
inlineexplicit

Definition at line 334 of file arser.h.

334 {})
335 : _program_description{program_description}
336 {
337 add_argument("-h", "--help").help("Show help message and exit").nargs(0);
338 }

Member Function Documentation

◆ add_argument() [1/6]

Argument & arser::Arser::add_argument ( const std::string &  arg_name)
inline

Definition at line 340 of file arser.h.

341 {
342 if (arg_name.at(0) != '-') /* positional */
343 {
344 _positional_arg_vec.emplace_back(arg_name);
345 _arg_map[arg_name] = &_positional_arg_vec.back();
346 }
347 else /* optional */
348 {
349 // The length of optional argument name must be 2 or more.
350 // And it shouldn't be hard to recognize. e.g. '-', '--'
351 if (arg_name.size() < 2)
352 {
353 throw std::runtime_error("Too short name. The length of argument name must be 2 or more.");
354 }
355 if (arg_name == "--")
356 {
357 throw std::runtime_error(
358 "Too short name. Option name must contain at least one character other than dash.");
359 }
360 _optional_arg_vec.emplace_back(arg_name);
361 _optional_arg_vec.back()._short_name = arg_name;
362 _arg_map[arg_name] = &_optional_arg_vec.back();
363 }
364 return *_arg_map[arg_name];
365 }

Referenced by add_argument().

◆ add_argument() [2/6]

Argument & arser::Arser::add_argument ( const std::string &  arg_name)
inline

Definition at line 340 of file arser.h.

341 {
342 if (arg_name.at(0) != '-') /* positional */
343 {
344 _positional_arg_vec.emplace_back(arg_name);
345 _arg_map[arg_name] = &_positional_arg_vec.back();
346 }
347 else /* optional */
348 {
349 // The length of optional argument name must be 2 or more.
350 // And it shouldn't be hard to recognize. e.g. '-', '--'
351 if (arg_name.size() < 2)
352 {
353 throw std::runtime_error("Too short name. The length of argument name must be 2 or more.");
354 }
355 if (arg_name == "--")
356 {
357 throw std::runtime_error(
358 "Too short name. Option name must contain at least one character other than dash.");
359 }
360 _optional_arg_vec.emplace_back(arg_name);
361 _optional_arg_vec.back()._short_name = arg_name;
362 _arg_map[arg_name] = &_optional_arg_vec.back();
363 }
364 return *_arg_map[arg_name];
365 }

◆ add_argument() [3/6]

template<typename... Ts>
Argument & arser::Arser::add_argument ( const std::string &  arg_name,
Ts...  arg_names 
)
inline

Definition at line 409 of file arser.h.

410 {
411 if (sizeof...(arg_names) == 0)
412 {
413 return add_argument(arg_name);
414 }
415 // sizeof...(arg_names) > 0
416 else
417 {
418 return add_argument(std::vector<std::string>{arg_name, arg_names...});
419 }
420 }

References add_argument().

◆ add_argument() [4/6]

template<typename... Ts>
Argument & arser::Arser::add_argument ( const std::string &  arg_name,
Ts...  arg_names 
)
inline

Definition at line 409 of file arser.h.

410 {
411 if (sizeof...(arg_names) == 0)
412 {
413 return add_argument(arg_name);
414 }
415 // sizeof...(arg_names) > 0
416 else
417 {
418 return add_argument(std::vector<std::string>{arg_name, arg_names...});
419 }
420 }

References add_argument().

◆ add_argument() [5/6]

Argument & arser::Arser::add_argument ( const std::vector< std::string > &  arg_name_vec)
inline

Definition at line 367 of file arser.h.

368 {
369 assert(arg_name_vec.size() >= 2);
370 std::string long_opt, short_opt;
371 // find long and short option
372 for (const auto &arg_name : arg_name_vec)
373 {
374 if (arg_name.at(0) != '-')
375 {
376 throw std::runtime_error("Invalid argument. "
377 "Positional argument cannot have short option.");
378 }
379 assert(arg_name.size() >= 2);
380 if (long_opt.empty() && arg_name.at(0) == '-' && arg_name.at(1) == '-')
381 {
382 long_opt = arg_name;
383 }
384 if (short_opt.empty() && arg_name.at(0) == '-' && arg_name.at(1) != '-')
385 {
386 short_opt = arg_name;
387 }
388 }
389 // If one of the two is empty, fill it with the non-empty one for pretty printing.
390 if (long_opt.empty())
391 {
392 assert(not short_opt.empty());
393 long_opt = short_opt;
394 }
395 if (short_opt.empty())
396 {
397 assert(not long_opt.empty());
398 short_opt = long_opt;
399 }
400
401 _optional_arg_vec.emplace_back(short_opt, long_opt, arg_name_vec);
402 for (const auto &arg_name : arg_name_vec)
403 {
404 _arg_map[arg_name] = &_optional_arg_vec.back();
405 }
406 return _optional_arg_vec.back();
407 }

◆ add_argument() [6/6]

Argument & arser::Arser::add_argument ( const std::vector< std::string > &  arg_name_vec)
inline

Definition at line 367 of file arser.h.

368 {
369 assert(arg_name_vec.size() >= 2);
370 std::string long_opt, short_opt;
371 // find long and short option
372 for (const auto &arg_name : arg_name_vec)
373 {
374 if (arg_name.at(0) != '-')
375 {
376 throw std::runtime_error("Invalid argument. "
377 "Positional argument cannot have short option.");
378 }
379 assert(arg_name.size() >= 2);
380 if (long_opt.empty() && arg_name.at(0) == '-' && arg_name.at(1) == '-')
381 {
382 long_opt = arg_name;
383 }
384 if (short_opt.empty() && arg_name.at(0) == '-' && arg_name.at(1) != '-')
385 {
386 short_opt = arg_name;
387 }
388 }
389 // If one of the two is empty, fill it with the non-empty one for pretty printing.
390 if (long_opt.empty())
391 {
392 assert(not short_opt.empty());
393 long_opt = short_opt;
394 }
395 if (short_opt.empty())
396 {
397 assert(not long_opt.empty());
398 short_opt = long_opt;
399 }
400
401 _optional_arg_vec.emplace_back(short_opt, long_opt, arg_name_vec);
402 for (const auto &arg_name : arg_name_vec)
403 {
404 _arg_map[arg_name] = &_optional_arg_vec.back();
405 }
406 return _optional_arg_vec.back();
407 }

◆ get() [1/2]

template<typename T >
T arser::Arser::get ( const std::string &  arg_name)

Definition at line 749 of file arser.h.

750{
751 return get_impl(arg_name, static_cast<T *>(nullptr));
752}
T get_impl(const std::string &arg_name, T *)
Definition arser.h:644

References get_impl().

◆ get() [2/2]

template<typename T >
T arser::Arser::get ( const std::string &  arg_name)

◆ get_impl() [1/6]

template<typename T >
std::vector< std::vector< T > > arser::Arser::get_impl ( const std::string &  arg_name,
std::vector< std::vector< T > > *   
)

Definition at line 716 of file arser.h.

718{
719 auto arg = _arg_map.find(arg_name);
720 if (arg == _arg_map.end())
721 throw std::runtime_error("Invalid argument. "
722 "There is no argument you are looking for: " +
723 arg_name);
724
725 if (not arg->second->_is_accumulated)
726 throw std::runtime_error("Type mismatch. "
727 "You called get using a type different from the one you specified: " +
728 arg_name);
729
730 if (arg->second->_type != TypeName<std::vector<T>>::Get())
731 throw std::runtime_error(
732 "Type mismatch. "
733 "You called get using a type different from the one you specified."
734 "Accumulated argument is returned as std::vector of the specified type: " +
735 arg_name);
736
737 std::vector<std::vector<T>> result;
738 for (auto values : arg->second->_accum_values)
739 {
740 std::vector<T> data;
741 std::transform(values.begin(), values.end(), std::back_inserter(data),
742 [](std::string str) -> T { return internal::lexical_cast<T>(str); });
743 result.emplace_back(data);
744 }
745
746 return result;
747}
result
Definition infer.py:103

◆ get_impl() [2/6]

template<typename T >
std::vector< std::vector< T > > arser::Arser::get_impl ( const std::string &  arg_name,
std::vector< std::vector< T > > *   
)

◆ get_impl() [3/6]

template<typename T >
std::vector< T > arser::Arser::get_impl ( const std::string &  arg_name,
std::vector< T > *   
)

Definition at line 676 of file arser.h.

677{
678 auto arg = _arg_map.find(arg_name);
679 if (arg == _arg_map.end())
680 throw std::runtime_error("Invalid argument. "
681 "There is no argument you are looking for: " +
682 arg_name);
683
684 // Accumulated arguments with scalar type (e.g., STR)
685 if (arg->second->_is_accumulated)
686 {
687 if (arg->second->_type != TypeName<T>::Get())
688 throw std::runtime_error(
689 "Type mismatch. "
690 "You called get using a type different from the one you specified: " +
691 arg_name);
692
693 std::vector<T> data;
694 for (auto values : arg->second->_accum_values)
695 {
696 assert(values.size() == 1);
697 data.emplace_back(internal::lexical_cast<T>(values[0]));
698 }
699 return data;
700 }
701
702 if (arg->second->_type != TypeName<std::vector<T>>::Get())
703 throw std::runtime_error(
704 "Type mismatch. "
705 ". You called get using a type different from the one you specified: " +
706 arg_name);
707
708 std::vector<T> data;
709 std::transform(arg->second->_values.begin(), arg->second->_values.end(), std::back_inserter(data),
710 [](std::string str) -> T { return internal::lexical_cast<T>(str); });
711 return data;
712}
static const char * Get()
Definition arser.h:102

◆ get_impl() [4/6]

template<typename T >
std::vector< T > arser::Arser::get_impl ( const std::string &  arg_name,
std::vector< T > *   
)

◆ get_impl() [5/6]

template<typename T >
T arser::Arser::get_impl ( const std::string &  arg_name,
T *   
)

Definition at line 644 of file arser.h.

645{
646 auto arg = _arg_map.find(arg_name);
647 if (arg == _arg_map.end())
648 throw std::runtime_error("Invalid argument. "
649 "There is no argument you are looking for: " +
650 arg_name);
651
652 if (arg->second->_is_accumulated)
653 throw std::runtime_error(
654 "Type mismatch. "
655 "You called get using a type different from the one you specified."
656 "Accumulated argument is returned as std::vector of the specified type: " +
657 arg_name);
658
659 if (arg->second->_type != TypeName<T>::Get())
660 throw std::runtime_error("Type mismatch. "
661 "You called get() method with a type different "
662 "from the one you specified. "
663 "Please check the type of what you specified in "
664 "add_argument() method: " +
665 arg_name);
666
667 if (arg->second->_values.size() == 0)
668 throw std::runtime_error("Wrong access. "
669 "You must make sure that the argument is given before accessing it. "
670 "You can do it by calling arser[\"" +
671 arg_name + "\"].");
672
673 return internal::lexical_cast<T>(arg->second->_values[0]);
674}

Referenced by get().

◆ get_impl() [6/6]

template<typename T >
T arser::Arser::get_impl ( const std::string &  arg_name,
T *   
)

◆ operator[]() [1/2]

bool arser::Arser::operator[] ( const std::string &  arg_name)
inline

Definition at line 523 of file arser.h.

524 {
525 auto arg = _arg_map.find(arg_name);
526 if (arg == _arg_map.end())
527 return false;
528
529 if (arg->second->_is_accumulated)
530 return arg->second->_accum_values.size() > 0 ? true : false;
531
532 return arg->second->_values.size() > 0 ? true : false;
533 }

◆ operator[]() [2/2]

bool arser::Arser::operator[] ( const std::string &  arg_name)
inline

Definition at line 523 of file arser.h.

524 {
525 auto arg = _arg_map.find(arg_name);
526 if (arg == _arg_map.end())
527 return false;
528
529 if (arg->second->_is_accumulated)
530 return arg->second->_accum_values.size() > 0 ? true : false;
531
532 return arg->second->_values.size() > 0 ? true : false;
533 }

◆ parse() [1/2]

void arser::Arser::parse ( int  argc,
char **  argv 
)
inline

Definition at line 436 of file arser.h.

437 {
439 _program_name = argv[0];
440 _program_name.erase(0, _program_name.find_last_of("/\\") + 1);
441 if (argc >= 2)
442 {
443 if (!std::strcmp(argv[1], "--help") || !std::strcmp(argv[1], "-h"))
444 {
445 std::cout << *this;
446 std::exit(0);
447 }
448 else
449 {
450 for (const auto &arg : _arg_map)
451 {
452 const auto &func = arg.second->_func;
453 if (func && !std::strcmp(argv[1], arg.first.c_str()))
454 {
455 func();
456 std::exit(0);
457 }
458 }
459 }
460 }
461 /*
462 ** ./program_name [optional argument] [positional argument]
463 */
464 // get the number of positioanl argument
465 size_t parg_num = _positional_arg_vec.size();
466 // get the number of "required" optional argument
467 size_t required_oarg_num = 0;
468 for (auto arg : _optional_arg_vec)
469 {
470 if (arg._is_required)
471 required_oarg_num++;
472 }
473 // parse argument
474 for (int c = 1; c < argc;)
475 {
476 std::string arg_name{argv[c++]};
477 auto arg = _arg_map.find(arg_name);
478 // check whether arg is positional or not
479 if (arg == _arg_map.end())
480 {
481 if (parg_num)
482 {
483 auto it = _positional_arg_vec.begin();
484 std::advance(it, _positional_arg_vec.size() - parg_num);
485 (*it)._values.clear();
486 (*it)._values.emplace_back(arg_name);
487 parg_num--;
488 }
489 else
490 throw std::runtime_error("Invalid argument. "
491 "You've given more positional argument than necessary.");
492 }
493 else // optional argument
494 {
495 // check whether arg is required or not
496 if (arg->second->_is_required)
497 required_oarg_num--;
498 arg->second->_values.clear();
499 for (uint32_t n = 0; n < arg->second->_nargs; n++)
500 {
501 if (c >= argc)
502 throw std::runtime_error("Invalid argument. "
503 "You must have missed some argument.");
504 arg->second->_values.emplace_back(argv[c++]);
505 }
506 // accumulate values
507 if (arg->second->_is_accumulated)
508 {
509 arg->second->_accum_values.emplace_back(arg->second->_values);
510 }
511 if (arg->second->_nargs == 0)
512 {
513 // TODO std::boolalpha for true or false
514 arg->second->_values.emplace_back("1");
515 }
516 }
517 }
518 if (parg_num || required_oarg_num)
519 throw std::runtime_error("Invalid argument. "
520 "You must have missed some argument.");
521 }
void validate_arguments(void)
Definition arser.h:422

References validate_arguments().

◆ parse() [2/2]

void arser::Arser::parse ( int  argc,
char **  argv 
)
inline

Definition at line 436 of file arser.h.

437 {
439 _program_name = argv[0];
440 _program_name.erase(0, _program_name.find_last_of("/\\") + 1);
441 if (argc >= 2)
442 {
443 if (!std::strcmp(argv[1], "--help") || !std::strcmp(argv[1], "-h"))
444 {
445 std::cout << *this;
446 std::exit(0);
447 }
448 else
449 {
450 for (const auto &arg : _arg_map)
451 {
452 const auto &func = arg.second->_func;
453 if (func && !std::strcmp(argv[1], arg.first.c_str()))
454 {
455 func();
456 std::exit(0);
457 }
458 }
459 }
460 }
461 /*
462 ** ./program_name [optional argument] [positional argument]
463 */
464 // get the number of positioanl argument
465 size_t parg_num = _positional_arg_vec.size();
466 // get the number of "required" optional argument
467 size_t required_oarg_num = 0;
468 for (auto arg : _optional_arg_vec)
469 {
470 if (arg._is_required)
471 required_oarg_num++;
472 }
473 // parse argument
474 for (int c = 1; c < argc;)
475 {
476 std::string arg_name{argv[c++]};
477 auto arg = _arg_map.find(arg_name);
478 // check whether arg is positional or not
479 if (arg == _arg_map.end())
480 {
481 if (parg_num)
482 {
483 auto it = _positional_arg_vec.begin();
484 std::advance(it, _positional_arg_vec.size() - parg_num);
485 (*it)._values.clear();
486 (*it)._values.emplace_back(arg_name);
487 parg_num--;
488 }
489 else
490 throw std::runtime_error("Invalid argument. "
491 "You've given more positional argument than necessary.");
492 }
493 else // optional argument
494 {
495 // check whether arg is required or not
496 if (arg->second->_is_required)
497 required_oarg_num--;
498 arg->second->_values.clear();
499 for (uint32_t n = 0; n < arg->second->_nargs; n++)
500 {
501 if (c >= argc)
502 throw std::runtime_error("Invalid argument. "
503 "You must have missed some argument.");
504 arg->second->_values.emplace_back(argv[c++]);
505 }
506 // accumulate values
507 if (arg->second->_is_accumulated)
508 {
509 arg->second->_accum_values.emplace_back(arg->second->_values);
510 }
511 if (arg->second->_nargs == 0)
512 {
513 // TODO std::boolalpha for true or false
514 arg->second->_values.emplace_back("1");
515 }
516 }
517 }
518 if (parg_num || required_oarg_num)
519 throw std::runtime_error("Invalid argument. "
520 "You must have missed some argument.");
521 }

References validate_arguments().

◆ validate_arguments() [1/2]

void arser::Arser::validate_arguments ( void  )
inline

Definition at line 422 of file arser.h.

423 {
424 // positional argument is always required.
425 for (const auto &arg : _positional_arg_vec)
426 {
427 if (arg._is_required)
428 {
429 throw std::runtime_error("Invalid arguments. Positional argument must always be required.");
430 }
431 }
432 // TODO accumulated arguments shouldn't be enabled to positional arguments.
433 // TODO accumulated arguments shouldn't be enabled to optional arguments whose `narg` == 0.
434 }

Referenced by parse().

◆ validate_arguments() [2/2]

void arser::Arser::validate_arguments ( void  )
inline

Definition at line 422 of file arser.h.

423 {
424 // positional argument is always required.
425 for (const auto &arg : _positional_arg_vec)
426 {
427 if (arg._is_required)
428 {
429 throw std::runtime_error("Invalid arguments. Positional argument must always be required.");
430 }
431 }
432 // TODO accumulated arguments shouldn't be enabled to positional arguments.
433 // TODO accumulated arguments shouldn't be enabled to optional arguments whose `narg` == 0.
434 }

Friends And Related Symbol Documentation

◆ operator<< [1/2]

std::ostream & operator<< ( std::ostream &  stream,
const Arser parser 
)
friend

Definition at line 544 of file arser.h.

545 {
546 // print description
547 if (!parser._program_description.empty())
548 {
549 stream << "What " << parser._program_name << " does: " << parser._program_description
550 << "\n\n";
551 }
552 /*
553 ** print usage
554 */
555 auto print_usage_arg = [&](const arser::Argument &arg) {
556 stream << " ";
557 std::string arg_name = arser::internal::remove_dash(arg._long_name);
558 std::for_each(arg_name.begin(), arg_name.end(),
559 [&stream](const char &c) { stream << static_cast<char>(::toupper(c)); });
560 };
561 stream << "Usage: ./" << parser._program_name << " ";
562 // required optional argument
563 for (const auto &arg : parser._optional_arg_vec)
564 {
565 if (!arg._is_required)
566 continue;
567 stream << arg._short_name;
568 print_usage_arg(arg);
569 stream << " ";
570 }
571 // rest of the optional argument
572 for (const auto &arg : parser._optional_arg_vec)
573 {
574 if (arg._is_required)
575 continue;
576 stream << "[" << arg._short_name;
577 if (arg._nargs)
578 {
579 print_usage_arg(arg);
580 }
581 stream << "]"
582 << " ";
583 }
584 // positional arguement
585 for (const auto &arg : parser._positional_arg_vec)
586 {
587 stream << arg._long_name << " ";
588 }
589 stream << "\n\n";
590 /*
591 ** print argument list and its help message
592 */
593 // get the length of the longest argument
594 size_t length_of_longest_arg = 0;
595 for (const auto &arg : parser._positional_arg_vec)
596 {
597 length_of_longest_arg = std::max(length_of_longest_arg,
599 }
600 for (const auto &arg : parser._optional_arg_vec)
601 {
602 length_of_longest_arg = std::max(length_of_longest_arg,
604 }
605
606 const size_t message_width = 60;
607 auto print_help_args = [&](const std::list<Argument> &args, const std::string &title) {
608 if (!args.empty())
609 {
610 stream << title << std::endl;
611 for (const auto &arg : args)
612 {
613 stream.width(length_of_longest_arg);
614 stream << std::left << arser::internal::make_comma_concatenated(arg._names) << "\t";
615 for (size_t i = 0; i < arg._help_message.size(); i++)
616 {
617 for (size_t j = 0; j < arg._help_message[i].length(); j += message_width)
618 {
619 if (i || j)
620 stream << std::string(length_of_longest_arg, ' ') << "\t";
621 stream << arg._help_message[i].substr(j, message_width) << std::endl;
622 }
623 }
624 }
625 std::cout << std::endl;
626 }
627 };
628 // positional argument
629 print_help_args(parser._positional_arg_vec, "[Positional argument]");
630 // optional argument
631 print_help_args(parser._optional_arg_vec, "[Optional argument]");
632
633 return stream;
634 }
std::string make_comma_concatenated(const std::vector< std::string > &vec)
Returns the string that created by concatenating the elements of a vector with commas.
Definition arser.h:85
std::string remove_dash(const std::string &str)
Returns the string with the leading dash removed.
Definition arser.h:73
args
Definition infer.py:21
parser
Definition infer.py:17

◆ operator<< [2/2]

std::ostream & operator<< ( std::ostream &  stream,
const Arser parser 
)
friend

Definition at line 544 of file arser.h.

545 {
546 // print description
547 if (!parser._program_description.empty())
548 {
549 stream << "What " << parser._program_name << " does: " << parser._program_description
550 << "\n\n";
551 }
552 /*
553 ** print usage
554 */
555 auto print_usage_arg = [&](const arser::Argument &arg) {
556 stream << " ";
557 std::string arg_name = arser::internal::remove_dash(arg._long_name);
558 std::for_each(arg_name.begin(), arg_name.end(),
559 [&stream](const char &c) { stream << static_cast<char>(::toupper(c)); });
560 };
561 stream << "Usage: ./" << parser._program_name << " ";
562 // required optional argument
563 for (const auto &arg : parser._optional_arg_vec)
564 {
565 if (!arg._is_required)
566 continue;
567 stream << arg._short_name;
568 print_usage_arg(arg);
569 stream << " ";
570 }
571 // rest of the optional argument
572 for (const auto &arg : parser._optional_arg_vec)
573 {
574 if (arg._is_required)
575 continue;
576 stream << "[" << arg._short_name;
577 if (arg._nargs)
578 {
579 print_usage_arg(arg);
580 }
581 stream << "]"
582 << " ";
583 }
584 // positional arguement
585 for (const auto &arg : parser._positional_arg_vec)
586 {
587 stream << arg._long_name << " ";
588 }
589 stream << "\n\n";
590 /*
591 ** print argument list and its help message
592 */
593 // get the length of the longest argument
594 size_t length_of_longest_arg = 0;
595 for (const auto &arg : parser._positional_arg_vec)
596 {
597 length_of_longest_arg = std::max(length_of_longest_arg,
599 }
600 for (const auto &arg : parser._optional_arg_vec)
601 {
602 length_of_longest_arg = std::max(length_of_longest_arg,
604 }
605
606 const size_t message_width = 60;
607 auto print_help_args = [&](const std::list<Argument> &args, const std::string &title) {
608 if (!args.empty())
609 {
610 stream << title << std::endl;
611 for (const auto &arg : args)
612 {
613 stream.width(length_of_longest_arg);
614 stream << std::left << arser::internal::make_comma_concatenated(arg._names) << "\t";
615 for (size_t i = 0; i < arg._help_message.size(); i++)
616 {
617 for (size_t j = 0; j < arg._help_message[i].length(); j += message_width)
618 {
619 if (i || j)
620 stream << std::string(length_of_longest_arg, ' ') << "\t";
621 stream << arg._help_message[i].substr(j, message_width) << std::endl;
622 }
623 }
624 }
625 std::cout << std::endl;
626 }
627 };
628 // positional argument
629 print_help_args(parser._positional_arg_vec, "[Positional argument]");
630 // optional argument
631 print_help_args(parser._optional_arg_vec, "[Optional argument]");
632
633 return stream;
634 }

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