From ce396bd2683b0ca4e11279af73f8e733dc16ddc6 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Thu, 9 Jul 2026 16:08:47 -0500 Subject: fix: inject the lookahead variables into the async fetch child The child sizes its agenda span from chime-modeline-lookahead-minutes and chime-tooltip-lookahead-hours, but neither was in chime-default-environment-regex. The child requires chime, so both were bound there at their defaults. Customizing either did nothing past the default eight days, with no error to explain why. The tooltip docstring invites 8760 hours to see distant events, and that setting was inert. I added both names to the injected set. The test that matters walks the child form and fails on any chime defcustom it reads that the regex doesn't cover, so a variable added to the child later can't reintroduce this quietly. Its companions pin the regex's anchoring and the additional-regexes extension point. --- chime.el | 8 ++- tests/test-chime-async-injection.el | 101 ++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 tests/test-chime-async-injection.el diff --git a/chime.el b/chime.el index dc74a8f..56fd9d1 100644 --- a/chime.el +++ b/chime.el @@ -1839,7 +1839,13 @@ because that is what real org-gcal exports use." "org-todo-keywords" "chime-alert-intervals" "chime-include-filters" - "chime-exclude-filters"))) + "chime-exclude-filters" + ;; The child sizes its agenda span from these two. The + ;; child requires chime, so an uninjected one is bound at + ;; its default there and a user's customization is + ;; silently ignored rather than erroring. + "chime-modeline-lookahead-minutes" + "chime-tooltip-lookahead-hours"))) string-end))) (defun chime--environment-regex () diff --git a/tests/test-chime-async-injection.el b/tests/test-chime-async-injection.el new file mode 100644 index 0000000..3c9e304 --- /dev/null +++ b/tests/test-chime-async-injection.el @@ -0,0 +1,101 @@ +;;; test-chime-async-injection.el --- Tests for async environment injection -*- lexical-binding: t; -*- + +;; Copyright (C) 2024-2026 Craig Jennings + +;; Author: Craig Jennings + +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;;; Commentary: + +;; Tests that every chime defcustom the async child reads is injected into +;; the child by `chime--environment-regex'. +;; +;; The child calls (require 'chime), so an uninjected defcustom is still +;; *bound* there -- at its default. A user who customizes it sees no error +;; and no effect, which is the worst shape a bug can take. That is exactly +;; what happened to chime-tooltip-lookahead-hours: the docstring invites +;; 8760 "to see distant events", and the child kept fetching 168 hours. +;; +;; The load-bearing test walks the child form and fails on any chime +;; defcustom it reads that the regex doesn't cover, so a variable added to +;; the child later cannot reintroduce the bug quietly. + +;;; Code: + +(require 'test-bootstrap (expand-file-name "test-bootstrap.el")) + +;;; Helpers + +(defun test-chime-injection--symbols (form) + "Return every symbol appearing anywhere in FORM." + (cond + ((symbolp form) (and form (list form))) + ((consp form) (append (test-chime-injection--symbols (car form)) + (test-chime-injection--symbols (cdr form)))) + (t nil))) + +(defun test-chime-injection--chime-defcustoms (form) + "Return the chime defcustoms appearing in FORM, deduplicated." + (seq-uniq + (seq-filter (lambda (sym) + (and (custom-variable-p sym) + (string-prefix-p "chime-" (symbol-name sym)))) + (test-chime-injection--symbols form)))) + +;;; Normal Cases + +(ert-deftest test-chime-async-injection-covers-every-chime-defcustom-in-the-child () + "Every chime defcustom the async child reads is injected into it. +An uninjected one silently runs at its default in the child, so a user's +customization is ignored without any error." + (let* ((form (chime--retrieve-events)) + (regex (chime--environment-regex)) + (uncovered (seq-remove + (lambda (sym) (string-match-p regex (symbol-name sym))) + (test-chime-injection--chime-defcustoms form)))) + (should-not uncovered))) + +(ert-deftest test-chime-async-injection-covers-the-lookahead-variables () + "Both lookahead variables reach the child. +The child sizes its agenda span from them, so without injection it fetches +the default 168-hour window no matter what the user set." + (let ((regex (chime--environment-regex))) + (should (string-match-p regex "chime-modeline-lookahead-minutes")) + (should (string-match-p regex "chime-tooltip-lookahead-hours")))) + +(ert-deftest test-chime-async-injection-covers-the-pre-existing-variables () + "The variables injected before the lookahead fix still are." + (let ((regex (chime--environment-regex))) + (dolist (name '("org-agenda-files" "load-path" "org-todo-keywords" + "chime-alert-intervals" "chime-include-filters" + "chime-exclude-filters")) + (should (string-match-p regex name))))) + +;;; Boundary Cases + +(ert-deftest test-chime-async-injection-regex-is-anchored () + "The regex matches whole variable names, not substrings. +Without anchoring, a user's unrelated `my-org-agenda-files-backup' would +be swept into the child." + (let ((regex (chime--environment-regex))) + (should-not (string-match-p regex "my-org-agenda-files")) + (should-not (string-match-p regex "org-agenda-files-extra")))) + +(ert-deftest test-chime-async-injection-honors-additional-regexes () + "`chime-additional-environment-regexes' extends the injected set." + (let* ((chime-additional-environment-regexes '("\\`my-var\\'")) + (regex (chime--environment-regex))) + (should (string-match-p regex "my-var")) + (should (string-match-p regex "org-agenda-files")))) + +(provide 'test-chime-async-injection) +;;; test-chime-async-injection.el ends here -- cgit v1.2.3