X-Git-Url: https://gerrit.akraino.org/r/gitweb?a=blobdiff_plain;f=src%2Ftype3_AndroidCloud%2Fanbox-master%2Fsrc%2Fanbox%2Fcli.cpp;fp=src%2Ftype3_AndroidCloud%2Fanbox-master%2Fsrc%2Fanbox%2Fcli.cpp;h=959a43c598be8af2bc0e071f8be7dcebc21c90d9;hb=e26c1ec581be598521517829adba8c8dd23a768f;hp=0000000000000000000000000000000000000000;hpb=6699c1aea74eeb0eb400e6299079f0c7576f716f;p=iec.git diff --git a/src/type3_AndroidCloud/anbox-master/src/anbox/cli.cpp b/src/type3_AndroidCloud/anbox-master/src/anbox/cli.cpp new file mode 100644 index 0000000..959a43c --- /dev/null +++ b/src/type3_AndroidCloud/anbox-master/src/anbox/cli.cpp @@ -0,0 +1,249 @@ +/* + * Copyright (C) 2016 Canonical, Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Authored by: Thomas Voß + * + */ + +#include +#include + +#include "anbox/cli.h" + +namespace cli = anbox::cli; +namespace po = boost::program_options; + +namespace { +namespace pattern { +static constexpr const char* help_for_command_with_subcommands = + "NAME:\n" + " %1% - %2%\n" + "\n" + "USAGE:\n" + " %3% [command options] [arguments...]"; + +static constexpr const char* commands = "COMMANDS:"; +static constexpr const char* command = " %1% %2%"; + +static constexpr const char* options = "OPTIONS:"; +static constexpr const char* option = " --%1% %2%"; +} + +void add_to_desc_for_flags(po::options_description& desc, + const std::set& flags) { + for (auto flag : flags) { + po::value_semantic *spec = nullptr; + flag->specify_option(spec); + if (!spec) continue; + desc.add_options()(flag->name().as_string().c_str(), spec, + flag->description().as_string().c_str()); + } +} +} + +std::vector cli::args(int argc, char** argv) { + std::vector result; + for (int i = 1; i < argc; i++) result.push_back(argv[i]); + return result; +} + +const cli::Name& cli::Flag::name() const { return name_; } + +const cli::Description& cli::Flag::description() const { return description_; } + +cli::Flag::Flag(const Name& name, const Description& description) + : name_{name}, description_{description} {} + +cli::Command::FlagsWithInvalidValue::FlagsWithInvalidValue() + : std::runtime_error{"Flags with invalid value"} {} + +cli::Command::FlagsMissing::FlagsMissing() + : std::runtime_error{"Flags are missing in command invocation"} {} + +cli::Name cli::Command::name() const { return name_; } + +cli::Usage cli::Command::usage() const { return usage_; } + +cli::Description cli::Command::description() const { return description_; } + +bool cli::Command::hidden() const { return hidden_; } + +cli::Command::Command(const cli::Name& name, const cli::Usage& usage, + const cli::Description& description, bool hidden) + : name_(name), usage_(usage), description_(description), hidden_(hidden) {} + +cli::CommandWithSubcommands::CommandWithSubcommands( + const Name& name, const Usage& usage, const Description& description) + : Command{name, usage, description} { + command(std::make_shared(*this)); +} + +cli::CommandWithSubcommands& cli::CommandWithSubcommands::command( + const Command::Ptr& command) { + commands_[command->name().as_string()] = command; + return *this; +} + +cli::CommandWithSubcommands& cli::CommandWithSubcommands::flag( + const Flag::Ptr& flag) { + flags_.insert(flag); + return *this; +} + +void cli::CommandWithSubcommands::help(std::ostream& out) { + out << boost::format(pattern::help_for_command_with_subcommands) % + name().as_string() % usage().as_string() % name().as_string() + << std::endl; + + if (flags_.size() > 0) { + out << std::endl + << pattern::options << std::endl; + for (const auto& flag : flags_) + out << boost::format(pattern::option) % flag->name() % flag->description() + << std::endl; + } + + if (commands_.size() > 0) { + out << std::endl + << pattern::commands << std::endl; + for (const auto& cmd : commands_) { + if (cmd.second && !cmd.second->hidden()) + out << boost::format(pattern::command) % cmd.second->name() % + cmd.second->description() + << std::endl; + } + } +} + +int cli::CommandWithSubcommands::run(const cli::Command::Context& ctxt) { + po::positional_options_description pdesc; + pdesc.add("command", 1); + + po::options_description desc("Options"); + desc.add_options()("command", po::value()->required(), + "the command to be executed"); + + add_to_desc_for_flags(desc, flags_); + + try { + po::variables_map vm; + auto parsed = po::command_line_parser(ctxt.args) + .options(desc) + .positional(pdesc) + .style(po::command_line_style::unix_style) + .allow_unregistered() + .run(); + + po::store(parsed, vm); + po::notify(vm); + + auto cmd = commands_[vm["command"].as()]; + if (!cmd) { + ctxt.cout << "Unknown command '" << vm["command"].as() << "'" + << std::endl; + help(ctxt.cout); + return EXIT_FAILURE; + } + + return cmd->run(cli::Command::Context{ + ctxt.cin, ctxt.cout, + po::collect_unrecognized(parsed.options, po::include_positional)}); + } catch (const po::error& e) { + ctxt.cout << e.what() << std::endl; + help(ctxt.cout); + return EXIT_FAILURE; + } + + return EXIT_FAILURE; +} + +cli::CommandWithFlagsAndAction::CommandWithFlagsAndAction( + const Name& name, const Usage& usage, const Description& description, bool hidden) + : Command{name, usage, description, hidden} {} + +cli::CommandWithFlagsAndAction& cli::CommandWithFlagsAndAction::flag( + const Flag::Ptr& flag) { + flags_.insert(flag); + return *this; +} + +cli::CommandWithFlagsAndAction& cli::CommandWithFlagsAndAction::action( + const Action& action) { + action_ = action; + return *this; +} + +int cli::CommandWithFlagsAndAction::run(const Context& ctxt) { + po::options_description cd(name().as_string()); + + bool help_requested{false}; + cd.add_options()("help", po::bool_switch(&help_requested), + "produces a help message"); + + add_to_desc_for_flags(cd, flags_); + + try { + po::variables_map vm; + auto parsed = po::command_line_parser(ctxt.args) + .options(cd) + .style(po::command_line_style::unix_style) + .allow_unregistered() + .run(); + po::store(parsed, vm); + po::notify(vm); + + if (help_requested) { + help(ctxt.cout); + return EXIT_SUCCESS; + } + + return action_(cli::Command::Context{ + ctxt.cin, ctxt.cout, + po::collect_unrecognized(parsed.options, po::include_positional)}); + } catch (const po::error& e) { + ctxt.cout << e.what() << std::endl; + help(ctxt.cout); + return EXIT_FAILURE; + } + + return EXIT_FAILURE; +} + +void cli::CommandWithFlagsAndAction::help(std::ostream& out) { + out << boost::format(pattern::help_for_command_with_subcommands) % + name().as_string() % description().as_string() % name().as_string() + << std::endl; + + if (flags_.size() > 0) { + out << std::endl + << boost::format(pattern::options) << std::endl; + for (const auto& flag : flags_) + out << boost::format(pattern::option) % flag->name() % flag->description() + << std::endl; + } +} + +cli::cmd::Help::Help(Command& cmd) + : Command{cli::Name{"help"}, cli::Usage{"Print a short help message"}, + cli::Description{"Print a short help message"}}, + command{cmd} {} + +// From Command +int cli::cmd::Help::run(const Context& context) { + command.help(context.cout); + return EXIT_FAILURE; +} + +void cli::cmd::Help::help(std::ostream& out) { command.help(out); }