From 7db85889802c9fecea5711ddf09f946f0aeaa913 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Fri, 17 Oct 2014 15:54:46 +0200 Subject: [PATCH] Implement auto-completion for positional arguments refs #7255 --- etc/bash_completion.d/icinga2 | 7 ++- icinga-app/icinga.cpp | 22 +++++++--- lib/base/clicommand.cpp | 67 ++++++++++++++++++----------- lib/base/clicommand.hpp | 17 ++++---- lib/cli/daemoncommand.cpp | 12 ++++-- lib/cli/daemoncommand.hpp | 4 +- lib/cli/featuredisablecommand.cpp | 3 +- lib/cli/featuredisablecommand.hpp | 3 +- lib/cli/featureenablecommand.cpp | 3 +- lib/cli/featureenablecommand.hpp | 3 +- lib/cli/featurelistcommand.cpp | 7 --- lib/cli/featurelistcommand.hpp | 3 -- lib/cli/objectlistcommand.cpp | 3 +- lib/cli/objectlistcommand.hpp | 3 +- lib/cli/pkinewcacommand.cpp | 7 --- lib/cli/pkinewcacommand.hpp | 3 -- lib/cli/pkinewcertcommand.cpp | 13 +++--- lib/cli/pkinewcertcommand.hpp | 4 +- lib/cli/pkirequestcommand.cpp | 19 +++++--- lib/cli/pkirequestcommand.hpp | 4 +- lib/cli/pkisigncsrcommand.cpp | 12 ++++-- lib/cli/pkisigncsrcommand.hpp | 4 +- lib/cli/pkiticketcommand.cpp | 3 +- lib/cli/pkiticketcommand.hpp | 3 +- lib/cli/repositoryobjectcommand.cpp | 14 +++--- lib/cli/repositoryobjectcommand.hpp | 4 +- 26 files changed, 133 insertions(+), 114 deletions(-) diff --git a/etc/bash_completion.d/icinga2 b/etc/bash_completion.d/icinga2 index 1b9013e86..5c49ab036 100644 --- a/etc/bash_completion.d/icinga2 +++ b/etc/bash_completion.d/icinga2 @@ -4,7 +4,12 @@ _icinga2() opts="${COMP_WORDS[*]}" cur="${COMP_WORDS[COMP_CWORD]}" COMPREPLY=($(icinga2 --autocomplete $COMP_CWORD ${COMP_WORDS[*]} < /dev/null)) - [[ $COMPREPLY = */ ]] && compopt -o nospace + case $COMPREPLY in + */|*=) + compopt -o nospace + ;; + esac + return 0 } diff --git a/icinga-app/icinga.cpp b/icinga-app/icinga.cpp index 385d764f0..9b37a2e61 100644 --- a/icinga-app/icinga.cpp +++ b/icinga-app/icinga.cpp @@ -48,7 +48,7 @@ SERVICE_STATUS l_SvcStatus; SERVICE_STATUS_HANDLE l_SvcStatusHandle; #endif /* _WIN32 */ -static std::vector LogLevelCompletion(const String& arg) +static std::vector GetLogLevelCompletionSuggestions(const String& arg) { std::vector result; @@ -75,6 +75,16 @@ static std::vector LogLevelCompletion(const String& arg) return result; } +static std::vector GlobalArgumentCompletion(const String& argument, const String& word) +{ + if (argument == "include") + return GetBashCompletionSuggestions("directory", word); + else if (argument == "log-level") + return GetLogLevelCompletionSuggestions(word); + else + return std::vector(); +} + int Main(void) { int argc = Application::GetArgC(); @@ -170,16 +180,13 @@ int Main(void) po::positional_options_description positionalDesc; positionalDesc.add("arg", -1); - ArgumentCompletionDescription argDesc; - argDesc["include"] = BashArgumentCompletion("directory"); - argDesc["log-level"] = LogLevelCompletion; - String cmdname; CLICommand::Ptr command; po::variables_map vm; try { - CLICommand::ParseCommand(argc, argv, visibleDesc, hiddenDesc, positionalDesc, argDesc, vm, cmdname, command, autocomplete); + CLICommand::ParseCommand(argc, argv, visibleDesc, hiddenDesc, positionalDesc, + vm, cmdname, command, autocomplete); } catch (const std::exception& ex) { std::ostringstream msgbuf; msgbuf << "Error while parsing command-line options: " << ex.what(); @@ -307,7 +314,8 @@ int Main(void) int rc = 1; if (autocomplete) { - CLICommand::ShowCommands(argc, argv, &visibleDesc, &hiddenDesc, &argDesc, true, autoindex); + CLICommand::ShowCommands(argc, argv, &visibleDesc, &hiddenDesc, + &GlobalArgumentCompletion, true, autoindex); rc = 0; } else if (command) { #ifndef _WIN32 diff --git a/lib/base/clicommand.cpp b/lib/base/clicommand.cpp index 3e52024ce..a2aed63f2 100644 --- a/lib/base/clicommand.cpp +++ b/lib/base/clicommand.cpp @@ -34,12 +34,12 @@ namespace po = boost::program_options; boost::mutex l_RegistryMutex; std::map, CLICommand::Ptr> l_Registry; -static std::vector BashArgumentCompletionHelper(const String& type, const String& arg) +std::vector icinga::GetBashCompletionSuggestions(const String& type, const String& word) { std::vector result; #ifndef _WIN32 - String bashArg = "compgen -A " + Utility::EscapeShellArg(type) + " " + Utility::EscapeShellArg(arg); + String bashArg = "compgen -A " + Utility::EscapeShellArg(type) + " " + Utility::EscapeShellArg(word); String cmd = "bash -c " + Utility::EscapeShellArg(bashArg); FILE *fp = popen(cmd.CStr(), "r"); @@ -69,25 +69,28 @@ static std::vector BashArgumentCompletionHelper(const String& type, cons return result; } -void icinga::AddTypeFields(const Type *type, boost::program_options::options_description& desc) +std::vector icinga::GetFieldCompletionSuggestions(const Type *type, const String& word) { + std::vector result; + for (int i = 0; i < type->GetFieldCount(); i++) { Field field = type->GetFieldInfo(i); - if (strcmp(field.Name, "__name") == 0) - continue; - if (!(field.Attributes & FAConfig)) continue; - desc.add_options() - (field.Name, po::value(), field.Name); - } -} + String fname = field.Name; -ArgumentCompletionCallback icinga::BashArgumentCompletion(const String& type) -{ - return boost::bind(BashArgumentCompletionHelper, type, _1); + if (fname == "__name" || fname == "templates") + continue; + + String suggestion = fname + "="; + + if (suggestion.Find(word) == 0) + result.push_back(suggestion); + } + + return result; } CLICommand::Ptr CLICommand::GetByName(const std::vector& name) @@ -121,10 +124,23 @@ RegisterCLICommandHelper::RegisterCLICommandHelper(const String& name, const CLI CLICommand::Register(vname, command); } +std::vector CLICommand::GetArgumentSuggestions(const String& argument, const String& word) const +{ + return std::vector(); +} + +std::vector CLICommand::GetPositionalSuggestions(const String& word) const +{ + return std::vector(); +} + +void CLICommand::InitParameters(boost::program_options::options_description& visibleDesc, + boost::program_options::options_description& hiddenDesc) const +{ } + bool CLICommand::ParseCommand(int argc, char **argv, po::options_description& visibleDesc, po::options_description& hiddenDesc, po::positional_options_description& positionalDesc, - ArgumentCompletionDescription& argCompletionDesc, po::variables_map& vm, String& cmdname, CLICommand::Ptr& command, bool autocomplete) { boost::mutex::scoped_lock lock(l_RegistryMutex); @@ -164,7 +180,7 @@ found_command: po::options_description vdesc("Command options"); if (command) - command->InitParameters(vdesc, hiddenDesc, argCompletionDesc); + command->InitParameters(vdesc, hiddenDesc); visibleDesc.add(vdesc); @@ -182,7 +198,8 @@ found_command: } void CLICommand::ShowCommands(int argc, char **argv, po::options_description *visibleDesc, - po::options_description *hiddenDesc, ArgumentCompletionDescription *argCompletionDesc, + po::options_description *hiddenDesc, + ArgumentCompletionCallback globalArgCompletionCallback, bool autocomplete, int autoindex) { boost::mutex::scoped_lock lock(l_RegistryMutex); @@ -263,7 +280,6 @@ void CLICommand::ShowCommands(int argc, char **argv, po::options_description *vi if (command && autocomplete) { String aname, prefix, pword; - ArgumentCompletionDescription::const_iterator it; const po::option_description *odesc; if (autoindex - 2 >= 0 && strcmp(argv[autoindex - 1], "=") == 0 && strstr(argv[autoindex - 2], "--") == argv[autoindex - 2]) { @@ -290,13 +306,12 @@ void CLICommand::ShowCommands(int argc, char **argv, po::options_description *vi if (odesc->semantic()->min_tokens() == 0) goto complete_option; - - it = argCompletionDesc->find(odesc->long_name()); - - if (it == argCompletionDesc->end()) - return; - - BOOST_FOREACH(const String& suggestion, it->second(pword)) { + + BOOST_FOREACH(const String& suggestion, globalArgCompletionCallback(aname, pword)) { + std::cout << prefix << suggestion << "\n"; + } + + BOOST_FOREACH(const String& suggestion, command->GetArgumentSuggestions(aname, pword)) { std::cout << prefix << suggestion << "\n"; } @@ -309,6 +324,10 @@ complete_option: if (cname.Find(aword) == 0) std::cout << cname << "\n"; } + + BOOST_FOREACH(const String& suggestion, command->GetPositionalSuggestions(aword)) { + std::cout << suggestion << "\n"; + } } return; diff --git a/lib/base/clicommand.hpp b/lib/base/clicommand.hpp index a75dc85e8..a324681cb 100644 --- a/lib/base/clicommand.hpp +++ b/lib/base/clicommand.hpp @@ -29,11 +29,8 @@ namespace icinga { -typedef boost::function (const String&)> ArgumentCompletionCallback; -typedef std::map ArgumentCompletionDescription; - -I2_BASE_API ArgumentCompletionCallback BashArgumentCompletion(const String& type); -I2_BASE_API void AddTypeFields(const Type *type, boost::program_options::options_description& desc); +I2_BASE_API std::vector GetBashCompletionSuggestions(const String& type, const String& word); +I2_BASE_API std::vector GetFieldCompletionSuggestions(const Type *type, const String& word); /** * A CLI command. @@ -45,12 +42,15 @@ class I2_BASE_API CLICommand : public Object public: DECLARE_PTR_TYPEDEFS(CLICommand); + typedef std::vector(*ArgumentCompletionCallback)(const String&, const String&); + virtual String GetDescription(void) const = 0; virtual String GetShortDescription(void) const = 0; virtual void InitParameters(boost::program_options::options_description& visibleDesc, - boost::program_options::options_description& hiddenDesc, - ArgumentCompletionDescription& argCompletionDesc) const = 0; + boost::program_options::options_description& hiddenDesc) const; virtual int Run(const boost::program_options::variables_map& vm, const std::vector& ap) const = 0; + virtual std::vector GetArgumentSuggestions(const String& argument, const String& word) const; + virtual std::vector GetPositionalSuggestions(const String& word) const; static CLICommand::Ptr GetByName(const std::vector& name); static void Register(const std::vector& name, const CLICommand::Ptr& command); @@ -59,14 +59,13 @@ public: static bool ParseCommand(int argc, char **argv, boost::program_options::options_description& visibleDesc, boost::program_options::options_description& hiddenDesc, boost::program_options::positional_options_description& positionalDesc, - ArgumentCompletionDescription& argCompletionDesc, 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 *visibleDesc = NULL, boost::program_options::options_description *hiddenDesc = NULL, - ArgumentCompletionDescription *argCompletionDesc = NULL, + ArgumentCompletionCallback globalArgCompletionCallback = NULL, bool autocomplete = false, int autoindex = -1); }; diff --git a/lib/cli/daemoncommand.cpp b/lib/cli/daemoncommand.cpp index f53e972f4..735566283 100644 --- a/lib/cli/daemoncommand.cpp +++ b/lib/cli/daemoncommand.cpp @@ -276,8 +276,7 @@ String DaemonCommand::GetShortDescription(void) const } void DaemonCommand::InitParameters(boost::program_options::options_description& visibleDesc, - boost::program_options::options_description& hiddenDesc, - ArgumentCompletionDescription& argCompletionDesc) const + boost::program_options::options_description& hiddenDesc) const { visibleDesc.add_options() ("config,c", po::value >(), "parse a configuration file") @@ -293,9 +292,14 @@ void DaemonCommand::InitParameters(boost::program_options::options_description& hiddenDesc.add_options() ("reload-internal", po::value(), "used internally to implement config reload: do not call manually, send SIGHUP instead"); #endif /* _WIN32 */ +} - argCompletionDesc["config"] = BashArgumentCompletion("file"); - argCompletionDesc["errorlog"] = BashArgumentCompletion("file"); +std::vector DaemonCommand::GetArgumentSuggestions(const String& argument, const String& word) const +{ + if (argument == "config" || argument == "errorlog") + return GetBashCompletionSuggestions("file", word); + else + return CLICommand::GetArgumentSuggestions(argument, word); } /** diff --git a/lib/cli/daemoncommand.hpp b/lib/cli/daemoncommand.hpp index 3341bcb30..14550ecc0 100644 --- a/lib/cli/daemoncommand.hpp +++ b/lib/cli/daemoncommand.hpp @@ -40,8 +40,8 @@ public: virtual String GetDescription(void) const; virtual String GetShortDescription(void) const; virtual void InitParameters(boost::program_options::options_description& visibleDesc, - boost::program_options::options_description& hiddenDesc, - ArgumentCompletionDescription& argCompletionDesc) const; + boost::program_options::options_description& hiddenDesc) const; + virtual std::vector GetArgumentSuggestions(const String& argument, const String& word) const; virtual int Run(const boost::program_options::variables_map& vm, const std::vector& ap) const; }; diff --git a/lib/cli/featuredisablecommand.cpp b/lib/cli/featuredisablecommand.cpp index 530ed21e7..79473db23 100644 --- a/lib/cli/featuredisablecommand.cpp +++ b/lib/cli/featuredisablecommand.cpp @@ -45,8 +45,7 @@ String FeatureDisableCommand::GetShortDescription(void) const } void FeatureDisableCommand::InitParameters(boost::program_options::options_description& visibleDesc, - boost::program_options::options_description& hiddenDesc, - ArgumentCompletionDescription& argCompletionDesc) const + boost::program_options::options_description& hiddenDesc) const { /* Command doesn't support any parameters. */ } diff --git a/lib/cli/featuredisablecommand.hpp b/lib/cli/featuredisablecommand.hpp index 32d9e8c4d..fcb6f7839 100644 --- a/lib/cli/featuredisablecommand.hpp +++ b/lib/cli/featuredisablecommand.hpp @@ -39,8 +39,7 @@ public: virtual String GetDescription(void) const; virtual String GetShortDescription(void) const; virtual void InitParameters(boost::program_options::options_description& visibleDesc, - boost::program_options::options_description& hiddenDesc, - ArgumentCompletionDescription& argCompletionDesc) const; + boost::program_options::options_description& hiddenDesc) const; virtual int Run(const boost::program_options::variables_map& vm, const std::vector& ap) const; }; diff --git a/lib/cli/featureenablecommand.cpp b/lib/cli/featureenablecommand.cpp index c5f357e90..642924bac 100644 --- a/lib/cli/featureenablecommand.cpp +++ b/lib/cli/featureenablecommand.cpp @@ -45,8 +45,7 @@ String FeatureEnableCommand::GetShortDescription(void) const } void FeatureEnableCommand::InitParameters(boost::program_options::options_description& visibleDesc, - boost::program_options::options_description& hiddenDesc, - ArgumentCompletionDescription& argCompletionDesc) const + boost::program_options::options_description& hiddenDesc) const { /* Command doesn't support any parameters. */ } diff --git a/lib/cli/featureenablecommand.hpp b/lib/cli/featureenablecommand.hpp index 529afba60..e675fe465 100644 --- a/lib/cli/featureenablecommand.hpp +++ b/lib/cli/featureenablecommand.hpp @@ -39,8 +39,7 @@ public: virtual String GetDescription(void) const; virtual String GetShortDescription(void) const; virtual void InitParameters(boost::program_options::options_description& visibleDesc, - boost::program_options::options_description& hiddenDesc, - ArgumentCompletionDescription& argCompletionDesc) const; + boost::program_options::options_description& hiddenDesc) const; virtual int Run(const boost::program_options::variables_map& vm, const std::vector& ap) const; }; diff --git a/lib/cli/featurelistcommand.cpp b/lib/cli/featurelistcommand.cpp index ed40ddb85..a9aa9d685 100644 --- a/lib/cli/featurelistcommand.cpp +++ b/lib/cli/featurelistcommand.cpp @@ -44,13 +44,6 @@ String FeatureListCommand::GetShortDescription(void) const return "lists all enabled features"; } -void FeatureListCommand::InitParameters(boost::program_options::options_description& visibleDesc, - boost::program_options::options_description& hiddenDesc, - ArgumentCompletionDescription& argCompletionDesc) const -{ - /* Command doesn't support any parameters. */ -} - /** * The entry point for the "feature list" CLI command. * diff --git a/lib/cli/featurelistcommand.hpp b/lib/cli/featurelistcommand.hpp index 272b0d0ed..399bf3c69 100644 --- a/lib/cli/featurelistcommand.hpp +++ b/lib/cli/featurelistcommand.hpp @@ -38,9 +38,6 @@ public: virtual String GetDescription(void) const; virtual String GetShortDescription(void) const; - virtual void InitParameters(boost::program_options::options_description& visibleDesc, - boost::program_options::options_description& hiddenDesc, - ArgumentCompletionDescription& argCompletionDesc) const; virtual int Run(const boost::program_options::variables_map& vm, const std::vector& ap) const; private: diff --git a/lib/cli/objectlistcommand.cpp b/lib/cli/objectlistcommand.cpp index d70324580..76ec05a8b 100644 --- a/lib/cli/objectlistcommand.cpp +++ b/lib/cli/objectlistcommand.cpp @@ -51,8 +51,7 @@ String ObjectListCommand::GetShortDescription(void) const } void ObjectListCommand::InitParameters(boost::program_options::options_description& visibleDesc, - boost::program_options::options_description& hiddenDesc, - ArgumentCompletionDescription& argCompletionDesc) const + boost::program_options::options_description& hiddenDesc) const { visibleDesc.add_options() ("count,c", "display object counts by types") diff --git a/lib/cli/objectlistcommand.hpp b/lib/cli/objectlistcommand.hpp index fdcca070a..2e191362d 100644 --- a/lib/cli/objectlistcommand.hpp +++ b/lib/cli/objectlistcommand.hpp @@ -42,8 +42,7 @@ public: virtual String GetDescription(void) const; virtual String GetShortDescription(void) const; virtual void InitParameters(boost::program_options::options_description& visibleDesc, - boost::program_options::options_description& hiddenDesc, - ArgumentCompletionDescription& argCompletionDesc) const; + boost::program_options::options_description& hiddenDesc) const; virtual int Run(const boost::program_options::variables_map& vm, const std::vector& ap) const; private: diff --git a/lib/cli/pkinewcacommand.cpp b/lib/cli/pkinewcacommand.cpp index 71ee57cb1..373ab7d49 100644 --- a/lib/cli/pkinewcacommand.cpp +++ b/lib/cli/pkinewcacommand.cpp @@ -38,13 +38,6 @@ String PKINewCACommand::GetShortDescription(void) const return "sets up a new CA"; } -void PKINewCACommand::InitParameters(boost::program_options::options_description& visibleDesc, - boost::program_options::options_description& hiddenDesc, - ArgumentCompletionDescription& argCompletionDesc) const -{ - /* Command doesn't support any parameters. */ -} - /** * The entry point for the "pki new-ca" CLI command. * diff --git a/lib/cli/pkinewcacommand.hpp b/lib/cli/pkinewcacommand.hpp index e063f70b8..6a6cf45c0 100644 --- a/lib/cli/pkinewcacommand.hpp +++ b/lib/cli/pkinewcacommand.hpp @@ -38,9 +38,6 @@ public: virtual String GetDescription(void) const; virtual String GetShortDescription(void) const; - virtual void InitParameters(boost::program_options::options_description& visibleDesc, - boost::program_options::options_description& hiddenDesc, - ArgumentCompletionDescription& argCompletionDesc) const; virtual int Run(const boost::program_options::variables_map& vm, const std::vector& ap) const; }; diff --git a/lib/cli/pkinewcertcommand.cpp b/lib/cli/pkinewcertcommand.cpp index 012f31994..fac38fd62 100644 --- a/lib/cli/pkinewcertcommand.cpp +++ b/lib/cli/pkinewcertcommand.cpp @@ -38,18 +38,21 @@ String PKINewCertCommand::GetShortDescription(void) const } void PKINewCertCommand::InitParameters(boost::program_options::options_description& visibleDesc, - boost::program_options::options_description& hiddenDesc, - ArgumentCompletionDescription& argCompletionDesc) const + boost::program_options::options_description& hiddenDesc) const { visibleDesc.add_options() ("cn", po::value(), "Common Name") ("keyfile", po::value(), "Key file path (output") ("csrfile", po::value(), "CSR file path (optional, output)") ("certfile", po::value(), "Certificate file path (optional, output)"); +} - argCompletionDesc["keyfile"] = BashArgumentCompletion("file"); - argCompletionDesc["csrfile"] = BashArgumentCompletion("file"); - argCompletionDesc["certfile"] = BashArgumentCompletion("file"); +std::vector PKINewCertCommand::GetArgumentSuggestions(const String& argument, const String& word) const +{ + if (argument == "keyfile" || argument == "csrfile" || argument == "certfile") + return GetBashCompletionSuggestions("file", word); + else + return CLICommand::GetArgumentSuggestions(argument, word); } /** diff --git a/lib/cli/pkinewcertcommand.hpp b/lib/cli/pkinewcertcommand.hpp index 98f356a5e..bff677274 100644 --- a/lib/cli/pkinewcertcommand.hpp +++ b/lib/cli/pkinewcertcommand.hpp @@ -39,8 +39,8 @@ public: virtual String GetDescription(void) const; virtual String GetShortDescription(void) const; virtual void InitParameters(boost::program_options::options_description& visibleDesc, - boost::program_options::options_description& hiddenDesc, - ArgumentCompletionDescription& argCompletionDesc) const; + boost::program_options::options_description& hiddenDesc) const; + virtual std::vector GetArgumentSuggestions(const String& argument, const String& word) const; virtual int Run(const boost::program_options::variables_map& vm, const std::vector& ap) const; }; diff --git a/lib/cli/pkirequestcommand.cpp b/lib/cli/pkirequestcommand.cpp index 04ddd61e0..f238197f8 100644 --- a/lib/cli/pkirequestcommand.cpp +++ b/lib/cli/pkirequestcommand.cpp @@ -44,8 +44,7 @@ String PKIRequestCommand::GetShortDescription(void) const } void PKIRequestCommand::InitParameters(boost::program_options::options_description& visibleDesc, - boost::program_options::options_description& hiddenDesc, - ArgumentCompletionDescription& argCompletionDesc) const + boost::program_options::options_description& hiddenDesc) const { visibleDesc.add_options() ("keyfile", po::value(), "Key file path") @@ -54,12 +53,18 @@ void PKIRequestCommand::InitParameters(boost::program_options::options_descripti ("host", po::value(), "Icinga 2 host") ("port", po::value(), "Icinga 2 port") ("ticket", po::value(), "Icinga 2 PKI ticket"); +} - argCompletionDesc["keyfile"] = BashArgumentCompletion("file"); - argCompletionDesc["certfile"] = BashArgumentCompletion("file"); - argCompletionDesc["cafile"] = BashArgumentCompletion("file"); - argCompletionDesc["host"] = BashArgumentCompletion("hostname"); - argCompletionDesc["port"] = BashArgumentCompletion("service"); +std::vector PKIRequestCommand::GetArgumentSuggestions(const String& argument, const String& word) const +{ + if (argument == "keyfile" || argument == "certfile" || argument == "cafile") + return GetBashCompletionSuggestions("file", word); + else if (argument == "host") + return GetBashCompletionSuggestions("hostname", word); + else if (argument == "port") + return GetBashCompletionSuggestions("service", word); + else + return CLICommand::GetArgumentSuggestions(argument, word); } /** diff --git a/lib/cli/pkirequestcommand.hpp b/lib/cli/pkirequestcommand.hpp index 357ded707..439548980 100644 --- a/lib/cli/pkirequestcommand.hpp +++ b/lib/cli/pkirequestcommand.hpp @@ -39,8 +39,8 @@ public: virtual String GetDescription(void) const; virtual String GetShortDescription(void) const; virtual void InitParameters(boost::program_options::options_description& visibleDesc, - boost::program_options::options_description& hiddenDesc, - ArgumentCompletionDescription& argCompletionDesc) const; + boost::program_options::options_description& hiddenDesc) const; + virtual std::vector GetArgumentSuggestions(const String& argument, const String& word) const; virtual int Run(const boost::program_options::variables_map& vm, const std::vector& ap) const; }; diff --git a/lib/cli/pkisigncsrcommand.cpp b/lib/cli/pkisigncsrcommand.cpp index a6b2ed09b..c69622ff1 100644 --- a/lib/cli/pkisigncsrcommand.cpp +++ b/lib/cli/pkisigncsrcommand.cpp @@ -40,15 +40,19 @@ String PKISignCSRCommand::GetShortDescription(void) const } void PKISignCSRCommand::InitParameters(boost::program_options::options_description& visibleDesc, - boost::program_options::options_description& hiddenDesc, - ArgumentCompletionDescription& argCompletionDesc) const + boost::program_options::options_description& hiddenDesc) const { visibleDesc.add_options() ("csrfile", po::value(), "CSR file path (input)") ("certfile", po::value(), "Certificate file path (output)"); +} - argCompletionDesc["csrfile"] = BashArgumentCompletion("file"); - argCompletionDesc["certfile"] = BashArgumentCompletion("file"); +std::vector PKISignCSRCommand::GetArgumentSuggestions(const String& argument, const String& word) const +{ + if (argument == "csrfile" || argument == "certfile") + return GetBashCompletionSuggestions("file", word); + else + return CLICommand::GetArgumentSuggestions(argument, word); } /** diff --git a/lib/cli/pkisigncsrcommand.hpp b/lib/cli/pkisigncsrcommand.hpp index 9d4c4ba2f..f38bb6bce 100644 --- a/lib/cli/pkisigncsrcommand.hpp +++ b/lib/cli/pkisigncsrcommand.hpp @@ -39,8 +39,8 @@ public: virtual String GetDescription(void) const; virtual String GetShortDescription(void) const; virtual void InitParameters(boost::program_options::options_description& visibleDesc, - boost::program_options::options_description& hiddenDesc, - ArgumentCompletionDescription& argCompletionDesc) const; + boost::program_options::options_description& hiddenDesc) const; + virtual std::vector GetArgumentSuggestions(const String& argument, const String& word) const; virtual int Run(const boost::program_options::variables_map& vm, const std::vector& ap) const; }; diff --git a/lib/cli/pkiticketcommand.cpp b/lib/cli/pkiticketcommand.cpp index 7cb8b61d9..2dc2932e1 100644 --- a/lib/cli/pkiticketcommand.cpp +++ b/lib/cli/pkiticketcommand.cpp @@ -44,8 +44,7 @@ String PKITicketCommand::GetShortDescription(void) const } void PKITicketCommand::InitParameters(boost::program_options::options_description& visibleDesc, - boost::program_options::options_description& hiddenDesc, - ArgumentCompletionDescription& argCompletionDesc) const + boost::program_options::options_description& hiddenDesc) const { visibleDesc.add_options() ("cn", po::value(), "Certificate common name") diff --git a/lib/cli/pkiticketcommand.hpp b/lib/cli/pkiticketcommand.hpp index ee25b5973..36fbc6471 100644 --- a/lib/cli/pkiticketcommand.hpp +++ b/lib/cli/pkiticketcommand.hpp @@ -39,8 +39,7 @@ public: virtual String GetDescription(void) const; virtual String GetShortDescription(void) const; virtual void InitParameters(boost::program_options::options_description& visibleDesc, - boost::program_options::options_description& hiddenDesc, - ArgumentCompletionDescription& argCompletionDesc) const; + boost::program_options::options_description& hiddenDesc) const; virtual int Run(const boost::program_options::variables_map& vm, const std::vector& ap) const; }; diff --git a/lib/cli/repositoryobjectcommand.cpp b/lib/cli/repositoryobjectcommand.cpp index db999e135..7b19d0fd8 100644 --- a/lib/cli/repositoryobjectcommand.cpp +++ b/lib/cli/repositoryobjectcommand.cpp @@ -103,17 +103,17 @@ String RepositoryObjectCommand::GetShortDescription(void) const } void RepositoryObjectCommand::InitParameters(boost::program_options::options_description& visibleDesc, - boost::program_options::options_description& hiddenDesc, - ArgumentCompletionDescription& argCompletionDesc) const + boost::program_options::options_description& hiddenDesc) const { visibleDesc.add_options() ("name", po::value(), "The name of the object"); +} - if (m_Command == RepositoryCommandAdd) { - const Type *ptype = Type::GetByName(m_Type); - ASSERT(ptype); - AddTypeFields(ptype, visibleDesc); - } +std::vector RepositoryObjectCommand::GetPositionalSuggestions(const String& word) const +{ + const Type *ptype = Type::GetByName(m_Type); + ASSERT(ptype); + return GetFieldCompletionSuggestions(ptype, word); } /** diff --git a/lib/cli/repositoryobjectcommand.hpp b/lib/cli/repositoryobjectcommand.hpp index 03600d83e..625d2ca26 100644 --- a/lib/cli/repositoryobjectcommand.hpp +++ b/lib/cli/repositoryobjectcommand.hpp @@ -48,8 +48,8 @@ public: virtual String GetDescription(void) const; virtual String GetShortDescription(void) const; virtual void InitParameters(boost::program_options::options_description& visibleDesc, - boost::program_options::options_description& hiddenDesc, - ArgumentCompletionDescription& argCompletionDesc) const; + boost::program_options::options_description& hiddenDesc) const; + virtual std::vector GetPositionalSuggestions(const String& word) const; virtual int Run(const boost::program_options::variables_map& vm, const std::vector& ap) const; private: