awful.rules: fix typo in example
[awesome.git] / lib / awful / rules.lua.in
blob2c944756f0a54f377b71ccabad8c8a6a011b9df1
1 ---------------------------------------------------------------------------
2 -- @author Julien Danjou <julien@danjou.info>
3 -- @copyright 2009 Julien Danjou
4 -- @release @AWESOME_VERSION@
5 ---------------------------------------------------------------------------
7 -- Grab environment we need
8 local client = client
9 local table = table
10 local type = type
11 local ipairs = ipairs
12 local pairs = pairs
13 local aclient = require("awful.client")
14 local atag = require("awful.tag")
16 --- Apply rules to clients at startup.
17 module("awful.rules")
19 --- This is the global rules table.
20 -- <p>You should fill this table with your rule and properties to apply.
21 -- For example, if you want to set xterm maximized at startup, you can add:
22 -- <br/>
23 -- <code>
24 -- { rule = { class = "xterm" },
25 -- properties = { maximized_vertical = true, maximized_horizontal = true } }
26 -- </code>
27 -- </p>
28 -- <p>If you want to set mplayer floating at startup, you can add:
29 -- <br/>
30 -- <code>
31 -- { rule = { name = "MPlayer" },
32 -- properties = { floating = true } }
33 -- </code>
34 -- </p>
35 -- <p>If you want to put Firefox on a specific tag at startup, you
36 -- can add:
37 -- <br/>
38 -- <code>
39 -- { rule = { instance = "firefox" },
40 -- properties = { tag = mytagobject } }
41 -- </code>
42 -- </p>
43 -- <p>If you want to put Emacs on a specific tag at startup, and
44 -- immediately switch to that tag you can add:
45 -- <br/>
46 -- <code>
47 -- { rule = { class = "Emacs" },
48 -- properties = { tag = mytagobject, switchtotag = true } }
49 -- </code>
50 -- </p>
51 -- <p>If you want to apply a custom callback to execute when a rule matched, you
52 -- can add:
53 -- <br/>
54 -- <code>
55 -- { rule = { class = "dosbox" },
56 -- callback = awful.placement.centered }
57 -- </code>
58 -- </p>
59 -- <p>Note that all "rule" entries need to match. If any of the entry does not
60 -- match, the rule won't be applied.</p>
61 -- <p>If a client matches multiple rules, their applied in the order they are
62 -- put in this global rules table. If the value of a rule is a string, then the
63 -- match function is used to determine if the client matches the rule.</p>
65 -- <p> To match multiple clients to a rule one need to use slightly different
66 -- syntax:
67 -- <br/>
68 -- <code>
69 -- { rule_any = { class = { "MPlayer", "Nitrogen" }, instance = { "xterm" } },
70 -- properties = { floating = true } }
71 -- </code>
72 -- </p>
74 -- <p> To match multiple clients with an exception one can couple 'except' or
75 -- 'except_any' with the rules:
76 -- <br/>
77 -- <code>
78 -- { rule = { class = "Firefox" },
79 -- except = { instance = "Navigator" },
80 -- properties = {floating = true},
81 -- },
82 -- </code>
83 -- <br/>
84 -- <code>
85 -- { rule_any = { class = { "Pidgin", "Xchat" } },
86 -- except_any = { role = { "conversation" } },
87 -- properties = { tag = tags[1][1] }
88 -- }
89 -- <br/>
90 -- <code>
91 -- { rule = {},
92 -- except_any = { class = { "Firefox", "Vim" } },
93 -- properties = { floating = true }
94 -- }
95 -- </code>
96 -- </p>
98 -- @class table
99 -- @name rules
100 rules = {}
102 --- Check if a client match a rule.
103 -- @param c The client.
104 -- @param rule The rule to check.
105 -- @return True if it matches, false otherwise.
106 function match(c, rule)
107 if not rule then return false end
108 for field, value in pairs(rule) do
109 if c[field] then
110 if type(c[field]) == "string" then
111 if not c[field]:match(value) and c[field] ~= value then
112 return false
114 elseif c[field] ~= value then
115 return false
117 else
118 return false
121 return true
124 --- Check if a client match a rule. Multiple clients can be matched
125 -- @param c The client.
126 -- @param rules The rule to check.
127 -- @return True if at least one rule is matched, false otherwise.
128 function match_any(c, rule)
129 if not rule then return false end
130 for field, values in pairs(rule) do
131 if c[field] then
132 for _, value in ipairs(values) do
133 if c[field] == value then
134 return true
135 elseif type(c[field]) == "string" and c[field]:match(value) then
136 return true
141 return false
144 --- Apply rules to a client.
145 -- @param c The client.
146 function apply(c)
147 local props = {}
148 local callbacks = {}
149 for _, entry in ipairs(rules) do
150 if (match(c, entry.rule) or match_any(c, entry.rule_any)) and
151 (not match(c, entry.except) and not match_any(c, entry.except_any)) then
152 if entry.properties then
153 for property, value in pairs(entry.properties) do
154 props[property] = value
157 if entry.callback then
158 table.insert(callbacks, entry.callback)
163 for property, value in pairs(props) do
164 if property == "floating" then
165 aclient.floating.set(c, value)
166 elseif property == "tag" then
167 c:tags({ value })
168 c.screen = value.screen
169 elseif property == "switchtotag" and value and props.tag then
170 atag.viewonly(props.tag)
171 elseif property == "height" or property == "width" or
172 property == "x" or property == "y" then
173 local geo = c:geometry();
174 geo[property] = value
175 c:geometry(geo);
176 elseif type(c[property]) == "function" then
177 c[property](c, value)
178 else
179 c[property] = value
183 -- If untagged, stick the client on the current one.
184 if #c:tags() == 0 then
185 atag.withcurrent(c)
188 -- Apply all callbacks from matched rules.
189 for i, callback in pairs(callbacks) do
190 callback(c)
193 -- Do this at last so we do not erase things done by the focus
194 -- signal.
195 if props.focus then
196 client.focus = c
200 client.add_signal("manage", apply)
201 client.remove_signal("manage", atag.withcurrent)
203 -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80