mirror of
https://github.com/hyprwm/hyprlang.git
synced 2025-12-20 03:50:02 +01:00
parser: fix lingering currentSpecialCat after dynamic calls
This commit is contained in:
parent
4302343ce7
commit
b0d7b375a9
2 changed files with 91 additions and 68 deletions
154
src/config.cpp
154
src/config.cpp
|
|
@ -290,6 +290,10 @@ std::pair<bool, CParseResult> CConfig::configSetValueSafe(const std::string& com
|
|||
|
||||
valueName += command;
|
||||
|
||||
// TODO: all this sucks xD
|
||||
|
||||
SSpecialCategory* overrideSpecialCat = nullptr;
|
||||
|
||||
if (valueName.contains('[') && valueName.contains(']')) {
|
||||
const auto L = valueName.find_first_of('[');
|
||||
const auto R = valueName.find_last_of(']');
|
||||
|
|
@ -313,7 +317,8 @@ std::pair<bool, CParseResult> CConfig::configSetValueSafe(const std::string& com
|
|||
continue;
|
||||
|
||||
// existing special
|
||||
keyExists = true;
|
||||
keyExists = true;
|
||||
overrideSpecialCat = specialCat.get();
|
||||
}
|
||||
|
||||
if (keyExists)
|
||||
|
|
@ -329,6 +334,8 @@ std::pair<bool, CParseResult> CConfig::configSetValueSafe(const std::string& com
|
|||
applyDefaultsToCat(*PCAT);
|
||||
|
||||
PCAT->values[sc->key].setFrom(CATKEY);
|
||||
overrideSpecialCat = PCAT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -338,82 +345,89 @@ std::pair<bool, CParseResult> CConfig::configSetValueSafe(const std::string& com
|
|||
// it might be in a special category
|
||||
bool found = false;
|
||||
|
||||
if (impl->currentSpecialCategory && valueName.starts_with(impl->currentSpecialCategory->name)) {
|
||||
VALUEIT = impl->currentSpecialCategory->values.find(valueName.substr(impl->currentSpecialCategory->name.length() + 1));
|
||||
if (overrideSpecialCat) {
|
||||
VALUEIT = overrideSpecialCat->values.find(valueName.substr(overrideSpecialCat->name.length() + 1));
|
||||
|
||||
if (VALUEIT != impl->currentSpecialCategory->values.end())
|
||||
if (VALUEIT != overrideSpecialCat->values.end())
|
||||
found = true;
|
||||
}
|
||||
} else {
|
||||
if (impl->currentSpecialCategory && valueName.starts_with(impl->currentSpecialCategory->name)) {
|
||||
VALUEIT = impl->currentSpecialCategory->values.find(valueName.substr(impl->currentSpecialCategory->name.length() + 1));
|
||||
|
||||
if (!found) {
|
||||
for (auto& sc : impl->specialCategories) {
|
||||
if (!valueName.starts_with(sc->name))
|
||||
continue;
|
||||
|
||||
if (!sc->isStatic && std::string{std::any_cast<const char*>(sc->values[sc->key].getValue())} != impl->currentSpecialKey)
|
||||
continue;
|
||||
|
||||
VALUEIT = sc->values.find(valueName.substr(sc->name.length() + 1));
|
||||
impl->currentSpecialCategory = sc.get();
|
||||
|
||||
if (VALUEIT != sc->values.end())
|
||||
if (VALUEIT != impl->currentSpecialCategory->values.end())
|
||||
found = true;
|
||||
else if (sc->descriptor->dontErrorOnMissing)
|
||||
return {true, result}; // will return a success, cuz we want to ignore missing
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
// could be a dynamic category that doesnt exist yet
|
||||
for (auto& sc : impl->specialCategoryDescriptors) {
|
||||
if (sc->key.empty() || !valueName.starts_with(sc->name + ":"))
|
||||
continue;
|
||||
if (!found) {
|
||||
for (auto& sc : impl->specialCategories) {
|
||||
if (!valueName.starts_with(sc->name))
|
||||
continue;
|
||||
|
||||
// found value root to be a special category, get the trunk
|
||||
const auto VALUETRUNK = valueName.substr(sc->name.length() + 1);
|
||||
if (!sc->isStatic && std::string{std::any_cast<const char*>(sc->values[sc->key].getValue())} != impl->currentSpecialKey)
|
||||
continue;
|
||||
|
||||
VALUEIT = sc->values.find(valueName.substr(sc->name.length() + 1));
|
||||
impl->currentSpecialCategory = sc.get();
|
||||
|
||||
if (VALUEIT != sc->values.end())
|
||||
found = true;
|
||||
else if (sc->descriptor->dontErrorOnMissing)
|
||||
return {true, result}; // will return a success, cuz we want to ignore missing
|
||||
|
||||
// check if trunk is a value within the special category
|
||||
if (!sc->defaultValues.contains(VALUETRUNK) && VALUETRUNK != sc->key)
|
||||
break;
|
||||
|
||||
// bingo
|
||||
const auto PCAT = impl->specialCategories.emplace_back(std::make_unique<SSpecialCategory>()).get();
|
||||
PCAT->descriptor = sc.get();
|
||||
PCAT->name = sc->name;
|
||||
PCAT->key = sc->key;
|
||||
addSpecialConfigValue(sc->name.c_str(), sc->key.c_str(), CConfigValue("0"));
|
||||
|
||||
applyDefaultsToCat(*PCAT);
|
||||
|
||||
VALUEIT = PCAT->values.find(valueName.substr(sc->name.length() + 1));
|
||||
impl->currentSpecialCategory = PCAT;
|
||||
|
||||
if (VALUEIT != PCAT->values.end())
|
||||
found = true;
|
||||
|
||||
if (sc->anonymous) {
|
||||
// find suitable key
|
||||
size_t biggest = 0;
|
||||
for (auto& catt : impl->specialCategories) {
|
||||
biggest = std::max(catt->anonymousID, biggest);
|
||||
}
|
||||
|
||||
biggest++;
|
||||
|
||||
PCAT->values[ANONYMOUS_KEY].setFrom(std::to_string(biggest));
|
||||
impl->currentSpecialKey = std::to_string(biggest);
|
||||
PCAT->anonymousID = biggest;
|
||||
} else {
|
||||
if (VALUEIT == PCAT->values.end() || VALUEIT->first != sc->key) {
|
||||
result.setError(std::format("special category's first value must be the key. Key for <{}> is <{}>", PCAT->name, PCAT->key));
|
||||
return {true, result};
|
||||
}
|
||||
impl->currentSpecialKey = value;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
if (!found) {
|
||||
// could be a dynamic category that doesnt exist yet
|
||||
for (auto& sc : impl->specialCategoryDescriptors) {
|
||||
if (sc->key.empty() || !valueName.starts_with(sc->name + ":"))
|
||||
continue;
|
||||
|
||||
// found value root to be a special category, get the trunk
|
||||
const auto VALUETRUNK = valueName.substr(sc->name.length() + 1);
|
||||
|
||||
// check if trunk is a value within the special category
|
||||
if (!sc->defaultValues.contains(VALUETRUNK) && VALUETRUNK != sc->key)
|
||||
break;
|
||||
|
||||
// bingo
|
||||
const auto PCAT = impl->specialCategories.emplace_back(std::make_unique<SSpecialCategory>()).get();
|
||||
PCAT->descriptor = sc.get();
|
||||
PCAT->name = sc->name;
|
||||
PCAT->key = sc->key;
|
||||
addSpecialConfigValue(sc->name.c_str(), sc->key.c_str(), CConfigValue("0"));
|
||||
|
||||
applyDefaultsToCat(*PCAT);
|
||||
|
||||
VALUEIT = PCAT->values.find(valueName.substr(sc->name.length() + 1));
|
||||
impl->currentSpecialCategory = PCAT;
|
||||
|
||||
if (VALUEIT != PCAT->values.end())
|
||||
found = true;
|
||||
|
||||
if (sc->anonymous) {
|
||||
// find suitable key
|
||||
size_t biggest = 0;
|
||||
for (auto& catt : impl->specialCategories) {
|
||||
biggest = std::max(catt->anonymousID, biggest);
|
||||
}
|
||||
|
||||
biggest++;
|
||||
|
||||
PCAT->values[ANONYMOUS_KEY].setFrom(std::to_string(biggest));
|
||||
impl->currentSpecialKey = std::to_string(biggest);
|
||||
PCAT->anonymousID = biggest;
|
||||
} else {
|
||||
if (VALUEIT == PCAT->values.end() || VALUEIT->first != sc->key) {
|
||||
result.setError(std::format("special category's first value must be the key. Key for <{}> is <{}>", PCAT->name, PCAT->key));
|
||||
return {true, result};
|
||||
}
|
||||
impl->currentSpecialKey = value;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1016,11 +1030,15 @@ CParseResult CConfig::parseFile(const char* file) {
|
|||
}
|
||||
|
||||
CParseResult CConfig::parseDynamic(const char* line) {
|
||||
return parseLine(line, true);
|
||||
auto ret = parseLine(line, true);
|
||||
impl->currentSpecialCategory = nullptr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
CParseResult CConfig::parseDynamic(const char* command, const char* value) {
|
||||
return parseLine(std::string{command} + "=" + std::string{value}, true);
|
||||
auto ret = parseLine(std::string{command} + "=" + std::string{value}, true);
|
||||
impl->currentSpecialCategory = nullptr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CConfig::clearState() {
|
||||
|
|
|
|||
|
|
@ -313,6 +313,11 @@ int main(int argc, char** argv, char** envp) {
|
|||
EXPECT(config.parseDynamic("specialAnonymousNested[c]:nested:value2 = 6").error, false);
|
||||
EXPECT(std::any_cast<int64_t>(config.getSpecialConfigValue("specialAnonymousNested", "nested:value2", "c")), (Hyprlang::INT)6);
|
||||
|
||||
EXPECT(config.parseDynamic("special[a]:value = 69").error, false);
|
||||
EXPECT(config.parseDynamic("special[b]:value = 420").error, false);
|
||||
EXPECT(std::any_cast<int64_t>(config.getSpecialConfigValue("special", "value", "a")), 69);
|
||||
EXPECT(std::any_cast<int64_t>(config.getSpecialConfigValue("special", "value", "b")), 420);
|
||||
|
||||
// test dynamic special variable
|
||||
EXPECT(config.parseDynamic("$SPECIALVAL1 = 2").error, false);
|
||||
EXPECT(std::any_cast<int64_t>(config.getSpecialConfigValue("special", "value", "a")), (Hyprlang::INT)2);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue