core: add variables

This commit is contained in:
Vaxry 2023-12-29 11:40:08 +01:00
parent 090dcb22ea
commit 158c66c5db
5 changed files with 72 additions and 4 deletions

View file

@ -80,6 +80,16 @@ static bool isNumber(const std::string& str, bool allowfloat) {
return true;
}
static void replaceAll(std::string& str, const std::string& from, const std::string& to) {
if (from.empty())
return;
size_t pos = 0;
while ((pos = str.find(from, pos)) != std::string::npos) {
str.replace(pos, from.length(), to);
pos += to.length();
}
}
static int64_t configStringToInt(const std::string& VALUE) {
if (VALUE.starts_with("0x")) {
// Values with 0x are hex
@ -155,7 +165,7 @@ CParseResult CConfig::configSetValueSafe(const std::string& command, const std::
const auto VALUEIT = impl->values.find(valueName);
if (VALUEIT == impl->values.end()) {
result.setError("config option doesn't exist");
result.setError(std::format("config option <{}> does not exist.", valueName));
return result;
}
@ -209,6 +219,13 @@ 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 result;
return result;
}
CParseResult CConfig::parseLine(std::string line) {
CParseResult result;
@ -245,10 +262,45 @@ CParseResult CConfig::parseLine(std::string line) {
if (equalsPos != std::string::npos) {
// set value or call handler
CParseResult ret;
const auto LHS = removeBeginEndSpacesTabs(line.substr(0, equalsPos));
const auto RHS = removeBeginEndSpacesTabs(line.substr(equalsPos + 1));
auto LHS = removeBeginEndSpacesTabs(line.substr(0, equalsPos));
auto RHS = removeBeginEndSpacesTabs(line.substr(equalsPos + 1));
bool found = false;
if (LHS.empty()) {
result.setError("Empty lhs.");
return result;
}
if (*LHS.begin() == '$')
return parseVariable(LHS, RHS);
// limit unwrapping iterations to 100. if exceeds, raise error
for (size_t i = 0; i < 100; ++i) {
bool anyMatch = false;
for (auto& var : impl->variables) {
const auto LHSIT = LHS.find("$" + var.name);
const auto RHSIT = RHS.find("$" + var.name);
if (LHSIT != std::string::npos)
replaceAll(LHS, "$" + var.name, var.value);
if (RHSIT != std::string::npos)
replaceAll(RHS, "$" + var.name, var.value);
if (RHSIT == std::string::npos && LHSIT == std::string::npos)
break;
anyMatch = true;
}
if (!anyMatch)
break;
if (i == 99) {
result.setError("Expanding variables exceeded max iteration limit");
return result;
}
}
bool found = false;
for (auto& h : impl->handlers) {
if (!h.options.allowFlags && h.name != LHS)
continue;

View file

@ -10,6 +10,11 @@ struct SHandler {
Hyprlang::PCONFIGHANDLERFUNC func = nullptr;
};
struct SVariable {
std::string name = "";
std::string value = "";
};
class CConfigImpl {
public:
std::string path = "";
@ -17,6 +22,7 @@ class CConfigImpl {
std::unordered_map<std::string, Hyprlang::CConfigValue> values;
std::unordered_map<std::string, Hyprlang::CConfigValue> defaultValues;
std::vector<SHandler> handlers;
std::vector<SVariable> variables;
std::vector<std::string> categories;

View file

@ -139,6 +139,7 @@ namespace Hyprlang {
CParseResult parseLine(std::string line);
CParseResult configSetValueSafe(const std::string& command, const std::string& value);
CParseResult parseVariable(const std::string& lhs, const std::string& rhs);
void clearState();
};
};

View file

@ -5,6 +5,10 @@ testInt = 123
testFloat = 123.456
testString = Hello World! ## This is not a comment! # This is!
$MY_VAR = 1337
$MY_VAR_2 = $MY_VAR
testVar = $MY_VAR$MY_VAR_2
testCategory {
testValueInt = 123456
testValueHex = 0xF

View file

@ -53,6 +53,7 @@ int main(int argc, char** argv, char** envp) {
config.addConfigValue("testFloat", 0.F);
config.addConfigValue("testVec", Hyprlang::SVector2D{69, 420});
config.addConfigValue("testString", "");
config.addConfigValue("testVar", 0L);
config.addConfigValue("testStringQuotes", "");
config.addConfigValue("testCategory:testValueInt", 0L);
config.addConfigValue("testCategory:testValueHex", 0xAL);
@ -106,6 +107,10 @@ int main(int argc, char** argv, char** envp) {
EXPECT(config.parseDynamic("testCategory:testValueHex", "0xaabbccdd").error, false);
EXPECT(std::any_cast<int64_t>(config.getConfigValue("testCategory:testValueHex")), 0xAABBCCDDL);
// test variables
std::cout << " → Testing variables\n";
EXPECT(std::any_cast<int64_t>(config.getConfigValue("testVar")), 13371337);
} catch (const char* e) {
std::cout << Colors::RED << "Error: " << Colors::RESET << e << "\n";
return 1;