<feed xmlns='http://www.w3.org/2005/Atom'>
<title>dotemacs.git/modules/user-constants.el, branch v0.7.2</title>
<subtitle>my Emacs configuration
</subtitle>
<id>https://git.cjennings.net/dotemacs.git/atom?h=v0.7.2</id>
<link rel='self' href='https://git.cjennings.net/dotemacs.git/atom?h=v0.7.2'/>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs.git/'/>
<updated>2026-02-21T21:17:16+00:00</updated>
<entry>
<title>fix(user-constants): create calendar data files on first launch</title>
<updated>2026-02-21T21:17:16+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-02-21T21:17:16+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs.git/commit/?id=df7cd0e30a2f338948a84c023422252c5f7ad63b'/>
<id>urn:sha1:df7cd0e30a2f338948a84c023422252c5f7ad63b</id>
<content type='text'>
org-agenda-list prompts interactively for missing files, which hangs
the async subprocess chime uses to fetch events. Create empty
placeholders at init so calendar-sync can populate them on first sync.
</content>
</entry>
<entry>
<title>chore(yasnippet): move snippets into emacs.d for source control</title>
<updated>2026-02-16T11:14:28+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-02-16T11:14:28+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs.git/commit/?id=9ed05f388d3cbd16a72f9ace130d1f59233354e7'/>
<id>urn:sha1:9ed05f388d3cbd16a72f9ace130d1f59233354e7</id>
<content type='text'>
Relocate snippets-dir from ~/sync/org/snippets/ to ~/.emacs.d/snippets/
and restore 28 snippet files from backup.
</content>
</entry>
<entry>
<title>feat(hugo): extract hugo-config module with C-; h keybindings</title>
<updated>2026-02-14T06:06:45+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-02-14T06:06:45+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs.git/commit/?id=78c3ef3c2008f72f9e46f30447c68d627bd693cd'/>
<id>urn:sha1:78c3ef3c2008f72f9e46f30447c68d627bd693cd</id>
<content type='text'>
Standalone module for ox-hugo blog workflow. One-file-per-post
structure with keybindings for new post, export, open dir (dirvish
and system file manager), and toggle draft.
</content>
</entry>
<entry>
<title>feat(calendar-sync): add RECURRENCE-ID exception handling for recurring events</title>
<updated>2026-02-03T13:39:50+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-02-03T13:39:50+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs.git/commit/?id=84a02097bf842e96f7f4dd4e4ac39e78faf64989'/>
<id>urn:sha1:84a02097bf842e96f7f4dd4e4ac39e78faf64989</id>
<content type='text'>
Handle rescheduled instances of recurring calendar events by processing
RECURRENCE-ID properties from ICS files. When someone reschedules a single
instance of a recurring meeting in Google Calendar, the calendar-sync module
now shows the rescheduled time instead of the original RRULE time.

New functions:
- calendar-sync--get-recurrence-id: Extract RECURRENCE-ID from event
- calendar-sync--get-recurrence-id-line: Get full line with TZID params
- calendar-sync--parse-recurrence-id: Parse into (year month day hour minute)
- calendar-sync--collect-recurrence-exceptions: Collect all exceptions by UID
- calendar-sync--occurrence-matches-exception-p: Match occurrences to exceptions
- calendar-sync--apply-single-exception: Apply exception data to occurrence
- calendar-sync--apply-recurrence-exceptions: Apply all exceptions to occurrences

Also adds DeepSat calendar configuration (dcal-file) to user-constants,
init.el, and org-agenda-config.

48 unit and integration tests added covering normal, boundary, and error cases.
</content>
</entry>
<entry>
<title>feat(calendar-sync): multi-calendar support with property tests</title>
<updated>2025-12-02T13:55:21+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2025-12-02T13:55:21+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs.git/commit/?id=fac78a8fc92b27c37e678ee70824eb5f70ceee8b'/>
<id>urn:sha1:fac78a8fc92b27c37e678ee70824eb5f70ceee8b</id>
<content type='text'>
Added multi-URL calendar sync supporting Google and Proton calendars.
Each calendar syncs to separate file with per-calendar state tracking.
Added 13 property-based tests for RRULE expansion. Total: 150 tests passing.
</content>
</entry>
<entry>
<title>feat(calendar-sync): Add automatic timezone detection and chronological sorting</title>
<updated>2025-11-17T00:09:17+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2025-11-17T00:09:17+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs.git/commit/?id=da0bd6883a4032054aef4b59c338f60796a0fd99'/>
<id>urn:sha1:da0bd6883a4032054aef4b59c338f60796a0fd99</id>
<content type='text'>
Implemented calendar-sync.el as a complete replacement for org-gcal, featuring:

**Core Functionality:**
- One-way sync from Google Calendar to Org (via .ics URL)
- UTC to local timezone conversion for all event timestamps
- Chronological event sorting (past → present → future)
- Non-blocking sync using curl (works reliably in daemon mode)

**Automatic Timezone Detection:**
- Detects timezone changes when traveling between timezones
- Tracks timezone offset in seconds (-21600 for CST, -28800 for PST, etc.)
- Triggers automatic re-sync when timezone changes detected
- Shows informative messages: "Timezone change detected (UTC-6 → UTC-8)"

**State Persistence:**
- Saves sync state to ~/.emacs.d/data/calendar-sync-state.el
- Persists timezone and last sync time across Emacs sessions
- Enables detection even after closing Emacs before traveling

**User Features:**
- Interactive commands: calendar-sync-now, calendar-sync-start/stop
- Keybindings: C-; g s (sync), C-; g a (start auto-sync), C-; g x (stop)
- Optional auto-sync every 15 minutes (disabled by default)
- Clear status messages for all operations

**Code Quality:**
- Comprehensive test coverage: 51 ERT tests (100% passing)
- Refactored UTC conversion into separate function
- Clean separation of concerns (parsing, conversion, formatting, sorting)
- Well-documented with timezone behavior guide and changelog

**Migration:**
- Removed org-gcal-config.el (archived in modules/archived/)
- Updated init.el to use calendar-sync
- Moved gcal.org to .emacs.d/data/ for machine-independent syncing
- Removed org-gcal appointment capture template

Files modified: modules/calendar-sync.el:442, tests/test-calendar-sync.el:577
Files created: data/calendar-sync-state.el, tests/testutil-calendar-sync.el
Documentation: docs/calendar-sync-timezones.md, docs/calendar-sync-changelog.md

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>feat(ui): Add buffer modification state to color indicators</title>
<updated>2025-11-14T07:53:30+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2025-11-14T07:53:30+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs.git/commit/?id=fd1a5d308e730bad2936adb2384897bb620458be'/>
<id>urn:sha1:fd1a5d308e730bad2936adb2384897bb620458be</id>
<content type='text'>
Change modeline filename and cursor colors to indicate buffer
modification status, not just read-only/overwrite state.

Color scheme changes:
- White (#ffffff): Unmodified writeable buffer
- Green (#64aa0f): Modified writeable buffer (unsaved changes)
- Red (#f06a3f): Read-only buffer
- Gold (#c48702): Overwrite mode active

Previously: All writeable buffers were green regardless of modification
Now: White when clean, green when dirty (better visual feedback)

Implementation:
- Updated cj/buffer-status-colors in user-constants.el:
  - Changed 'normal' → 'unmodified' (white)
  - Added new 'modified' state (green)
- Updated state detection in modeline-config.el:
  - Now checks (buffer-modified-p) before defaulting to unmodified
- Updated cursor color logic in ui-config.el:
  - Same state detection as modeline for consistency
  - Added after-change-functions hook for real-time updates
  - Added after-save-hook to update on save

Priority order (highest to lowest):
1. Read-only (red) - takes precedence over everything
2. Overwrite mode (gold) - takes precedence over modified state
3. Modified (green) - buffer has unsaved changes
4. Unmodified (white) - default for clean writeable buffers

Tests:
- 18 comprehensive tests in test-ui-buffer-status-colors.el
- Tests state detection logic and priority order
- Tests color constant definitions and mappings
- Tests integration with cursor and modeline
- All tests passing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>feat: Add complete async audio transcription workflow</title>
<updated>2025-11-04T20:35:50+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2025-11-04T20:35:50+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs.git/commit/?id=45cab5c38dc089935416a89d36b461d9127094ac'/>
<id>urn:sha1:45cab5c38dc089935416a89d36b461d9127094ac</id>
<content type='text'>
Implemented full transcription system with local Whisper and OpenAI API
support. Includes comprehensive test suite (60 tests) and reorganized
keybindings for better discoverability.

Features:
- Async transcription (non-blocking workflow)
- Desktop notifications (started/complete/error)
- Output: audio.txt (transcript) + audio.log (process logs)
- Modeline integration showing active transcription count
- Dired integration (press T on audio files)
- Process management and tracking

Scripts:
- install-whisper.sh: Install Whisper via AUR or pip
- uninstall-whisper.sh: Clean removal with cache cleanup
- local-whisper: Offline transcription using installed Whisper
- oai-transcribe: Cloud transcription via OpenAI API

Tests (60 passing):
- Audio file detection (16 tests)
- Path generation logic (11 tests)
- Log cleanup behavior (5 tests)
- Duration formatting (9 tests)
- Active counter &amp; modeline (11 tests)
- Integration workflows (8 tests)

Keybindings:
- Reorganized gcal to C-; g submenu (s/t/r/c)
- Added C-; t transcription submenu (t/b/k)
- Dired: T to transcribe file at point

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>feat: Complete modeline overhaul with custom segments and interactive features</title>
<updated>2025-11-04T00:01:24+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2025-11-04T00:01:24+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs.git/commit/?id=c0c4b176ace7910cbc1a71b5ec473873b6d821be'/>
<id>urn:sha1:c0c4b176ace7910cbc1a71b5ec473873b6d821be</id>
<content type='text'>
Replaced mood-line with a custom, minimal modeline using only built-in
Emacs functionality to avoid native compilation issues.

**Architecture:**
- Named segment system using defvar-local for easy reordering
- Emacs 30 built-in right-alignment (mode-line-format-right-align)
- All segments marked as risky-local-variable for proper evaluation

**Features:**
- Color-coded buffer names (green=writeable, red=read-only, gold=overwrite)
- VC branch with git symbol (U+E0A0) and state-based coloring
- Position format: L:line C:col
- Help-echo tooltips on all segments
- Mouse click handlers for interactive actions
- String truncation in narrow windows (&lt; 100 chars)
- Active-window-only display for branch and misc-info

**Interactive Actions:**
- Buffer name: mouse-1 = prev-buffer, mouse-3 = next-buffer
- Major mode: mouse-1 = describe-mode
- Git branch: mouse-1 = vc-diff, mouse-3 = vc-root-diff

**Bug Fixes:**
- Disabled async native compilation to prevent "Selecting deleted buffer" errors
- Fixed difftastic loading by changing :demand to :defer
- Abstracted buffer status colors to user-constants.el for reuse

Inspired by Prot's modeline design patterns.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>feat: add debug infrastructure for config modules</title>
<updated>2025-10-29T14:38:53+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2025-10-29T14:38:53+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs.git/commit/?id=bb4def1a5c3adb157d699ebb932d0de34fecd66d'/>
<id>urn:sha1:bb4def1a5c3adb157d699ebb932d0de34fecd66d</id>
<content type='text'>
This commit establishes a pattern for organizing debug code in separate
files that can be enabled/disabled via a central toggle.

## Changes

**1. Added debug toggle to user-constants.el**

New variable `cj/debug-modules` controls which modules load debug functions:
- Set to nil (default): No debug functions loaded
- Set to list of symbols: Load debug for specific modules
  Example: (setq cj/debug-modules '(org-agenda mail))
- Set to t: Load all debug modules
  Example: (setq cj/debug-modules t)

Placed early in user-constants.el so it's available before other modules load.

**2. Created org-agenda-config-debug.el**

New debug file contains:
- `cj/org-agenda-debug-dump-files` - Shows all org-agenda-files with status,
  file sizes, and modification times
- `cj/org-agenda-debug-rebuild-timing` - Measures rebuild performance and
  reports detailed timing statistics
- `cj/log-silently` - Helper function to write to *Messages* without echo

All functions use ;;;###autoload for easy invocation before explicit loading.

**3. Added conditional require to org-agenda-config.el**

Checks `cj/debug-modules` and conditionally loads org-agenda-config-debug.el:
```elisp
(when (or (eq cj/debug-modules t)
          (memq 'org-agenda cj/debug-modules))
  (require 'org-agenda-config-debug ...))
```

## Benefits

**Cleaner separation of concerns:**
- Production code stays in main config files
- Debug code isolated in *-debug.el files
- Easy to enable/disable debugging per module

**Reusable pattern:**
- Can be applied to any config module (mail, chime, etc.)
- Consistent naming: &lt;module&gt;-debug.el
- Consistent namespace: cj/&lt;module&gt;-debug-*

**Zero overhead when disabled:**
- Debug files not loaded unless explicitly enabled
- No performance impact on normal usage

## Usage

To enable org-agenda debug functions:
```elisp
;; In user-constants.el or early-init.el
(setq cj/debug-modules '(org-agenda))
```

Then restart Emacs and run:
- M-x cj/org-agenda-debug-dump-files
- M-x cj/org-agenda-debug-rebuild-timing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude &lt;noreply@anthropic.com&gt;
</content>
</entry>
</feed>
