mirror of
https://github.com/hyprwm/hyprlang.git
synced 2025-12-24 22:10: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;
|
valueName += command;
|
||||||
|
|
||||||
|
// TODO: all this sucks xD
|
||||||
|
|
||||||
|
SSpecialCategory* overrideSpecialCat = nullptr;
|
||||||
|
|
||||||
if (valueName.contains('[') && valueName.contains(']')) {
|
if (valueName.contains('[') && valueName.contains(']')) {
|
||||||
const auto L = valueName.find_first_of('[');
|
const auto L = valueName.find_first_of('[');
|
||||||
const auto R = valueName.find_last_of(']');
|
const auto R = valueName.find_last_of(']');
|
||||||
|
|
@ -313,7 +317,8 @@ std::pair<bool, CParseResult> CConfig::configSetValueSafe(const std::string& com
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// existing special
|
// existing special
|
||||||
keyExists = true;
|
keyExists = true;
|
||||||
|
overrideSpecialCat = specialCat.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keyExists)
|
if (keyExists)
|
||||||
|
|
@ -329,6 +334,8 @@ std::pair<bool, CParseResult> CConfig::configSetValueSafe(const std::string& com
|
||||||
applyDefaultsToCat(*PCAT);
|
applyDefaultsToCat(*PCAT);
|
||||||
|
|
||||||
PCAT->values[sc->key].setFrom(CATKEY);
|
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
|
// it might be in a special category
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
if (impl->currentSpecialCategory && valueName.starts_with(impl->currentSpecialCategory->name)) {
|
if (overrideSpecialCat) {
|
||||||
VALUEIT = impl->currentSpecialCategory->values.find(valueName.substr(impl->currentSpecialCategory->name.length() + 1));
|
VALUEIT = overrideSpecialCat->values.find(valueName.substr(overrideSpecialCat->name.length() + 1));
|
||||||
|
|
||||||
if (VALUEIT != impl->currentSpecialCategory->values.end())
|
if (VALUEIT != overrideSpecialCat->values.end())
|
||||||
found = true;
|
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) {
|
if (VALUEIT != impl->currentSpecialCategory->values.end())
|
||||||
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())
|
|
||||||
found = true;
|
found = true;
|
||||||
else if (sc->descriptor->dontErrorOnMissing)
|
|
||||||
return {true, result}; // will return a success, cuz we want to ignore missing
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
// could be a dynamic category that doesnt exist yet
|
for (auto& sc : impl->specialCategories) {
|
||||||
for (auto& sc : impl->specialCategoryDescriptors) {
|
if (!valueName.starts_with(sc->name))
|
||||||
if (sc->key.empty() || !valueName.starts_with(sc->name + ":"))
|
continue;
|
||||||
continue;
|
|
||||||
|
|
||||||
// found value root to be a special category, get the trunk
|
if (!sc->isStatic && std::string{std::any_cast<const char*>(sc->values[sc->key].getValue())} != impl->currentSpecialKey)
|
||||||
const auto VALUETRUNK = valueName.substr(sc->name.length() + 1);
|
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;
|
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) {
|
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) {
|
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() {
|
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(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(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
|
// test dynamic special variable
|
||||||
EXPECT(config.parseDynamic("$SPECIALVAL1 = 2").error, false);
|
EXPECT(config.parseDynamic("$SPECIALVAL1 = 2").error, false);
|
||||||
EXPECT(std::any_cast<int64_t>(config.getSpecialConfigValue("special", "value", "a")), (Hyprlang::INT)2);
|
EXPECT(std::any_cast<int64_t>(config.getSpecialConfigValue("special", "value", "a")), (Hyprlang::INT)2);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue