]> git.madduck.net Git - etc/awesome.git/blob - .config/awesome/rc.lua

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

new keybinding syntax
[etc/awesome.git] / .config / awesome / rc.lua
1 -- Standard awesome library
2 require("awful")
3 require("beautiful")
4 require("naughty")
5
6 -- Load Debian menu entries
7 require("debian.menu")
8
9 -- {{{ Variable definitions
10 -- Themes define colours, icons, and wallpapers
11 -- The default is a dark theme
12 theme_path = "/usr/share/awesome/themes/default/theme"
13 -- Uncommment this for a lighter theme
14 -- theme_path = "/usr/share/awesome/themes/sky/theme"
15
16 -- Actually load theme
17 beautiful.init(theme_path)
18
19 -- This is used later as the default terminal and editor to run.
20 terminal = "x-terminal-emulator"
21 editor = os.getenv("EDITOR") or "editor"
22 editor_cmd = terminal .. " -e " .. editor
23
24 -- Default modkey.
25 -- Usually, Mod4 is the key with a logo between Control and Alt.
26 -- If you do not like this or do not have such a key,
27 -- I suggest you to remap Mod4 to another key using xmodmap or other tools.
28 -- However, you can use another modifier like Mod1, but it may interact with others.
29 modkey = "Mod4"
30
31 -- Table of layouts to cover with awful.layout.inc, order matters.
32 layouts =
33 {
34     awful.layout.suit.tile,
35     awful.layout.suit.tile.left,
36     awful.layout.suit.tile.bottom,
37     awful.layout.suit.tile.top,
38     awful.layout.suit.fair,
39     awful.layout.suit.fair.horizontal,
40     awful.layout.suit.max,
41     awful.layout.suit.max.fullscreen,
42     awful.layout.suit.magnifier,
43     awful.layout.suit.floating
44 }
45
46 -- Table of clients that should be set floating. The index may be either
47 -- the application class or instance. The instance is useful when running
48 -- a console app in a terminal like (Music on Console)
49 --    xterm -name mocp -e mocp
50 -- OVERRULED BY TILEDAPPS BELOW
51 floatapps =
52 {
53     -- by class
54     ["MPlayer"] = true,
55     ["pinentry"] = true,
56     ["GIMP"] = true,
57     ["twinkle"] = true,
58     ["Add-ons"] = true,
59     ["Play stream"] = true,
60 }
61
62 -- Applications that should never float, assuming everything else floats
63 -- (by instance)
64 tiledapps =
65 {
66     ["urxvt"] = true,
67 }
68
69 -- Applications that should be maximised
70 -- (by instance)
71 maxapps =
72 {
73     ["Navigator"] = true,
74     -- jpilot is -v
75     ["-v"] = true,
76     ["Xpdf"] = true,
77     ["gscan2pdf"] = true
78 }
79
80 -- Applications to be moved to a pre-defined tag by class or instance.
81 -- Use the screen and tags indices.
82 apptags =
83 {
84     ["Navigator"] = { screen = 1, tag = 9 },
85     -- jpilot is -v
86     ["-v"] = { screen = 1, tag = 8 },
87 }
88
89 -- Define if we want to use titlebar on all applications.
90 use_titlebar = false
91 -- }}}
92
93 -- {{{ Tags
94 -- Define tags table.
95 tags = {}
96 for s = 1, screen.count() do
97     -- Each screen has its own tag table.
98     tags[s] = {}
99     -- Create 9 tags per screen.
100     for tagnumber = 1, 9 do
101         tags[s][tagnumber] = tag(tagnumber)
102         -- Add tags to screen one by one
103         -- split at 0.5/50% exactly
104         -- tags[s][tagnumber].mwfact = 0.5
105         tags[s][tagnumber].screen = s
106         awful.layout.set(layouts[5], tags[s][tagnumber])
107     end
108     -- I'm sure you want to see at least one tag.
109     tags[s][1].selected = true
110 end
111 -- }}}
112
113 -- {{{ Wibox
114 -- Create a textbox widget
115 mytextbox = widget({ type = "textbox", align = "right" })
116 -- Set the default text in textbox
117 mytextbox.text = "<b><small> " .. AWESOME_RELEASE .. " </small></b>"
118
119 -- Create a laucher widget and a main menu
120 myawesomemenu = {
121    { "manual", terminal .. " -e man awesome" },
122    { "edit config", editor_cmd .. " " .. awful.util.getdir("config") .. "/rc.lua" },
123    { "restart", awesome.restart },
124    { "quit", awesome.quit }
125 }
126
127 mymainmenu = awful.menu.new({ items = { { "awesome", myawesomemenu, beautiful.awesome_icon },
128                                         { "open terminal", terminal },
129                                         { "Debian", debian.menu.Debian_menu.Debian }
130                                       }
131                             })
132
133 mylauncher = awful.widget.launcher({ image = image(beautiful.awesome_icon),
134                                      menu = mymainmenu })
135
136 -- Create a systray
137 mysystray = widget({ type = "systray", align = "right" })
138
139 -- Create textbox widgets
140 mytimebox = widget({ type = "textbox", name = "mytimebox", align = "right" })
141 mybatterybox = widget({ type = "textbox", name = "mybatterybox", align = "right" })
142
143 -- Create a wibox for each screen and add it
144 mywibox = {}
145 mypromptbox = {}
146 mylayoutbox = {}
147 mytaglist = {}
148 mytaglist.buttons = { button({ }, 1, awful.tag.viewonly),
149                       button({ modkey }, 1, awful.client.movetotag),
150                       button({ }, 3, function (tag) tag.selected = not tag.selected end),
151                       button({ modkey }, 3, awful.client.toggletag),
152                       button({ }, 4, awful.tag.viewnext),
153                       button({ }, 5, awful.tag.viewprev) }
154 mytasklist = {}
155 mytasklist.buttons = { button({ }, 1, function (c)
156                                           if not c:isvisible() then
157                                               awful.tag.viewonly(c:tags()[1])
158                                           end
159                                           client.focus = c
160                                           c:raise()
161                                       end),
162                        button({ }, 3, function () if instance then instance:hide() end instance = awful.menu.clients({ width=250 }) end),
163                        button({ }, 4, function () awful.client.focus.byidx(1) end),
164                        button({ }, 5, function () awful.client.focus.byidx(-1) end) }
165
166 for s = 1, screen.count() do
167     -- Create a promptbox for each screen
168     mypromptbox[s] = widget({ type = "textbox", align = "left" })
169     -- Create an imagebox widget which will contains an icon indicating which layout we're using.
170     -- We need one layoutbox per screen.
171     mylayoutbox[s] = widget({ type = "imagebox", align = "right" })
172     mylayoutbox[s]:buttons({ button({ }, 1, function () awful.layout.inc(layouts, 1) end),
173                              button({ }, 3, function () awful.layout.inc(layouts, -1) end),
174                              button({ }, 4, function () awful.layout.inc(layouts, 1) end),
175                              button({ }, 5, function () awful.layout.inc(layouts, -1) end) })
176     -- Create a taglist widget
177     mytaglist[s] = awful.widget.taglist.new(s, awful.widget.taglist.label.all, mytaglist.buttons)
178
179     -- Create a tasklist widget
180     mytasklist[s] = awful.widget.tasklist.new(function(c)
181                                                   return awful.widget.tasklist.label.currenttags(c, s)
182                                               end, mytasklist.buttons)
183
184     -- Create the wibox
185     mywibox[s] = wibox({ position = "top", fg = beautiful.fg_normal, bg = beautiful.bg_normal })
186     -- Add widgets to the wibox - order matters
187     mywibox[s].widgets = { mytaglist[s],
188                            mytasklist[s],
189                            mypromptbox[s],
190                            mybatterybox,
191                            mytimebox,
192                            mylayoutbox[s],
193                            s == screen.count() and mysystray or nil }
194     mywibox[s].screen = s
195 end
196 -- }}}
197
198 --Battery widget
199 batterywidget = widget({ type = 'progressbar', name = 'batterywidget' })
200 batterywidget.width = 100
201 batterywidget.height = 0.8
202 batterywidget.gap = 1
203 batterywidget.border_padding = 1
204 batterywidget.border_width = 1
205 batterywidget.ticks_count = 10
206 batterywidget.ticks_gap = 1
207 batterywidget.vertical = false
208 batterywidget:bar_properties_set('bat', {
209   bg = 'black',
210   fg = 'blue4',
211   fg_off = 'red',
212   reverse = false,
213   min_value = 0,
214   max_value = 100
215 })
216 -- }}}
217
218
219 -- {{{ Mouse bindings
220 root.buttons({
221     button({ }, 3, function () mymainmenu:toggle() end),
222     button({ }, 4, awful.tag.viewnext),
223     button({ }, 5, awful.tag.viewprev)
224 })
225 -- }}}
226
227 -- {{{ Key bindings
228 globalkeys =
229 {
230     key({ modkey,           }, "Left",   awful.tag.viewprev       ),
231     key({ modkey,           }, "Right",  awful.tag.viewnext       ),
232     key({ modkey,           }, "Escape", awful.tag.history.restore),
233
234     key({ modkey,           }, "j",
235         function ()
236             awful.client.focus.byidx( 1)
237             if client.focus then client.focus:raise() end
238         end),
239     key({ modkey,           }, "k",
240         function ()
241             awful.client.focus.byidx(-1)
242             if client.focus then client.focus:raise() end
243         end),
244
245     -- Layout manipulation
246     key({ modkey, "Shift"   }, "j", function () awful.client.swap.byidx(  1) end),
247     key({ modkey, "Shift"   }, "k", function () awful.client.swap.byidx( -1) end),
248     key({ modkey, "Control" }, "j", function () awful.screen.focus( 1)       end),
249     key({ modkey, "Control" }, "k", function () awful.screen.focus(-1)       end),
250     key({ modkey,           }, "u", awful.client.urgent.jumpto),
251     key({ modkey,           }, "Tab",
252         function ()
253             awful.client.focus.history.previous()
254             if client.focus then
255                 client.focus:raise()
256             end
257         end),
258
259     -- Standard program
260     key({ modkey,           }, "Return", function () awful.util.spawn(terminal) end),
261     key({ modkey, "Control" }, "r", awesome.restart),
262     key({ modkey, "Shift"   }, "q", awesome.quit),
263
264     key({ modkey,           }, "l",     function () awful.tag.incmwfact( 0.05)    end),
265     key({ modkey,           }, "h",     function () awful.tag.incmwfact(-0.05)    end),
266     key({ modkey, "Shift"   }, "h",     function () awful.tag.incnmaster( 1)      end),
267     key({ modkey, "Shift"   }, "l",     function () awful.tag.incnmaster(-1)      end),
268     key({ modkey, "Control" }, "h",     function () awful.tag.incncol( 1)         end),
269     key({ modkey, "Control" }, "l",     function () awful.tag.incncol(-1)         end),
270     key({ modkey,           }, "space", function () awful.layout.inc(layouts,  1) end),
271     key({ modkey, "Shift"   }, "space", function () awful.layout.inc(layouts, -1) end),
272
273     -- Prompt
274     key({ modkey }, "F1",
275         function ()
276             awful.prompt.run({ prompt = "Run: " },
277             mypromptbox[mouse.screen],
278             awful.util.spawn, awful.completion.bash,
279             awful.util.getdir("cache") .. "/history")
280         end),
281
282     key({ modkey }, "F4",
283         function ()
284             awful.prompt.run({ prompt = "Run Lua code: " },
285             mypromptbox[mouse.screen],
286             awful.util.eval, awful.prompt.bash,
287             awful.util.getdir("cache") .. "/history_eval")
288         end),
289 }
290
291 -- Client awful tagging: this is useful to tag some clients and then do stuff like move to tag on them
292 clientkeys =
293 {
294     key({ modkey,           }, "f",      function (c) c.fullscreen = not c.fullscreen  end),
295     key({ modkey, "Shift"   }, "c",      function (c) c:kill()                         end),
296     key({ modkey, "Control" }, "space",  awful.client.floating.toggle                     ),
297     key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end),
298     key({ modkey,           }, "o",      awful.client.movetoscreen                        ),
299     key({ modkey, "Shift"   }, "r",      function (c) c:redraw()                       end),
300     key({ modkey }, "t", awful.client.togglemarked),
301     key({ modkey,}, "m",
302         function (c)
303             c.maximized_horizontal = not c.maximized_horizontal
304             c.maximized_vertical   = not c.maximized_vertical
305         end),
306 }
307
308 -- Bind keyboard digits
309 -- Compute the maximum number of digit we need, limited to 9
310 keynumber = 0
311 for s = 1, screen.count() do
312    keynumber = math.min(9, math.max(#tags[s], keynumber));
313 end
314
315 for i = 1, keynumber do
316     table.insert(globalkeys,
317         key({ modkey }, i,
318             function ()
319                 local screen = mouse.screen
320                 if tags[screen][i] then
321                     awful.tag.viewonly(tags[screen][i])
322                 end
323             end))
324     table.insert(globalkeys,
325         key({ modkey, "Control" }, i,
326             function ()
327                 local screen = mouse.screen
328                 if tags[screen][i] then
329                     tags[screen][i].selected = not tags[screen][i].selected
330                 end
331             end))
332     table.insert(globalkeys,
333         key({ modkey, "Shift" }, i,
334             function ()
335                 if client.focus and tags[client.focus.screen][i] then
336                     awful.client.movetotag(tags[client.focus.screen][i])
337                 end
338             end))
339     table.insert(globalkeys,
340         key({ modkey, "Control", "Shift" }, i,
341             function ()
342                 if client.focus and tags[client.focus.screen][i] then
343                     awful.client.toggletag(tags[client.focus.screen][i])
344                 end
345             end))
346 end
347
348
349 for i = 1, keynumber do
350     table.insert(globalkeys, key({ modkey, "Shift" }, "F" .. i,
351                  function ()
352                      local screen = mouse.screen
353                      if tags[screen][i] then
354                          for k, c in pairs(awful.client.getmarked()) do
355                              awful.client.movetotag(tags[screen][i], c)
356                          end
357                      end
358                  end))
359 end
360
361 cmdmodkey = "Mod3"
362
363 -- xmms2 & sound
364 table.insert(globalkeys, key({ cmdmodkey }, "Prior", function () awful.util.spawn("amixer set Master 2+") end))
365 table.insert(globalkeys, key({ cmdmodkey }, "Next", function () awful.util.spawn("amixer set Master 2-") end))
366 table.insert(globalkeys, key({ cmdmodkey }, "Up", function () awful.util.spawn("amixer set PCM 2+") end))
367 table.insert(globalkeys, key({ cmdmodkey }, "Down", function () awful.util.spawn("amixer set PCM 2-") end))
368 table.insert(globalkeys, key({ cmdmodkey }, "Home", function () awful.util.spawn("amixer set Mic toggle") end))
369 table.insert(globalkeys, key({ cmdmodkey }, "End", function () awful.util.spawn("amixer set Master toggle") end))
370 table.insert(globalkeys, key({ cmdmodkey }, "Left", function () awful.util.spawn("xmms2 prev") end))
371 table.insert(globalkeys, key({ cmdmodkey }, "Right", function () awful.util.spawn("xmms2 next") end))
372 table.insert(globalkeys, key({ cmdmodkey }, "space", function () awful.util.spawn("xmms2 toggleplay") end))
373 table.insert(globalkeys, key({ cmdmodkey }, "backslash", function () awful.util.spawn("xmms2 current | head -1 | xmessage -nearmouse -timeout 5 -file -") end))
374 table.insert(globalkeys, key({ cmdmodkey, "Shift" }, "backslash", function () awful.util.spawn("xmms2 list | xmessage -nearmouse -timeout 5 -file -") end))
375
376 -- misc apps
377 table.insert(globalkeys, key({ cmdmodkey }, "n", function () awful.util.spawn("sensible-browser") end))
378 table.insert(globalkeys, key({ cmdmodkey }, "m", function () awful.util.spawn(terminal .. " -e mutt -f =store") end))
379 table.insert(globalkeys, key({ cmdmodkey }, "t", function () awful.util.spawn(terminal) end))
380 table.insert(globalkeys, key({ cmdmodkey }, "c", function () awful.util.spawn(terminal .. " -e python") end))
381 table.insert(globalkeys, key({ cmdmodkey }, "r", function () awful.util.spawn("gmrun") end))
382 table.insert(globalkeys, key({ cmdmodkey }, "j", function () awful.util.spawn("jpilot") end))
383 table.insert(globalkeys, key({ cmdmodkey }, "x", function () awful.util.spawn("/sbin/start-stop-daemon --start --background --exec /usr/bin/xscreensaver; xscreensaver-command -lock") end))
384 table.insert(globalkeys, key({ cmdmodkey, "Shift" }, "x", function () awful.util.spawn("xscreensaver-command -exit") end))
385
386 -- Set keys
387 root.keys(globalkeys)
388 -- }}}
389
390 -- {{{ Hooks
391 -- Hook function to execute when focusing a client.
392 awful.hooks.focus.register(function (c)
393     if not awful.client.ismarked(c) then
394         c.border_color = beautiful.border_focus
395     end
396 end)
397
398 -- Hook function to execute when unfocusing a client.
399 awful.hooks.unfocus.register(function (c)
400     if not awful.client.ismarked(c) then
401         c.border_color = beautiful.border_normal
402     end
403 end)
404
405 -- Hook function to execute when marking a client
406 awful.hooks.marked.register(function (c)
407     c.border_color = beautiful.border_marked
408 end)
409
410 -- Hook function to execute when unmarking a client.
411 awful.hooks.unmarked.register(function (c)
412     c.border_color = beautiful.border_focus
413 end)
414
415 -- Hook function to execute when the mouse enters a client.
416 awful.hooks.mouse_enter.register(function (c)
417     -- Sloppy focus, but disabled for magnifier layout
418     if awful.layout.get(c.screen) ~= awful.layout.suit.magnifier
419         and awful.client.focus.filter(c) then
420         client.focus = c
421     end
422 end)
423
424 -- Hook function to execute when a new client appears.
425 awful.hooks.manage.register(function (c, startup)
426     -- If we are not managing this application at startup,
427     -- move it to the screen where the mouse is.
428     -- We only do it for filtered windows (i.e. no dock, etc).
429     if not startup and awful.client.focus.filter(c) then
430         c.screen = mouse.screen
431     end
432
433     if use_titlebar then
434         -- Add a titlebar
435         awful.titlebar.add(c, { modkey = modkey })
436     end
437     -- Add mouse bindings
438     c:buttons({
439         button({ }, 1, function (c) client.focus = c; c:raise() end),
440         button({ modkey }, 1, awful.mouse.client.move),
441         button({ modkey }, 3, awful.mouse.client.resize)
442     })
443     -- New client may not receive focus
444     -- if they're not focusable, so set border anyway.
445     c.border_width = beautiful.border_width
446     c.border_color = beautiful.border_normal
447
448     -- Check if the application should be floating.
449     -- OVERRIDDEN, SEE tiledapps BELOW
450     local cls = c.class
451     local inst = c.instance
452     if floatapps[cls] then
453         awful.client.floating.set(c, floatapps[cls])
454     elseif floatapps[inst] then
455         awful.client.floating.set(c, floatapps[inst])
456     end
457
458     -- Override with tiledapps
459     awful.client.floating.set(c, not (tiledapps[inst] or tiledapps[cls]))
460
461     -- Check application->screen/tag mappings.
462     local target
463     if apptags[cls] then
464         target = apptags[cls]
465     elseif apptags[inst] then
466         target = apptags[inst]
467     end
468     if target then
469         c.screen = target.screen
470         awful.client.movetotag(tags[target.screen][target.tag], c)
471     end
472
473     -- Do this after tag mapping, so you don't see it on the wrong tag for a split second.
474     client.focus = c
475
476     -- Set key bindings
477     c:keys(clientkeys)
478
479     -- Set the windows at the slave,
480     -- i.e. put it at the end of others instead of setting it master.
481     -- awful.client.setslave(c)
482
483     -- Honor size hints: if you want to drop the gaps between windows, set this to false.
484     c.size_hints_honor = true
485
486     -- Maximise some
487     if maxapps[inst] or maxapps[cls] then
488       awful.client.maximize(c)
489     end
490 end)
491
492 -- Hook function to execute when arranging the screen.
493 -- (tag switch, new client, etc)
494 awful.hooks.arrange.register(function (screen)
495     local layout = awful.layout.getname(awful.layout.get(screen))
496     if layout and beautiful["layout_" ..layout] then
497         mylayoutbox[screen].image = image(beautiful["layout_" .. layout])
498     else
499         mylayoutbox[screen].image = nil
500     end
501
502     -- Give focus to the latest client in history if no window has focus
503     -- or if the current window is a desktop or a dock one.
504     if not client.focus then
505         local c = awful.client.focus.history.get(screen, 0)
506         if c then client.focus = c end
507     end
508
509     -- Uncomment if you want mouse warping
510     --[[
511     if client.focus then
512         local c_c = client.focus:fullgeometry()
513         local m_c = mouse.coords()
514
515         if m_c.x < c_c.x or m_c.x >= c_c.x + c_c.width or
516             m_c.y < c_c.y or m_c.y >= c_c.y + c_c.height then
517             if table.maxn(m_c.buttons) == 0 then
518                 mouse.coords({ x = c_c.x + 5, y = c_c.y + 5})
519             end
520         end
521     end
522     ]]
523 end)
524
525 -- Hook called every second
526 awful.hooks.timer.register(1, function ()
527     -- For unix time_t lovers
528     -- mytextbox.text = " " .. os.time() .. " time_t "
529     -- Otherwise use:
530     mytimebox.text = " " .. os.date() .. " "
531 end)
532
533 -- Hook called every sixty seconds
534 function hook_battery()
535     mybatterybox.text = " " .. get_acpibatt() .. " "
536 end
537
538 -- {{{ Statusbar battery
539 --
540 function get_acpibatt()
541
542     local f = io.popen('acpi -b', 'r')
543     if not f then
544       return "acpi -b failed"
545     end
546
547     local s = f:read('*l')
548     f:close()
549     if not s then
550       return '-';
551     end
552
553     -- Battery 0: Discharging, 89%, 00:02:14 remaining
554     -- Battery 0: Charging, 58%, 00:02:14 until charged
555     -- Battery 0: Full, 100%
556     -- so find the first bit first and then go look for the time
557     local st, en, status, percent = string.find(s, '%a+%s%d:%s(%a+),%s(%d+%%)');
558     local st, en, time = string.find(s, ',%s(%d+:%d+:%d+)%s%a+', en);
559
560     if not status or not percent then -- time can be empty if we're full
561       return "couldn't parse line " .. s
562     end
563
564     if not time then
565       return percent
566     end
567
568     if status == 'Charging' then
569       status = 'c';
570     elseif status == 'Discarching' then
571       status = 'd';
572     else
573       status = '-';
574     end
575
576     return percent; -- .. ' (' .. status .. ')'; -- .. ' ' .. time .. ' left';
577 end
578 -- }}}
579
580 --{{{ batt hook
581 local function get_bat()
582   local a = io.open("/sys/class/power_supply/BAT1/charge_full")
583   for line in a:lines() do
584     full = line
585   end
586   a:close()
587   local b = io.open("/sys/class/power_supply/BAT1/charge_now")
588   for line in b:lines() do
589     now = line
590   end
591   b:close()
592   batt=math.floor(now*100/full)
593   batterywidget:bar_data_add("bat",batt )
594 end
595 --}}}
596
597 -- Set up some hooks
598 awful.hooks.timer.register(120, hook_battery)
599 -- awful.hooks.timer.register(5, get_bat)
600 -- }}}
601
602 -- Highlight statusbars on the screen that has focus,
603 -- set this to false if you only have one screen or
604 -- you don't like it :P
605 if screen.count() > 1 then
606   statusbar_highlight_focus = true
607 else
608   statusbar_highlight_focus = false
609 end
610
611 hook_battery()
612
613 function displayMonth(month,year,weekStart)
614     local t,wkSt=os.time{year=year, month=month+1, day=0},weekStart or 1
615     local d=os.date("*t",t)
616     local mthDays,stDay=d.day,(d.wday-d.day-wkSt+1)%7
617
618     local lines = {}
619
620     for x=0,6 do
621         lines[x+1] = os.date("%a ",os.time{year=2006,month=1,day=x+wkSt})
622     end
623     lines[8] = "    "
624
625     local writeLine = 1
626     while writeLine < (stDay + 1) do
627         lines[writeLine] = lines[writeLine] .. "   "
628         writeLine = writeLine + 1
629     end
630
631     for x=1,mthDays do
632         if writeLine == 8 then
633             writeLine = 1
634         end
635         if writeLine == 1 or x == 1 then
636             lines[8] = lines[8] .. os.date(" %V",os.time{year=year,month=month,day=x})
637         end
638         if (#(tostring(x)) == 1) then
639             x = " " .. x
640         end
641         lines[writeLine] = lines[writeLine] .. " " .. x
642         writeLine = writeLine + 1
643     end
644     local header = os.date("%B %Y\n",os.time{year=year,month=month,day=1})
645     header = string.rep(" ", math.floor((#(lines[1]) - #header) / 2 )) .. header
646
647     return header .. table.concat(lines, '\n')
648 end
649
650 local calendar = {}
651 function switchNaughtyMonth(switchMonths)
652     if (#calendar < 3) then return end
653     local swMonths = switchMonths or 1
654     calendar[1] = calendar[1] + swMonths
655     calendar[3].box.widgets[2].text = displayMonth(calendar[1], calendar[2], 2)
656 end
657
658 mytimebox.mouse_enter = function ()
659     local month, year = os.date('%m'), os.date('%Y')
660     calendar = { month, year,
661                 naughty.notify({
662                     text = displayMonth(month, year, 2),
663                     timeout = 0, hover_timeout = 0.5,
664                     width = 200, screen = mouse.screen
665                 })
666                }
667 end
668 mytimebox.mouse_leave = function () naughty.destroy(calendar[3]) end
669
670 mytimebox:buttons({
671     button({ }, 1, function()
672         switchNaughtyMonth(-1)
673     end),
674     button({ }, 3, function()
675         switchNaughtyMonth(1)
676     end),
677     button({ }, 4, function()
678         switchNaughtyMonth(-1)
679     end),
680     button({ }, 5, function()
681         switchNaughtyMonth(1)
682     end),
683     button({ 'Shift' }, 1, function()
684         switchNaughtyMonth(-12)
685     end),
686     button({ 'Shift' }, 3, function()
687         switchNaughtyMonth(12)
688     end),
689     button({ 'Shift' }, 4, function()
690         switchNaughtyMonth(-12)
691     end),
692     button({ 'Shift' }, 5, function()
693         switchNaughtyMonth(12)
694     end)
695 })