/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ module; #include #include #include #include #include #include export module katja.command_line; namespace katja { export enum class command { updates, search, help }; export struct command_line { const command type; 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; public: invalid_command_error() : std::runtime_error("Expecting the command line to begin with a 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) { throw invalid_command_error(); } std::vector arguments; std::copy(argv + 2, argv + argc, std::back_inserter(arguments)); if (strcmp("updates", argv[1]) == 0) { return command_line{ command::updates, std::move(arguments) }; } if (strcmp("search", argv[1]) == 0) { return command_line{ command::search, std::move(arguments) }; } if (strcmp("help", argv[1]) == 0) { return command_line{ command::help, std::move(arguments) }; } 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(); } } }