Fix autocomplete bugs.
Some checks failed
Dropshell Test / Build_and_Test (push) Failing after 20s

This commit is contained in:
Your Name 2025-05-11 19:26:25 +12:00
parent 7e95779d98
commit a2340dcb80
7 changed files with 79 additions and 38 deletions

View File

@ -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<std::string> CommandRegistry::list_primary_commands(bool include_hid
}
void CommandRegistry::autocomplete(const std::vector<std::string>& args) const {
void CommandRegistry::autocomplete(const CommandContext& ctx) const {
// dropshell autocomplete <command> <arg> <arg> ...
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<std::string>(ctx.args.begin() + 1, ctx.args.end())
};
auto* info = find_command(childcontext.command);
if (info && info->autocomplete) {
CommandContext ctx{args[0], cmd, std::vector<std::string>(args.begin() + 2, args.end())};
info->autocomplete(ctx);
info->autocomplete(childcontext);
}
}
}
} // namespace dropshell

View File

@ -1,4 +1,6 @@
#pragma once
#ifndef COMMAND_REGISTRY_HPP
#define COMMAND_REGISTRY_HPP
#include <string>
#include <vector>
#include <functional>
@ -7,6 +9,8 @@
#include <memory>
#include <iostream>
namespace dropshell {
struct CommandContext {
std::string exename;
std::string command;
@ -42,10 +46,14 @@ public:
std::vector<std::string> list_primary_commands(bool include_hidden = false) const;
// For autocomplete
void autocomplete(const std::vector<std::string>& args) const;
void autocomplete(const CommandContext& ctx) const;
private:
CommandRegistry() = default;
std::map<std::string, std::shared_ptr<CommandInfo>> command_map_;
std::vector<std::shared_ptr<CommandInfo>> all_commands_;
};
} // namespace dropshell
#endif // COMMAND_REGISTRY_HPP

View File

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

View File

@ -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<ServerInfo> 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<LocalServiceInfo> services = get_server_services_info(ctx.args[2]);
std::vector<LocalServiceInfo> services = get_server_services_info(ctx.args[0]);
for (const auto& service : services) {
std::cout << service.service_name << std::endl;
}

View File

@ -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<std::string>(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<std::string>(args.begin() + 2, args.end())};
return info->handler(ctx);
}

View File

@ -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<int>(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<int>(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<int>(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<int>(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<int>(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<int>(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, ' ');
}

View File

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