This commit is contained in:
169
src/commands/edit.cpp
Normal file
169
src/commands/edit.cpp
Normal file
@ -0,0 +1,169 @@
|
||||
#include "command_registry.hpp"
|
||||
#include "config.hpp"
|
||||
#include "utils/utils.hpp"
|
||||
#include "service_runner.hpp"
|
||||
#include "utils/directories.hpp"
|
||||
#include "standard_autocomplete.hpp"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <filesystem>
|
||||
#include <libassert/assert.hpp>
|
||||
|
||||
namespace dropshell {
|
||||
|
||||
void edit_autocomplete(const CommandContext& ctx);
|
||||
int edit_handler(const CommandContext& ctx);
|
||||
|
||||
static std::vector<std::string> edit_name_list={"edit"};
|
||||
|
||||
// Static registration
|
||||
struct EditCommandRegister {
|
||||
EditCommandRegister() {
|
||||
CommandRegistry::instance().register_command({
|
||||
edit_name_list,
|
||||
edit_handler,
|
||||
edit_autocomplete,
|
||||
false, // hidden
|
||||
false, // requires_config
|
||||
0, // min_args (after command)
|
||||
2 // max_args (after command)
|
||||
});
|
||||
}
|
||||
} edit_command_register;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// edit command implementation
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// utility function to edit a file
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool edit_file(const std::string &file_path)
|
||||
{
|
||||
// make sure parent directory exists.
|
||||
std::string parent_dir = get_parent(file_path);
|
||||
std::filesystem::create_directories(parent_dir);
|
||||
|
||||
std::string editor_cmd;
|
||||
const char* editor_env = std::getenv("EDITOR");
|
||||
|
||||
if (editor_env && std::strlen(editor_env) > 0) {
|
||||
editor_cmd = std::string(editor_env) + " " + quote(file_path);
|
||||
} else if (isatty(STDIN_FILENO)) {
|
||||
// Check if stdin is connected to a terminal if EDITOR is not set
|
||||
editor_cmd = "nano -w " + quote(file_path);
|
||||
} else {
|
||||
std::cerr << "Error: Standard input is not a terminal and EDITOR environment variable is not set." << std::endl;
|
||||
std::cerr << "Try setting the EDITOR environment variable (e.g., export EDITOR=nano) or run in an interactive terminal." << std::endl;
|
||||
std::cerr << "You can manually edit the file at: " << file_path << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::cout << "Editing file: " << file_path << std::endl;
|
||||
return execute_local_command(editor_cmd, nullptr, cMode::Interactive | cMode::RawCommand);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// edit config
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
int edit_config()
|
||||
{
|
||||
if (!gConfig().is_config_set())
|
||||
gConfig().save_config(false); // save defaults.
|
||||
|
||||
std::string config_file = localfile::dropshell_json();
|
||||
if (!edit_file(config_file) || !std::filesystem::exists(config_file))
|
||||
return die("Error: Failed to edit config file.");
|
||||
|
||||
gConfig().load_config();
|
||||
if (!gConfig().is_config_set())
|
||||
return die("Error: Failed to load and parse edited config file!");
|
||||
|
||||
gConfig().save_config(true);
|
||||
std::cout << "Successfully edited config file at " << config_file << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// edit server
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
int edit_server(const std::string &server_name)
|
||||
{
|
||||
std::string serverpath = localpath::server(server_name);
|
||||
if (serverpath.empty()) {
|
||||
std::cerr << "Error: Server not found: " << server_name << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::ostringstream aftertext;
|
||||
aftertext << "If you have changed DROPSHELL_DIR, you should manually move the files to the new location NOW.\n"
|
||||
<< "You can ssh in to the remote server with: dropshell ssh "<<server_name<<"\n"
|
||||
<< "Once moved, reinstall all services with: dropshell install " << server_name;
|
||||
|
||||
std::string config_file = serverpath + "/server.env";
|
||||
if (!edit_file(config_file)) {
|
||||
std::cerr << "Error: Failed to edit server.env" << std::endl;
|
||||
std::cerr << "You can manually edit this file at: " << config_file << std::endl;
|
||||
std::cerr << "After editing, " << aftertext.str() << std::endl;
|
||||
}
|
||||
else
|
||||
std::cout << aftertext.str() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// edit service config
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
int edit_service_config(const std::string &server, const std::string &service)
|
||||
{
|
||||
std::string config_file = localfile::service_env(server, service);
|
||||
if (!std::filesystem::exists(config_file))
|
||||
{
|
||||
std::cerr << "Error: Service config file not found: " << config_file << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (edit_file(config_file) && std::filesystem::exists(config_file))
|
||||
std::cout << "To apply your changes, run:\n dropshell install " + server + " " + service << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// edit command handler
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
int edit_handler(const CommandContext& ctx) {
|
||||
// edit dropshell config
|
||||
if (ctx.args.size() < 3)
|
||||
return edit_config();
|
||||
|
||||
// edit server config
|
||||
if (ctx.args.size() < 4) {
|
||||
edit_server(safearg(ctx.args,2));
|
||||
return 0;
|
||||
}
|
||||
|
||||
// edit service config
|
||||
if (ctx.args.size() < 5) {
|
||||
edit_service_config(safearg(ctx.args,2), safearg(ctx.args,3));
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::cout << "Edit handler called with " << ctx.args.size() << " args\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// edit command autocomplete
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void edit_autocomplete(const CommandContext& ctx) {
|
||||
std_autocomplete(edit_name_list, ctx);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace dropshell
|
27
src/commands/standard_autocomplete.cpp
Normal file
27
src/commands/standard_autocomplete.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
#include "standard_autocomplete.hpp"
|
||||
|
||||
#include "servers.hpp"
|
||||
#include "services.hpp"
|
||||
void dropshell::std_autocomplete(const std::vector<std::string> &name_list, const CommandContext &ctx)
|
||||
{
|
||||
if (ctx.args.size() == 1) {
|
||||
// edit command
|
||||
for (const auto& name : name_list) {
|
||||
std::cout << name << std::endl;
|
||||
}
|
||||
}
|
||||
else if (ctx.args.size() == 2) {
|
||||
// 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() == 3) {
|
||||
// list services
|
||||
std::vector<LocalServiceInfo> services = get_server_services_info(ctx.args[2]);
|
||||
for (const auto& service : services) {
|
||||
std::cout << service.service_name << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
15
src/commands/standard_autocomplete.hpp
Normal file
15
src/commands/standard_autocomplete.hpp
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef STANDARD_AUTOCOMPLETE_HPP
|
||||
#define STANDARD_AUTOCOMPLETE_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "command_registry.hpp"
|
||||
|
||||
namespace dropshell {
|
||||
|
||||
|
||||
void std_autocomplete(const std::vector<std::string>& name_list, const CommandContext& ctx);
|
||||
|
||||
} // namespace dropshell
|
||||
#endif
|
Reference in New Issue
Block a user