| #ifndef SHAREDDATALAYER_CLI_COMMANDMAP_HPP |
| #define SHAREDDATALAYER_CLI_COMMANDMAP_HPP |
| |
| #include <string> |
| #include <functional> |
| #include <iosfwd> |
| #include <map> |
| #include <vector> |
| #include <cstddef> |
| #include <boost/program_options.hpp> |
| #include <sdl/exception.hpp> |
| |
| namespace shareddatalayer |
| { |
| namespace cli |
| { |
| class CommandMap |
| { |
| public: |
| class CommandNameAlreadyRegistered; |
| |
| class UnknownCommandName; |
| |
| class CategoryOffsetAlreadyRegistered; |
| |
| enum class Category |
| { |
| UNDEFINED, |
| UTIL, |
| }; |
| |
| CommandMap(); |
| |
| ~CommandMap(); |
| |
| using CommandFunction = std::function<int(std::ostream& out, |
| std::ostream& err, |
| const boost::program_options::variables_map& params)>; |
| |
| boost::program_options::options_description& |
| registerCommand(const std::string& commandName, |
| const std::string& shortHelp, |
| const std::string& longHelp, |
| const CommandFunction& commandFunction, |
| Category category, |
| int categoryOffset); |
| |
| std::vector<std::string> getCommandNames() const; |
| |
| const boost::program_options::options_description& |
| getCommandOptions(const std::string& commandName) const; |
| |
| int execute(const std::string& commandName, |
| std::ostream& out, |
| std::ostream& err, |
| const boost::program_options::variables_map& params, |
| size_t count); |
| |
| void shortHelp(std::ostream& out) const; |
| |
| void longHelp(std::ostream& out, const std::string& commandName) const; |
| |
| static CommandMap& getCommandMap() noexcept; |
| |
| CommandMap(const CommandMap&) = delete; |
| CommandMap(CommandMap&&) = delete; |
| CommandMap& operator = (const CommandMap&) = delete; |
| CommandMap& operator = (CommandMap&&) = delete; |
| |
| private: |
| struct Info; |
| |
| std::map<std::string, Info> map; |
| using CategoryKey = std::pair<Category, int>; |
| std::map<CategoryKey, std::string> categoryMap; |
| }; |
| |
| class CommandMap::CommandNameAlreadyRegistered: public Exception |
| { |
| public: |
| explicit CommandNameAlreadyRegistered(const std::string& commandName); |
| }; |
| |
| class CommandMap::UnknownCommandName: public Exception |
| { |
| public: |
| explicit UnknownCommandName(const std::string& commandName); |
| }; |
| |
| class CommandMap::CategoryOffsetAlreadyRegistered: public Exception |
| { |
| public: |
| CategoryOffsetAlreadyRegistered(const std::string& commandName, int offset); |
| }; |
| } |
| } |
| |
| #define AUTO_REGISTER_COMMAND_XTOKENPASTE(x, y) x ## y |
| #define AUTO_REGISTER_COMMAND_TOKENPASTE(x, y) AUTO_REGISTER_COMMAND_XTOKENPASTE(x, y) |
| |
| #define AUTO_REGISTER_COMMAND(_function, _name, _shortHelp, _longHelp, _category, _categoryOffset, ...) \ |
| namespace \ |
| { \ |
| struct AUTO_REGISTER_COMMAND_TOKENPASTE(AutoRegister, __LINE__) \ |
| { \ |
| AUTO_REGISTER_COMMAND_TOKENPASTE(AutoRegister, __LINE__)() \ |
| { \ |
| ::shareddatalayer::cli::CommandMap::getCommandMap().registerCommand(_name, _shortHelp, _longHelp, _function, _category, _categoryOffset).add_options() \ |
| __VA_ARGS__; \ |
| } \ |
| ~AUTO_REGISTER_COMMAND_TOKENPASTE(AutoRegister, __LINE__)() { } \ |
| }; \ |
| AUTO_REGISTER_COMMAND_TOKENPASTE(AutoRegister, __LINE__) AUTO_REGISTER_COMMAND_TOKENPASTE(autoRegister, __LINE__); \ |
| } |
| |
| #endif |
| |
| |