diff options
| author | Craig Jennings <c@cjennings.net> | 2026-05-21 20:42:05 -0400 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-05-21 20:42:05 -0400 |
| commit | 099a771275607db3a362e4239c69e7ab58f3ad7c (patch) | |
| tree | 9c83a6319fcd4cfcd0dd4d93c3caeafa2cc78e8d | |
| parent | c38683f13cf361adc93b72c1e87244a0153b2387 (diff) | |
| download | dotemacs-099a771275607db3a362e4239c69e7ab58f3ad7c.tar.gz dotemacs-099a771275607db3a362e4239c69e7ab58f3ad7c.zip | |
fix(org-contacts): set org-contacts-files eagerly so launch doesn't error
At startup the agenda-finalize hook ran cj/org-contacts-anniversaries-safe, which calls org-contacts-anniversaries, which calls org-contacts-files. That function messages "[org-contacts] ERROR: Your custom variable `org-contacts-files' is nil." when the variable is nil, and at that point it was nil. The value was set via the use-package :custom, which only applies when org-contacts loads, and that load is deferred behind :after (org mu4e) — later than the first agenda finalize.
I set org-contacts-files eagerly at require time instead, so it's never nil by the time the hook fires. I also guarded the wrapper: org-contacts-files emits a message rather than signaling, so ignore-errors couldn't suppress it on its own. Now the call only runs when the variable is set.
Three tests cover the eager set, the guard skipping when files are nil, and the wrapper running when they're set. Full suite green.
| -rw-r--r-- | modules/org-contacts-config.el | 22 | ||||
| -rw-r--r-- | tests/test-org-contacts-config-anniversaries.el | 53 |
2 files changed, 71 insertions, 4 deletions
diff --git a/modules/org-contacts-config.el b/modules/org-contacts-config.el index 2f919c19..ff14629b 100644 --- a/modules/org-contacts-config.el +++ b/modules/org-contacts-config.el @@ -12,6 +12,16 @@ (require 'user-constants) +;; Set `org-contacts-files' eagerly at require time. Setting it in the +;; `use-package' form below would only apply when org-contacts loads, which is +;; deferred behind `:after (org mu4e)' -- later than the first +;; `org-agenda-finalize'. The anniversaries hook below runs on that finalize +;; and calls `org-contacts-files', which *messages* (not signals) an error when +;; the variable is nil, so the hook's `ignore-errors' can't suppress it. Set +;; it here so the variable is never nil by the time the hook fires. +(defvar org-contacts-files nil) +(setq org-contacts-files (list contacts-file)) + ;; --------------------------- Org Agenda Integration -------------------------- (with-eval-after-load 'org-agenda @@ -29,8 +39,12 @@ (let ((date (calendar-current-date)) (entry "") (original-date (calendar-current-date))) - (ignore-errors - (org-contacts-anniversaries)))) + ;; `org-contacts-anniversaries' calls `org-contacts-files', which + ;; messages an error when the variable is nil. A message isn't a + ;; signal, so `ignore-errors' alone can't suppress it -- guard the call. + (when org-contacts-files + (ignore-errors + (org-contacts-anniversaries))))) ;; Use the safe wrapper instead (add-hook 'org-agenda-finalize-hook 'cj/org-contacts-anniversaries-safe)) @@ -209,8 +223,8 @@ module provides more sophisticated completion." (use-package org-contacts :after (org mu4e) - :custom - (org-contacts-files (list contacts-file)) + ;; `org-contacts-files' is set eagerly near the top of this file, not here, + ;; so the agenda-finalize anniversaries hook never sees it nil at startup. :config (require 'mu4e) ;; Basic settings diff --git a/tests/test-org-contacts-config-anniversaries.el b/tests/test-org-contacts-config-anniversaries.el new file mode 100644 index 00000000..09e14d06 --- /dev/null +++ b/tests/test-org-contacts-config-anniversaries.el @@ -0,0 +1,53 @@ +;;; test-org-contacts-config-anniversaries.el --- Tests for org-contacts launch wiring -*- lexical-binding: t; -*- + +;;; Commentary: +;; Covers two launch-time concerns that produced the +;; "[org-contacts] ERROR: Your custom variable `org-contacts-files' is +;; nil." message at startup: +;; +;; 1. `org-contacts-files' must be set to the configured contacts file +;; as soon as the module is required -- not deferred behind the +;; package load -- so the agenda-finalize anniversaries hook never +;; sees it nil. +;; 2. `cj/org-contacts-anniversaries-safe' must not call +;; `org-contacts-anniversaries' when `org-contacts-files' is nil +;; (the function messages an error rather than signalling, so the +;; wrapper's `ignore-errors' can't suppress it). +;; +;; `org-agenda' is required first so the `with-eval-after-load' that +;; defines the wrapper fires. + +;;; Code: + +(require 'ert) +(require 'cl-lib) + +(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory)) +(require 'user-constants) +(require 'org-agenda) +(require 'org-contacts-config) + +(ert-deftest test-org-contacts-config-files-configured-on-load () + "Normal: requiring the module sets `org-contacts-files' to the contacts file." + (should (equal org-contacts-files (list contacts-file)))) + +(ert-deftest test-org-contacts-anniversaries-safe-skips-when-files-nil () + "Error: wrapper does not call `org-contacts-anniversaries' when files are nil." + (let ((called nil) + (org-contacts-files nil)) + (cl-letf (((symbol-function 'org-contacts-anniversaries) + (lambda (&rest _) (setq called t)))) + (cj/org-contacts-anniversaries-safe)) + (should-not called))) + +(ert-deftest test-org-contacts-anniversaries-safe-runs-when-files-set () + "Normal: wrapper calls `org-contacts-anniversaries' when files are configured." + (let ((called nil) + (org-contacts-files (list contacts-file))) + (cl-letf (((symbol-function 'org-contacts-anniversaries) + (lambda (&rest _) (setq called t)))) + (cj/org-contacts-anniversaries-safe)) + (should called))) + +(provide 'test-org-contacts-config-anniversaries) +;;; test-org-contacts-config-anniversaries.el ends here |
