aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md3
-rwxr-xr-xbin/calendar-sample.sh10
-rw-r--r--lib/data.lua15
-rw-r--r--test/test_data.lua8
-rw-r--r--widgets/calendar.lua13
5 files changed, 42 insertions, 7 deletions
diff --git a/README.md b/README.md
index fa2451b..eb35020 100644
--- a/README.md
+++ b/README.md
@@ -122,7 +122,8 @@ for, including ones with nothing on this week: it is a colour key, not a second
list of what is coming.
Events come from a cache file written by `bin/calendar-sample.sh`, which shells
-out to `khal`. The card shows as many rows as the cell affords and ends with
+out to `khal` for the rest of the month (at least 8 days), so the grid marks
+every remaining day with an event while the rows stay the coming week. The card shows as many rows as the cell affords and ends with
`+N more` when the week does not fit, since a card that silently drops the rest
of the week defeats its own purpose. A cell too short for even one row draws
the grid alone, without the legend, rather than a clipped half-row.
diff --git a/bin/calendar-sample.sh b/bin/calendar-sample.sh
index af583f6..a0fb87e 100755
--- a/bin/calendar-sample.sh
+++ b/bin/calendar-sample.sh
@@ -45,9 +45,17 @@ trap 'rm -f "$TMP"' EXIT
# 8d, not 7d: khal's range is exclusive of the final day in practice for
# all-day events, and one extra day costs nothing but avoids a birthday
# vanishing from the card on the morning it matters.
+#
+# The range runs to the end of the month when that is further out, because
+# the month grid colours every day with an event, not just this week's. The
+# widget cuts the event table back to the 8 days itself. khal's Nd covers day
+# offsets 0..N-1, so the month's last day needs last - today + 1.
+LAST=$(date -d "$(date +%Y-%m-01) +1 month -1 day" +%-d)
+DAYS=$(( LAST - $(date +%-d) + 1 ))
+[ "$DAYS" -lt 8 ] && DAYS=8
EVENTS=$(khal list --day-format '' \
--format '{start-date-long}|{start-time}|{end-time}|{calendar}|{title}' \
- --notstarted today 8d 2>/dev/null)
+ --notstarted today "${DAYS}d" 2>/dev/null)
# khal's exit status is 0 even with no calendars configured, so emptiness is
# not distinguishable from failure by status alone. The widget treats a missing
diff --git a/lib/data.lua b/lib/data.lua
index 1b4c64f..818bbf1 100644
--- a/lib/data.lua
+++ b/lib/data.lua
@@ -131,6 +131,21 @@ function M.calendar_month_days(events, year, month)
return out
end
+-- The events falling within `days` days of `today` ({ y, m, d }), today
+-- included. The cache spans the rest of the month so the grid can mark it,
+-- while the event table under the grid stays a week's view.
+function M.calendar_upcoming(events, today, days)
+ local out = {}
+ if type(events) ~= 'table' or type(today) ~= 'table' then return out end
+ local t0 = os.time({ year = today[1], month = today[2], day = today[3],
+ hour = 12 })
+ for _, e in ipairs(events) do
+ local t = os.time({ year = e.y, month = e.m, day = e.d, hour = 12 })
+ if (t - t0) / 86400 < days then out[#out + 1] = e end
+ end
+ return out
+end
+
-- Days in a month, and the weekday its 1st falls on.
--
-- os.time/os.date rather than a leap-year rule: the C library already knows,
diff --git a/test/test_data.lua b/test/test_data.lua
index 9066241..01a55cc 100644
--- a/test/test_data.lua
+++ b/test/test_data.lua
@@ -109,6 +109,14 @@ assert(days[18] == 'personal', 'first event of the day owns it, got '
assert(days[24] == 'work' and days[26] == 'birthdays', 'later days marked')
assert(days[2] == nil, 'October event does not mark September')
+-- upcoming: the table's week out of a month-long cache, across a month end.
+local up = data.calendar_upcoming({ { y = 2026, m = 10, d = 18 },
+ { y = 2026, m = 10, d = 25 }, { y = 2026, m = 10, d = 26 },
+ { y = 2026, m = 10, d = 29 } }, { 2026, 10, 18 }, 8)
+assert(#up == 2 and up[2].d == 25, 'eight days from the 18th end on the 25th')
+assert(#data.calendar_upcoming({ { y = 2026, m = 11, d = 2 } },
+ { 2026, 10, 28 }, 8) == 1, 'week crosses into next month')
+
-- month_shape: September 2026 has 30 days and starts on a Tuesday.
-- Monday = 1, so Tuesday = 2.
local ndays, first = data.month_shape(2026, 9)
diff --git a/widgets/calendar.lua b/widgets/calendar.lua
index 11dcb63..5e08a7b 100644
--- a/widgets/calendar.lua
+++ b/widgets/calendar.lua
@@ -209,7 +209,10 @@ function M.draw(cr, rect, colors)
local ey = grid_bottom + ev_size * 1.1
- if #cal.events == 0 then
+ -- The cache spans the month for the grid; the table is the week ahead.
+ local events = data.calendar_upcoming(cal.events, today, 8)
+
+ if #events == 0 then
card.font(cr, card.FONT_UI, ev_size, false)
card.rgba(cr, colors.label, 0.8)
card.text(cr, inner.x, ey, 'nothing this week')
@@ -225,7 +228,7 @@ function M.draw(cr, rect, colors)
-- 'all day' is wider than '13:00'.
card.font(cr, card.FONT_MONO, ev_size, false)
local time_w = 0
- for _, e in ipairs(cal.events) do
+ for _, e in ipairs(events) do
local w = card.advance(cr, when(e))
if w > time_w then time_w = w end
end
@@ -253,16 +256,16 @@ function M.draw(cr, rect, colors)
local probe = ey
while probe <= floor_y do room = room + 1; probe = probe + ev_step end
- local shown = #cal.events
+ local shown = #events
-- The overflow line costs a row, so it is only worth taking when it reports
-- more than the row it displaces.
if room < shown then
shown = (room >= 2) and (room - 1) or room
end
- local hidden = #cal.events - shown
+ local hidden = #events - shown
for i = 1, shown do
- local e = cal.events[i]
+ local e = events[i]
if ey > floor_y then break end
local colour = cal_colour(e.calendar, colors, cal.colors)