#include "FileAddressList.hpp" #include #include #include #include #include namespace tw::app { namespace { std::string get_config_dir() { // Try XDG_CONFIG_HOME first const char* xdg_config_home = std::getenv("XDG_CONFIG_HOME"); if(xdg_config_home && xdg_config_home[0] != '\0') { return std::string(xdg_config_home) + "/towards"; } // Fall back to $HOME/.config/towards const char* home = std::getenv("HOME"); if(home && home[0] != '\0') { return std::string(home) + "/.config/towards"; } // Both unset return ""; } } // anonymous namespace FileAddressList::FileAddressList(const std::string& file_name) { std::string config_dir = get_config_dir(); if(config_dir.empty()) { spdlog::debug("XDG_CONFIG_HOME and HOME not set; address lists will not be persisted"); m_can_save = false; return; } m_path = config_dir + "/" + file_name; m_can_save = true; } void FileAddressList::load() { if(m_path.empty()) { return; // No config path available } std::ifstream file(m_path); if(!file.is_open()) { // File doesn't exist or can't be read; this is not an error return; } m_entries.clear(); std::string line; while(std::getline(file, line)) { // Trim whitespace from the line size_t start = line.find_first_not_of(" \t\r\n"); size_t end = line.find_last_not_of(" \t\r\n"); if(start != std::string::npos) { line = line.substr(start, end - start + 1); if(!line.empty()) { m_entries.push_back(line); } } } } void FileAddressList::save() const { if(!m_can_save || m_path.empty()) { return; // Cannot save without config path } // Create the directory if needed std::filesystem::path config_path(m_path); std::filesystem::path config_dir = config_path.parent_path(); try { std::filesystem::create_directories(config_dir); } catch(const std::filesystem::filesystem_error&) { // If we can't create the directory, silently fail to save return; } // Write entries to file std::ofstream file(m_path); if(!file.is_open()) { return; // Can't open file for writing; silently fail } for(const auto& entry : m_entries) { file << entry << "\n"; } } void FileAddressList::remove(const std::string& entry) { auto it = std::find(m_entries.begin(), m_entries.end(), entry); if(it != m_entries.end()) { m_entries.erase(it); } } const std::vector& FileAddressList::entries() const { return m_entries; } } // namespace tw::app