matcher: Add a "every" and "every_any" sections to the rules.

So far the "any" rules had a "OR" and "NOT" logic "gates", but not
an "AND".
This commit is contained in:
Emmanuel Lepage Vallee 2019-07-21 22:05:45 -04:00
parent 3e4f292906
commit b40083780e
2 changed files with 55 additions and 13 deletions

View File

@ -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

View File

@ -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.