mirror of
https://github.com/hyprwm/hyprlang.git
synced 2024-11-16 18:25:57 +01:00
core: add variables
This commit is contained in:
parent
090dcb22ea
commit
158c66c5db
5 changed files with 72 additions and 4 deletions
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
};
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue