diff --git a/README.md b/README.md index a9a1063..7a0f550 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ * [Default Arguments](#default-arguments) * [Gathering Remaining Arguments](#gathering-remaining-arguments) * [Parent Parsers](#parent-parsers) + * [Subparsers](#subparsers) * [Further Examples](#further-examples) * [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) @@ -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. +### 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 ### Construct a JSON object from a filename argument diff --git a/include/argparse/argparse.hpp b/include/argparse/argparse.hpp index 48307e0..fb3ad9f 100644 --- a/include/argparse/argparse.hpp +++ b/include/argparse/argparse.hpp @@ -924,7 +924,8 @@ public: explicit ArgumentParser(std::string program_name = {}, std::string version = "1.0", 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) { add_argument("-h", "--help") .action([&](const auto & /*unused*/) { @@ -957,7 +958,9 @@ public: m_description(other.m_description), m_epilog(other.m_epilog), m_is_parsed(other.m_is_parsed), 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); it != std::end(m_positional_arguments); ++it) { index_argument(it); @@ -966,6 +969,10 @@ public: it != std::end(m_optional_arguments); ++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; @@ -1106,7 +1113,7 @@ public: friend auto operator<<(std::ostream &stream, const ArgumentParser &parser) -> std::ostream & { 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) { stream << argument.m_names.front() << " "; } @@ -1184,7 +1191,7 @@ public: } 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); m_subparser_map.insert_or_assign(parser.m_program_name, it); } @@ -1286,6 +1293,7 @@ private: std::list m_positional_arguments; std::list m_optional_arguments; std::map> m_argument_map; + std::string m_parser_path; std::list> m_subparsers; std::map> m_subparser_map; };