diff --git a/src/config.cpp b/src/config.cpp index bbe7f4d..444a66e 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -219,14 +219,29 @@ CParseResult CConfig::configSetValueSafe(const std::string& command, const std:: return result; } -CParseResult CConfig::parseVariable(const std::string& lhs, const std::string& rhs) { - impl->variables.push_back({lhs.substr(1), rhs}); - std::sort(impl->variables.begin(), impl->variables.end(), [](const auto& lhs, const auto& rhs) { return lhs.name.length() > rhs.name.length(); }); +CParseResult CConfig::parseVariable(const std::string& lhs, const std::string& rhs, bool dynamic) { + auto IT = std::find_if(impl->variables.begin(), impl->variables.end(), [&](const auto& v) { return v.name == lhs.substr(1); }); + + if (IT != impl->variables.end()) + IT->value = rhs; + else { + impl->variables.push_back({lhs.substr(1), rhs}); + std::sort(impl->variables.begin(), impl->variables.end(), [](const auto& lhs, const auto& rhs) { return lhs.name.length() > rhs.name.length(); }); + } + + if (dynamic) { + if (IT == impl->variables.end()) + IT = std::find_if(impl->variables.begin(), impl->variables.end(), [&](const auto& v) { return v.name == lhs.substr(1); }); + for (auto& l : IT->linesContainingVar) { + parseLine(l, true); + } + } + CParseResult result; return result; } -CParseResult CConfig::parseLine(std::string line) { +CParseResult CConfig::parseLine(std::string line, bool dynamic) { CParseResult result; auto commentPos = line.find('#'); @@ -271,7 +286,7 @@ CParseResult CConfig::parseLine(std::string line) { } if (*LHS.begin() == '$') - return parseVariable(LHS, RHS); + return parseVariable(LHS, RHS, dynamic); // limit unwrapping iterations to 100. if exceeds, raise error for (size_t i = 0; i < 100; ++i) { @@ -287,6 +302,8 @@ CParseResult CConfig::parseLine(std::string line) { if (RHSIT == std::string::npos && LHSIT == std::string::npos) break; + else + var.linesContainingVar.push_back(line); anyMatch = true; } @@ -387,11 +404,11 @@ CParseResult CConfig::parse() { } CParseResult CConfig::parseDynamic(const char* line) { - return parseLine(line); + return parseLine(line, true); } CParseResult CConfig::parseDynamic(const char* command, const char* value) { - return parseLine(std::string{command} + "=" + std::string{value}); + return parseLine(std::string{command} + "=" + std::string{value}, true); } void CConfig::clearState() { diff --git a/src/config.hpp b/src/config.hpp index 5acfe80..d1005b9 100644 --- a/src/config.hpp +++ b/src/config.hpp @@ -11,8 +11,9 @@ struct SHandler { }; struct SVariable { - std::string name = ""; - std::string value = ""; + std::string name = ""; + std::string value = ""; + std::vector linesContainingVar; // for dynamic updates }; class CConfigImpl { diff --git a/src/public.hpp b/src/public.hpp index da5dd20..eab2ec1 100644 --- a/src/public.hpp +++ b/src/public.hpp @@ -137,9 +137,9 @@ namespace Hyprlang { CConfigImpl* impl; - CParseResult parseLine(std::string line); + CParseResult parseLine(std::string line, bool dynamic = false); CParseResult configSetValueSafe(const std::string& command, const std::string& value); - CParseResult parseVariable(const std::string& lhs, const std::string& rhs); + CParseResult parseVariable(const std::string& lhs, const std::string& rhs, bool dynamic = false); void clearState(); }; }; \ No newline at end of file diff --git a/tests/main.cpp b/tests/main.cpp index 46b6db9..f69203e 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -111,6 +111,11 @@ int main(int argc, char** argv, char** envp) { std::cout << " → Testing variables\n"; EXPECT(std::any_cast(config.getConfigValue("testVar")), 13371337); + // test dynamic variables + std::cout << " → Testing dynamic variables\n"; + EXPECT(config.parseDynamic("$MY_VAR_2 = 420").error, false); + EXPECT(std::any_cast(config.getConfigValue("testVar")), 1337420); + } catch (const char* e) { std::cout << Colors::RED << "Error: " << Colors::RESET << e << "\n"; return 1;