From ff6f09803274b41d695e9e632db41b380d9e9c99 Mon Sep 17 00:00:00 2001 From: Pavel Belikov Date: Mon, 6 Nov 2017 10:57:00 +0300 Subject: add description for commands --- args.hxx | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 82 insertions(+), 8 deletions(-) (limited to 'args.hxx') diff --git a/args.hxx b/args.hxx index 53b8718..ca4d966 100644 --- a/args.hxx +++ b/args.hxx @@ -473,12 +473,20 @@ namespace args */ bool showProglinePositionals = true; + /** The prefix for short flags + */ std::string shortPrefix; + /** The prefix for long flags + */ std::string longPrefix; + /** The separator for short flags + */ std::string shortSeparator; + /** The separator for long flags + */ std::string longSeparator; }; @@ -1081,10 +1089,11 @@ namespace args std::vector args; std::vector kicked; ArgumentParser &parser; + Command &command; bool isParsed = false; public: - Subparser(std::vector args_, ArgumentParser &parser_) : args(std::move(args_)), parser(parser_) + Subparser(std::vector args_, ArgumentParser &parser_, Command &command_) : args(std::move(args_)), parser(parser_), command(command_) { } @@ -1093,6 +1102,11 @@ namespace args Subparser &operator = (const Subparser&) = delete; Subparser &operator = (Subparser&&) = delete; + Command &GetCommand() + { + return command; + } + bool IsParsed() const { return isParsed; @@ -1109,10 +1123,13 @@ namespace args class Command : public Group { private: + friend class Subparser; + std::string name; std::string description; std::function parserCoroutine; bool commandIsRequired = false; + std::vector> subparserDescription; protected: @@ -1146,6 +1163,17 @@ namespace args return selectedCommand != nullptr ? selectedCommand->GetCoroutine() : parserCoroutine; } + Command &SelectedCommand() + { + Command *res = this; + while (res->selectedCommand != nullptr) + { + res = res->selectedCommand; + } + + return *res; + } + public: Command(Group &base_, std::string name_, std::string description_, std::function coroutine_ = {}) : name(std::move(name_)), description(std::move(description_)), parserCoroutine(std::move(coroutine_)) @@ -1300,6 +1328,54 @@ namespace args return { this }; } + virtual std::vector> GetDescription(const HelpParams ¶ms, const unsigned int indent) const + { + if (selectedCommand != nullptr) + { + return selectedCommand->GetDescription(params, indent); + } + + std::vector> descriptions; + unsigned addindent = 0; + + std::tuple desc; + std::get<0>(desc) = Name(); + std::get<1>(desc) = description; + std::get<2>(desc) = indent; + if (!Name().empty()) + { + addindent = 1; + descriptions.push_back(desc); + } + + if (!Matched()) + { + return descriptions; + } + + for (Base *child: Children()) + { + if ((child->GetOptions() & Options::Hidden) != Options::None) + { + continue; + } + + auto groupDescriptions = child->GetDescription(params, indent + addindent); + descriptions.insert( + std::end(descriptions), + std::make_move_iterator(std::begin(groupDescriptions)), + std::make_move_iterator(std::end(groupDescriptions))); + } + + for (auto childDescription: subparserDescription) + { + std::get<2>(childDescription) += indent + addindent; + descriptions.push_back(std::move(childDescription)); + } + + return descriptions; + } + virtual void Validate(const std::string &shortprefix, const std::string &longprefix) override { for (Base *child: Children()) @@ -1630,6 +1706,7 @@ namespace args ShortPrefix("-"); LongSeparator("="); SetArgumentSeparations(true, true, true, true); + matched = true; } /** The program name for help generation @@ -1921,18 +1998,15 @@ namespace args } }; - Command::RaiiSubparser::RaiiSubparser(ArgumentParser &parser_, std::vector args_) : command(&parser_), parser(std::move(args_), parser_) + Command::RaiiSubparser::RaiiSubparser(ArgumentParser &parser_, std::vector args_) : command(&parser_), parser(std::move(args_), parser_, parser_.SelectedCommand()) { - while (command->selectedCommand != nullptr) - { - command = command->selectedCommand; - } - - command->subparser = &parser; + parser.GetCommand().subparser = &parser; } void Subparser::Parse() { + isParsed = true; + command.subparserDescription = GetDescription(parser.helpParams, 0); auto it = parser.Parse(args.begin(), args.end()); kicked.assign(it, args.end()); } -- cgit v1.2.1