diff --git a/include/hyprutils/path/Path.hpp b/include/hyprutils/path/Path.hpp new file mode 100644 index 0000000..8634f20 --- /dev/null +++ b/include/hyprutils/path/Path.hpp @@ -0,0 +1,42 @@ +#pragma once +#include "../string/VarList.hpp" +#include +#include +#include + +namespace Hyprutils { + namespace Path { + /** Check whether a config in the form basePath/hypr/programName.conf exists. + @param basePath the path where the config will be searched + @param programName name of the program (and config file) to search for + */ + bool checkConfigExists(const std::string basePath, const std::string programName); + + /** Constructs a full config path given the basePath and programName. + @param basePath the path where the config hypr/programName.conf is located + @param programName name of the program (and config file) + */ + std::string fullConfigPath(const std::string basePath, const std::string programName); + + /** Retrieves the absolute path of the $HOME env variable. + */ + std::optional getHome(); + + /** Retrieves a CVarList of paths from the $XDG_CONFIG_DIRS env variable. + */ + std::optional getXdgConfigDirs(); + + /** Retrieves the absolute path of the $XDG_CONFIG_HOME env variable. + */ + std::optional getXdgConfigHome(); + + /** Searches for a config according to the XDG Base Directory specification. + Returns a pair of the full path to a config and the base path. + Returns std::nullopt in case of a non-existent value. + @param programName name of the program (and config file) + */ + + using T = std::optional; + std::pair findConfig(const std::string programName); + } +} diff --git a/src/path/Path.cpp b/src/path/Path.cpp new file mode 100644 index 0000000..b6f9997 --- /dev/null +++ b/src/path/Path.cpp @@ -0,0 +1,81 @@ +#include +#include +#include + +using namespace Hyprutils; + +namespace Hyprutils::Path { + std::string fullConfigPath(std::string basePath, std::string programName) { + return basePath + "/hypr/" + programName + ".conf"; + } + + bool checkConfigExists(std::string basePath, std::string programName) { + return std::filesystem::exists(fullConfigPath(basePath, programName)); + } + + std::optional getHome() { + static const auto homeDir = getenv("HOME"); + + if (!homeDir || !std::filesystem::path(homeDir).is_absolute()) + return std::nullopt; + + return std::string(homeDir).append("/.config"); + } + + std::optional getXdgConfigDirs() { + static const auto xdgConfigDirs = getenv("XDG_CONFIG_DIRS"); + + if (!xdgConfigDirs) + return std::nullopt; + + static const auto xdgConfigDirsList = String::CVarList(xdgConfigDirs, 0, ':'); + + return xdgConfigDirsList; + } + + std::optional getXdgConfigHome() { + static const auto xdgConfigHome = getenv("XDG_CONFIG_HOME"); + + if (!xdgConfigHome || !std::filesystem::path(xdgConfigHome).is_absolute()) + return std::nullopt; + + return xdgConfigHome; + } + + using T = std::optional; + std::pair findConfig(std::string programName) { + bool xdgConfigHomeExists = false; + static const auto xdgConfigHome = getXdgConfigHome(); + if (xdgConfigHome.has_value()) { + xdgConfigHomeExists = true; + if (checkConfigExists(xdgConfigHome.value(), programName)) + return std::make_pair(fullConfigPath(xdgConfigHome.value(), programName), xdgConfigHome); + } + + bool homeExists = false; + static const auto home = getHome(); + if (home.has_value()) { + homeExists = true; + if (checkConfigExists(home.value(), programName)) + return std::make_pair(fullConfigPath(home.value(), programName), home); + } + + static const auto xdgConfigDirs = getXdgConfigDirs(); + if (xdgConfigDirs.has_value()) { + for (auto dir : xdgConfigDirs.value()) { + if (checkConfigExists(dir, programName)) + return std::make_pair(fullConfigPath(dir, programName), std::nullopt); + } + } + + if (checkConfigExists("/etc/xdg", programName)) + return std::make_pair(fullConfigPath("/etc/xdg", programName), std::nullopt); + + if (xdgConfigHomeExists) + return std::make_pair(std::nullopt, xdgConfigHome); + else if (homeExists) + return std::make_pair(std::nullopt, home); + + return std::make_pair(std::nullopt, std::nullopt); + } +}