#include "autocomplete.hpp" #include "servers.hpp" #include "config.hpp" #include "templates.hpp" #include "services.hpp" #include "servers.hpp" #include <libassert/assert.hpp> #include <algorithm> #include <iostream> namespace autocomplete { const std::set<std::string> system_commands_noargs = {"templates","autocomplete_list_servers","autocomplete_list_services","autocomplete_list_commands"}; const std::set<std::string> system_commands_always_available = {"help","edit"}; const std::set<std::string> system_commands_require_config = {"server","templates","create-service","create-template","create-server","ssh","list"}; const std::set<std::string> system_commands_hidden = {"nuke","_allservicesstatus"}; const std::set<std::string> service_commands_require_config = {"ssh","edit","nuke","_allservicesstatus"}; void merge_commands(std::set<std::string> &commands, const std::set<std::string> &new_commands) { commands.insert(new_commands.begin(), new_commands.end()); } bool is_no_arg_cmd(std::string cmd) { return system_commands_noargs.find(cmd) != system_commands_noargs.end(); } bool autocomplete(const std::vector<std::string> &args) { if (args.size() < 3) // dropshell autocomplete ??? { autocomplete_list_commands(); return true; } ASSERT(args.size() >= 3); std::string cmd = args[2]; // std::cout<<" cmd = ["<<cmd<<"]"<<std::endl; if (cmd=="hash") { // output files and folders in the current directory, one per line. std::filesystem::directory_iterator dir_iter(std::filesystem::current_path()); for (const auto& entry : dir_iter) std::cout << entry.path().filename().string() << std::endl; return true; } if (autocomplete::is_no_arg_cmd(cmd)) return true; // no arguments needed. if (!dropshell::gConfig().is_config_set()) return false; // can't help without working config. if (args.size()==3) // we have the command but nothing else. dropshell autocomplete command <server> { auto servers = dropshell::get_configured_servers(); for (const auto& server : servers) std::cout << server.name << std::endl; return true; } if (args.size()==4) // we have the command and the server. dropshell autocomplete command server <service> { std::string server = args[3]; if (cmd=="create-service") { // create-service <server> <template> <service> auto templates = dropshell::gTemplateManager().get_template_list(); for (const auto& t : templates) std::cout << t << std::endl; return true; } auto services = dropshell::get_server_services_info(server); for (const auto& service : services) std::cout << service.service_name << std::endl; return true; } if (args.size()==5) // we have the command and the server and the service. dropshell autocomplete command server service_name <command?> { std::string server_name = args[3]; std::string service_name = args[4]; if (cmd=="restore") { std::set<std::string> backups = dropshell::list_backups(server_name, service_name); for (auto backup : backups) std::cout << backup << std::endl; return true; } return false; // no more autocompletion possible - don't know what the argument is for. } // args>5 - no more autocompletion possible - don't know what the argument is for. return false; // catch-all. } bool autocomplete_list_commands() { std::set<std::string> commands; dropshell::get_all_used_commands(commands); // add in commmands hard-coded and handled in main autocomplete::merge_commands(commands, autocomplete::system_commands_always_available); if (dropshell::gConfig().is_config_set()) autocomplete::merge_commands(commands, autocomplete::system_commands_require_config); for (const auto& command : commands) { std::cout << command << std::endl; } return true; } } // namespace autocomplete