config: add source parsing (#28)

* config: add source parsing

* config: add nested source parsing

* config: streamlined absolutePath impl
This commit is contained in:
Maurice Kraus 2024-02-22 00:52:12 +01:00 committed by GitHub
parent 59997a7c38
commit 2fc23cbfc8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 95 additions and 1 deletions

View file

@ -1,5 +1,20 @@
#include "ConfigManager.hpp" #include "ConfigManager.hpp"
#include "../helpers/MiscFunctions.hpp"
#include <filesystem> #include <filesystem>
#include <glob.h>
#include <cstring>
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 std::string getConfigDir() {
static const char* xdgConfigHome = getenv("XDG_CONFIG_HOME"); static const char* xdgConfigHome = getenv("XDG_CONFIG_HOME");
@ -15,7 +30,7 @@ static std::string getMainConfigPath() {
} }
CConfigManager::CConfigManager() : m_config(getMainConfigPath().c_str(), Hyprlang::SConfigOptions{.throwAllErrors = true, .allowMissingConfig = true}) { CConfigManager::CConfigManager() : m_config(getMainConfigPath().c_str(), Hyprlang::SConfigOptions{.throwAllErrors = true, .allowMissingConfig = true}) {
; configCurrentPath = getMainConfigPath();
} }
void CConfigManager::init() { void CConfigManager::init() {
@ -62,6 +77,8 @@ void CConfigManager::init() {
m_config.addSpecialConfigValue("label", "halign", Hyprlang::STRING{"none"}); m_config.addSpecialConfigValue("label", "halign", Hyprlang::STRING{"none"});
m_config.addSpecialConfigValue("label", "valign", Hyprlang::STRING{"none"}); m_config.addSpecialConfigValue("label", "valign", Hyprlang::STRING{"none"});
m_config.registerHandler(&::handleSource, "source", {false});
m_config.commence(); m_config.commence();
auto result = m_config.parse(); auto result = m_config.parse();
@ -149,3 +166,48 @@ std::vector<CConfigManager::SWidgetConfig> CConfigManager::getWidgetConfigs() {
return result; return result;
} }
std::optional<std::string> 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_t, void (*)(glob_t*)> 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 pathValueOpt = absolutePath(glob_buf->gl_pathv[i], configCurrentPath);
if (pathValueOpt->empty()) {
Debug::log(WARN, "source= skipping invalid path");
continue;
}
auto pathValue = pathValueOpt.value();
if (!std::filesystem::is_regular_file(pathValue)) {
if (std::filesystem::exists(pathValue)) {
Debug::log(WARN, "source= skipping non-file {}", pathValue);
continue;
}
Debug::log(ERR, "source= file doesnt exist");
return "source file " + pathValue + " doesn't exist!";
}
// allow for nested config parsing
auto backupConfigPath = configCurrentPath;
configCurrentPath = pathValue;
m_config.parseFile(pathValue.c_str());
configCurrentPath = backupConfigPath;
}
return {};
}

View file

@ -22,6 +22,9 @@ class CConfigManager {
}; };
std::vector<SWidgetConfig> getWidgetConfigs(); std::vector<SWidgetConfig> getWidgetConfigs();
std::optional<std::string> handleSource(const std::string&, const std::string&);
std::string configCurrentPath;
private: private:
Hyprlang::CConfig m_config; Hyprlang::CConfig m_config;

View file

@ -0,0 +1,23 @@
#include <filesystem>
#include "MiscFunctions.hpp"
std::optional<std::string> absolutePath(const std::string& rawpath, const std::string& rawcurrentpath) {
std::filesystem::path path(rawpath);
// Handling where rawpath starts with '~'
if (!rawpath.empty() && rawpath[0] == '~') {
static const char* const ENVHOME = getenv("HOME");
return std::filesystem::path(ENVHOME) / path.relative_path().string().substr(2);
}
// Handling e.g. ./, ../
else if (path.is_relative()) {
const std::filesystem::path currentDir = std::filesystem::path(rawcurrentpath).parent_path();
auto finalPath = currentDir / path;
if (exists(finalPath))
return std::filesystem::canonical(currentDir / path);
return {};
} else {
return std::filesystem::canonical(path);
}
}

View file

@ -0,0 +1,6 @@
#pragma once
#include <string>
#include <optional>
std::optional<std::string> absolutePath(const std::string&, const std::string&);