core: support nesting with special categories

This commit is contained in:
Maximilian Seidler 2025-09-09 21:08:20 +02:00
parent 3d63fb4a42
commit 85d2defd78
3 changed files with 52 additions and 10 deletions

View file

@ -283,16 +283,12 @@ CParseResult CConfig::configSetValueSafe(const std::string& command, const std::
CParseResult result;
std::string valueName;
std::string catPrefix;
for (auto& c : impl->categories) {
valueName += c + ':';
catPrefix += c + ':';
}
valueName += command;
const auto VALUEONLYNAME = command.starts_with(catPrefix) ? command.substr(catPrefix.length()) : command;
// FIXME: this will bug with nested.
if (valueName.contains('[') && valueName.contains(']')) {
const auto L = valueName.find_first_of('[');
@ -306,7 +302,7 @@ CParseResult CConfig::configSetValueSafe(const std::string& command, const std::
// if it doesn't exist, make it
for (auto& sc : impl->specialCategoryDescriptors) {
if (sc->key.empty() || !valueName.starts_with(sc->name))
if (sc->key.empty() || !valueName.starts_with(sc->name + ":"))
continue;
// bingo
@ -358,11 +354,14 @@ CParseResult CConfig::configSetValueSafe(const std::string& command, const std::
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))
if (sc->key.empty() || !valueName.starts_with(sc->name + ":"))
continue;
// category does exist, check if value exists
if (!sc->defaultValues.contains(VALUEONLYNAME) && VALUEONLYNAME != sc->key)
// 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
@ -835,9 +834,12 @@ CParseResult CConfig::parseLine(std::string line, bool dynamic) {
return result;
}
impl->currentSpecialKey = "";
impl->currentSpecialCategory = nullptr;
impl->categories.pop_back();
if (impl->categories.empty()) {
impl->currentSpecialKey = "";
impl->currentSpecialCategory = nullptr;
}
} else {
// open a category.
if (!line.ends_with("{")) {

View file

@ -127,6 +127,27 @@ specialAnonymous {
value = 3
}
specialAnonymousNested {
nested:value1 = 1
nested:value2 = 2
nested1:nested2:value1 = 10
nested1:nested2:value2 = 11
}
specialAnonymousNested {
nested {
value1 = 3
value2 = 4
}
nested1 {
nested2 {
value1 = 12
value2 = 13
}
}
}
flagsStuff {
value = 2
}

View file

@ -154,6 +154,12 @@ int main(int argc, char** argv, char** envp) {
config.addSpecialCategory("specialAnonymous", {.key = nullptr, .ignoreMissing = false, .anonymousKeyBased = true});
config.addSpecialConfigValue("specialAnonymous", "value", (Hyprlang::INT)0);
config.addSpecialCategory("specialAnonymousNested", {.key = nullptr, .ignoreMissing = false, .anonymousKeyBased = true});
config.addSpecialConfigValue("specialAnonymousNested", "nested:value1", (Hyprlang::INT)0);
config.addSpecialConfigValue("specialAnonymousNested", "nested:value2", (Hyprlang::INT)0);
config.addSpecialConfigValue("specialAnonymousNested", "nested1:nested2:value1", (Hyprlang::INT)0);
config.addSpecialConfigValue("specialAnonymousNested", "nested1:nested2:value2", (Hyprlang::INT)0);
config.addConfigValue("multiline", "");
config.commence();
@ -302,8 +308,21 @@ int main(int argc, char** argv, char** envp) {
// test anonymous
EXPECT(config.listKeysForSpecialCategory("specialAnonymous").size(), 2);
const auto KEYS = config.listKeysForSpecialCategory("specialAnonymous");
EXPECT(std::any_cast<int64_t>(config.getSpecialConfigValue("specialAnonymous", "value", KEYS[0].c_str())), 2);
EXPECT(std::any_cast<int64_t>(config.getSpecialConfigValue("specialAnonymous", "value", KEYS[1].c_str())), 3);
// test anonymous nested
EXPECT(config.listKeysForSpecialCategory("specialAnonymousNested").size(), 2);
const auto KEYS2 = config.listKeysForSpecialCategory("specialAnonymousNested");
EXPECT(std::any_cast<int64_t>(config.getSpecialConfigValue("specialAnonymousNested", "nested:value1", KEYS2[0].c_str())), 1);
EXPECT(std::any_cast<int64_t>(config.getSpecialConfigValue("specialAnonymousNested", "nested:value2", KEYS2[0].c_str())), 2);
EXPECT(std::any_cast<int64_t>(config.getSpecialConfigValue("specialAnonymousNested", "nested:value1", KEYS2[1].c_str())), 3);
EXPECT(std::any_cast<int64_t>(config.getSpecialConfigValue("specialAnonymousNested", "nested:value2", KEYS2[1].c_str())), 4);
EXPECT(std::any_cast<int64_t>(config.getSpecialConfigValue("specialAnonymousNested", "nested1:nested2:value1", KEYS2[0].c_str())), 10);
EXPECT(std::any_cast<int64_t>(config.getSpecialConfigValue("specialAnonymousNested", "nested1:nested2:value2", KEYS2[0].c_str())), 11);
EXPECT(std::any_cast<int64_t>(config.getSpecialConfigValue("specialAnonymousNested", "nested1:nested2:value1", KEYS2[1].c_str())), 12);
EXPECT(std::any_cast<int64_t>(config.getSpecialConfigValue("specialAnonymousNested", "nested1:nested2:value2", KEYS2[1].c_str())), 13);
// test sourcing
std::cout << " → Testing sourcing\n";
EXPECT(std::any_cast<int64_t>(config.getConfigValue("myColors:pink")), (Hyprlang::INT)0xFFc800c8);