Updated copy constructor and added parser path to correctly print program name in help for subparsers

This commit is contained in:
Pranav Srinivas Kumar 2022-09-20 20:45:32 -07:00
parent 6c7da857b6
commit 6ed180f89e
2 changed files with 17 additions and 4 deletions

View File

@ -36,6 +36,7 @@
* [Default Arguments](#default-arguments) * [Default Arguments](#default-arguments)
* [Gathering Remaining Arguments](#gathering-remaining-arguments) * [Gathering Remaining Arguments](#gathering-remaining-arguments)
* [Parent Parsers](#parent-parsers) * [Parent Parsers](#parent-parsers)
* [Subparsers](#subparsers)
* [Further Examples](#further-examples) * [Further Examples](#further-examples)
* [Construct a JSON object from a filename argument](#construct-a-json-object-from-a-filename-argument) * [Construct a JSON object from a filename argument](#construct-a-json-object-from-a-filename-argument)
* [Positional Arguments with Compound Toggle Arguments](#positional-arguments-with-compound-toggle-arguments) * [Positional Arguments with Compound Toggle Arguments](#positional-arguments-with-compound-toggle-arguments)
@ -692,6 +693,10 @@ bar_parser.parse_args({ "./main", "--bar", "YYY" }); // bar = YYY
Note You must fully initialize the parsers before passing them via ```.add_parents```. If you change the parent parsers after the child parser, those changes will not be reflected in the child. Note You must fully initialize the parsers before passing them via ```.add_parents```. If you change the parent parsers after the child parser, those changes will not be reflected in the child.
### Subparsers
Many programs split up their functionality into a number of sub-commands, for example, the `git` program can invoke sub-commands like `git checkout`, `git add`, and `git commit`. Splitting up functionality this way can be a particularly good idea when a program performs several different functions which require different kinds of command-line arguments. `ArgumentParser` supports the creation of such sub-commands with the `add_subparser()` member function.
## Further Examples ## Further Examples
### Construct a JSON object from a filename argument ### Construct a JSON object from a filename argument

View File

@ -924,7 +924,8 @@ public:
explicit ArgumentParser(std::string program_name = {}, explicit ArgumentParser(std::string program_name = {},
std::string version = "1.0", std::string version = "1.0",
default_arguments add_args = default_arguments::all) default_arguments add_args = default_arguments::all)
: m_program_name(std::move(program_name)), m_version(std::move(version)) { : m_program_name(std::move(program_name)), m_version(std::move(version)),
m_parser_path(m_program_name) {
if ((add_args & default_arguments::help) == default_arguments::help) { if ((add_args & default_arguments::help) == default_arguments::help) {
add_argument("-h", "--help") add_argument("-h", "--help")
.action([&](const auto & /*unused*/) { .action([&](const auto & /*unused*/) {
@ -957,7 +958,9 @@ public:
m_description(other.m_description), m_epilog(other.m_epilog), m_description(other.m_description), m_epilog(other.m_epilog),
m_is_parsed(other.m_is_parsed), m_is_parsed(other.m_is_parsed),
m_positional_arguments(other.m_positional_arguments), m_positional_arguments(other.m_positional_arguments),
m_optional_arguments(other.m_optional_arguments) { m_optional_arguments(other.m_optional_arguments),
m_parser_path(other.m_parser_path),
m_subparsers(other.m_subparsers) {
for (auto it = std::begin(m_positional_arguments); for (auto it = std::begin(m_positional_arguments);
it != std::end(m_positional_arguments); ++it) { it != std::end(m_positional_arguments); ++it) {
index_argument(it); index_argument(it);
@ -966,6 +969,10 @@ public:
it != std::end(m_optional_arguments); ++it) { it != std::end(m_optional_arguments); ++it) {
index_argument(it); index_argument(it);
} }
for (auto it = std::begin(m_subparsers);
it != std::end(m_subparsers); ++it) {
m_subparser_map.insert_or_assign(it->get().m_program_name, it);
}
} }
~ArgumentParser() = default; ~ArgumentParser() = default;
@ -1106,7 +1113,7 @@ public:
friend auto operator<<(std::ostream &stream, const ArgumentParser &parser) friend auto operator<<(std::ostream &stream, const ArgumentParser &parser)
-> std::ostream & { -> std::ostream & {
stream.setf(std::ios_base::left); stream.setf(std::ios_base::left);
stream << "Usage: " << parser.m_program_name << " [options] "; stream << "Usage: " << parser.m_parser_path << " [options] ";
for (const auto &argument : parser.m_positional_arguments) { for (const auto &argument : parser.m_positional_arguments) {
stream << argument.m_names.front() << " "; stream << argument.m_names.front() << " ";
} }
@ -1184,7 +1191,7 @@ public:
} }
void add_subparser(ArgumentParser &parser) { void add_subparser(ArgumentParser &parser) {
parser.m_parser_path = m_program_name + " " + parser.m_program_name;
auto it = m_subparsers.emplace(std::cend(m_subparsers), parser); auto it = m_subparsers.emplace(std::cend(m_subparsers), parser);
m_subparser_map.insert_or_assign(parser.m_program_name, it); m_subparser_map.insert_or_assign(parser.m_program_name, it);
} }
@ -1286,6 +1293,7 @@ private:
std::list<Argument> m_positional_arguments; std::list<Argument> m_positional_arguments;
std::list<Argument> m_optional_arguments; std::list<Argument> m_optional_arguments;
std::map<std::string_view, argument_it, std::less<>> m_argument_map; std::map<std::string_view, argument_it, std::less<>> m_argument_map;
std::string m_parser_path;
std::list<std::reference_wrapper<ArgumentParser>> m_subparsers; std::list<std::reference_wrapper<ArgumentParser>> m_subparsers;
std::map<std::string_view, argument_parser_it, std::less<>> m_subparser_map; std::map<std::string_view, argument_parser_it, std::less<>> m_subparser_map;
}; };