From 005c2d61a0372be7cba06837e21d3fc5e3fb9eff Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Thu, 21 Oct 2021 15:16:38 -0700 Subject: [PATCH 1/3] gears.matcher: Fix `rule_every`. It really didn't do the right thing and didn't work anyway. --- lib/gears/matcher.lua | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/gears/matcher.lua b/lib/gears/matcher.lua index c7a66ca2a..6f78b73e1 100644 --- a/lib/gears/matcher.lua +++ b/lib/gears/matcher.lua @@ -133,7 +133,7 @@ end -- Check if an object matches any part of a rule. -- @param o The object. --- #tparam table rule The rule _match_anyto check. +-- @tparam table rule The rule to check. -- @treturn boolean True if at least one rule is matched, false otherwise. -- @method _match_any function matcher:_match_any(o, rule) @@ -146,6 +146,7 @@ function matcher:_match_any(o, rule) return true end + for _, value in ipairs(values) do if field_matcher(self, o, field, value) then return true @@ -160,7 +161,7 @@ end -- Check if an object matches at least one of every part of a rule. -- -- @param o The object. --- @tparam table rule The rule _match_anyto check. +-- @tparam table rule The rule to check. -- @tparam boolean multi If the entries are table of choices. -- @treturn boolean True if all rules are matched. -- @method _match_every @@ -170,7 +171,7 @@ function matcher:_match_every(o, rule) for field, values in pairs(rule) do local found = false for _, value in ipairs(values) do - if not field_matcher(self, o, field, value) then + if field_matcher(self, o, field, value) then found = true break end From 9db62b824ca9858034bd89e0617cdf0364eb387a Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Fri, 22 Oct 2021 15:25:01 -0700 Subject: [PATCH 2/3] gears.matcher: Add `fallback` rules. Right now, all rules are additive, they are squashed into one big array of properties. This is normally fine, but sometime you want explicit rules for some objects, but also default rules if nothing matches. While this can be expressed in the current system by overriding *all* properties, this require more effort than having "special" and "fallback" rules. --- lib/gears/matcher.lua | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/gears/matcher.lua b/lib/gears/matcher.lua index 6f78b73e1..d024a2134 100644 --- a/lib/gears/matcher.lua +++ b/lib/gears/matcher.lua @@ -324,7 +324,20 @@ function matcher:add_property_setter(name, f) end local function default_rules_callback(self, o, props, callbacks, rules) - for _, entry in ipairs(self:matching_rules(o, rules)) do + -- Get all matching rules. + local matches = self:matching_rules(o, rules) + + -- Split the main ones from the fallback ones. + local main, fallback = {}, {} + + for _, match in ipairs(matches) do + table.insert(match.fallback and fallback or main, match) + end + + -- Select which set to use. + matches = #main > 0 and main or fallback + + for _, entry in ipairs(matches) do gtable.crush(props, entry.properties or {}) if entry.callback then From ffb95eec8d5b26cd030b6f3b0ba078c3967e40f8 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Fri, 22 Oct 2021 23:01:06 -0700 Subject: [PATCH 3/3] tests: Improve gears.matcher tests. --- spec/gears/matcher_spec.lua | 93 +++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/spec/gears/matcher_spec.lua b/spec/gears/matcher_spec.lua index 01969ec01..4b59be4e9 100644 --- a/spec/gears/matcher_spec.lua +++ b/spec/gears/matcher_spec.lua @@ -41,6 +41,99 @@ describe("gears.matcher", function() assert.is_false(matcher_instance:_match(test_obj, rule)) end) + describe("match_any positive", function() + local rule = { + foo={''}, + spam={''}, + } + assert.is_true(matcher_instance:_match_any(test_obj, rule)) + end) + + describe("match_any negative", function() + local rule = { + foo={''}, + spam={'bar'}, + } + assert.is_false(matcher_instance:_match_any(test_obj, rule)) + end) + + describe("match_every full negative", function() + local rule = { + foo={''}, + spam={'bar'}, + } + assert.is_false(matcher_instance:_match_every(test_obj, rule)) + end) + + describe("match_every partial negative", function() + local rule = { + foo={''}, + spam={''}, + } + assert.is_false(matcher_instance:_match_every(test_obj, rule)) + end) + + describe("match_every positive", function() + local rule = { + foo={'bar'}, + spam={''}, + } + assert.is_true(matcher_instance:_match_every(test_obj, rule)) + end) + + describe("check main vs. fallback rules", function() + local m = matcher() + + local rules = { + { + id = "main", + fallback = false, + rule = { + foo = "bar" + }, + properties = { + main_applied = true, + } + }, + { + id = "fallback", + fallback = true, + rule = { + everything = 42 + }, + properties = { + fallback_applied = true, + } + }, + } + + m:append_rules("default", rules) + + -- Matches `main` and `fallback` + local obj1 = { + foo = "bar", + everything = 42, + } + + -- Only matches `fallback`. + local obj2 = { + foo = "baz", + everything = 42, + } + + m:apply(obj1) + m:apply(obj2) + + assert.is_true(m:_match(obj1, rules[1]["rule"])) + assert.is_true(m:_match(obj1, rules[2]["rule"])) + assert.is_true(m:_match(obj2, rules[2]["rule"])) + assert.is_false(m:_match(obj2, rules[1]["rule"])) + + assert.is_true(obj1.main_applied) + assert.is_true(obj2.fallback_applied) + assert.is_nil(obj2.main_applied) + assert.is_nil(obj1.fallback_applied) + end) end) -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80