From 2439b58f2fadb093e3e4f93c7de8cc3c5d7beb7d Mon Sep 17 00:00:00 2001 From: Maurice Kraus Date: Tue, 20 Feb 2024 22:50:08 +0100 Subject: [PATCH] config: add source parsing --- src/config/ConfigManager.cpp | 123 ++++++++++++++++++++++++---------- src/config/ConfigManager.hpp | 6 +- src/helpers/MiscFunctions.cpp | 25 +++++++ src/helpers/MiscFunctions.hpp | 6 ++ 4 files changed, 123 insertions(+), 37 deletions(-) create mode 100644 src/helpers/MiscFunctions.cpp create mode 100644 src/helpers/MiscFunctions.hpp diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 7342127b..5a450d31 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1,5 +1,21 @@ #include "ConfigManager.hpp" +#include "../helpers/MiscFunctions.hpp" #include +#include +#include + +static Hyprlang::CParseResult handleSource(const char* c, const char* v) { + const std::string VALUE = v; + const std::string COMMAND = c; + + const auto RESULT = g_pConfigManager->handleSource(COMMAND, VALUE); + + Hyprlang::CParseResult result; + if (RESULT.has_value()) + result.setError(RESULT.value().c_str()); + return result; +} + static std::string getConfigDir() { static const char* xdgConfigHome = getenv("XDG_CONFIG_HOME"); @@ -15,7 +31,7 @@ static std::string getMainConfigPath() { } CConfigManager::CConfigManager() : m_config(getMainConfigPath().c_str(), Hyprlang::SConfigOptions{.throwAllErrors = true, .allowMissingConfig = true}) { - ; + configCurrentPath = getMainConfigPath(); } void CConfigManager::init() { @@ -53,6 +69,8 @@ void CConfigManager::init() { m_config.addSpecialConfigValue("label", "halign", Hyprlang::STRING{"none"}); m_config.addSpecialConfigValue("label", "valign", Hyprlang::STRING{"none"}); + m_config.registerHandler(&::handleSource, "source", {false}); + m_config.commence(); auto result = m_config.parse(); @@ -76,12 +94,12 @@ std::vector CConfigManager::getWidgetConfigs() { for (auto& k : keys) { // clang-format off result.push_back(CConfigManager::SWidgetConfig{ - "background", - std::any_cast(m_config.getSpecialConfigValue("background", "monitor", k.c_str())), - { - {"path", m_config.getSpecialConfigValue("background", "path", k.c_str())}, - {"color", m_config.getSpecialConfigValue("background", "color", k.c_str())}, - } + "background", + std::any_cast(m_config.getSpecialConfigValue("background", "monitor", k.c_str())), + { + {"path", m_config.getSpecialConfigValue("background", "path", k.c_str())}, + {"color", m_config.getSpecialConfigValue("background", "color", k.c_str())}, + } }); // clang-format on } @@ -90,23 +108,23 @@ std::vector CConfigManager::getWidgetConfigs() { for (auto& k : keys) { // clang-format off result.push_back(CConfigManager::SWidgetConfig{ - "input-field", - std::any_cast(m_config.getSpecialConfigValue("input-field", "monitor", k.c_str())), - { - {"size", m_config.getSpecialConfigValue("input-field", "size", k.c_str())}, - {"inner_color", m_config.getSpecialConfigValue("input-field", "inner_color", k.c_str())}, - {"outer_color", m_config.getSpecialConfigValue("input-field", "outer_color", k.c_str())}, - {"outline_thickness", m_config.getSpecialConfigValue("input-field", "outline_thickness", k.c_str())}, - {"dots_size", m_config.getSpecialConfigValue("input-field", "dots_size", k.c_str())}, - {"dots_spacing", m_config.getSpecialConfigValue("input-field", "dots_spacing", k.c_str())}, - {"fade_on_empty", m_config.getSpecialConfigValue("input-field", "fade_on_empty", k.c_str())}, - {"font_color", m_config.getSpecialConfigValue("input-field", "font_color", k.c_str())}, - {"halign", m_config.getSpecialConfigValue("input-field", "halign", k.c_str())}, - {"valign", m_config.getSpecialConfigValue("input-field", "valign", k.c_str())}, - {"position", m_config.getSpecialConfigValue("input-field", "position", k.c_str())}, - {"placeholder_text", m_config.getSpecialConfigValue("input-field", "placeholder_text", k.c_str())}, - {"hide_input", m_config.getSpecialConfigValue("input-field", "hide_input", k.c_str())}, - } + "input-field", + std::any_cast(m_config.getSpecialConfigValue("input-field", "monitor", k.c_str())), + { + {"size", m_config.getSpecialConfigValue("input-field", "size", k.c_str())}, + {"inner_color", m_config.getSpecialConfigValue("input-field", "inner_color", k.c_str())}, + {"outer_color", m_config.getSpecialConfigValue("input-field", "outer_color", k.c_str())}, + {"outline_thickness", m_config.getSpecialConfigValue("input-field", "outline_thickness", k.c_str())}, + {"dots_size", m_config.getSpecialConfigValue("input-field", "dots_size", k.c_str())}, + {"dots_spacing", m_config.getSpecialConfigValue("input-field", "dots_spacing", k.c_str())}, + {"fade_on_empty", m_config.getSpecialConfigValue("input-field", "fade_on_empty", k.c_str())}, + {"font_color", m_config.getSpecialConfigValue("input-field", "font_color", k.c_str())}, + {"halign", m_config.getSpecialConfigValue("input-field", "halign", k.c_str())}, + {"valign", m_config.getSpecialConfigValue("input-field", "valign", k.c_str())}, + {"position", m_config.getSpecialConfigValue("input-field", "position", k.c_str())}, + {"placeholder_text", m_config.getSpecialConfigValue("input-field", "placeholder_text", k.c_str())}, + {"hide_input", m_config.getSpecialConfigValue("input-field", "hide_input", k.c_str())}, + } }); // clang-format on } @@ -115,20 +133,55 @@ std::vector CConfigManager::getWidgetConfigs() { for (auto& k : keys) { // clang-format off result.push_back(CConfigManager::SWidgetConfig{ - "label", - std::any_cast(m_config.getSpecialConfigValue("label", "monitor", k.c_str())), - { - {"position", m_config.getSpecialConfigValue("label", "position", k.c_str())}, - {"color", m_config.getSpecialConfigValue("label", "color", k.c_str())}, - {"font_size", m_config.getSpecialConfigValue("label", "font_size", k.c_str())}, - {"font_family", m_config.getSpecialConfigValue("label", "font_family", k.c_str())}, - {"text", m_config.getSpecialConfigValue("label", "text", k.c_str())}, - {"halign", m_config.getSpecialConfigValue("label", "halign", k.c_str())}, - {"valign", m_config.getSpecialConfigValue("label", "valign", k.c_str())}, - } + "label", + std::any_cast(m_config.getSpecialConfigValue("label", "monitor", k.c_str())), + { + {"position", m_config.getSpecialConfigValue("label", "position", k.c_str())}, + {"color", m_config.getSpecialConfigValue("label", "color", k.c_str())}, + {"font_size", m_config.getSpecialConfigValue("label", "font_size", k.c_str())}, + {"font_family", m_config.getSpecialConfigValue("label", "font_family", k.c_str())}, + {"text", m_config.getSpecialConfigValue("label", "text", k.c_str())}, + {"halign", m_config.getSpecialConfigValue("label", "halign", k.c_str())}, + {"valign", m_config.getSpecialConfigValue("label", "valign", k.c_str())}, + } }); // clang-format on } return result; } + + +std::optional CConfigManager::handleSource(const std::string& command, const std::string& rawpath) { + if (rawpath.length() < 2) { + Debug::log(ERR, "source= path garbage"); + return "source path " + rawpath + " bogus!"; + } + std::unique_ptr glob_buf{new glob_t, [](glob_t* g) { globfree(g); }}; + memset(glob_buf.get(), 0, sizeof(glob_t)); + + if (auto r = glob(absolutePath(rawpath, configCurrentPath).c_str(), GLOB_TILDE, nullptr, glob_buf.get()); r != 0) { + std::string err = std::format("source= globbing error: {}", r == GLOB_NOMATCH ? "found no match" : GLOB_ABORTED ? "read error" : "out of memory"); + Debug::log(ERR, "{}", err); + return err; + } + + for (size_t i = 0; i < glob_buf->gl_pathc; i++) { + auto value = absolutePath(glob_buf->gl_pathv[i], configCurrentPath); + + if (!std::filesystem::is_regular_file(value)) { + if (std::filesystem::exists(value)) { + Debug::log(WARN, "source= skipping non-file {}", value); + continue; + } + + Debug::log(ERR, "source= file doesnt exist"); + return "source file " + value + " doesn't exist!"; + } + + m_config.parseFile(value.c_str()); + + } + + return {}; +} \ No newline at end of file diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index c0ab72bb..2f18d705 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -9,7 +9,7 @@ #include class CConfigManager { - public: +public: CConfigManager(); void init(); void* const* getValuePtr(const std::string& name); @@ -22,8 +22,10 @@ class CConfigManager { }; std::vector getWidgetConfigs(); + std::optional handleSource(const std::string&, const std::string&); - private: + std::string configCurrentPath; +private: Hyprlang::CConfig m_config; }; diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp new file mode 100644 index 00000000..b8796441 --- /dev/null +++ b/src/helpers/MiscFunctions.cpp @@ -0,0 +1,25 @@ +#include "MiscFunctions.hpp" + +std::string absolutePath(const std::string& rawpath, const std::string& currentPath) { + auto value = rawpath; + + if (value[0] == '~') { + static const char* const ENVHOME = getenv("HOME"); + value.replace(0, 1, std::string(ENVHOME)); + } else if (value[0] != '/') { + auto currentDir = currentPath.substr(0, currentPath.find_last_of('/')); + + if (value[0] == '.') { + if (value[1] == '.' && value[2] == '/') { + auto parentDir = currentDir.substr(0, currentDir.find_last_of('/')); + value.replace(0, 2 + currentPath.empty(), parentDir); + } else if (value[1] == '/') + value.replace(0, 1 + currentPath.empty(), currentDir); + else + value = currentDir + '/' + value; + } else + value = currentDir + '/' + value; + } + + return value; +} \ No newline at end of file diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp new file mode 100644 index 00000000..10daa689 --- /dev/null +++ b/src/helpers/MiscFunctions.hpp @@ -0,0 +1,6 @@ +#pragma once + +#include + +std::string absolutePath(const std::string&, const std::string&); +