diff --git a/src/config.cpp b/src/config.cpp index c727bec..97af421 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -361,8 +361,22 @@ std::pair CConfig::configSetValueSafe(const std::string& com if (!valueName.starts_with(sc->name + ":")) continue; - if (!sc->isStatic && std::string{std::any_cast(sc->values[sc->key].getValue())} != impl->currentSpecialKey) - continue; + if (!sc->isStatic) { + const auto fieldName = valueName.substr(sc->name.length() + 1); + const auto existingKeyValue = std::string{std::any_cast(sc->values[sc->key].getValue())}; + + // When parsing the key field itself, match by the value being set. + // Otherwise, match by currentSpecialKey. + // This ensures multiple blocks with different key values create separate categories, + // and correctly handles empty string keys. + if (fieldName == sc->key) { + if (existingKeyValue != value) + continue; + } else { + if (existingKeyValue != impl->currentSpecialKey) + continue; + } + } VALUEIT = sc->values.find(valueName.substr(sc->name.length() + 1)); impl->currentSpecialCategory = sc.get(); diff --git a/tests/config/config.conf b/tests/config/config.conf index 096bf09..7658591 100644 --- a/tests/config/config.conf +++ b/tests/config/config.conf @@ -108,6 +108,12 @@ special[b] { value = 2 } +# Test empty key value - should create separate entry from "a" and "b" +special { + key = + value = 100 +} + specialGeneric { one { value = 1 diff --git a/tests/parse/main.cpp b/tests/parse/main.cpp index 309040d..c3b0ef4 100644 --- a/tests/parse/main.cpp +++ b/tests/parse/main.cpp @@ -353,6 +353,19 @@ int main(int argc, char** argv, char** envp) { // test listing keys EXPECT(config.listKeysForSpecialCategory("special")[1], "b"); + // test empty key value - should be a separate entry from "a" and "b" + const auto SPECIAL_KEYS = config.listKeysForSpecialCategory("special"); + EXPECT(SPECIAL_KEYS.size(), 3); + // Find and verify the empty key entry + auto emptyKeyIt = std::find(SPECIAL_KEYS.begin(), SPECIAL_KEYS.end(), ""); + if (emptyKeyIt == SPECIAL_KEYS.end()) { + std::cout << Colors::RED << "Failed: " << Colors::RESET << "empty key not found in listKeysForSpecialCategory\n"; + ret = 1; + } else { + std::cout << Colors::GREEN << "Passed " << Colors::RESET << "empty key found in listKeysForSpecialCategory\n"; + EXPECT(std::any_cast(config.getSpecialConfigValue("special", "value", "")), (Hyprlang::INT)100); + } + // test anonymous EXPECT(config.listKeysForSpecialCategory("specialAnonymous").size(), 2); const auto KEYS = config.listKeysForSpecialCategory("specialAnonymous");