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

8631b6a042fa1f994947b4cb7e1d9d3fc9898c8d
[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[6], 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 -- Set keys
362 root.keys(globalkeys)
363 -- }}}
364
365 -- {{{ Hooks
366 -- Hook function to execute when focusing a client.
367 awful.hooks.focus.register(function (c)
368     if not awful.client.ismarked(c) then
369         c.border_color = beautiful.border_focus
370     end
371 end)
372
373 -- Hook function to execute when unfocusing a client.
374 awful.hooks.unfocus.register(function (c)
375     if not awful.client.ismarked(c) then
376         c.border_color = beautiful.border_normal
377     end
378 end)
379
380 -- Hook function to execute when marking a client
381 awful.hooks.marked.register(function (c)
382     c.border_color = beautiful.border_marked
383 end)
384
385 -- Hook function to execute when unmarking a client.
386 awful.hooks.unmarked.register(function (c)
387     c.border_color = beautiful.border_focus
388 end)
389
390 -- Hook function to execute when the mouse enters a client.
391 awful.hooks.mouse_enter.register(function (c)
392     -- Sloppy focus, but disabled for magnifier layout
393     if awful.layout.get(c.screen) ~= awful.layout.suit.magnifier
394         and awful.client.focus.filter(c) then
395         client.focus = c
396     end
397 end)
398
399 -- Hook function to execute when a new client appears.
400 awful.hooks.manage.register(function (c, startup)
401     -- If we are not managing this application at startup,
402     -- move it to the screen where the mouse is.
403     -- We only do it for filtered windows (i.e. no dock, etc).
404     if not startup and awful.client.focus.filter(c) then
405         c.screen = mouse.screen
406     end
407
408     if use_titlebar then
409         -- Add a titlebar
410         awful.titlebar.add(c, { modkey = modkey })
411     end
412     -- Add mouse bindings
413     c:buttons({
414         button({ }, 1, function (c) client.focus = c; c:raise() end),
415         button({ modkey }, 1, awful.mouse.client.move),
416         button({ modkey }, 3, awful.mouse.client.resize)
417     })
418     -- New client may not receive focus
419     -- if they're not focusable, so set border anyway.
420     c.border_width = beautiful.border_width
421     c.border_color = beautiful.border_normal
422
423     -- Check if the application should be floating.
424     -- OVERRIDDEN, SEE tiledapps BELOW
425     local cls = c.class
426     local inst = c.instance
427     if floatapps[cls] then
428         awful.client.floating.set(c, floatapps[cls])
429     elseif floatapps[inst] then
430         awful.client.floating.set(c, floatapps[inst])
431     end
432
433     -- Override with tiledapps
434     awful.client.floating.set(c, not (tiledapps[inst] or tiledapps[cls]))
435
436     -- Check application->screen/tag mappings.
437     local target
438     if apptags[cls] then
439         target = apptags[cls]
440     elseif apptags[inst] then
441         target = apptags[inst]
442     end
443     if target then
444         c.screen = target.screen
445         awful.client.movetotag(tags[target.screen][target.tag], c)
446     end
447
448     -- Do this after tag mapping, so you don't see it on the wrong tag for a split second.
449     client.focus = c
450
451     -- Set key bindings
452     c:keys(clientkeys)
453
454     -- Set the windows at the slave,
455     -- i.e. put it at the end of others instead of setting it master.
456     -- awful.client.setslave(c)
457
458     -- Honor size hints: if you want to drop the gaps between windows, set this to false.
459     c.size_hints_honor = true
460
461     -- Maximise some
462     if maxapps[inst] or maxapps[cls] then
463       awful.client.maximize(c)
464     end
465 end)
466
467 -- Hook function to execute when arranging the screen.
468 -- (tag switch, new client, etc)
469 awful.hooks.arrange.register(function (screen)
470     local layout = awful.layout.getname(awful.layout.get(screen))
471     if layout and beautiful["layout_" ..layout] then
472         mylayoutbox[screen].image = image(beautiful["layout_" .. layout])
473     else
474         mylayoutbox[screen].image = nil
475     end
476
477     -- Give focus to the latest client in history if no window has focus
478     -- or if the current window is a desktop or a dock one.
479     if not client.focus then
480         local c = awful.client.focus.history.get(screen, 0)
481         if c then client.focus = c end
482     end
483
484     -- Uncomment if you want mouse warping
485     --[[
486     if client.focus then
487         local c_c = client.focus:fullgeometry()
488         local m_c = mouse.coords()
489
490         if m_c.x < c_c.x or m_c.x >= c_c.x + c_c.width or
491             m_c.y < c_c.y or m_c.y >= c_c.y + c_c.height then
492             if table.maxn(m_c.buttons) == 0 then
493                 mouse.coords({ x = c_c.x + 5, y = c_c.y + 5})
494             end
495         end
496     end
497     ]]
498 end)
499
500 -- Hook called every second
501 awful.hooks.timer.register(1, function ()
502     -- For unix time_t lovers
503     -- mytextbox.text = " " .. os.time() .. " time_t "
504     -- Otherwise use:
505     mytimebox.text = " " .. os.date() .. " "
506 end)
507
508 -- Hook called every sixty seconds
509 function hook_battery()
510     mybatterybox.text = " " .. get_acpibatt() .. " "
511 end
512
513 -- {{{ Statusbar battery
514 --
515 function get_acpibatt()
516
517     local f = io.popen('acpi -b', 'r')
518     if not f then
519       return "acpi -b failed"
520     end
521
522     local s = f:read('*l')
523     f:close()
524     if not s then
525       return '-';
526     end
527
528     -- Battery 0: Discharging, 89%, 00:02:14 remaining
529     -- Battery 0: Charging, 58%, 00:02:14 until charged
530     -- Battery 0: Full, 100%
531     -- so find the first bit first and then go look for the time
532     local st, en, status, percent = string.find(s, '%a+%s%d:%s(%a+),%s(%d+%%)');
533     local st, en, time = string.find(s, ',%s(%d+:%d+:%d+)%s%a+', en);
534
535     if not status or not percent then -- time can be empty if we're full
536       return "couldn't parse line " .. s
537     end
538
539     if not time then
540       return percent
541     end
542
543     if status == 'Charging' then
544       status = 'c';
545     elseif status == 'Discarching' then
546       status = 'd';
547     else
548       status = '-';
549     end
550
551     return percent; -- .. ' (' .. status .. ')'; -- .. ' ' .. time .. ' left';
552 end
553 -- }}}
554
555 --{{{ batt hook
556 local function get_bat()
557   local a = io.open("/sys/class/power_supply/BAT1/charge_full")
558   for line in a:lines() do
559     full = line
560   end
561   a:close()
562   local b = io.open("/sys/class/power_supply/BAT1/charge_now")
563   for line in b:lines() do
564     now = line
565   end
566   b:close()
567   batt=math.floor(now*100/full)
568   batterywidget:bar_data_add("bat",batt )
569 end
570 --}}}
571
572 -- Set up some hooks
573 awful.hooks.timer.register(120, hook_battery)
574 -- awful.hooks.timer.register(5, get_bat)
575 -- }}}
576
577 cmdmodkey = "Mod3"
578
579 -- xmms2 & sound
580 keybinding({ cmdmodkey }, "Prior", function () awful.util.spawn("amixer set Master 2+") end):add()
581 keybinding({ cmdmodkey }, "Next", function () awful.util.spawn("amixer set Master 2-") end):add()
582 keybinding({ cmdmodkey }, "Up", function () awful.util.spawn("amixer set PCM 2+") end):add()
583 keybinding({ cmdmodkey }, "Down", function () awful.util.spawn("amixer set PCM 2-") end):add()
584 keybinding({ cmdmodkey }, "Home", function () awful.util.spawn("amixer set Mic toggle") end):add()
585 keybinding({ cmdmodkey }, "End", function () awful.util.spawn("amixer set Master toggle") end):add()
586 keybinding({ cmdmodkey }, "Left", function () awful.util.spawn("xmms2 prev") end):add()
587 keybinding({ cmdmodkey }, "Right", function () awful.util.spawn("xmms2 next") end):add()
588 keybinding({ cmdmodkey }, "space", function () awful.util.spawn("xmms2 toggleplay") end):add()
589 keybinding({ cmdmodkey }, "backslash", function () awful.util.spawn("xmms2 current | head -1 | xmessage -nearmouse -timeout 5 -file -") end):add()
590 keybinding({ cmdmodkey, "Shift" }, "backslash", function () awful.util.spawn("xmms2 list | xmessage -nearmouse -timeout 5 -file -") end):add()
591
592 -- misc apps
593 keybinding({ cmdmodkey }, "n", function () awful.util.spawn("sensible-browser") end):add()
594 keybinding({ cmdmodkey }, "m", function () awful.util.spawn(terminal .. " -e mutt -f =store") end):add()
595 keybinding({ cmdmodkey }, "t", function () awful.util.spawn(terminal) end):add()
596 keybinding({ cmdmodkey }, "c", function () awful.util.spawn(terminal .. " -e python") end):add()
597 keybinding({ cmdmodkey }, "r", function () awful.util.spawn("gmrun") end):add()
598 keybinding({ cmdmodkey }, "j", function () awful.util.spawn("jpilot") end):add()
599 keybinding({ cmdmodkey }, "x", function () awful.util.spawn("/sbin/start-stop-daemon --start --background --exec /usr/bin/xscreensaver; xscreensaver-command -lock") end):add()
600 keybinding({ cmdmodkey, "Shift" }, "x", function () awful.util.spawn("xscreensaver-command -exit") end):add()
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 })