diff --git a/etc/bash_completion.d/icinga2 b/etc/bash_completion.d/icinga2 index 0af84850c..425939210 100644 --- a/etc/bash_completion.d/icinga2 +++ b/etc/bash_completion.d/icinga2 @@ -3,7 +3,7 @@ _icinga2() local cur opts opts="${COMP_WORDS[*]}" cur="${COMP_WORDS[COMP_CWORD]}" - COMPREPLY=($(icinga2 --autocomplete ${COMP_WORDS[*]:1} < /dev/null)) + COMPREPLY=($(icinga2 --autocomplete $COMP_CWORD ${COMP_WORDS[*]:1} < /dev/null)) return 0 } diff --git a/icinga-app/icinga.cpp b/icinga-app/icinga.cpp index 771ff4665..bc46a8be4 100644 --- a/icinga-app/icinga.cpp +++ b/icinga-app/icinga.cpp @@ -47,9 +47,20 @@ int Main(void) int argc = Application::GetArgC(); char **argv = Application::GetArgV(); + bool autocomplete = false; + int autoindex = 0; + + if (argc >= 4 && strcmp(argv[1], "--autocomplete") == 0) { + autocomplete = true; + autoindex = Convert::ToLong(argv[2]); + argc -= 3; + argv += 3; + } + Application::SetStartTime(Utility::GetTime()); - Application::SetResourceLimits(); + if (!autocomplete) + Application::SetResourceLimits(); /* Set thread title. */ Utility::SetThreadName("Main Thread", false); @@ -114,12 +125,10 @@ int Main(void) ("library,l", po::value >(), "load a library") ("include,I", po::value >(), "add include search directory") ("log-level,x", po::value(), "specify the log level for the console log") - ("no-stack-rlimit", "used internally, do not specify manually") - ("autocomplete", "auto-complete arguments"); + ("no-stack-rlimit", "used internally, do not specify manually"); String cmdname; CLICommand::Ptr command; - bool autocomplete; po::variables_map vm; try { @@ -230,7 +239,7 @@ int Main(void) if (!command || vm.count("help")) { if (!command) { std::cout << std::endl; - CLICommand::ShowCommands(argc, argv, NULL, false); + CLICommand::ShowCommands(argc, argv, NULL); } std::cout << std::endl @@ -244,7 +253,7 @@ int Main(void) int rc = 1; if (autocomplete) { - CLICommand::ShowCommands(argc, argv, &desc, true); + CLICommand::ShowCommands(argc, argv, &desc, true, autoindex); rc = 0; } else if (command) rc = command->Run(vm); diff --git a/lib/base/clicommand.cpp b/lib/base/clicommand.cpp index 01e718635..3856ac36a 100644 --- a/lib/base/clicommand.cpp +++ b/lib/base/clicommand.cpp @@ -64,12 +64,10 @@ RegisterCLICommandHelper::RegisterCLICommandHelper(const String& name, const CLI } bool CLICommand::ParseCommand(int argc, char **argv, po::options_description& desc, po::variables_map& vm, - String& cmdname, CLICommand::Ptr& command, bool& autocomplete) + String& cmdname, CLICommand::Ptr& command, bool autocomplete) { boost::mutex::scoped_lock lock(l_RegistryMutex); - autocomplete = false; - typedef std::map, CLICommand::Ptr>::value_type CLIKeyValue; std::vector best_match; @@ -80,11 +78,6 @@ bool CLICommand::ParseCommand(int argc, char **argv, po::options_description& de for (int i = 0, k = 1; i < vname.size() && k < argc; i++, k++) { if (strcmp(argv[k], "--no-stack-rlimit") == 0 || strcmp(argv[k], "--autocomplete") == 0) { - if (strcmp(argv[k], "--autocomplete") == 0) { - autocomplete = true; - return false; - } - i--; continue; } @@ -111,16 +104,20 @@ found_command: if (command) command->InitParameters(ldesc); - + desc.add(ldesc); - + + if (autocomplete) + return true; + po::store(po::parse_command_line(argc - arg_end, argv + arg_end, desc), vm); po::notify(vm); return true; } -void CLICommand::ShowCommands(int argc, char **argv, po::options_description *desc, bool autocomplete) +void CLICommand::ShowCommands(int argc, char **argv, po::options_description *desc, + bool autocomplete, int autoindex) { boost::mutex::scoped_lock lock(l_RegistryMutex); @@ -156,12 +153,17 @@ void CLICommand::ShowCommands(int argc, char **argv, po::options_description *de } } - if (!autocomplete) + String aword; + + if (autocomplete) { + if (autoindex < argc) + aword = argv[autoindex]; + } else std::cout << "Supported commands: " << std::endl; - + BOOST_FOREACH(const CLIKeyValue& kv, l_Registry) { const std::vector& vname = kv.first; - + if (vname.size() < best_match.size()) continue; @@ -178,20 +180,18 @@ void CLICommand::ShowCommands(int argc, char **argv, po::options_description *de continue; if (autocomplete) { - if (best_match.size() < vname.size()) { - String cname = vname[best_match.size()]; - String pname; - - if (arg_begin + best_match.size() + 1 < argc) - pname = argv[arg_begin + best_match.size() + 1]; - - if (cname.Find(pname) == 0) - std::cout << vname[best_match.size()] << " "; + String cname; + + if (autoindex - 1 < vname.size()) { + cname = vname[autoindex - 1]; + + if (cname.Find(aword) == 0) + std::cout << cname << "\n"; } } else std::cout << " * " << boost::algorithm::join(vname, " ") << " (" << kv.second->GetShortDescription() << ")" << std::endl; } - + if (command && autocomplete) { po::options_description ldesc("Command options"); @@ -202,10 +202,9 @@ void CLICommand::ShowCommands(int argc, char **argv, po::options_description *de BOOST_FOREACH(const shared_ptr& odesc, desc->options()) { String cname = "--" + odesc->long_name(); - String pname = argv[argc - 1]; - - if (cname.Find(pname) == 0) - std::cout << cname << " "; + + if (cname.Find(aword) == 0) + std::cout << cname << "\n"; } } diff --git a/lib/base/clicommand.hpp b/lib/base/clicommand.hpp index ee7d1c6d6..b2f52dd7c 100644 --- a/lib/base/clicommand.hpp +++ b/lib/base/clicommand.hpp @@ -49,8 +49,8 @@ public: static void Unregister(const std::vector& name); static bool ParseCommand(int argc, char **argv, boost::program_options::options_description& desc, - boost::program_options::variables_map& vm, String& cmdname, CLICommand::Ptr& command, bool& autocomplete); - static void ShowCommands(int argc, char **argv, boost::program_options::options_description *desc, bool autocomplete); + boost::program_options::variables_map& vm, String& cmdname, CLICommand::Ptr& command, bool autocomplete); + static void ShowCommands(int argc, char **argv, boost::program_options::options_description *desc = NULL, bool autocomplete = false, int autoindex = -1); }; /**