From 338e715a95e03bbd929e0db3871533ce2edf9e5e Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sun, 7 Jul 2024 21:35:29 +0300 Subject: [PATCH] path: add findConfig and dir utils --- include/hyprutils/path/Path.hpp | 39 ++++++++++++++++ src/path/Path.cpp | 82 +++++++++++++++++++++++++++++++++ 2 files changed, 121 insertions(+) create mode 100644 include/hyprutils/path/Path.hpp create mode 100644 src/path/Path.cpp diff --git a/include/hyprutils/path/Path.hpp b/include/hyprutils/path/Path.hpp new file mode 100644 index 0000000..d95a211 --- /dev/null +++ b/include/hyprutils/path/Path.hpp @@ -0,0 +1,39 @@ +#pragma once +#include "../string/VarList.hpp" +#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 either the full path to a config if found, or + $XDG_CONFIG_HOME/$HOME if no config could be found. + @param programName name of the program (and config file) + */ + std::optional findConfig(const std::string programName); + } +} diff --git a/src/path/Path.cpp b/src/path/Path.cpp new file mode 100644 index 0000000..923aba5 --- /dev/null +++ b/src/path/Path.cpp @@ -0,0 +1,82 @@ +#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; + } + + std::optional findConfig(std::string programName) { + bool xdgConfigHomeExists = false; + static const auto xdgConfigHome = getXdgConfigHome(); + if (xdgConfigHome.has_value()) { + if (checkConfigExists(xdgConfigHome.value(), programName)) + return fullConfigPath(xdgConfigHome.value(), programName); + else + xdgConfigHomeExists = true; + } + + bool homeExists = false; + static const auto home = getHome(); + if (home.has_value()) { + if (checkConfigExists(home.value(), programName)) + return fullConfigPath(home.value(), programName); + else + homeExists = true; + } + + static const auto xdgConfigDirs = getXdgConfigDirs(); + if (xdgConfigDirs.has_value()) { + for (auto dir : xdgConfigDirs.value()) { + if (checkConfigExists(dir, programName)) + return fullConfigPath(dir, programName); + } + } + + if (checkConfigExists("/etc/xdg", programName)) + return fullConfigPath("/etc/xdg", programName); + + if (xdgConfigHomeExists) + return xdgConfigHome; + else if (homeExists) + return home; + else + return std::nullopt; + } +}