mirror of
https://github.com/hyprwm/hyprlang.git
synced 2026-05-05 23:48:00 +02:00
core/parser: correctly match keyed special categories by value being set (#89)
When parsing multiple special category blocks with different key values,
the second block would incorrectly overwrite the first instead of creating
a separate category entry.
Root cause:
When parsing a block like:
wallpaper {
monitor =
path = /path/image.png
}
wallpaper {
monitor = DP-1
path = /path/image.png
}
1. After closing the first block, `currentSpecialKey` resets to ""
2. When parsing `monitor = DP-1` in the second block, the code looks
for an existing category where key value == currentSpecialKey ("")
3. The first category's key value IS "", so it matches incorrectly
4. The second block overwrites the first, leaving only one category
The fix:
When looking for an existing category to reuse, check what field we're
parsing:
- If parsing the KEY field itself, match by the VALUE being set
- If parsing other fields, match by currentSpecialKey (existing behavior)
This ensures `monitor = DP-1` looks for a category with `monitor == "DP-1"`,
not `monitor == ""`, allowing empty string keys to work correctly alongside
non-empty keys.
This bug affects any hyprlang consumer using keyed special categories where
empty string is a valid key value (e.g., hyprpaper's wallpaper category
with `monitor =` for default/wildcard).
This commit is contained in:
parent
0d00dc1189
commit
0567ba7607
3 changed files with 35 additions and 2 deletions
|
|
@ -361,8 +361,22 @@ std::pair<bool, CParseResult> CConfig::configSetValueSafe(const std::string& com
|
|||
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;
|
||||
if (!sc->isStatic) {
|
||||
const auto fieldName = valueName.substr(sc->name.length() + 1);
|
||||
const auto existingKeyValue = std::string{std::any_cast<const char*>(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();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<int64_t>(config.getSpecialConfigValue("special", "value", "")), (Hyprlang::INT)100);
|
||||
}
|
||||
|
||||
// test anonymous
|
||||
EXPECT(config.listKeysForSpecialCategory("specialAnonymous").size(), 2);
|
||||
const auto KEYS = config.listKeysForSpecialCategory("specialAnonymous");
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue