diff --git a/cli/command_line.cpp b/cli/command_line.cpp index ff6c928..3e92a20 100644 --- a/cli/command_line.cpp +++ b/cli/command_line.cpp @@ -30,6 +30,25 @@ namespace katja const std::vector arguments; }; + export struct search_command + { + const std::string needle; + }; + + export struct updates_command + { + }; + + export struct help_command + { + }; + + export using subcommand = std::variant< + search_command, + updates_command, + help_command + >; + export class invalid_command_error : public std::runtime_error { const std::string command; @@ -40,13 +59,26 @@ namespace katja { } - invalid_command_error(const std::string& invalid_command) + explicit invalid_command_error(const std::string& invalid_command) : command{ invalid_command }, std::runtime_error("Unknown command given on the command line.") { } }; + export class command_line_error : public std::runtime_error + { + boost::program_options::options_description description; + + public: + command_line_error(const std::string& message, + boost::program_options::options_description&& description) + : description(std::move(description)), + std::runtime_error(message) + { + } + }; + export command_line parse_command_line(int argc, const char **argv) { if (argc == 1) @@ -70,4 +102,42 @@ namespace katja } throw invalid_command_error(argv[1]); } + + search_command parse_search_command(const std::vector& arguments) + { + boost::program_options::options_description search_description("Search packages"); + search_description + .add_options()("name", "Find packages by name"); + + boost::program_options::positional_options_description positional_arguments; + positional_arguments.add("name", 1); + + boost::program_options::variables_map option_map; + auto command_parser = boost::program_options::command_line_parser(arguments) + .options(search_description).positional(positional_arguments); + boost::program_options::store(command_parser.run(), option_map); + boost::program_options::notify(option_map); + + if (!option_map.count("name")) + { + throw command_line_error("Search string wasn't specified.", + std::move(search_description)); + } + return search_command{ option_map["name"].as() }; + } + + export subcommand parse_subcommand(const command_line& subcommand_line) + { + switch (subcommand_line.type) + { + case command::updates: + return updates_command(); + case command::search: + return parse_search_command(subcommand_line.arguments); + case command::help: + return help_command(); + default: + std::unreachable(); + } + } } diff --git a/cli/configuration.cpp b/cli/configuration.cpp index 4ca36c1..e927c92 100644 --- a/cli/configuration.cpp +++ b/cli/configuration.cpp @@ -26,7 +26,13 @@ export namespace katja class configuration { public: - using repositories_t = std::forward_list>; + using value_type = std::pair; + using reference_type = value_type&; + using const_reference_type = const value_type&; + + using repositories_t = std::forward_list; + using size_type = repositories_t::size_type; + using difference_type = repositories_t::difference_type; private: repositories_t repositories; @@ -47,6 +53,16 @@ export namespace katja return this->repositories.end(); } + repositories_t::const_iterator begin() const + { + return this->repositories.begin(); + } + + repositories_t::const_iterator end() const + { + return this->repositories.end(); + } + repositories_t::const_iterator cbegin() { return this->repositories.cbegin(); diff --git a/cli/main.cpp b/cli/main.cpp index da0d1b8..4964498 100644 --- a/cli/main.cpp +++ b/cli/main.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include @@ -36,14 +37,13 @@ static void search_names(std::shared_ptr repository, const st } } -int main(int argc, const char **argv) +static void handle_subcommand(const katja::configuration& configuration, + const katja::subcommand& command) { - katja::configuration configuration = katja::read_configuration("katja.toml"); - katja::package_database installed_database = katja::read_installed_database(); - - katja::command_line command_line = katja::parse_command_line(argc, argv); - if (command_line.type == katja::command::updates) + if (std::holds_alternative(command)) { + katja::package_database installed_database = katja::read_installed_database(); + for (const auto& [repository_name, repository_configuration] : configuration) { std::filesystem::path slackbuild_repository{ repository_configuration.path }; @@ -52,34 +52,25 @@ int main(int argc, const char **argv) get_updates(repository, std::move(installed_database)); } } - else if (command_line.type == katja::command::search) + else if (std::holds_alternative(command)) { - boost::program_options::options_description search_description("Search packages"); - search_description - .add_options()("name", "Find packages by name"); - - boost::program_options::positional_options_description positional_arguments; - positional_arguments.add("name", 1); - - boost::program_options::variables_map option_map; - auto command_parser = boost::program_options::command_line_parser(command_line.arguments) - .options(search_description).positional(positional_arguments); - boost::program_options::store(command_parser.run(), option_map); - boost::program_options::notify(option_map); - - if (!option_map.count("name")) - { - std::cerr << search_description; - return EXIT_FAILURE; - } for (const auto& [repository_name, repository_configuration] : configuration) { std::filesystem::path slackbuild_repository{ repository_configuration.path }; auto repository = std::make_shared(slackbuild_repository); - search_names(repository, option_map["name"].as()); + search_names(repository, std::get(command).needle); } } +} + +int main(int argc, const char **argv) +{ + katja::configuration configuration = katja::read_configuration("katja.toml"); + katja::command_line command_line = katja::parse_command_line(argc, argv); + katja::subcommand subcommand = katja::parse_subcommand(command_line); + + handle_subcommand(configuration, subcommand); return EXIT_SUCCESS; }