1 #include "private/cli/commandmap.hpp"
6 #include <boost/io/ios_state.hpp>
8 using namespace shareddatalayer::cli;
12 std::string buildCommandNameAlreadyRegisteredError(const std::string& commandName)
14 std::ostringstream os;
15 os << "command name \"" << commandName << "\" already registered";
19 std::string buildUnknownCommandNameError(const std::string& commandName)
21 std::ostringstream os;
22 os << "unknown command: \"" << commandName << '\"';
26 std::string buildCategoryOffsetAlreadyRegisteredError(const std::string& commandName, int offset)
28 std::ostringstream os;
29 os << commandName << ": Offset " << offset << " already registered";
33 std::string getCategoryName(CommandMap::Category category)
37 case CommandMap::Category::UTIL:
45 CommandMap::CommandNameAlreadyRegistered::CommandNameAlreadyRegistered(const std::string& commandName):
46 Exception(buildCommandNameAlreadyRegisteredError(commandName))
50 CommandMap::UnknownCommandName::UnknownCommandName(const std::string& commandName):
51 Exception(buildUnknownCommandNameError(commandName))
55 CommandMap::CategoryOffsetAlreadyRegistered::CategoryOffsetAlreadyRegistered(const std::string& commandName, int offset):
56 Exception(buildCategoryOffsetAlreadyRegisteredError(commandName, offset))
60 struct CommandMap::Info
62 CommandFunction function;
63 std::string shortHelp;
65 boost::program_options::options_description options;
67 Info(const CommandFunction& function,
68 const std::string& shortHelp,
69 const std::string& longHelp);
72 CommandMap::Info::Info(const CommandFunction& function,
73 const std::string& shortHelp,
74 const std::string& longHelp):
81 CommandMap::CommandMap()
85 CommandMap::~CommandMap()
89 boost::program_options::options_description&
90 CommandMap::registerCommand(const std::string& commandName,
91 const std::string& shortHelp,
92 const std::string& longHelp,
93 const CommandFunction& commandFunction,
97 const auto ret(map.insert(std::make_pair(commandName, Info(commandFunction, shortHelp, longHelp))));
99 throw CommandNameAlreadyRegistered(commandName);
100 const auto retCat(categoryMap.insert(std::make_pair(CategoryKey(category, categoryOffset), commandName)));
102 throw CategoryOffsetAlreadyRegistered(commandName, categoryOffset);
103 return ret.first->second.options;
106 std::vector<std::string> CommandMap::getCommandNames() const
108 std::vector<std::string> ret;
109 for (const auto& i : map)
110 ret.push_back(i.first);
114 const boost::program_options::options_description&
115 CommandMap::getCommandOptions(const std::string& commandName) const
117 const auto i(map.find(commandName));
119 throw UnknownCommandName(commandName);
120 return i->second.options;
123 void CommandMap::shortHelp(std::ostream& out) const
125 boost::io::ios_all_saver guard(out);
127 Category currentCategory(Category::UNDEFINED);
128 for (const auto& i : map)
129 if (maxWidth < i.first.size())
130 maxWidth = i.first.size();
131 for (const auto& i : categoryMap)
133 if (currentCategory != i.first.first)
135 currentCategory = i.first.first;
137 out << getCategoryName(currentCategory) << " commands:" << std::endl;
139 out << std::left << std::setw(maxWidth + 2U) << i.second << map.at(i.second).shortHelp << '\n';
143 void CommandMap::longHelp(std::ostream& out, const std::string& commandName) const
145 const auto i(map.find(commandName));
147 throw UnknownCommandName(commandName);
149 if (!i->second.options.options().empty())
151 out << " OPTIONS\n\n" << i->second.longHelp << "\n\nOptions:\n";
152 i->second.options.print(out);
156 out << "\n\n" << i->second.longHelp << '\n';
160 int CommandMap::execute(const std::string& commandName,
163 const boost::program_options::variables_map& params,
166 const auto i(map.find(commandName));
169 err << "unknown command: \"" << commandName << '\"' << std::endl;
172 const auto& function(i->second.function);
173 int ret(EXIT_SUCCESS);
174 for (size_t i = 0U; i < count; ++i)
175 if ((ret = function(out, err, params)) != EXIT_SUCCESS)
180 CommandMap& CommandMap::getCommandMap() noexcept
182 static CommandMap instance;