diff options
| author | Craig Jennings <c@cjennings.net> | 2026-05-05 12:39:55 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-05-05 12:39:55 -0500 |
| commit | 3019a33d391912120a78cad43a49eb34c4a1d044 (patch) | |
| tree | 4941d154529ce988bbdeb5e1929fa6cdea35f94a /README.org | |
| parent | 26fabb22edfea51e8a686c179ab91d00a2ff0bc3 (diff) | |
| download | chime-3019a33d391912120a78cad43a49eb34c4a1d044.tar.gz chime-3019a33d391912120a78cad43a49eb34c4a1d044.zip | |
refactor!: collapse six filter defcustoms into include/exclude alists
Six per-axis filter variables (keyword/tags/predicate × whitelist/blacklist)
were carrying parallel structure for what's really one decision: include
events that look like X, exclude events that look like Y. I merged them
into two alists, `chime-include-filters' and `chime-exclude-filters', each
keyed by axis (`keywords', `tags', `predicates').
Default for `chime-exclude-filters' keeps the same out-of-the-box
behavior — done items and declined Google Calendar invites stay
filtered:
((predicates . (chime-done-keywords-predicate
chime-declined-events-predicate)))
Implementation: one shared `chime--filter-predicates' helper that walks
the alist and emits a marker-taking predicate per non-empty axis. The
public callers — now `chime--apply-include-filters' and
`chime--apply-exclude-filters' — wrap that helper with
`-orfn'-then-`-filter' and `-orfn'-then-`-remove' respectively. The
async-environment regex injection list shrank from six names to two,
and the debug config dump in chime-debug.el follows.
The terminology shift (whitelist/blacklist → include/exclude) drops
loaded language for descriptive intent. The internal helpers and the
public function names all moved together.
Tests: 700-ish lines across five test files (test-chime-apply-whitelist,
test-chime-apply-blacklist, test-chime-whitelist-blacklist-conflicts,
test-chime-environment-regex, test-chime-declined-events-predicate)
were rewritten to bind the new alists. The dedup-conflict tests still
exercise the same precedence rule (exclude wins on overlap). README's
filtering section was rewritten end-to-end with new examples.
Migration:
(setq chime-keyword-whitelist '("TODO"))
;; ->
(setq chime-include-filters '((keywords . ("TODO"))))
(setq chime-predicate-blacklist '(my-pred))
;; ->
(setq chime-exclude-filters '((predicates . (my-pred))))
This brings the consolidation pass to 37 -> 29 defcustoms, the target
from .ai/settings-consolidation.org.
Diffstat (limited to 'README.org')
| -rw-r--r-- | README.org | 113 |
1 files changed, 68 insertions, 45 deletions
@@ -79,13 +79,14 @@ The quickest way to try it out: ;; Notification settings (setq chime-notification-title "Reminder") - ;; Don't filter by TODO keywords - notify for all events - (setq chime-keyword-whitelist nil) - (setq chime-keyword-blacklist nil) + ;; Filtering — leave nil to notify for everything that isn't excluded + (setq chime-include-filters nil) - ;; Only notify for non-done items - (setq chime-predicate-blacklist - '(chime-done-keywords-predicate)) + ;; Default exclude rules: skip done items and declined invitations. + ;; (Both predicates ship with chime; this is the package default.) + (setq chime-exclude-filters + '((predicates . (chime-done-keywords-predicate + chime-declined-events-predicate)))) ;; Enable chime-mode automatically (chime-mode 1)) @@ -570,70 +571,94 @@ For maximum modeline space savings: *** Filtering -#+BEGIN_SRC elisp -;; Only notify for specific TODO keywords -(setq chime-keyword-whitelist '("TODO" "NEXT")) +Two alists control which events trigger notifications: +=chime-include-filters= (must match) and =chime-exclude-filters= (must +not match). Each takes the same shape: -;; Never notify for these keywords -(setq chime-keyword-blacklist '("DONE" "CANCELLED")) +#+BEGIN_SRC elisp +'((keywords . ("TODO" "NEXT")) ; org TODO keywords + (tags . ("work" "urgent")) ; org tags + (predicates . (my-predicate-fn))) ; functions taking a marker +#+END_SRC -;; Only notify for specific org tags -(setq chime-tags-whitelist '("important")) +When =chime-include-filters= is nil (the default), every event passes the +include phase. When it's set, an event must match at least one listed +value in any one entry. =chime-exclude-filters= then drops anything +matching any of its entries. -;; Never notify for these org-tags -(setq chime-tags-blacklist '("someday")) +#+BEGIN_SRC elisp +;; Only notify for specific TODO keywords and tags +(setq chime-include-filters + '((keywords . ("TODO" "NEXT")) + (tags . ("important")))) + +;; Never notify for these keywords or tags +(setq chime-exclude-filters + '((keywords . ("DONE" "CANCELLED")) + (tags . ("someday")) + (predicates . (chime-done-keywords-predicate + chime-declined-events-predicate)))) #+END_SRC -**** Whitelist and Blacklist Precedence +**** Include and Exclude Precedence -If the same keyword or tag appears in both a whitelist and blacklist, the *blacklist wins* and the item is filtered out. +If the same keyword or tag appears in both filters, the *exclude wins* +and the item is filtered out. Examples: -- Item with =TODO= keyword when =TODO= is in both ~chime-keyword-whitelist~ and ~chime-keyword-blacklist~ → *filtered out* (blacklist wins) -- Item with =:urgent:= tag when =urgent= is in both ~chime-tags-whitelist~ and ~chime-tags-blacklist~ → *filtered out* (blacklist wins) -- Item with whitelisted keyword but blacklisted tag → *filtered out* (blacklist wins) +- Item with =TODO= keyword when =TODO= appears under =keywords= in both filters → *filtered out* +- Item with =:urgent:= tag when =urgent= appears under =tags= in both filters → *filtered out* +- Item with an included keyword but an excluded tag → *filtered out* -Most users configure either whitelists or blacklists, not both. If you use both, ensure they don't overlap to avoid confusion. +Most users set one or the other, not both. If you set both, ensure +they don't overlap to avoid confusion. **** Custom Predicate Filtering -Keywords and tags cover most filtering needs, but sometimes you want logic they can't express — like silencing work events on weekends, or only getting notified about events in a specific file. +Keywords and tags cover most filtering needs, but sometimes you want +logic they can't express — like silencing work events on weekends, or +only getting notified about events in a specific file. -For filtering logic that goes beyond keywords and tags, you can write custom predicate functions. Each predicate receives an org marker (POM) and should return non-nil to match. Whitelisted predicates include events that match; blacklisted predicates exclude them. +For filtering logic that goes beyond keywords and tags, you can write +custom predicate functions. Each predicate receives an org marker +(POM) and should return non-nil to match. Predicates listed under the +=predicates= key in =chime-include-filters= include events that match; +predicates under =predicates= in =chime-exclude-filters= drop them. #+BEGIN_SRC elisp -;; Whitelist: only notify for events in work.org +;; Include: only notify for events in work.org (defun my-work-file-predicate (marker) "Match events that live in work.org." (string-match-p "work\\.org" (or (buffer-file-name (marker-buffer marker)) ""))) -(setq chime-predicate-whitelist '(my-work-file-predicate)) +(setq chime-include-filters + '((predicates . (my-work-file-predicate)))) -;; Blacklist: silence work events on weekends +;; Exclude: silence work events on weekends (defun my-weekend-work-silencer (marker) "Match work.org events on Saturday or Sunday." (and (memq (nth 6 (decode-time)) '(0 6)) (string-match-p "work\\.org" (or (buffer-file-name (marker-buffer marker)) "")))) -;; Blacklist: exclude events with a NO_NOTIFY property +;; Exclude: drop events with a NO_NOTIFY property (defun my-no-notify-predicate (marker) "Match events with a NO_NOTIFY property set." (org-entry-get marker "NO_NOTIFY")) -;; Whitelist: only notify for high-priority items -(defun my-priority-a-only (marker) - "Match events with a [#A] priority cookie." - (string= (org-entry-get marker "PRIORITY") "A")) - -(setq chime-predicate-blacklist - '(chime-done-keywords-predicate - my-weekend-work-silencer - my-no-notify-predicate)) +;; Compose multiple exclude predicates with chime's defaults +(setq chime-exclude-filters + '((predicates . (chime-done-keywords-predicate + chime-declined-events-predicate + my-weekend-work-silencer + my-no-notify-predicate)))) #+END_SRC -The built-in =chime-done-keywords-predicate= is in the blacklist by default, filtering out DONE items. +The built-in =chime-done-keywords-predicate= and +=chime-declined-events-predicate= ship in =chime-exclude-filters= by +default, filtering out done items and declined Google Calendar +invitations. *** All-Day Events @@ -856,13 +881,11 @@ If you have custom variables that need to be available in chime's async subproce ;; Notification settings (setq chime-notification-title "Reminder") - ;; Don't filter by TODO keywords - notify for all events - (setq chime-keyword-whitelist nil) - (setq chime-keyword-blacklist nil) - - ;; Only notify for non-done items - (setq chime-predicate-blacklist - '(chime-done-keywords-predicate)) + ;; Filtering — leave nil to notify for everything that isn't excluded + (setq chime-include-filters nil) + (setq chime-exclude-filters + '((predicates . (chime-done-keywords-predicate + chime-declined-events-predicate)))) ;; Enable chime-mode automatically (chime-mode 1)) @@ -1055,7 +1078,7 @@ It also monitors event loading timing and async process performance in the backg 1. Ensure files are in =org-agenda-files= 2. Verify timestamps have time components: =<2025-10-25 Sat 14:00>= not =<2025-10-25 Sat>= -3. Check filtering settings (keyword/tag whitelist/blacklist) +3. Check filtering settings (`chime-include-filters' / `chime-exclude-filters') 4. Timestamps support both 24-hour (=14:00=) and 12-hour (=2:00pm=, =2:00 PM=) formats *** Multiple Emacs Instances Producing Duplicate Notifications |
