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

c7cd4055cab163d20bbeee815348955ea56fde18
[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         c.maximized_horizontal = not c.maximized_horizontal
492         c.maximized_vertical   = not c.maximized_vertical
493     end
494 end)
495
496 -- Hook function to execute when arranging the screen.
497 -- (tag switch, new client, etc)
498 awful.hooks.arrange.register(function (screen)
499     local layout = awful.layout.getname(awful.layout.get(screen))
500     if layout and beautiful["layout_" ..layout] then
501         mylayoutbox[screen].image = image(beautiful["layout_" .. layout])
502     else
503         mylayoutbox[screen].image = nil
504     end
505
506     -- Give focus to the latest client in history if no window has focus
507     -- or if the current window is a desktop or a dock one.
508     if not client.focus then
509         local c = awful.client.focus.history.get(screen, 0)
510         if c then client.focus = c end
511     end
512
513     -- Uncomment if you want mouse warping
514     --[[
515     if client.focus then
516         local c_c = client.focus:fullgeometry()
517         local m_c = mouse.coords()
518
519         if m_c.x < c_c.x or m_c.x >= c_c.x + c_c.width or
520             m_c.y < c_c.y or m_c.y >= c_c.y + c_c.height then
521             if table.maxn(m_c.buttons) == 0 then
522                 mouse.coords({ x = c_c.x + 5, y = c_c.y + 5})
523             end
524         end
525     end
526     ]]
527 end)
528
529 -- Hook called every second
530 awful.hooks.timer.register(1, function ()
531     -- For unix time_t lovers
532     -- mytextbox.text = " " .. os.time() .. " time_t "
533     -- Otherwise use:
534     mytimebox.text = " " .. os.date() .. " "
535 end)
536
537 -- Hook called every sixty seconds
538 function hook_battery()
539     mybatterybox.text = " " .. get_acpibatt() .. " "
540 end
541
542 -- {{{ Statusbar battery
543 --
544 function get_acpibatt()
545
546     local f = io.popen('acpi -b', 'r')
547     if not f then
548       return "acpi -b failed"
549     end
550
551     local s = f:read('*l')
552     f:close()
553     if not s then
554       return '-';
555     end
556
557     -- Battery 0: Discharging, 89%, 00:02:14 remaining
558     -- Battery 0: Charging, 58%, 00:02:14 until charged
559     -- Battery 0: Full, 100%
560     -- so find the first bit first and then go look for the time
561     local st, en, status, percent = string.find(s, '%a+%s%d:%s(%a+),%s(%d+%%)');
562     local st, en, time = string.find(s, ',%s(%d+:%d+):%d+%s%a+', en);
563
564     if not status or not percent then -- time can be empty if we're full
565       return "couldn't parse line " .. s
566     end
567
568     if not time then
569       return percent
570     end
571
572     if status == 'Charging' then
573       status = '+';
574     elseif status == 'Discharging' then
575       status = '-';
576     else
577       status = 'x';
578     end
579
580     return status .. ' ' .. time;
581     -- return percent .. ' (' .. status .. ')'; -- .. ' ' .. time .. ' left';
582 end
583 -- }}}
584
585 --{{{ batt hook
586 local function get_bat()
587   local a = io.open("/sys/class/power_supply/BAT1/charge_full")
588   for line in a:lines() do
589     full = line
590   end
591   a:close()
592   local b = io.open("/sys/class/power_supply/BAT1/charge_now")
593   for line in b:lines() do
594     now = line
595   end
596   b:close()
597   batt=math.floor(now*100/full)
598   batterywidget:bar_data_add("bat",batt )
599 end
600 --}}}
601
602 -- Set up some hooks
603 awful.hooks.timer.register(120, hook_battery)
604 -- awful.hooks.timer.register(5, get_bat)
605 -- }}}
606
607 -- Highlight statusbars on the screen that has focus,
608 -- set this to false if you only have one screen or
609 -- you don't like it :P
610 if screen.count() > 1 then
611   statusbar_highlight_focus = true
612 else
613   statusbar_highlight_focus = false
614 end
615
616 hook_battery()
617
618 function displayMonth(month,year,weekStart)
619     local t,wkSt=os.time{year=year, month=month+1, day=0},weekStart or 1
620     local d=os.date("*t",t)
621     local mthDays,stDay=d.day,(d.wday-d.day-wkSt+1)%7
622
623     local lines = {}
624
625     for x=0,6 do
626         lines[x+1] = os.date("%a ",os.time{year=2006,month=1,day=x+wkSt})
627     end
628     lines[8] = "    "
629
630     local writeLine = 1
631     while writeLine < (stDay + 1) do
632         lines[writeLine] = lines[writeLine] .. "   "
633         writeLine = writeLine + 1
634     end
635
636     for x=1,mthDays do
637         if writeLine == 8 then
638             writeLine = 1
639         end
640         if writeLine == 1 or x == 1 then
641             lines[8] = lines[8] .. os.date(" %V",os.time{year=year,month=month,day=x})
642         end
643         if (#(tostring(x)) == 1) then
644             x = " " .. x
645         end
646         lines[writeLine] = lines[writeLine] .. " " .. x
647         writeLine = writeLine + 1
648     end
649     local header = os.date("%B %Y\n",os.time{year=year,month=month,day=1})
650     header = string.rep(" ", math.floor((#(lines[1]) - #header) / 2 )) .. header
651
652     return header .. table.concat(lines, '\n')
653 end
654
655 local calendar = {}
656 function switchNaughtyMonth(switchMonths)
657     if (#calendar < 3) then return end
658     local swMonths = switchMonths or 1
659     calendar[1] = calendar[1] + swMonths
660     calendar[3].box.widgets[2].text = displayMonth(calendar[1], calendar[2], 2)
661 end
662
663 mytimebox.mouse_enter = function ()
664     local month, year = os.date('%m'), os.date('%Y')
665     calendar = { month, year,
666                 naughty.notify({
667                     text = displayMonth(month, year, 2),
668                     timeout = 0, hover_timeout = 0.5,
669                     width = 200, screen = mouse.screen
670                 })
671                }
672 end
673 mytimebox.mouse_leave = function () naughty.destroy(calendar[3]) end
674
675 mytimebox:buttons({
676     button({ }, 1, function()
677         switchNaughtyMonth(-1)
678     end),
679     button({ }, 3, function()
680         switchNaughtyMonth(1)
681     end),
682     button({ }, 4, function()
683         switchNaughtyMonth(-1)
684     end),
685     button({ }, 5, function()
686         switchNaughtyMonth(1)
687     end),
688     button({ 'Shift' }, 1, function()
689         switchNaughtyMonth(-12)
690     end),
691     button({ 'Shift' }, 3, function()
692         switchNaughtyMonth(12)
693     end),
694     button({ 'Shift' }, 4, function()
695         switchNaughtyMonth(-12)
696     end),
697     button({ 'Shift' }, 5, function()
698         switchNaughtyMonth(12)
699     end)
700 })