#!/bin/bash # Sample khal's upcoming events into a cache file, for widgets/calendar.lua. # # Conky's Lua has no way to run a process, and shelling out to khal every two # seconds would fork a Python interpreter per draw. khal takes ~200ms to start, # which is two orders of magnitude more than the whole frame budget. set -u CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/udt" CACHE="$CACHE_DIR/calendar.txt" umask 077 mkdir -p "$CACHE_DIR" TMP="$CACHE.tmp.$$" trap 'rm -f "$TMP"' EXIT # {start-date-long}, not {start-date}: the latter renders with khal's # `dateformat`, which here is '%d.%m.' with no year at all, so an event in # January sorts before one in December of the year before and the widget cannot # tell which is which. The long form uses `longdateformat` and carries the # year. Both are the user's own format strings and khal offers no ISO override # (a strftime spec inside the field, '{start-date:%Y-%m-%d}', raises), so the # widget parses the three numbers out by position rather than assuming an # order. # # --day-format '' suppresses the 'Today, 18.09.2026' header lines khal # interleaves between days; without it every group of events is preceded by a # line that does not parse as a record. # # Fields are pipe-separated: a title may contain anything except a newline, so # the separator has to be a character no date, time or calendar name uses, and # the parser splits on the first four only, leaving the title intact even if it # contains a pipe itself. # # 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. EVENTS=$(khal list --day-format '' \ --format '{start-date-long}|{start-time}|{end-time}|{calendar}|{title}' \ --notstarted today 8d 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 # 'generated' key as "the sampler never ran" and an empty event list as "no # events", which are genuinely different states and read differently on the # card. { echo "generated $(date +%s)" date +'today %Y-%m-%d' # Calendar colours, as khal itself declares them. Parsed from khal's config # rather than hardcoded, so adding a calendar does not mean editing Lua. # Only the [[name]] / color = value pairs inside [calendars]; the section # test stops at the next top-level [section] so a 'color' key elsewhere in # the config cannot be misread as a calendar's. awk ' /^\[calendars\]/ { in_cal = 1; next } /^\[[^[]/ { in_cal = 0 } in_cal && /^\[\[/ { name = $0 gsub(/^\[\[|\]\]$/, "", name) next } in_cal && /^[ \t]*color[ \t]*=/ { sub(/^[^=]*=[ \t]*/, "") if (name != "") print "color " name " " $0 } ' "${XDG_CONFIG_HOME:-$HOME/.config}/khal/config" 2>/dev/null if [ -n "$EVENTS" ]; then printf '%s\n' "$EVENTS" | sed 's/^/event /' fi } > "$TMP" mv -f "$TMP" "$CACHE"