diff options
| -rw-r--r-- | README.md | 3 | ||||
| -rwxr-xr-x | bin/calendar-sample.sh | 10 | ||||
| -rw-r--r-- | lib/data.lua | 15 | ||||
| -rw-r--r-- | test/test_data.lua | 8 | ||||
| -rw-r--r-- | widgets/calendar.lua | 13 |
5 files changed, 42 insertions, 7 deletions
@@ -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) |
