This commit is contained in:
j842 2025-04-23 13:57:28 +12:00
parent caf1e87718
commit 88106b3260
6 changed files with 118 additions and 86 deletions

View File

@ -43,6 +43,24 @@ if ! command -v make &> /dev/null; then
exit 1 exit 1
fi fi
# Check if pkg-config is installed
if ! command -v pkg-config &> /dev/null; then
print_error "pkg-config is not installed. Please install pkg-config first."
print_warning "On Ubuntu/Debian: sudo apt-get install pkg-config"
print_warning "On Fedora: sudo dnf install pkg-config"
print_warning "On Arch: sudo pacman -S pkg-config"
exit 1
fi
# Check if ncurses is installed
if ! pkg-config --exists ncurses; then
print_error "ncurses is not installed. Please install ncurses first."
print_warning "On Ubuntu/Debian: sudo apt-get install libncurses-dev"
print_warning "On Fedora: sudo dnf install ncurses-devel"
print_warning "On Arch: sudo pacman -S ncurses"
exit 1
fi
# Configure with CMake # Configure with CMake
print_status "Configuring with CMake..." print_status "Configuring with CMake..."
cmake .. -DCMAKE_BUILD_TYPE=Release cmake .. -DCMAKE_BUILD_TYPE=Release

View File

@ -63,17 +63,6 @@ std::vector<std::string> autocomplete_list_commands() {
std::vector<std::string> commands; std::vector<std::string> commands;
std::set<std::string> unique_commands; // To ensure deduplication std::set<std::string> unique_commands; // To ensure deduplication
// System templates directory
const std::string system_templates_dir = "/opt/dropshell/templates";
// User templates directory
std::string user_templates_dir;
if (!get_user_directory(user_templates_dir)) {
std::cerr << "Error: User directory not set" << std::endl;
return commands;
}
user_templates_dir += "/usertemplates";
// Helper function to add commands from a directory // Helper function to add commands from a directory
auto add_commands_from_dir = [&unique_commands](const std::string& dir_path) { auto add_commands_from_dir = [&unique_commands](const std::string& dir_path) {
if (!fs::exists(dir_path)) { if (!fs::exists(dir_path)) {
@ -96,11 +85,17 @@ std::vector<std::string> autocomplete_list_commands() {
} }
} }
}; };
// Add commands from both template locations // System templates directory
const std::string system_templates_dir = "/opt/dropshell/templates";
add_commands_from_dir(system_templates_dir); add_commands_from_dir(system_templates_dir);
add_commands_from_dir(user_templates_dir);
std::string user_templates_dir;
if (get_user_directory(user_templates_dir)) {
// User templates directory
user_templates_dir += "/usertemplates";
add_commands_from_dir(user_templates_dir);
}
// Convert set to vector for return // Convert set to vector for return
commands.assign(unique_commands.begin(), unique_commands.end()); commands.assign(unique_commands.begin(), unique_commands.end());
return commands; return commands;

View File

@ -5,6 +5,7 @@
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <boost/property_tree/ptree.hpp> #include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp> #include <boost/property_tree/ini_parser.hpp>
#include "config.hpp"
namespace fs = boost::filesystem; namespace fs = boost::filesystem;
namespace pt = boost::property_tree; namespace pt = boost::property_tree;
@ -18,18 +19,14 @@ bool is_config_loaded() {
return config_loaded; return config_loaded;
} }
bool get_config_path(std::string& path) { bool get_config_path(std::string &path)
{
// Try ~/.config/dropshell/dropshell.conf // Try ~/.config/dropshell/dropshell.conf
const char* home = std::getenv("HOME"); const char* home = std::getenv("HOME");
if (home) { if (home) {
fs::path user_path = fs::path(home) / ".config" / "dropshell" / "dropshell.conf"; fs::path user_path = fs::path(home) / ".config" / "dropshell" / "dropshell.conf";
if (!fs::exists(user_path)) {
// create path
fs::create_directories(user_path.parent_path());
}
path = user_path.string(); path = user_path.string();
return true; return fs::exists(path);
} }
std::cerr << "Warning: Couldn't determine user directory" << std::endl; std::cerr << "Warning: Couldn't determine user directory" << std::endl;
path = ""; path = "";
@ -39,12 +36,7 @@ bool get_config_path(std::string& path) {
bool load_config() { bool load_config() {
std::string config_path; std::string config_path;
if (!get_config_path(config_path)) if (!get_config_path(config_path))
return true; return false;
if (config_path.empty()) {
// No config file found, but this is not an error
return true;
}
try { try {
pt::ptree tree; pt::ptree tree;

View File

@ -7,9 +7,6 @@ _dropshell_completions() {
prev="${COMP_WORDS[COMP_CWORD-1]}" prev="${COMP_WORDS[COMP_CWORD-1]}"
root="${COMP_WORDS[1]}" root="${COMP_WORDS[1]}"
# List of main commands
opts="help version servers templates install backup"
# add all commands to opts # add all commands to opts
local commands=($(dropshell autocomplete_list_commands)) local commands=($(dropshell autocomplete_list_commands))
opts="${opts} ${commands[*]}" opts="${opts} ${commands[*]}"

View File

@ -63,23 +63,28 @@ std::string safearg(int argc, char *argv[], int index)
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
try { try {
// Load configuration
if (!dropshell::load_config()) {
std::cerr << "Error: Failed to load configuration" << std::endl;
return 1;
}
// No arguments provided
if (argc < 2) {
dropshell::interactive_mode();
return 0;
}
// Handle commands // Handle commands
std::string cmd = argv[1]; std::string cmd;
if (argc > 1) {
cmd = argv[1];
}
// don't load old config if we're initializing
if (cmd == "init") {
if (argc < 3) {
std::cerr << "Error: init command requires a directory argument" << std::endl;
return 1;
}
try {
dropshell::init_user_directory(argv[2]);
return 0;
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
return 1;
}
}
auto commands = dropshell::autocomplete_list_commands();
if (cmd == "help" || cmd == "-h" || cmd == "--help") { if (cmd == "help" || cmd == "-h" || cmd == "--help") {
dropshell::print_help(); dropshell::print_help();
return 0; return 0;
@ -90,6 +95,70 @@ int main(int argc, char* argv[]) {
return 0; return 0;
} }
// silently attempt to load the config file.
dropshell::load_config();
// auto compeltion stuff.
auto commands = dropshell::autocomplete_list_commands();
if (cmd == "autocomplete_list_commands") {
// add in standard commands.
commands.insert(commands.end(), {
"help",
"version",
"init"
});
if (dropshell::is_config_loaded()) { // these only work if the config is loaded.
commands.insert(commands.end(), {
"servers",
"templates",
"install",
"backup"
});
}
for (const auto& command : commands) {
std::cout << command << std::endl;
}
return 0;
}
if (cmd == "autocomplete_list_servers") {
if (dropshell::is_config_loaded())
{
auto servers = dropshell::autocomplete_list_servers();
for (const auto& server : servers)
std::cout << server << std::endl;
}
return 0;
}
if (cmd == "autocomplete_list_services") {
if (argc < 3) {
std::cerr << "Error: autocomplete_list_services requires a server name" << std::endl;
return 1;
}
if (dropshell::is_config_loaded()) {
auto services = dropshell::autocomplete_list_services(argv[2]);
for (const auto& service : services)
std::cout << service << std::endl;
}
return 0;
}
// ------------------------------------------------------------
// from here we require the config file to be loaded.
if (!dropshell::is_config_loaded()) {
std::cerr << "Error: Failed to load configuration." << std::endl << "Please run 'dropshell init <path>' to initialise the user directory and create a configuration file." << std::endl;
return 1;
}
// No arguments provided
if (argc < 2) {
dropshell::interactive_mode();
return 0;
}
if (cmd == "servers") { if (cmd == "servers") {
if (argc > 2) { if (argc > 2) {
// Show details for specific server // Show details for specific server
@ -106,47 +175,6 @@ int main(int argc, char* argv[]) {
return 0; return 0;
} }
if (cmd == "init") {
if (argc < 3) {
std::cerr << "Error: init command requires a directory argument" << std::endl;
return 1;
}
try {
dropshell::init_user_directory(argv[2]);
return 0;
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
return 1;
}
}
if (cmd == "autocomplete_list_servers") {
auto servers = dropshell::autocomplete_list_servers();
for (const auto& server : servers) {
std::cout << server << std::endl;
}
return 0;
}
if (cmd == "autocomplete_list_services") {
if (argc < 3) {
std::cerr << "Error: autocomplete_list_services requires a server name" << std::endl;
return 1;
}
auto services = dropshell::autocomplete_list_services(argv[2]);
for (const auto& service : services) {
std::cout << service << std::endl;
}
return 0;
}
if (cmd == "autocomplete_list_commands") {
for (const auto& command : commands) {
std::cout << command << std::endl;
}
return 0;
}
if (cmd == "install") { if (cmd == "install") {
std::string server_name; std::string server_name;
std::vector<std::string> servicelist; std::vector<std::string> servicelist;
@ -191,6 +219,8 @@ int main(int argc, char* argv[]) {
return 0; return 0;
} }
// handle running a command.
for (const auto& command : commands) { for (const auto& command : commands) {
if (cmd == command) { if (cmd == command) {
std::string server_name; std::string server_name;