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

Merge pull request #439 from gregflynn/201908_gf_customize_pulsebar_notification_char...
[etc/awesome.git] / widget / cal.lua
index 7a81c68924fcc76f77e1d1924f03766b91cc38cb..928a7bd91f15119e582584b8ac6412a41e6a0930 100644 (file)
@@ -11,80 +11,154 @@ local awful    = require("awful")
 local naughty  = require("naughty")
 local floor    = math.floor
 local os       = os
+local pairs    = pairs
 local string   = string
-local ipairs   = ipairs
 local tconcat  = table.concat
+local type     = type
 local tonumber = tonumber
 local tostring = tostring
 
 -- Calendar notification
 -- lain.widget.cal
+
 local function factory(args)
     args = args or {}
     local cal = {
-        weekStart           = args.weekStart or 2,
         attach_to           = args.attach_to or {},
+        week_start          = args.week_start or 2,
+        three               = args.three or false,
         followtag           = args.followtag or false,
+        week_number         = args.week_number or "none",
+        week_number_format  = args.week_number_format or args.week_number == "left" and "%3d | " or "| %-3d",
         icons               = args.icons or helpers.icons_dir .. "cal/white/",
         notification_preset = args.notification_preset or {
             font = "Monospace 10", fg = "#FFFFFF", bg = "#000000"
         }
     }
 
-    function cal.hide()
-        if not cal.notification then return end
-        naughty.destroy(cal.notification)
-        cal.notification = nil
+    function cal.get_week_number(m, st_day, x)
+        return string.format(cal.week_number_format, os.date("%V", m) + (x ~= 0 and floor((x + st_day) / 7) - 1 or 0))
     end
 
-    function cal.show(timeout, month, year)
+    function cal.sum_week_days(x, y)
+        return (x + y) % 7
+    end
+
+    function cal.build(month, year)
         local current_month, current_year = tonumber(os.date("%m")), tonumber(os.date("%Y"))
         local is_current_month = (not month or not year) or (month == current_month and year == current_year)
         local today = is_current_month and tonumber(os.date("%d")) -- otherwise nil and not highlighted
         local t = os.time { year = year or current_year, month = month and month+1 or current_month+1, day = 0 }
         local d = os.date("*t", t)
-        local mthDays, stDay, cmonth = d.day, (d.wday-d.day-cal.weekStart+1)%7, os.date("%B %Y", t)
-        local notifytable = { [1] = string.format("%s%s\n", string.rep(" ", floor((28 - cmonth:len())/2)), markup.bold(cmonth)) }
-        for x = 0,6 do notifytable[#notifytable+1] = os.date("%a ", os.time { year=2006, month=1, day=x+cal.weekStart }) end
-        notifytable[#notifytable] = string.format("%s\n%s", notifytable[#notifytable]:sub(1, -2), string.rep(" ", stDay*4))
-        for x = 1,mthDays do
-            local strx = x ~= today and x or markup.bold(markup.color(cal.notification_preset.bg, cal.notification_preset.fg, x) .. " ")
+        local mth_days, st_day, this_month = d.day, (d.wday-d.day-cal.week_start+1)%7, os.date("%B %Y", t)
+        local notifytable = { [1] = string.format("%s%s\n", string.rep(" ", floor((28 - this_month:len())/2)), markup.bold(this_month)) }
+        for x = 0,6 do notifytable[#notifytable+1] = os.date("%a", os.time { year=2006, month=1, day=x+cal.week_start }):sub(1, 3) .. " " end
+        notifytable[#notifytable] = string.format("%s\n%s", notifytable[#notifytable]:sub(1, -2), string.rep(" ", st_day*4))
+        local strx
+        for x = 1,mth_days do
+            strx = x
+            if x == today then
+                if x < 10 then x = " " .. x end
+                strx = markup.bold(markup.color(cal.notification_preset.bg, cal.notification_preset.fg, x) .. " ")
+            end
             strx = string.format("%s%s", string.rep(" ", 3 - tostring(x):len()), strx)
-            notifytable[#notifytable+1] = string.format("%-4s%s", strx, (x+stDay)%7==0 and x ~= mthDays and "\n" or "")
+            notifytable[#notifytable+1] = string.format("%-4s%s", strx, (x+st_day)%7==0 and x ~= mth_days and "\n" or "")
+        end
+        if string.len(cal.icons or "") > 0 and today then cal.icon = cal.icons .. today .. ".png" end
+        cal.month, cal.year = d.month, d.year
+
+        if cal.week_number ~= "none" then
+            local m = os.time { year = year or current_year, month = month and month or current_month, day = 0 }
+            local head_prepend = string.rep(" ", tostring(string.format(cal.week_number_format, 0)):len())
+
+            if cal.week_number == "left" then
+                notifytable[1] = head_prepend .. notifytable[1] -- month-year row
+                notifytable[2] = head_prepend .. notifytable[2] -- weekdays row
+                notifytable[8] = notifytable[8]:gsub("\n", "\n" .. cal.get_week_number(m, st_day, 0)) -- first week of the month
+
+                for x = 10,#notifytable do
+                    if cal.sum_week_days(st_day, x) == 2 then
+                        notifytable[x] = cal.get_week_number(m, st_day, x) .. notifytable[x]
+                    end
+                end
+            elseif cal.week_number == "right" then
+                notifytable[8] = notifytable[8]:gsub("\n", head_prepend .. "\n") -- weekdays row
+                for x = 9,#notifytable do
+                    if cal.sum_week_days(st_day, x) == 1 then
+                        notifytable[x] = notifytable[x]:gsub("\n", cal.get_week_number(m, st_day, x - 7) .. "\n")
+                    end
+                end
+                -- last week of the month
+                local end_days = cal.sum_week_days(st_day, mth_days)
+                if end_days ~= 0 then end_days = 7 - end_days end
+                notifytable[#notifytable] = notifytable[#notifytable] .. string.rep(" ", 4 * end_days) .. cal.get_week_number(m, st_day, mth_days + end_days)
+            end
+        end
+
+        return notifytable
+    end
+
+    function cal.getdate(month, year, offset)
+        if not month or not year then
+            month = tonumber(os.date("%m"))
+            year  = tonumber(os.date("%Y"))
+        end
+
+        month = month + offset
+
+        while month > 12 do
+            month = month - 12
+            year = year + 1
+        end
+
+        while month < 1 do
+            month = month + 12
+            year = year - 1
+        end
+
+        return month, year
+    end
+
+    function cal.hide()
+        if not cal.notification then return end
+        naughty.destroy(cal.notification)
+        cal.notification = nil
+    end
+
+    function cal.show(seconds, month, year, scr)
+        cal.notification_preset.text = tconcat(cal.build(month, year))
+
+        if cal.three then
+            local current_month, current_year = cal.month, cal.year
+            local prev_month, prev_year = cal.getdate(cal.month, cal.year, -1)
+            local next_month, next_year = cal.getdate(cal.month, cal.year,  1)
+            cal.notification_preset.text = string.format("%s\n\n%s\n\n%s",
+            tconcat(cal.build(prev_month, prev_year)), cal.notification_preset.text,
+            tconcat(cal.build(next_month, next_year)))
+            cal.month, cal.year = current_month, current_year
         end
 
-        cal.notification_preset.text = tconcat(notifytable)
         cal.hide()
         cal.notification = naughty.notify {
             preset  = cal.notification_preset,
+            screen  = cal.followtag and awful.screen.focused() or scr or 1,
             icon    = cal.icon,
-            timeout = timeout or cal.notification_preset.timeout or 5
+            timeout = type(seconds) == "number" and seconds or cal.notification_preset.timeout or 5
         }
-        cal.month, cal.year = d.month, d.year
     end
 
     function cal.hover_on() cal.show(0) end
-    function cal.hover_off() cal.hide() end
-    function cal.prev()
-        cal.month = cal.month - 1
-        if cal.month == 0 then
-            cal.month = 12
-            cal.year = cal.year - 1
-        end
-        cal.show(0, cal.month, cal.year)
-    end
-    function cal.next()
-        cal.month = cal.month + 1
-        if cal.month == 13 then
-            cal.month = 1
-            cal.year = cal.year + 1
-        end
+    function cal.move(offset)
+        local offset = offset or 0
+        cal.month, cal.year = cal.getdate(cal.month, cal.year, offset)
         cal.show(0, cal.month, cal.year)
     end
+    function cal.prev() cal.move(-1) end
+    function cal.next() cal.move( 1) end
 
     function cal.attach(widget)
         widget:connect_signal("mouse::enter", cal.hover_on)
-        widget:connect_signal("mouse::leave", cal.hover_off)
+        widget:connect_signal("mouse::leave", cal.hide)
         widget:buttons(awful.util.table.join(
                     awful.button({}, 1, cal.prev),
                     awful.button({}, 3, cal.next),
@@ -93,7 +167,7 @@ local function factory(args)
                     awful.button({}, 4, cal.next)))
     end
 
-    for _, widget in ipairs(cal.attach_to) do cal.attach(widget) end
+    for _, widget in pairs(cal.attach_to) do cal.attach(widget) end
 
     return cal
 end