<feed xmlns='http://www.w3.org/2005/Atom'>
<title>dotemacs/modules/calendar-sync-ics.el, branch main</title>
<subtitle>My Emacs configuration
</subtitle>
<id>https://git.cjennings.net/dotemacs/atom?h=main</id>
<link rel='self' href='https://git.cjennings.net/dotemacs/atom?h=main'/>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/'/>
<updated>2026-06-29T09:23:56+00:00</updated>
<entry>
<title>refactor: split calendar-sync.el into layered modules</title>
<updated>2026-06-29T09:23:56+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-29T09:23:56+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=54250d958f2829ff0f44a223a1481b6ec55a6d91'/>
<id>urn:sha1:54250d958f2829ff0f44a223a1481b6ec55a6d91</id>
<content type='text'>
Break the 1724-line calendar-sync.el into a thin public face plus four layered libraries, moving every function verbatim so behavior and public names are unchanged:

- calendar-sync-ics.el — base parsing: RFC 5545 text cleaning, VEVENT property extraction, attendee/organizer/URL parsing, timezone and timestamp conversion, date arithmetic, single-event parsing. Depends on neither of the other new modules.
- calendar-sync-recurrence.el — RRULE/EXDATE/RECURRENCE-ID expansion.
- calendar-sync-org.el — Org rendering and atomic file output.
- calendar-sync-source.el — sync state and persistence, async .ics fetch, the batch conversion worker, and the Google Calendar API path.

calendar-sync.el keeps configuration, the parse orchestrator, sync dispatch, the user commands, the timer, and the C-; g keymap, and requires the four layers. Each layer forward-declares the config defvars it reads, so no layer requires the top module back. The batch worker loads the whole graph, so source forward-declares the two functions it calls there.

Every public name is preserved, so all 574 existing calendar-sync tests pass unchanged through the require chain. The four new modules carry the load-graph and package headers and join the header-contract allowlist.

Claude-Session: https://claude.ai/code/session_014fyKMTTqLrZpL3rDF3dYc3
</content>
</entry>
</feed>
