Preserve the sequence of commands provided by the user. Without that, the commands are just shown alphabetically, but the user of the subcommands might want to group these by importance. Always provide 'help' as first command. While at it: remove the heterogenous lookup ifdefs as we are using C++17 throughout these days. Update the "error" text so that calling 'help invalidcommand' provides a sensible message. Signed-off-by: Henner Zeller <hzeller@google.com>
diff --git a/common/util/subcommand.cc b/common/util/subcommand.cc index 560bd58..9a7652c 100644 --- a/common/util/subcommand.cc +++ b/common/util/subcommand.cc
@@ -42,19 +42,15 @@ const auto unused_status = Help({}, ins, outs, errs); return absl::InvalidArgumentError("Unknown subcommand."); }, - "same as 'help', but exits non-zero to signal a wrong command.\n", - false}}, - } {} + "This is not a valid command.\n", false}}, + } { + command_listing_.emplace_back("help"); +} const SubcommandEntry& SubcommandRegistry::GetSubcommandEntry( absl::string_view command) const { const SubcommandMap& commands(subcommand_map_); -#if __cplusplus >= 201402L - const auto iter = commands.find(command); // heterogenous lookup -#else - // without heterogenous lookup - const auto iter = commands.find(std::string(command.begin(), command.end())); -#endif + const auto iter = commands.find(command); if (iter == commands.end()) { // Command not found, print help and exit non-zero. return commands.find("error")->second; @@ -64,17 +60,14 @@ absl::Status SubcommandRegistry::RegisterCommand( absl::string_view name, const SubcommandEntry& command) { - const auto p = subcommand_map_.emplace( -#if __cplusplus >= 201402L - name, // heterogenous lookup -#else - std::string(name.begin(), name.end()), // without heterogenous lookup -#endif - command); + const auto p = subcommand_map_.emplace(name, command); if (!p.second) { return absl::InvalidArgumentError(absl::StrCat( "A function named \"", name, "\" has already been registered.")); } + if (command.show_in_help) { + command_listing_.emplace_back(name); + } return absl::OkStatus(); } @@ -92,15 +85,7 @@ } std::string SubcommandRegistry::ListCommands() const { - const SubcommandMap& commands(subcommand_map_); - std::vector<absl::string_view> public_commands; - for (const auto& command : commands) { - // List only public commands. - if (command.second.show_in_help) { - public_commands.emplace_back(command.first); - } - } - return absl::StrCat(" ", absl::StrJoin(public_commands, "\n "), "\n"); + return absl::StrCat(" ", absl::StrJoin(command_listing_, "\n "), "\n"); } } // namespace verible
diff --git a/common/util/subcommand.h b/common/util/subcommand.h index 98fa79b..4c94704 100644 --- a/common/util/subcommand.h +++ b/common/util/subcommand.h
@@ -92,6 +92,9 @@ // The map of names to functions. SubcommandMap subcommand_map_; + + // Sequence in which commands have been registered for display purposes. + std::vector<std::string> command_listing_; }; // class SubcommandRegistry } // namespace verible