Fix auto-completion for arguments

refs #7246
This commit is contained in:
Gunnar Beutner 2014-10-10 10:07:56 +02:00
parent c1d507a793
commit 4c8d0b9283
4 changed files with 45 additions and 37 deletions

View File

@ -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
}

View File

@ -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<std::vector<std::string> >(), "load a library")
("include,I", po::value<std::vector<std::string> >(), "add include search directory")
("log-level,x", po::value<std::string>(), "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);

View File

@ -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<std::vector<String>, CLICommand::Ptr>::value_type CLIKeyValue;
std::vector<String> 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<String>& 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<po::option_description>& 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";
}
}

View File

@ -49,8 +49,8 @@ public:
static void Unregister(const std::vector<String>& 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);
};
/**