]> git.madduck.net Git - etc/awesome.git/blob - widget/cal.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:

widget.cal: add options for displaying 3 months spanning the date
[etc/awesome.git] / widget / cal.lua
1 --[[
2
3      Licensed under GNU General Public License v2
4       * (c) 2018, Luca CPZ
5
6 --]]
7
8 local helpers  = require("lain.helpers")
9 local markup   = require("lain.util.markup")
10 local awful    = require("awful")
11 local naughty  = require("naughty")
12 local floor    = math.floor
13 local os       = os
14 local pairs    = pairs
15 local string   = string
16 local tconcat  = table.concat
17 local tonumber = tonumber
18 local tostring = tostring
19
20 -- Calendar notification
21 -- lain.widget.cal
22 local function factory(args)
23     args = args or {}
24     local cal = {
25         attach_to           = args.attach_to or {},
26         week_start          = args.week_start or 2,
27         three               = args.three or false,
28         followtag           = args.followtag or false,
29         icons               = args.icons or helpers.icons_dir .. "cal/white/",
30         notification_preset = args.notification_preset or {
31             font = "Monospace 10", fg = "#FFFFFF", bg = "#000000"
32         }
33     }
34
35     function cal.build(month, year)
36         local current_month, current_year = tonumber(os.date("%m")), tonumber(os.date("%Y"))
37         local is_current_month = (not month or not year) or (month == current_month and year == current_year)
38         local today = is_current_month and tonumber(os.date("%d")) -- otherwise nil and not highlighted
39         local t = os.time { year = year or current_year, month = month and month+1 or current_month+1, day = 0 }
40         local d = os.date("*t", t)
41         local mth_days, st_day, this_month = d.day, (d.wday-d.day-cal.week_start+1)%7, os.date("%B %Y", t)
42         local notifytable = { [1] = string.format("%s%s\n", string.rep(" ", floor((28 - this_month:len())/2)), markup.bold(this_month)) }
43         for x = 0,6 do notifytable[#notifytable+1] = os.date("%a ", os.time { year=2006, month=1, day=x+cal.week_start }) end
44         notifytable[#notifytable] = string.format("%s\n%s", notifytable[#notifytable]:sub(1, -2), string.rep(" ", st_day*4))
45         for x = 1,mth_days do
46             local strx = x ~= today and x or markup.bold(markup.color(cal.notification_preset.bg, cal.notification_preset.fg, x) .. " ")
47             strx = string.format("%s%s", string.rep(" ", 3 - tostring(x):len()), strx)
48             notifytable[#notifytable+1] = string.format("%-4s%s", strx, (x+st_day)%7==0 and x ~= mth_days and "\n" or "")
49         end
50         cal.month, cal.year = d.month, d.year
51         return notifytable
52     end
53
54     function cal.getdate(month, year, offset)
55         if not month or not year then
56             month = tonumber(os.date("%m"))
57             year  = tonumber(os.date("%Y"))
58         end
59
60         month = month + offset
61
62         while month > 12 do
63             month = month - 12
64             year = year + 1
65         end
66
67         while month < 1 do
68             month = month + 12
69             year = year - 1
70         end
71
72         return month, year
73     end
74
75     function cal.hide()
76         if not cal.notification then return end
77         naughty.destroy(cal.notification)
78         cal.notification = nil
79     end
80
81     function cal.show(timeout, month, year)
82         cal.notification_preset.text = tconcat(cal.build(month, year))
83
84         if cal.three then
85             local current_month, current_year = cal.month, cal.year
86             local prev_month, prev_year = cal.getdate(cal.month, cal.year, -1)
87             local next_month, next_year = cal.getdate(cal.month, cal.year,  1)
88             cal.notification_preset.text = string.format("%s\n\n%s\n\n%s",
89             tconcat(cal.build(prev_month, prev_year)), cal.notification_preset.text,
90             tconcat(cal.build(next_month, next_year)))
91             cal.month, cal.year = current_month, current_year
92         end
93
94         cal.hide()
95         cal.notification = naughty.notify {
96             preset  = cal.notification_preset,
97             icon    = cal.icon,
98             timeout = timeout or cal.notification_preset.timeout or 5
99         }
100     end
101
102     function cal.hover_on() cal.show(0) end
103     function cal.move(offset)
104         local offset = offset or 0
105         cal.month, cal.year = cal.getdate(cal.month, cal.year, offset)
106         cal.show(0, cal.month, cal.year)
107     end
108     function cal.prev() cal.move(-1) end
109     function cal.next() cal.move( 1) end
110
111     function cal.attach(widget)
112         widget:connect_signal("mouse::enter", cal.hover_on)
113         widget:connect_signal("mouse::leave", cal.hide)
114         widget:buttons(awful.util.table.join(
115                     awful.button({}, 1, cal.prev),
116                     awful.button({}, 3, cal.next),
117                     awful.button({}, 2, cal.hover_on),
118                     awful.button({}, 5, cal.prev),
119                     awful.button({}, 4, cal.next)))
120     end
121
122     for _, widget in pairs(cal.attach_to) do cal.attach(widget) end
123
124     return cal
125 end
126
127 return factory