From 46396369d7f4211c3b587b7ebdc38b97f5c11619 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 11 May 2025 12:48:30 +1200 Subject: [PATCH] . --- src/commands/edit.cpp | 4 +- src/commands/help.cpp | 136 +++++++++++++++++++++++++++++++++++++++++ src/main.cpp | 114 ++++++++++++++++++---------------- src/service_runner.cpp | 2 +- src/utils/utils.cpp | 22 +++++++ src/utils/utils.hpp | 4 ++ 6 files changed, 229 insertions(+), 53 deletions(-) create mode 100644 src/commands/help.cpp diff --git a/src/commands/edit.cpp b/src/commands/edit.cpp index 4a9c885..4fb3752 100644 --- a/src/commands/edit.cpp +++ b/src/commands/edit.cpp @@ -29,7 +29,9 @@ struct EditCommandRegister { false, // hidden false, // requires_config 0, // min_args (after command) - 2 // max_args (after command) + 2, // max_args (after command) + "edit [SERVER] [SERVICE]", + "Edit dropshell, server or service configuration" }); } } edit_command_register; diff --git a/src/commands/help.cpp b/src/commands/help.cpp new file mode 100644 index 0000000..7232cd0 --- /dev/null +++ b/src/commands/help.cpp @@ -0,0 +1,136 @@ +#include "command_registry.hpp" +#include "config.hpp" +#include "utils/utils.hpp" +#include "service_runner.hpp" +#include "utils/directories.hpp" +#include "standard_autocomplete.hpp" +#include "version.hpp" + +#include +#include +#include +#include +#include +#include + +namespace dropshell { + +void help_autocomplete(const CommandContext& ctx); +int help_handler(const CommandContext& ctx); + +static std::vector help_name_list={"help","h","--help","-h"}; + +// Static registration +struct HelpCommandRegister { + HelpCommandRegister() { + CommandRegistry::instance().register_command({ + help_name_list, + help_handler, + help_autocomplete, + false, // hidden + false, // requires_config + 0, // min_args (after command) + 0, // max_args (after command) + "help", + "Show help for dropshell" + }); + } +} help_command_register; + + +void help_autocomplete(const CommandContext& ctx) { + if (ctx.args.size() == 1) { + std::cout << "help" << std::endl; + } + return; +} + +void show_command(const std::string& cmd) { + const auto& cmd_info = CommandRegistry::instance().find_command(cmd); + if (!cmd_info) + std::cout << "Unknown command: " << cmd << std::endl; + + std::cout << " "; + print_left_aligned(cmd_info->help_usage, 30); + std::cout << cmd_info->help_description << std::endl; +} + +extern const std::string VERSION; +extern const std::string RELEASE_DATE; +extern const std::string AUTHOR; +extern const std::string LICENSE; + +int help_handler(const CommandContext& ctx) { + std::cout << std::endl; + maketitle("DropShell version " + VERSION); + std::cout << std::endl; + std::cout << "A tool for managing remote servers, by " << AUTHOR << std::endl; + std::cout << std::endl; + std::cout << "dropshell ..." << std::endl; + + show_command("help"); + show_command("edit"); + + + if (gConfig().is_config_set()) { + // show more! + } + + return 0; +} + + + +// void show_command(const std::string& cmd) { +// const auto& cmd_info = CommandRegistry::instance().find_command(cmd); +// if (cmd_info) { +// std::cout << " " << cmd_info->help_usage +// << std::string(' ', std::min(1,(int)(30-cmd_info->help_usage.length()))) +// << cmd_info->help_description << std::endl; +// } +// } + +// bool print_help() { +// std::cout << std::endl; +// maketitle("DropShell version " + VERSION); +// std::cout << std::endl; +// std::cout << "A tool for managing server configurations" << std::endl; +// std::cout << std::endl; +// std::cout << "dropshell ..." << std::endl; +// show_command("help"); +// show_command("edit"); + +// if (gConfig().is_config_set()) { +// std::cout << " templates List all available templates" << std::endl; +// std::cout << std::endl; +// std::cout << std::endl; +// std::cout << "Service commands: (if no service is specified, all services for the server are affected)" << std::endl; +// std::cout << " list [SERVER] [SERVICE] List status/details of all servers/server/service." << std::endl; +// std::cout << " edit [SERVER] [SERVICE] Edit the configuration of dropshell/server/service." << std::endl; +// std::cout << std::endl; +// std::cout << " install SERVER [SERVICE] Install/reinstall/update service(s). Safe/non-destructive." << std::endl; +// std::cout << " uninstall SERVER [SERVICE] Uninstalls the service on the remote server. Leaves data intact." << std::endl; +// std::cout << " nuke SERVER SERVICE Nuke the service, deleting ALL local and remote data." << std::endl; +// std::cout << std::endl; +// std::cout << " COMMAND SERVER [SERVICE] Run a command on service(s), e.g." << std::endl; +// std::cout << " backup, restore, start, stop, logs" << std::endl; +// std::cout << std::endl; +// std::cout << " ssh SERVER SERVICE Launch an interactive shell on a server or service" << std::endl; +// std::cout << std::endl; +// std::cout << "Creation commands: (apply to the first local config directory)"<help_usage - << std::string(' ', std::min(1,(int)(30-cmd_info->help_usage.length()))) - << cmd_info->help_description << std::endl; - } + +int main(int argc, char* argv[]) { + + try { + // silently attempt to load the config file and templates. + gConfig().load_config(); + if (gConfig().is_config_set()) + gTemplateManager().load_sources(); + + + // process the command line arguments. + std::vector args(argv, argv + argc); + + if (args.size() < 2) + args.push_back("help"); + + std::string cmd = args[1]; + + if (cmd == "autocomplete") { + CommandRegistry::instance().autocomplete(args); + return 0; + } + + const CommandInfo* info = CommandRegistry::instance().find_command(cmd); + if (!info) { + std::cerr << "Unknown command: " << cmd << std::endl; + return 1; + } + if (info->requires_config && !gConfig().is_config_set()) { + std::cerr << "Configuration required for command: " << cmd << std::endl; + std::cerr << "Please run 'dropshell edit' to set up the dropshell configuration." << std::endl; + return 1; + } + int arg_count = args.size() - 2; + if (arg_count < info->min_args || (info->max_args != -1 && arg_count > info->max_args)) { + std::cerr << "Invalid number of arguments for command: " << cmd << std::endl; + std::cerr << "Usage: " << std::endl; + std::cout << " " << info->help_usage + << std::string(' ', std::max(1, (int)(30 - info->help_usage.length()))) + << info->help_description << std::endl; + return 1; + } + CommandContext ctx{args}; + return info->handler(ctx); + + } + catch (const std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + return 1; + } } -bool print_help() { - std::cout << std::endl; - maketitle("DropShell version " + VERSION); - std::cout << std::endl; - std::cout << "A tool for managing server configurations" << std::endl; - std::cout << std::endl; - std::cout << "dropshell ..." << std::endl; - show_command("help"); - show_command("edit"); - if (gConfig().is_config_set()) { - std::cout << " templates List all available templates" << std::endl; - std::cout << std::endl; - std::cout << std::endl; - std::cout << "Service commands: (if no service is specified, all services for the server are affected)" << std::endl; - std::cout << " list [SERVER] [SERVICE] List status/details of all servers/server/service." << std::endl; - std::cout << " edit [SERVER] [SERVICE] Edit the configuration of dropshell/server/service." << std::endl; - std::cout << std::endl; - std::cout << " install SERVER [SERVICE] Install/reinstall/update service(s). Safe/non-destructive." << std::endl; - std::cout << " uninstall SERVER [SERVICE] Uninstalls the service on the remote server. Leaves data intact." << std::endl; - std::cout << " nuke SERVER SERVICE Nuke the service, deleting ALL local and remote data." << std::endl; - std::cout << std::endl; - std::cout << " COMMAND SERVER [SERVICE] Run a command on service(s), e.g." << std::endl; - std::cout << " backup, restore, start, stop, logs" << std::endl; - std::cout << std::endl; - std::cout << " ssh SERVER SERVICE Launch an interactive shell on a server or service" << std::endl; - std::cout << std::endl; - std::cout << "Creation commands: (apply to the first local config directory)"< } -int main(int argc, char* argv[]) { + + +int old_main(int argc, char* argv[]) { HAPPYEXIT("hash", hash_demo_raw(safearg(argc,argv,2))) HAPPYEXIT("makesafecmd", std::cout<(str.size()) < width) + std::cout << std::string(width - str.size(), ' '); +} + +void print_centered(const std::string & str, int width) { + int pad = width - static_cast(str.size()); + int pad_left = pad > 0 ? pad / 2 : 0; + int pad_right = pad > 0 ? pad - pad_left : 0; + std::cout << std::string(pad_left, ' ') << str << std::string(pad_right, ' '); +} + +void print_right_aligned(const std::string & str, int width) { + if (static_cast(str.size()) < width) + std::cout << std::string(width - str.size(), ' '); + std::cout << str; +} + + + } // namespace dropshell \ No newline at end of file diff --git a/src/utils/utils.hpp b/src/utils/utils.hpp index 603409e..1dd2a31 100644 --- a/src/utils/utils.hpp +++ b/src/utils/utils.hpp @@ -45,4 +45,8 @@ int die(const std::string & msg); std::string safearg(int argc, char *argv[], int index); std::string safearg(const std::vector & args, int index); +void print_left_aligned(const std::string & str, int width); +void print_centered(const std::string & str, int width); +void print_right_aligned(const std::string & str, int width); + } // namespace dropshell \ No newline at end of file