Browse Source

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".
Emmanuel Lepage Vallee 3 months ago
parent
commit
b40083780e
2 changed files with 55 additions and 11 deletions
  1. 7
    1
      docs/common/rule.ldoc
  2. 48
    10
      lib/gears/matcher.lua

+ 7
- 1
docs/common/rule.ldoc View File

@@ -2,8 +2,6 @@
2 2
 
3 3
 --- A table which content will be used to set the target object properties.
4 4
 --
5
---
6 5
 -- @rulecomponent properties
7 6
 -- @param table
8 7
 -- @see callbacks
@@ -45,6 +43,13 @@
45 43
 -- @see rule
46 44
 -- @see except
47 45
 
46
+--- Matches when one of every "category" of components match.
47
+--
48
+-- @rulecomponent rule_every
49
+-- @param table
50
+-- @see rule
51
+-- @see except
52
+
48 53
 --- An identifier for this rule.
49 54
 --
50 55
 -- It can be anything. It will be compared with the `==` operator. Strings are

+ 48
- 10
lib/gears/matcher.lua View File

@@ -25,6 +25,8 @@
25 25
 --
26 26
 -- @DOC_text_gears_matcher_default_EXAMPLE@
27 27
 --
28
+-- @DOC_text_gears_matcher_types_EXAMPLE@
29
+--
28 30
 -- More examples are available in `awful.rules`.
29 31
 --
30 32
 -- @author Julien Danjou <julien@danjou.info>
@@ -101,29 +103,63 @@ function matcher:_match(o, rule)
101 103
     return true
102 104
 end
103 105
 
106
+local function field_matcher(self, o, field, value)
107
+    local pm = self._private.prop_matchers[field]
108
+
109
+    if pm and pm(o, value, field) then
110
+        return true
111
+    elseif o[field] == value then
112
+        return true
113
+    elseif type(o[field]) == "string" and o[field]:match(value) then
114
+        return true
115
+    end
116
+
117
+    return false
118
+end
119
+
104 120
 -- Check if an object matches any part of a rule.
105 121
 -- @param o The object.
122
+-- #tparam table rule The rule _match_anyto check.
106 123
 -- @treturn boolean True if at least one rule is matched, false otherwise.
107 124
 function matcher:_match_any(o, rule)
108 125
     if not rule then return false end
109 126
     for field, values in pairs(rule) do
110 127
         if o[field] then
111 128
             for _, value in ipairs(values) do
112
-                local pm = self._private.prop_matchers[field]
113
-                if pm and pm(o, value, field) then
114
-                    return true
115
-                elseif o[field] == value then
116
-                    return true
117
-                elseif type(o[field]) == "string" and o[field]:match(value) then
118
-                    return true
119
-                end
129
+                if field_matcher(self, o, field, value) then return true end
120 130
             end
121 131
         end
122 132
     end
133
+
123 134
     return false
124 135
 end
125 136
 
137
+-- Check if an object matches at least one of every part of a rule.
138
+--
139
+-- @param o The object.
140
+-- @tparam table rule The rule _match_anyto check.
141
+-- @tparam boolean multi If the entries are table of choices.
142
+-- @treturn boolean True if all rules are matched.
143
+function matcher:_match_every(o, rule)
144
+    if not rule then return true end
145
+
146
+    for field, values in pairs(rule) do
147
+        local found = false
148
+        for _, value in ipairs(values) do
149
+            if not field_matcher(self, o, field, value) then
150
+                found = true
151
+                break
152
+            end
153
+        end
154
+
155
+        if not found then
156
+            return false
157
+        end
158
+    end
159
+
160
+    return true
161
+end
162
+
126 163
 --- Does a given rule entry match an object?
127 164
 -- @param o The object.
128 165
 -- @tparam table entry Rule entry (with keys `rule`, `rule_any`, `except` and/or
@@ -133,8 +169,9 @@ end
133 169
 function matcher:matches_rule(o, entry)
134 170
     local match = self:_match(o, entry.rule) or self:_match_any(o, entry.rule_any)
135 171
     return match
136
-        and (not self:_match(o, entry.except))
137
-        and (not self:_match_any(o, entry.except_any))
172
+        and self:_match_every     (o, entry.rule_every)
173
+        and (not self:_match      (o, entry.except    ))
174
+        and (not self:_match_any  (o, entry.except_any))
138 175
 end
139 176
 
140 177
 --- Get list of matching rules for an object.

Loading…
Cancel
Save