]> 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:

float clients on maximise
[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             if not awful.client.floating then
304                 awful.client.floating.toggle()
305             end
306             c.maximized_horizontal = not c.maximized_horizontal
307             c.maximized_vertical   = not c.maximized_vertical
308         end),
309 }
310
311 -- Bind keyboard digits
312 -- Compute the maximum number of digit we need, limited to 9
313 keynumber = 0
314 for s = 1, screen.count() do
315    keynumber = math.min(9, math.max(#tags[s], keynumber));
316 end
317
318 for i = 1, keynumber do
319     table.insert(globalkeys,
320         key({ modkey }, i,
321             function ()
322                 local screen = mouse.screen
323                 if tags[screen][i] then
324                     awful.tag.viewonly(tags[screen][i])
325                 end
326             end))
327     table.insert(globalkeys,
328         key({ modkey, "Control" }, i,
329             function ()
330                 local screen = mouse.screen
331                 if tags[screen][i] then
332                     tags[screen][i].selected = not tags[screen][i].selected
333                 end
334             end))
335     table.insert(globalkeys,
336         key({ modkey, "Shift" }, i,
337             function ()
338                 if client.focus and tags[client.focus.screen][i] then
339                     awful.client.movetotag(tags[client.focus.screen][i])
340                 end
341             end))
342     table.insert(globalkeys,
343         key({ modkey, "Control", "Shift" }, i,
344             function ()
345                 if client.focus and tags[client.focus.screen][i] then
346                     awful.client.toggletag(tags[client.focus.screen][i])
347                 end
348             end))
349 end
350
351
352 for i = 1, keynumber do
353     table.insert(globalkeys, key({ modkey, "Shift" }, "F" .. i,
354                  function ()
355                      local screen = mouse.screen
356                      if tags[screen][i] then
357                          for k, c in pairs(awful.client.getmarked()) do
358                              awful.client.movetotag(tags[screen][i], c)
359                          end
360                      end
361                  end))
362 end
363
364 cmdmodkey = "Mod3"
365
366 -- xmms2 & sound
367 table.insert(globalkeys, key({ cmdmodkey }, "Prior", function () awful.util.spawn("amixer set Master 2+") end))
368 table.insert(globalkeys, key({ cmdmodkey }, "Next", function () awful.util.spawn("amixer set Master 2-") end))
369 table.insert(globalkeys, key({ cmdmodkey }, "Up", function () awful.util.spawn("amixer set PCM 2+") end))
370 table.insert(globalkeys, key({ cmdmodkey }, "Down", function () awful.util.spawn("amixer set PCM 2-") end))
371 table.insert(globalkeys, key({ cmdmodkey }, "Home", function () awful.util.spawn("amixer set Mic toggle") end))
372 table.insert(globalkeys, key({ cmdmodkey }, "End", function () awful.util.spawn("amixer set Master toggle") end))
373 table.insert(globalkeys, key({ cmdmodkey }, "Left", function () awful.util.spawn("xmms2 prev") end))
374 table.insert(globalkeys, key({ cmdmodkey }, "Right", function () awful.util.spawn("xmms2 next") end))
375 table.insert(globalkeys, key({ cmdmodkey }, "space", function () awful.util.spawn("xmms2 toggleplay") end))
376 table.insert(globalkeys, key({ cmdmodkey }, "backslash", function () awful.util.spawn("xmms2 current | head -1 | xmessage -nearmouse -timeout 5 -file -") end))
377 table.insert(globalkeys, key({ cmdmodkey, "Shift" }, "backslash", function () awful.util.spawn("xmms2 list | xmessage -nearmouse -timeout 5 -file -") end))
378
379 -- misc apps
380 table.insert(globalkeys, key({ cmdmodkey }, "n", function () awful.util.spawn("sensible-browser") end))
381 table.insert(globalkeys, key({ cmdmodkey }, "m", function () awful.util.spawn(terminal .. " -e mutt -f =store") end))
382 table.insert(globalkeys, key({ cmdmodkey }, "t", function () awful.util.spawn(terminal) end))
383 table.insert(globalkeys, key({ cmdmodkey }, "c", function () awful.util.spawn(terminal .. " -e python") end))
384 table.insert(globalkeys, key({ cmdmodkey }, "r", function () awful.util.spawn("gmrun") end))
385 table.insert(globalkeys, key({ cmdmodkey }, "j", function () awful.util.spawn("jpilot") end))
386 table.insert(globalkeys, key({ cmdmodkey }, "x", function () awful.util.spawn("/sbin/start-stop-daemon --start --background --exec /usr/bin/xscreensaver; xscreensaver-command -lock") end))
387 table.insert(globalkeys, key({ cmdmodkey, "Shift" }, "x", function () awful.util.spawn("xscreensaver-command -exit") end))
388
389 -- Set keys
390 root.keys(globalkeys)
391 -- }}}
392
393 -- {{{ Hooks
394 -- Hook function to execute when focusing a client.
395 awful.hooks.focus.register(function (c)
396     if not awful.client.ismarked(c) then
397         c.border_color = beautiful.border_focus
398     end
399 end)
400
401 -- Hook function to execute when unfocusing a client.
402 awful.hooks.unfocus.register(function (c)
403     if not awful.client.ismarked(c) then
404         c.border_color = beautiful.border_normal
405     end
406 end)
407
408 -- Hook function to execute when marking a client
409 awful.hooks.marked.register(function (c)
410     c.border_color = beautiful.border_marked
411 end)
412
413 -- Hook function to execute when unmarking a client.
414 awful.hooks.unmarked.register(function (c)
415     c.border_color = beautiful.border_focus
416 end)
417
418 -- Hook function to execute when the mouse enters a client.
419 awful.hooks.mouse_enter.register(function (c)
420     -- Sloppy focus, but disabled for magnifier layout
421     if awful.layout.get(c.screen) ~= awful.layout.suit.magnifier
422         and awful.client.focus.filter(c) then
423         client.focus = c
424     end
425 end)
426
427 -- Hook function to execute when a new client appears.
428 awful.hooks.manage.register(function (c, startup)
429     -- If we are not managing this application at startup,
430     -- move it to the screen where the mouse is.
431     -- We only do it for filtered windows (i.e. no dock, etc).
432     if not startup and awful.client.focus.filter(c) then
433         c.screen = mouse.screen
434     end
435
436     if use_titlebar then
437         -- Add a titlebar
438         awful.titlebar.add(c, { modkey = modkey })
439     end
440     -- Add mouse bindings
441     c:buttons({
442         button({ }, 1, function (c) client.focus = c; c:raise() end),
443         button({ modkey }, 1, awful.mouse.client.move),
444         button({ modkey }, 3, awful.mouse.client.resize)
445     })
446     -- New client may not receive focus
447     -- if they're not focusable, so set border anyway.
448     c.border_width = beautiful.border_width
449     c.border_color = beautiful.border_normal
450
451     -- Check if the application should be floating.
452     -- OVERRIDDEN, SEE tiledapps BELOW
453     local cls = c.class
454     local inst = c.instance
455     if floatapps[cls] then
456         awful.client.floating.set(c, floatapps[cls])
457     elseif floatapps[inst] then
458         awful.client.floating.set(c, floatapps[inst])
459     end
460
461     -- Override with tiledapps
462     awful.client.floating.set(c, not (tiledapps[inst] or tiledapps[cls]))
463
464     -- Check application->screen/tag mappings.
465     local target
466     if apptags[cls] then
467         target = apptags[cls]
468     elseif apptags[inst] then
469         target = apptags[inst]
470     end
471     if target then
472         c.screen = target.screen
473         awful.client.movetotag(tags[target.screen][target.tag], c)
474     end
475
476     -- Do this after tag mapping, so you don't see it on the wrong tag for a split second.
477     client.focus = c
478
479     -- Set key bindings
480     c:keys(clientkeys)
481
482     -- Set the windows at the slave,
483     -- i.e. put it at the end of others instead of setting it master.
484     -- awful.client.setslave(c)
485
486     -- Honor size hints: if you want to drop the gaps between windows, set this to false.
487     c.size_hints_honor = true
488
489     -- Maximise some
490     if maxapps[inst] or maxapps[cls] then
491       awful.client.maximize(c)
492     end
493 end)
494
495 -- Hook function to execute when arranging the screen.
496 -- (tag switch, new client, etc)
497 awful.hooks.arrange.register(function (screen)
498     local layout = awful.layout.getname(awful.layout.get(screen))
499     if layout and beautiful["layout_" ..layout] then
500         mylayoutbox[screen].image = image(beautiful["layout_" .. layout])
501     else
502         mylayoutbox[screen].image = nil
503     end
504
505     -- Give focus to the latest client in history if no window has focus
506     -- or if the current window is a desktop or a dock one.
507     if not client.focus then
508         local c = awful.client.focus.history.get(screen, 0)
509         if c then client.focus = c end
510     end
511
512     -- Uncomment if you want mouse warping
513     --[[
514     if client.focus then
515         local c_c = client.focus:fullgeometry()
516         local m_c = mouse.coords()
517
518         if m_c.x < c_c.x or m_c.x >= c_c.x + c_c.width or
519             m_c.y < c_c.y or m_c.y >= c_c.y + c_c.height then
520             if table.maxn(m_c.buttons) == 0 then
521                 mouse.coords({ x = c_c.x + 5, y = c_c.y + 5})
522             end
523         end
524     end
525     ]]
526 end)
527
528 -- Hook called every second
529 awful.hooks.timer.register(1, function ()
530     -- For unix time_t lovers
531     -- mytextbox.text = " " .. os.time() .. " time_t "
532     -- Otherwise use:
533     mytimebox.text = " " .. os.date() .. " "
534 end)
535
536 -- Hook called every sixty seconds
537 function hook_battery()
538     mybatterybox.text = " " .. get_acpibatt() .. " "
539 end
540
541 -- {{{ Statusbar battery
542 --
543 function get_acpibatt()
544
545     local f = io.popen('acpi -b', 'r')
546     if not f then
547       return "acpi -b failed"
548     end
549
550     local s = f:read('*l')
551     f:close()
552     if not s then
553       return '-';
554     end
555
556     -- Battery 0: Discharging, 89%, 00:02:14 remaining
557     -- Battery 0: Charging, 58%, 00:02:14 until charged
558     -- Battery 0: Full, 100%
559     -- so find the first bit first and then go look for the time
560     local st, en, status, percent = string.find(s, '%a+%s%d:%s(%a+),%s(%d+%%)');
561     local st, en, time = string.find(s, ',%s(%d+:%d+:%d+)%s%a+', en);
562
563     if not status or not percent then -- time can be empty if we're full
564       return "couldn't parse line " .. s
565     end
566
567     if not time then
568       return percent
569     end
570
571     if status == 'Charging' then
572       status = 'c';
573     elseif status == 'Discarching' then
574       status = 'd';
575     else
576       status = '-';
577     end
578
579     return percent; -- .. ' (' .. status .. ')'; -- .. ' ' .. time .. ' left';
580 end
581 -- }}}
582
583 --{{{ batt hook
584 local function get_bat()
585   local a = io.open("/sys/class/power_supply/BAT1/charge_full")
586   for line in a:lines() do
587     full = line
588   end
589   a:close()
590   local b = io.open("/sys/class/power_supply/BAT1/charge_now")
591   for line in b:lines() do
592     now = line
593   end
594   b:close()
595   batt=math.floor(now*100/full)
596   batterywidget:bar_data_add("bat",batt )
597 end
598 --}}}
599
600 -- Set up some hooks
601 awful.hooks.timer.register(120, hook_battery)
602 -- awful.hooks.timer.register(5, get_bat)
603 -- }}}
604
605 -- Highlight statusbars on the screen that has focus,
606 -- set this to false if you only have one screen or
607 -- you don't like it :P
608 if screen.count() > 1 then
609   statusbar_highlight_focus = true
610 else
611   statusbar_highlight_focus = false
612 end
613
614 hook_battery()
615
616 function displayMonth(month,year,weekStart)
617     local t,wkSt=os.time{year=year, month=month+1, day=0},weekStart or 1
618     local d=os.date("*t",t)
619     local mthDays,stDay=d.day,(d.wday-d.day-wkSt+1)%7
620
621     local lines = {}
622
623     for x=0,6 do
624         lines[x+1] = os.date("%a ",os.time{year=2006,month=1,day=x+wkSt})
625     end
626     lines[8] = "    "
627
628     local writeLine = 1
629     while writeLine < (stDay + 1) do
630         lines[writeLine] = lines[writeLine] .. "   "
631         writeLine = writeLine + 1
632     end
633
634     for x=1,mthDays do
635         if writeLine == 8 then
636             writeLine = 1
637         end
638         if writeLine == 1 or x == 1 then
639             lines[8] = lines[8] .. os.date(" %V",os.time{year=year,month=month,day=x})
640         end
641         if (#(tostring(x)) == 1) then
642             x = " " .. x
643         end
644         lines[writeLine] = lines[writeLine] .. " " .. x
645         writeLine = writeLine + 1
646     end
647     local header = os.date("%B %Y\n",os.time{year=year,month=month,day=1})
648     header = string.rep(" ", math.floor((#(lines[1]) - #header) / 2 )) .. header
649
650     return header .. table.concat(lines, '\n')
651 end
652
653 local calendar = {}
654 function switchNaughtyMonth(switchMonths)
655     if (#calendar < 3) then return end
656     local swMonths = switchMonths or 1
657     calendar[1] = calendar[1] + swMonths
658     calendar[3].box.widgets[2].text = displayMonth(calendar[1], calendar[2], 2)
659 end
660
661 mytimebox.mouse_enter = function ()
662     local month, year = os.date('%m'), os.date('%Y')
663     calendar = { month, year,
664                 naughty.notify({
665                     text = displayMonth(month, year, 2),
666                     timeout = 0, hover_timeout = 0.5,
667                     width = 200, screen = mouse.screen
668                 })
669                }
670 end
671 mytimebox.mouse_leave = function () naughty.destroy(calendar[3]) end
672
673 mytimebox:buttons({
674     button({ }, 1, function()
675         switchNaughtyMonth(-1)
676     end),
677     button({ }, 3, function()
678         switchNaughtyMonth(1)
679     end),
680     button({ }, 4, function()
681         switchNaughtyMonth(-1)
682     end),
683     button({ }, 5, function()
684         switchNaughtyMonth(1)
685     end),
686     button({ 'Shift' }, 1, function()
687         switchNaughtyMonth(-12)
688     end),
689     button({ 'Shift' }, 3, function()
690         switchNaughtyMonth(12)
691     end),
692     button({ 'Shift' }, 4, function()
693         switchNaughtyMonth(-12)
694     end),
695     button({ 'Shift' }, 5, function()
696         switchNaughtyMonth(12)
697     end)
698 })