diff --git a/src/commands/command_registry.cpp b/src/commands/command_registry.cpp index 88e1516..b82d6ad 100644 --- a/src/commands/command_registry.cpp +++ b/src/commands/command_registry.cpp @@ -1,4 +1,7 @@ #include "command_registry.hpp" +#include "utils/utils.hpp" + +namespace dropshell { CommandRegistry& CommandRegistry::instance() { static CommandRegistry reg; @@ -41,18 +44,25 @@ std::vector CommandRegistry::list_primary_commands(bool include_hid } -void CommandRegistry::autocomplete(const std::vector& args) const { +void CommandRegistry::autocomplete(const CommandContext& ctx) const { // dropshell autocomplete ... - if (args.size() < 3) { + if (ctx.args.size() < 1) { for (const auto& name : list_primary_commands(false)) { std::cout << name << std::endl; } return; } - std::string cmd = args[2]; - auto* info = find_command(cmd); + + // ctx command is autocomplete, so recreate ctx with the first arg removed + CommandContext childcontext = { + ctx.exename, + ctx.args[0], + std::vector(ctx.args.begin() + 1, ctx.args.end()) + }; + auto* info = find_command(childcontext.command); if (info && info->autocomplete) { - CommandContext ctx{args[0], cmd, std::vector(args.begin() + 2, args.end())}; - info->autocomplete(ctx); + info->autocomplete(childcontext); } -} \ No newline at end of file +} + +} // namespace dropshell \ No newline at end of file diff --git a/src/commands/command_registry.hpp b/src/commands/command_registry.hpp index 5e341be..a59cfe9 100644 --- a/src/commands/command_registry.hpp +++ b/src/commands/command_registry.hpp @@ -1,4 +1,6 @@ -#pragma once +#ifndef COMMAND_REGISTRY_HPP +#define COMMAND_REGISTRY_HPP + #include #include #include @@ -7,6 +9,8 @@ #include #include +namespace dropshell { + struct CommandContext { std::string exename; std::string command; @@ -42,10 +46,14 @@ public: std::vector list_primary_commands(bool include_hidden = false) const; // For autocomplete - void autocomplete(const std::vector& args) const; + void autocomplete(const CommandContext& ctx) const; private: CommandRegistry() = default; std::map> command_map_; std::vector> all_commands_; }; + +} // namespace dropshell + +#endif // COMMAND_REGISTRY_HPP diff --git a/src/commands/health.cpp b/src/commands/health.cpp index 47b63f2..40f8b6e 100644 --- a/src/commands/health.cpp +++ b/src/commands/health.cpp @@ -2,11 +2,11 @@ #include "config.hpp" #include "utils/utils.hpp" #include "utils/directories.hpp" -#include "templates.hpp" #include "shared_commands.hpp" #include "server_env_manager.hpp" #include "services.hpp" #include "servers.hpp" +#include "transwarp.hpp" namespace dropshell { @@ -118,13 +118,18 @@ namespace dropshell if (ctx.args.size() == 1) { // get all services on server std::vector services = get_server_services_info(server); - for (const auto& service : services) { - std::cout << service.service_name << " " << healthtick(server, service.service_name) << std::endl; - } + transwarp::parallel exec{services.size()}; + auto task = transwarp::for_each(exec, services.begin(), services.end(), [&](const LocalServiceInfo& service) { + std::string status = healthtick(server, service.service_name); + std::cout << status << " " << service.service_name << " (" << service.template_name << ")" << std::endl << std::flush; + }); + task->wait(); + return 0; } else { // get service status std::string service = safearg(ctx.args, 1); - std::cout << service << " " << healthtick(server, service) << std::endl; + LocalServiceInfo service_info = get_service_info(server, service); + std::cout << healthtick(server, service) << " " << service << " (" << service_info.template_name << ")" << std::endl << std::flush; } return 0; } diff --git a/src/commands/standard_autocomplete.cpp b/src/commands/standard_autocomplete.cpp index af8f34a..6352afc 100644 --- a/src/commands/standard_autocomplete.cpp +++ b/src/commands/standard_autocomplete.cpp @@ -10,17 +10,16 @@ namespace dropshell { void std_autocomplete(const CommandContext &ctx) { - ASSERT(ctx.args.size() > 0); - if (ctx.args.size() == 1) { + if (ctx.args.size() == 0) { // just the command health. // list servers std::vector servers = get_configured_servers(); for (const auto& server : servers) { std::cout << server.name << std::endl; } - } - else if (ctx.args.size() == 2) { + } + else if (ctx.args.size() == 1) { // list services - std::vector services = get_server_services_info(ctx.args[2]); + std::vector services = get_server_services_info(ctx.args[0]); for (const auto& service : services) { std::cout << service.service_name << std::endl; } diff --git a/src/main.cpp b/src/main.cpp index 9728ef5..668ee6e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -41,34 +41,34 @@ int main(int argc, char* argv[]) { if (args.size() < 2) args.push_back("help"); + ASSERT(args.size() > 1, "No command provided, logic error."); - std::string cmd = args[1]; + CommandContext ctx{args[0], args[1], std::vector(args.begin() + 2, args.end())}; - if (cmd == "autocomplete") { - CommandRegistry::instance().autocomplete(args); + if (ctx.command == "autocomplete") { + CommandRegistry::instance().autocomplete(ctx); return 0; } - const CommandInfo* info = CommandRegistry::instance().find_command(cmd); + const CommandInfo* info = CommandRegistry::instance().find_command(ctx.command); if (!info) { - std::cerr << "Unknown command: " << cmd << std::endl; + std::cerr << "Unknown command: " << ctx.command << std::endl; return 1; } if (info->requires_config && !gConfig().is_config_set()) { - std::cerr << "Configuration required for command: " << cmd << std::endl; + std::cerr << "Valid dropshell configuration required for command: " << ctx.command << std::endl; std::cerr << "Please run 'dropshell edit' to set up the dropshell configuration." << std::endl; return 1; } - int arg_count = args.size() - 2; + int arg_count = ctx.args.size(); 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 << "Invalid number of arguments for command: " << ctx.command << std::endl; std::cerr << "Usage: " << std::endl; std::cout << " "; print_left_aligned(info->help_usage,30); std::cout << info->help_description << std::endl; return 1; } - CommandContext ctx{args[0], cmd, std::vector(args.begin() + 2, args.end())}; return info->handler(ctx); } diff --git a/src/utils/utils.cpp b/src/utils/utils.cpp index b39f5c8..fad7193 100644 --- a/src/utils/utils.cpp +++ b/src/utils/utils.cpp @@ -336,22 +336,37 @@ std::string safearg(int argc, char *argv[], int index) void print_left_aligned(const std::string & str, int width) { - std::cout << str; - if (static_cast(str.size()) < width) - std::cout << std::string(width - str.size(), ' '); + std::cout << left_align(str, width); } 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, ' '); + std::cout << center_align(str, width); } 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; + std::cout << right_align(str, width); +} + + +std::string left_align(const std::string & str, int width) { + if (static_cast(str.size()) >= width) + return str; + return str + std::string(width - str.size(), ' '); +} + +std::string right_align(const std::string & str, int width) { + if (static_cast(str.size()) >= width) + return str; + return std::string(width - str.size(), ' ') + str; +} + +std::string center_align(const std::string & str, int width) { + int pad = width - static_cast(str.size()); + if (pad <= 0) + return str; + int pad_left = pad / 2; + int pad_right = pad - pad_left; + return std::string(pad_left, ' ') + str + std::string(pad_right, ' '); } diff --git a/src/utils/utils.hpp b/src/utils/utils.hpp index 1dd2a31..9c00450 100644 --- a/src/utils/utils.hpp +++ b/src/utils/utils.hpp @@ -49,4 +49,8 @@ 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); +std::string left_align(const std::string & str, int width); +std::string right_align(const std::string & str, int width); +std::string center_align(const std::string & str, int width); + } // namespace dropshell \ No newline at end of file