import all my dotfiles, awesome included.
[~madcoder/dotfiles.git] / config / awesome / rc.lua
1 -- awesome 3 configuration file
2
3 -- Include awesome library, with lots of useful function!
4 require("awful")
5 require("eminent")
6 require("wicked")
7 require("beautiful")
8
9 function table.append(t, ...)
10     for _, v in ipairs({...}) do
11         table.insert(t, v)
12     end
13 end
14
15 terminal = "x-terminal-emulator"
16 lock     = 'xscreensaver-command -lock'
17 beautiful.init(awful.util.getdir("config").."/theme")
18
19 -- {{{ Modkeys
20 modkey = "Mod4"
21 shift = "Shift"
22 alt = "Mod1"
23 control = "Control"
24
25 k_n  = {}
26 k_m  = {modkey}
27 k_ms = {modkey, shift}
28 k_ma = {modkey, alt}
29 k_mc = {modkey, control}
30 k_a  = {alt}
31 k_ac = {alt, control}
32 k_c  = {control}
33 k_cs = {control, shift}
34 k_s = {shift}
35
36 -- }}}
37
38 -- {{{ Markup helper functions
39 -- Inline markup is a tad ugly, so use these functions
40 -- to dynamically create markup.
41 function fg(color, text)
42     return '<span color="'..color..'">'..text..'</span>'
43 end
44
45 function heading(text)
46     return fg(beautiful.fg_focus, text)
47 end
48
49 -- }}}
50 -- {{{ Functions
51 -- Toggle whether we're viewing a tag
52 function tag_toggleview(tag)
53     tag:view(not tag:isselected())
54 end
55
56 -- Get the screen number we're on
57 function getscreen()
58     local sel = client.focus
59     return (sel and sel.screen) or mouse.screen
60 end
61
62 -- Move current client to a specific screen
63 function client_movetoscreen(i)
64     client.focus.screen = i
65 end
66
67 -- }}}
68 -- {{{ Set tag names
69
70 for s = 1, screen.count() do
71     eminent.newtag(s, 5)
72     for i = 1, 10 do
73         eminent.tag.name(i, s, 'work-'..i)
74     end
75 end
76
77 -- }}}
78 -- {{{ Taglist
79
80 maintaglist = {}
81 maintaglist.buttons = {
82     button(k_n, 1, awful.tag.viewonly),
83     button(k_s, 1, awful.client.toggletag)
84 }
85
86 -- }}}
87 -- {{{ Widgets
88
89 -- {{{ Load Averages Widget
90
91 loadwidget = widget({
92     type = 'textbox',
93     name = 'gpuwidget',
94     align = 'right'
95 })
96
97 wicked.register(loadwidget, 'function', function (widget, args)
98     -- Use /proc/loadavg to get the average system load on 1, 5 and 15 minute intervals
99     local f = io.open('/proc/loadavg')
100     local n = f:read()
101     f:close()
102
103     -- Find the third space
104     local pos = n:find(' ', n:find(' ', n:find(' ')+1)+1)
105
106     return heading('Load')..': '..n:sub(1,pos-1)
107
108 end, 2)
109
110 -- }}}
111 -- {{{ CPU Usage Widget
112
113 cputextwidget = widget({
114     type = 'textbox',
115     name = 'cputextwidget',
116     align = 'right'
117 })
118
119 cputextwidget.text = heading('CPU')..': 00% '
120 wicked.register(cputextwidget, 'cpu', function (widget, args)
121     local r = tonumber(args[1])
122     local percent = args[1]..'%'
123     if r < 10 then
124         percent = '0'..percent
125     end
126     if r < 25 then
127         percent = fg('green', percent)
128     elseif r < 50 then
129         percent = fg('yellow', percent)
130     elseif r < 75 then
131         percent = fg('orange', percent)
132     else
133         percent = fg('red', percent)
134     end
135     return heading('CPU')..': '..percent..' '
136 end, 2)
137
138 -- }}}
139 -- {{{ CPU Graph Widget
140
141 cpugraphwidget = widget({
142     type = 'graph',
143     name = 'cpugraphwidget',
144     align = 'right'
145 })
146
147 cpugraphwidget.height = 0.85
148 cpugraphwidget.width = 45
149 cpugraphwidget.bg = '#333333'
150 cpugraphwidget.border_color = '#0a0a0a'
151 cpugraphwidget.grow = 'right'
152
153 cpugraphwidget:plot_properties_set('cpu', {
154     fg = '#AEC6D8',
155     fg_center = '#285577',
156     fg_end = '#285577',
157     vertical_gradient = false
158 })
159
160 wicked.register(cpugraphwidget, 'cpu', '$1', 2, 'cpu')
161
162 -- }}}
163 -- {{{ Memory Usage Widget
164
165 memtextwidget = widget({
166     type = 'textbox',
167     name = 'memtextwidget',
168     align = 'right'
169 })
170
171 memtextwidget.text = heading('MEM')..': '
172 wicked.register(memtextwidget, 'mem', function (widget, args)
173     -- Add extra preceding zeroes when needed
174     local r = tonumber(args[1])
175     local percent = args[1]..'%'
176     if r < 10 then
177         percent = '0'..percent
178     end
179     if r < 50 then
180         percent = fg('green', percent)
181     elseif r < 80 then
182         percent = fg('orange', percent)
183     else
184         percent = fg('red', percent)
185     end
186     return heading('MEM')..': '..percent..' '..args[2]..'M'
187 end, 2)
188
189 -- }}}
190 -- {{{ Battery widget
191 --[[
192 batterywidget = widget({
193     type = 'textbox',
194     name = 'batterywidget',
195     align = 'right'
196 })
197
198 function batterywidget_update()
199     local v = io.popen("powersave -b|sed -ne 's/.*Remaining percent: \\(.*\\)/\\1/p'"):read()
200     local r = tonumber(v)
201
202     percent = v
203     if r < 10 then
204         percent = fg('red', percent)
205     elseif r < 25 then
206         percent = fg('orange', percent)
207     else
208         percent = fg('green', percent)
209     end
210     batterywidget.text = heading('BAT')..': '..percent
211 end
212 batterywidget_update()
213 awful.hooks.timer.register(30, batterywidget_update)
214 --]]
215 -- }}}
216 -- {{{ spacers
217
218 rspacer = widget({ type = 'textbox', name = 'rspacer', align = 'right' })
219 rspacer.text = " │ "
220
221 -- }}}
222 -- {{{ Clock
223 clockwidget = widget({ type = "textbox", name = "clockwidget", align = "right" })
224 clock_update = function()
225     clockwidget.text = fg("#dddddd", os.date("%a %d %b - %H:%M"))
226 end
227 clock_update()
228 awful.hooks.timer.register(10, clock_update)
229
230 -- }}}
231
232 mymenubox = widget{ type = "textbox", name = "mytextbox", align = "left" }
233 mysystray = widget{ type = "systray", name = "mysystray", align = "right" }
234
235 -- {{{ Statusbar
236
237 mainstatusbar = {}
238
239 for s = 1, screen.count() do
240     mainstatusbar[s] = wibox{
241         position = "top",
242         height = 18,
243         name = "mainstatusbar" .. s,
244     }
245
246     mainstatusbar[s].widgets = {
247         awful.widget.taglist.new(s, awful.widget.taglist.label.noempty, maintaglist.buttons),
248         maintaglist,
249         mymenubox,
250
251         rspacer, loadwidget,
252         rspacer, cputextwidget, cpugraphwidget,
253         rspacer, memtextwidget,
254         rspacer, clockwidget,
255         s == 1 and rspacer or nil,
256         s == 1 and mysystray or nil,
257     }
258     mainstatusbar[s].screen = s
259 end
260
261 -- }}}
262 -- }}}
263
264 -- {{{ Keys
265 ---- {{{ Global keys
266
267 local hist = os.getenv("HOME") .. "/.cache/awesome/history"
268 globalkeys = {
269     -- Mod+{A/S}: Switch to prev/next tag
270     key(k_m, "Left",  eminent.tag.prev),
271     key(k_m, "Right", eminent.tag.next),
272
273     -- Mod+Shift+{A/S}: Move window to Prev/Next tag
274     key(k_ms, "Left", function()
275         awful.client.movetotag(eminent.tag.getprev())
276         eminent.tag.prev()
277     end),
278     key(k_ms, "Right", function()
279         awful.client.movetotag(eminent.tag.getnext())
280         eminent.tag.next()
281     end),
282
283     -- Mod+Shift_{E/D}: move window to next/prev screen
284     key(k_mc, "Right", function()
285        local s = getscreen() + 1
286        while s > screen.count() do
287            s = s-screen.count()
288        end
289        client_movetoscreen(s)
290     end),
291     key(k_mc, "Left", function()
292        local s = getscreen() - 1
293        while s < 1 do
294            s = s+screen.count()
295        end
296        client_movetoscreen(s)
297     end),
298
299
300     -- Focus Prev/Next window
301     key(k_m, "j",
302         function ()
303             awful.client.focus.byidx(1)
304             if client.focus then client.focus:raise() end
305         end),
306     key(k_m, "k",
307         function ()
308             awful.client.focus.byidx(-1)
309             if client.focus then client.focus:raise() end
310         end),
311
312     -- Swap window with the Prev/Next one
313     key(k_ms, "j", function () awful.client.swap.byidx(1) end),
314     key(k_ms, "k", function () awful.client.swap.byidx(-1) end),
315
316     -- Mod+{E/D}: Switch to next/previous screen
317     key(k_m, "Tab",  function () awful.screen.focus(1) end),
318     key(k_ms, "Tab", function () awful.screen.focus(-1) end),
319
320     -- Mod+Enter: Launch a new terminal
321     key(k_m,  "Return", function() awful.util.spawn(terminal) end),
322     key(k_ac, "Delete", awesome.restart),
323     key(k_m, "F12", function() awful.util.spawn(lock) end),
324
325     -- Layout manipulation
326     key(k_m,  "l", function () awful.tag.incmwfact(0.05) end),
327     key(k_m,  "h", function () awful.tag.incmwfact(-0.05) end),
328     key(k_ms, "h", function () awful.tag.incnmaster(1) end),
329     key(k_ms, "l", function () awful.tag.incnmaster(-1) end),
330     key(k_mc, "h", function () awful.tag.incncol(1) end),
331     key(k_mc, "l", function () awful.tag.incncol(-1) end),
332
333     -- Menu
334     key(k_m, "r",
335         function ()
336             awful.prompt.run({ prompt = "Run: " },
337                              mymenubox,
338                              awful.util.spawn,
339                              awful.completion.bash,
340                              awful.util.getdir("cache").."/commands")
341         end),
342     key(k_m, "F4",
343         function ()
344             awful.prompt.run({ prompt = "Run Lua code: " },
345                              mymenubox,
346                              awful.util.eval,
347                              awful.prompt.bash,
348                              awful.util.getdir("cache").."/lua_commands")
349     end),
350 }
351
352 -- Mod+#: Switch to tag
353 -- Mod+Shift+#: Toggle tag display
354 -- Mod+Control+#: Move client to tag
355 -- Mod+Alt+#: Toggle client on tag
356
357 for i = 1, 10 do
358     table.append(globalkeys,
359                  key(k_m, i % 10,
360                      function()
361                          eminent.tag.goto(i, nil, true)
362                      end),
363
364                  key(k_ms, i % 10,
365                      function ()
366                          local t = eminent.tag.getn(i, nil, true)
367                          if t ~= nil then t.selected = not t.selected end
368                      end),
369                  key(k_mc, i % 10,
370                      function ()
371                          local t = eminent.tag.getn(i, nil, true)
372                          if t ~= nil then awful.client.movetotag(t) end
373                      end)
374                  )
375 end
376
377 ---- }}}
378 ---- {{{ Client hotkeys
379
380 clientkeys = {
381     key(k_m, "i", function (c)
382         if mymenubox.text then
383             mymenubox.text = ""
384         else
385             mymenubox.text = "Class: " .. c.class .. " Instance: ".. c.instance
386         end
387     end),
388
389     -- Client manipulation
390     key(k_m, "c", function (c) c:kill() end),
391     key(k_m, "o", awful.client.floating.toggle),
392     key(k_m, "t", awful.client.togglemarked),
393     key(k_m, "F11", function (c) c.fullscreen = not c.fullscreen end)
394 }
395
396 ---- }}}
397
398 root.keys(globalkeys)
399 -- }}}
400 -- {{{ Hooks
401
402 awful.hooks.focus.register(function (c)
403     if not awful.client.ismarked(c) then
404         c.border_color = beautiful.border_focus
405     end
406 end)
407
408 awful.hooks.unfocus.register(function (c)
409     if not awful.client.ismarked(c) then
410         c.border_color = beautiful.border_normal
411     end
412 end)
413
414 awful.hooks.marked.register(function (c)
415     c.border_color = beautiful.border_marked
416 end)
417
418 awful.hooks.unmarked.register(function (c)
419     c.border_color = beautiful.border_focus
420 end)
421
422 -- Hook function to execute when the mouse enters a client.
423 awful.hooks.mouse_enter.register(function (c)
424     -- Sloppy focus
425     client.focus = c
426 end)
427
428 awful.hooks.manage.register(function (c, startup)
429     if not startup and awful.client.focus.filter(c) then
430         c.screen = mouse.screen
431     end
432
433     -- Add mouse bindings
434     c:buttons{
435         button({ }, 1, function (c) client.focus = c; c:raise() end),
436         button(k_a, 1, awful.mouse.client.move),
437         button(k_a, 3, awful.mouse.client.resize)
438     }
439
440     -- Create border
441     c.border_width = beautiful.border_width
442     c.border_color = beautiful.border_normal
443
444     -- Make certain windows floating
445     local name = c.name:lower()
446     if name:find('pinentry')
447     then
448         c.floating = true
449     end
450
451     -- Focus new clients
452     client.focus = c
453     c:keys(clientkeys)
454     c.size_hints_honor = false
455 end)
456
457 -- Hook function to execute when arranging the screen
458 -- (tag switch, new client, etc)
459 awful.hooks.arrange.register(function (screen)
460     local sel = client.focus
461     if not sel then
462         sel = awful.client.focus.history.get(screen, 0)
463         if sel then client.focus = sel end
464     end
465     --[[
466     if sel then
467         local m_c = mouse.coords()
468
469         if m_c.x < sel.x - 1 or m_c.x > sel.x + sel.width + 1 or
470             m_c.y < sel.y - 1 or m_c.y > sel.y + sel.height + 1 then
471             if #m_c.buttons == 0 then
472                 mouse.coords{x = sel.x + 5, y = sel.y + 5}
473             end
474         end
475     end
476     ]]--
477 end)
478
479 -- }}}