diff --git a/docs/common/rule.ldoc b/docs/common/rule.ldoc index 776e50bd3..ec0fa7a54 100644 --- a/docs/common/rule.ldoc +++ b/docs/common/rule.ldoc @@ -2,8 +2,6 @@ --- A table which content will be used to set the target object properties. -- --- foo --- -- @rulecomponent properties -- @param table -- @see callbacks @@ -45,6 +43,13 @@ -- @see rule -- @see except +--- Matches when one of every "category" of components match. +-- +-- @rulecomponent rule_every +-- @param table +-- @see rule +-- @see except + --- An identifier for this rule. -- -- It can be anything. It will be compared with the `==` operator. Strings are diff --git a/lib/gears/matcher.lua b/lib/gears/matcher.lua index 036da00a0..9929eaa69 100644 --- a/lib/gears/matcher.lua +++ b/lib/gears/matcher.lua @@ -25,6 +25,8 @@ -- -- @DOC_text_gears_matcher_default_EXAMPLE@ -- +-- @DOC_text_gears_matcher_types_EXAMPLE@ +-- -- More examples are available in `awful.rules`. -- -- @author Julien Danjou <julien@danjou.info> @@ -101,29 +103,63 @@ function matcher:_match(o, rule) return true end +local function field_matcher(self, o, field, value) + local pm = self._private.prop_matchers[field] + + if pm and pm(o, value, field) then + return true + elseif o[field] == value then + return true + elseif type(o[field]) == "string" and o[field]:match(value) then + return true + end + + return false +end + -- Check if an object matches any part of a rule. -- @param o The object. --- #tparam table rule The rule to check. +-- #tparam table rule The rule _match_anyto check. -- @treturn boolean True if at least one rule is matched, false otherwise. function matcher:_match_any(o, rule) if not rule then return false end for field, values in pairs(rule) do if o[field] then for _, value in ipairs(values) do - local pm = self._private.prop_matchers[field] - if pm and pm(o, value, field) then - return true - elseif o[field] == value then - return true - elseif type(o[field]) == "string" and o[field]:match(value) then - return true - end + if field_matcher(self, o, field, value) then return true end end end end + return false 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 boolean multi If the entries are table of choices. +-- @treturn boolean True if all rules are matched. +function matcher:_match_every(o, rule) + if not rule then return true end + + 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 + found = true + break + end + end + + if not found then + return false + end + end + + return true +end + --- Does a given rule entry match an object? -- @param o The object. -- @tparam table entry Rule entry (with keys `rule`, `rule_any`, `except` and/or @@ -133,8 +169,9 @@ end function matcher:matches_rule(o, entry) local match = self:_match(o, entry.rule) or self:_match_any(o, entry.rule_any) return match - and (not self:_match(o, entry.except)) - and (not self:_match_any(o, entry.except_any)) + and self:_match_every (o, entry.rule_every) + and (not self:_match (o, entry.except )) + and (not self:_match_any (o, entry.except_any)) end --- Get list of matching rules for an object.