# Module: `gears.matcher`

A module to build a set of properties based on a graph of rules.

Sources =======

This module holds the business logic used by ruled.client. It provides an object on which one can add sets of rules or, alternatively, functions. In this module, the sets of rules or custom functions are called sources.

The sources are used to build a property table. Once all sources are evaluated, the `:apply()` method will set the properties on the target object.

Sources can have dependencies between them and the property table can only be built if the sources graph can be resolved.

Rules =====

The `rules` sources themselves are composed, as the name imply, of a set of rule. A rule is a table with a properties *or* `callbacks` attribute along with either rule or rule_any. It is also possible to add an except or except_any attribute to narrow the scope in which the rule is applied. Here's a basic example of a minimal gears.matcher.

**Usage example output**:

**Usage example:**

local o = { foo = "bar", answer = 42, } -- This rule will match local rule1 = { rule = { answer = 42, everything = true, }, properties = { name = "baz", }, } -- This rule will **not** match local rule2 = { -- When the rule properties are strings, the Lua --pattern matching is used. rule = { foo = "[f]+", }, properties = { name = "foobar", }, } local rules = { rule1, rule2, } local matcher = gears.matcher() local function first_source(self, object, props, callbacks) --luacheck: no unused args -- In this callback, you can add new elements to the props and -- callbacks tables. It is not recommended the modify object in -- this callback. if object.answer == 42 then props.is_everything = true end end -- This will add a custom function to add properties to the rules. matcher:add_matching_function("first", first_source, {}, {}) -- This will add the `rules` to this matcher. matcher:add_matching_rules("second", rules, {"first"}, {}) -- Some properties cannot be checked with the `==` operator (like those -- with multiple possible types). In that case, it is possible to define -- special comparator function. matcher:add_property_matcher("everything", function(obj, value) return value and obj.answer == 42 end) -- The same can be done for the property section. matcher:add_property_setter("multiply_by", function(obj, value) obj.answer = (obj.answer or 1) * value end) -- It is possible to append rules to existing (or new) sources. matcher:append_rule( "second", { id = "rule_with_id", rule = { has_elite = true, }, properties = { multiply_by = "1337", }, }) -- Or remove them. matcher:remove_rule("second", "rule_with_id") -- Apply the properties to `o` matcher:apply(o)

This example shows the different matching sections:

local matcher = gears.matcher() matcher:append_rule( "my.source", { rule = { my_any_rule = true, }, rule_every = { every1 = {1, 42}, every2 = {2, 42}, every3 = {3, 42}, }, except = { except1 = 1, }, properties = { was_a_match = true, }, }) local candidate1 = { my_any_rule = true, every1 = 1, every2 = 2, every3 = 3, was_a_match = false, } local candidate2 = { every2 = 2, was_a_match = false, } local candidate3 = { my_any_rule = true, was_a_match = false, every1 = 1, every2 = 2, every3 = 3, except1 = 1, } matcher:apply(candidate1) matcher:apply(candidate2) matcher:apply(candidate3) -- Only candidate1 fits all criteria. assert(candidate1.was_a_match == true ) assert(candidate2.was_a_match == false) assert(candidate3.was_a_match == false) -- It is also possible to match number property by range. matcher:append_rule( "my.source", { rule_greater = { value = 50, }, rule_lesser = { value = 100, }, properties = { was_a_match = true, }, }) local candidate4 = { value = 40 , was_a_match = false } local candidate5 = { value = 75 , was_a_match = false } local candidate6 = { value = 101, was_a_match = false } matcher:apply(candidate4) matcher:apply(candidate5) matcher:apply(candidate6) -- Only candidate5 fits all criteria. assert(candidate4.was_a_match == false) assert(candidate5.was_a_match == true ) assert(candidate6.was_a_match == false)

More examples are available in ruled.client.

### Info:

- Copyright: 2009 Julien Danjou
- Originally authored by: Julien Danjou <julien@danjou.info>
  (Full contributors list available on our github project)

### See also:

ruled.client

## Constructors

gears.matcher () | Create a new rule solver object. |

## Object methods

:matches_rule (o, entry) -> boolean | Does a given rule entry match an object? |
:matching_rules (o, rules) -> table | Get list of matching rules for an object. |
:matches_rules (o, rules) -> boolean | Check if an object matches a given set of rules. |
:add_property_matcher (name, f) | Assign a function to match an object property against a value. |
:add_property_setter (name, f) | Add a special setter for a property. |
:add_matching_rules (name, rules, depends_on, precede) -> boolean | Add a set of matching rules. |
:add_matching_function (name, callback, depends_on, precede) -> boolean | Add a matching function. |
:remove_matching_source (name) -> boolean | Remove a source. |
:apply (o) | Apply ruled.client.rules to an object. |
:append_rule (source, rule) | Add a new rule to the default set. |
:append_rules (source, rules) | Add a new rules to the default set. |
:remove_rule (source, rule) -> boolean | Remove a new rule from the default set. |
:emit_signal (name, ...) | Emit a signal. | Inherited from gears.object
:connect_signal (name, func) | Connect to a signal. | Inherited from gears.object
:weak_connect_signal (name, func) | Connect to a signal weakly. | Inherited from gears.object

## Signals

rule::appended | A rule has been added to a set of matching rules. |
rule::removed | A rule has been removed to a set of matching rules. |
matching_function::added | A matching source function has been added. |
matching_rules::added | A matching source table has been added. |
matching_source::removed | A matching source function has been removed. |

## Rule components

properties | table | A table whose content will be used to set the target object properties. |
callback | function | A callback function to call *before* the properties have been applied. |
rule | table | A table whose content will be compared to the target object current properties. |
rule_any | table | Similar to rule, but each entry is a table with multiple values. |
except | table | The negative equivalent of rule. |
except_any | table | The negative equivalent of rule_any. |
rule_every | table | Matches when one of every \"category\" of components match. |
rule_lesser | table | A table whose content will be compared to the target object current properties. |
rule_greater | table | A table whose content will be compared to the target object current properties. |
id | table or string or number or function | An identifier for this rule. |

## Constructors

🔗 gears.matcher ()
  Create a new rule solver object.

  ### Returns:

  A new rule solver object.

## Object methods

🔗 :matches_rule (o, entry) -> boolean
  Does a given rule entry match an object?

  ### Parameters:

  Name |  | Type(s) | Description
  --- | --- | --- | ---
  o |  |  | The object.
  entry |  | table | Rule entry (with keys rule, rule_any, except and/or except_any).

  ### Returns:

  boolean If `o` matches `entry`.
🔗 :matching_rules (o, rules) -> table
  Get list of matching rules for an object.

  If the `rules` argument is not provided, the rules added with add_matching_rules will be used.

  ### Parameters:

  Name |  | Type(s) | Description | Default value
  --- | --- | --- | --- | ---
  o |  |  | The object. | Not applicable
  rules | Optional | table | The rules to check. List with "rule", "rule_any", "except" and "except_any" keys. If no rules are provided, all rules registered with a source will be matched. | `nil`

  ### Returns:

  table The matching rules.
🔗 :matches_rules (o, rules) -> boolean
  Check if an object matches a given set of rules.

  ### Parameters:

  Name |  | Type(s) | Description
  --- | --- | --- | ---
  o |  |  | The object.
  rules |  | table | The rules to check. List of tables with rule, rule_any, except and except_any keys.

  ### Returns:

  boolean True if at least one rule is matched, false otherwise.
🔗 :add_property_matcher (name, f)
  Assign a function to match an object property against a value.

  The default matcher uses the `==` operator for all types. It also uses the `:match()` method for string and allows pattern matching. If the value is a function, then that function is called with the object and the current properties to be applied. If the function returns true, the match is accepted.

  Custom property matcher are useful when objects are compared. This avoids having to implement custom metatable for everything.

  The `f` function receives 3 arguments:

  * The object to match against (anything) * The value to compare * The property/field name.

  It should return `true` if it matches and `false` otherwise.

  ### Parameters:

  Name |  | Type(s) | Description
  --- | --- | --- | ---
  name |  | string | The property name.
  f |  | function | The matching function.

  ### Usage:

      -- Manually match the screen in various ways.
      matcher:add_property_matcher("screen", function(c, value)
         return c.screen == value
             or screen[c.screen] == value
             or c.screen.outputs[value] ~= nil
             or value == "any"
             or (value == "primary" and c.screen == screen.primary)
      end)

🔗 :add_property_setter (name, f)
  Add a special setter for a property.

  This is useful to add more properties to object which only make sense within the context of a rule.

  ### Parameters:

  Name |  | Type(s) | Description
  --- | --- | --- | ---
  name |  | string | The property name.
  f |  | function | The setter function.

🔗 :add_matching_rules (name, rules, depends_on, precede) -> boolean
  Add a set of matching rules.

  ### Parameters:

  Name |  | Type(s) | Description | Default value
  --- | --- | --- | --- | ---
  name |  | string | The provider name. It must be unique. | Not applicable
  rules |  | table | A set of rules (see how they work at the top of this page). | Not applicable
  depends_on | Optional | table | A list of names of sources this source depends on (sources that must be executed *before* `name`). | `{}`
  precede | Optional | table | A list of names of sources this source has a priority over. | `{}`

  ### Returns:

  boolean Returns false if a dependency conflict was found.
🔗 :add_matching_function (name, callback, depends_on, precede) -> boolean
  Add a matching function.

  ### Parameters:

  Name |  | Type(s) | Description | Default value
  --- | --- | --- | --- | ---
  name |  | string | The provider name. It must be unique. | Not applicable
  callback |  | table | The callback that is called to produce properties. | Not applicable
  self |  | gears.matcher | The matcher object. | Not applicable
  o |  |  | The object. | Not applicable
  properties |  | table | The current properties. The callback should add to and overwrite properties in this table. | Not applicable
  callbacks |  | table | A table of all callbacks scheduled to be executed after the main properties are applied. | Not applicable
  depends_on | Optional | table | A list of names of sources this source depends on (sources that must be executed *before* `name`). | `{}`
  precede | Optional | table | A list of names of sources this source has a priority over. | `{}`

  ### Returns:

  boolean Returns false if a dependency conflict was found.
🔗 :remove_matching_source (name) -> boolean
  Remove a source.

  This removes sources added with add_matching_function or add_matching_rules.

  ### Parameters:

  Name |  | Type(s) | Description
  --- | --- | --- | ---
  name |  | string | The source name.

  ### Returns:

  boolean If the source has been removed.
🔗 :apply (o)
  Apply ruled.client.rules to an object.

  Calling this will apply all properties provided by the matching functions and rules.

  ### Parameters:

  Name |  | Type(s) | Description
  --- | --- | --- | ---
  o |  |  | The object.

🔗 :append_rule (source, rule)
  Add a new rule to the default set.

  ### Parameters:

  Name |  | Type(s) | Description
  --- | --- | --- | ---
  source |  | string | The source name.
  rule |  | table | A valid rule.

🔗 :append_rules (source, rules)
  Add a new rules to the default set.

  ### Parameters:

  Name |  | Type(s) | Description
  --- | --- | --- | ---
  source |  | string | The source name.
  rules |  | table | A table with rules.

🔗 :remove_rule (source, rule) -> boolean
  Remove a new rule from the default set.

  ### Parameters:

  Name |  | Type(s) | Description
  --- | --- | --- | ---
  source |  | string | The source name.
  rule |  | string or table | An existing rule or its id.

  ### Returns:

  boolean If the rule was removed.
🔗 :emit_signal (name, ...) · Inherited from gears.object
  Emit a signal.

  ### Parameters:

  Name |  | Type(s) | Description
  --- | --- | --- | ---
  name |  | string | The name of the signal.
  ... |  |  | Extra arguments for the callback functions. Each connected function receives the object as first argument and then any extra arguments that are given to emit_signal().

🔗 :connect_signal (name, func) · Inherited from gears.object
  Connect to a signal.

  ### Parameters:

  Name |  | Type(s) | Description
  --- | --- | --- | ---
  name |  | string | The name of the signal.
  func |  | function | The callback to call when the signal is emitted.

🔗 :weak_connect_signal (name, func) · Inherited from gears.object
  Connect to a signal weakly.

  This allows the callback function to be garbage collected and automatically disconnects the signal when that happens.

  **Warning:** Only use this function if you really, really, really know what you are doing.

  ### Parameters:

  Name |  | Type(s) | Description
  --- | --- | --- | ---
  name |  | string | The name of the signal.
  func |  | function | The callback to call when the signal is emitted.

## Signals

🔗 rule::appended
  A rule has been added to a set of matching rules.

  ### Arguments:

  Name |  | Type(s) | Description
  --- | --- | --- | ---
  rule |  | table | The rule.
  source |  | table | The matching rules source name.
  content |  | table | The matching rules source content.

  ### See also:

  append_rule | Add a new rule to the default set. | object methods
  append_rules | Add a new rules to the default set. | object methods

🔗 rule::removed
  A rule has been removed to a set of matching rules.

  ### Arguments:

  Name |  | Type(s) | Description
  --- | --- | --- | ---
  rule |  | table | The rule.
  source |  | table | The matching rules source name.
  content |  | table | The matching rules source content.

  ### See also:

  remove_rule | Remove a new rule from the default set. | object methods

🔗 matching_function::added
  A matching source function has been added.

  ### Arguments:

  Name |  | Type(s) | Description
  --- | --- | --- | ---
  callback |  | function | The callback.

  ### See also:

  add_matching_function | Add a matching function. | object methods

🔗 matching_rules::added
  A matching source table has been added.

  ### Arguments:

  Name |  | Type(s) | Description
  --- | --- | --- | ---
  callback |  | function | The callback.

  ### See also:

  add_matching_rules | Add a set of matching rules. | object methods

🔗 matching_source::removed
  A matching source function has been removed.

  ### See also:

  remove_matching_source | Remove a source. | object methods

## Rule components

🔗 properties table
  A table whose content will be used to set the target object properties.

  ### See also:

  callback | A callback function to call *before* the properties have been applied. | rule components

🔗 callback function
  A callback function to call *before* the properties have been applied.

  The callback is called with the current client as first argument.

🔗 rule table
  A table whose content will be compared to the target object current properties.

  ### See also:

  rule_any | Similar to rule, but each entry is a table with multiple values. | rule components
  except | The negative equivalent of rule. | rule components

🔗 rule_any table
  Similar to rule, but each entry is a table with multiple values.

  ### See also:

  rule | A table whose content will be compared to the target object current properties. | rule components
  except_any | The negative equivalent of rule_any. | rule components

🔗 except table
  The negative equivalent of rule.

  ### See also:

  rule | A table whose content will be compared to the target object current properties. | rule components
  except_any | The negative equivalent of rule_any. | rule components

🔗 except_any table
  The negative equivalent of rule_any.

  ### See also:

  rule | A table whose content will be compared to the target object current properties. | rule components
  except | The negative equivalent of rule. | rule components

🔗 rule_every table
  Matches when one of every \"category\" of components match.

  ### See also:

  rule | A table whose content will be compared to the target object current properties. | rule components
  except | The negative equivalent of rule. | rule components

🔗 rule_lesser table
  A table whose content will be compared to the target object current properties.

  The comparison will be made using the lesser (`<`) operator.

  ### See also:

  rule | A table whose content will be compared to the target object current properties. | rule components
  except | The negative equivalent of rule. | rule components

🔗 rule_greater table
  A table whose content will be compared to the target object current properties.

  The comparison will be made using the greater (`>`) operator.

  ### See also:

  rule | A table whose content will be compared to the target object current properties. | rule components
  except | The negative equivalent of rule. | rule components

🔗 id table or string or number or function
  An identifier for this rule.

  It can be anything. It will be compared with the `==` operator. Strings are highly recommended.

  Setting an id is useful to be able to remove the rule by using its id instead of a table reference. Modules can also listen to rule::appended and modify or disable a rule.

generated by LDoc 1.5.0