From: Jason Dillaman Date: Mon, 19 Oct 2015 19:07:50 +0000 (-0400) Subject: rbd: hidden 'bash-completion' command dumps all available commands X-Git-Tag: v10.0.1~88^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=01c720b1b3f3b87cb363f12644daeb49aa87a03c;p=ceph.git rbd: hidden 'bash-completion' command dumps all available commands It also extracts all available options for a given command for use which can be used by an improved bash completion script. Signed-off-by: Jason Dillaman --- diff --git a/src/tools/rbd/Shell.cc b/src/tools/rbd/Shell.cc index ec2e8d25ad61..8ca87ebe8bd5 100644 --- a/src/tools/rbd/Shell.cc +++ b/src/tools/rbd/Shell.cc @@ -19,6 +19,9 @@ namespace po = boost::program_options; namespace { +static const std::string HELP_SPEC("help"); +static const std::string BASH_COMPLETION_SPEC("bash-completion"); + struct Secret {}; void validate(boost::any& v, const std::vector& values, @@ -50,6 +53,22 @@ std::string format_command_name(const Shell::CommandSpec &spec, return name; } +std::string format_option_suffix( + const boost::shared_ptr &option) { + std::string suffix; + if (option->semantic()->max_tokens() != 0) { + if (option->description().find("path") != std::string::npos || + option->description().find("file") != std::string::npos) { + suffix += " path"; + } else if (option->description().find("host") != std::string::npos) { + suffix += " host"; + } else { + suffix += " arg"; + } + } + return suffix; +} + } // anonymous namespace std::vector Shell::s_actions; @@ -68,7 +87,7 @@ int Shell::execute(int arg_count, const char **arg_values) { // list all available actions print_help(app_name); return 0; - } else if (command_spec[0] == "help") { + } else if (command_spec[0] == HELP_SPEC) { // list help for specific action command_spec.erase(command_spec.begin()); Action *action = find_action(command_spec, NULL); @@ -79,6 +98,10 @@ int Shell::execute(int arg_count, const char **arg_values) { print_action_help(app_name, action); return 0; } + } else if (command_spec[0] == BASH_COMPLETION_SPEC) { + command_spec.erase(command_spec.begin()); + print_bash_completion(command_spec); + return 0; } CommandSpec *matching_spec; @@ -154,7 +177,7 @@ void Shell::get_command_spec(const std::vector &arguments, for (size_t i = 0; i < arguments.size(); ++i) { std::string arg(arguments[i]); if (arg == "-h" || arg == "--help") { - *command_spec = {"help"}; + *command_spec = {HELP_SPEC}; return; } else if (arg == "--") { // all arguments after a double-dash are positional @@ -335,4 +358,47 @@ void Shell::print_unknown_action(const std::string &app_name, print_help(app_name); } +void Shell::print_bash_completion(const CommandSpec &command_spec) { + Action *action = find_action(command_spec, NULL); + po::options_description global_opts; + get_global_options(&global_opts); + print_bash_completion_options(global_opts); + + if (action != nullptr) { + po::options_description positional_opts; + po::options_description command_opts; + (*action->get_arguments)(&positional_opts, &command_opts); + print_bash_completion_options(command_opts); + } else { + std::cout << "|help"; + for (size_t i = 0; i < s_actions.size(); ++i) { + Action *action = s_actions[i]; + std::cout << "|" + << joinify(action->command_spec.begin(), + action->command_spec.end(), " "); + if (!action->alias_command_spec.empty()) { + std::cout << "|" + << joinify(action->alias_command_spec.begin(), + action->alias_command_spec.end(), + " "); + } + } + } + std::cout << "|" << std::endl; +} + +void Shell::print_bash_completion_options(const po::options_description &ops) { + for (size_t i = 0; i < ops.options().size(); ++i) { + auto option = ops.options()[i]; + std::string long_name(option->canonical_display_name(0)); + std::string short_name(option->canonical_display_name( + po::command_line_style::allow_dash_for_short)); + + std::cout << "|--" << long_name << format_option_suffix(option); + if (long_name != short_name) { + std::cout << "|" << short_name << format_option_suffix(option); + } + } +} + } // namespace rbd diff --git a/src/tools/rbd/Shell.h b/src/tools/rbd/Shell.h index 63fede31963f..5422a4764d90 100644 --- a/src/tools/rbd/Shell.h +++ b/src/tools/rbd/Shell.h @@ -65,7 +65,11 @@ private: void print_help(const std::string &app_name); void print_action_help(const std::string &app_name, Action *action); void print_unknown_action(const std::string &app_name, - const std::vector &command_spec); + const CommandSpec &command_spec); + + void print_bash_completion(const CommandSpec &command_spec); + void print_bash_completion_options( + const boost::program_options::options_description &ops); }; } // namespace rbd