diff options
| author | Craig Jennings <c@cjennings.net> | 2026-06-14 15:43:36 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-06-14 15:43:36 -0500 |
| commit | 92c062b8b4cc70b09d5487d1cc29287ad52babdf (patch) | |
| tree | 418d0b261f85c7183ae925cc171ae13ba1322282 | |
| parent | 808607872702075e638e5813f3c2958c100cdb6c (diff) | |
| download | dotemacs-92c062b8b4cc70b09d5487d1cc29287ad52babdf.tar.gz dotemacs-92c062b8b4cc70b09d5487d1cc29287ad52babdf.zip | |
fix(erc): one mention notification, real server list, runtime require
Three audit defects. erc-modules carried the built-in notifications module while :config also added cj/erc-notify-on-mention to the same erc-text-matched-hook, so every mention popped two desktop notifications. Dropped notifications from erc-modules and kept the custom one. cj/erc-connected-servers compared a buffer's erc-server-process to itself inside with-current-buffer (always true), so it returned every ERC buffer; it now filters on erc-server-buffer-p and erc-server-process-alive. And user-constants moved from an eval-when-compile-only require to a runtime require, since user-whole-name is read at load time for erc-user-full-name.
| -rw-r--r-- | modules/erc-config.el | 9 | ||||
| -rw-r--r-- | tests/test-erc-config-connected-servers.el | 48 | ||||
| -rw-r--r-- | todo.org | 18 |
3 files changed, 70 insertions, 5 deletions
diff --git a/modules/erc-config.el b/modules/erc-config.el index 22ba7f53d..067b1e577 100644 --- a/modules/erc-config.el +++ b/modules/erc-config.el @@ -28,8 +28,10 @@ ;; Load cl-lib at compile time and runtime (lightweight, already loaded in most configs) (require 'cl-lib) (require 'keybindings) ;; provides cj/custom-keymap -(eval-when-compile (require 'erc) - (require 'user-constants)) +(eval-when-compile (require 'erc)) +;; user-constants is required at runtime, not just compile time: `user-whole-name' +;; is read at load time below (erc-user-full-name), so a standalone .elc needs it. +(require 'user-constants) ;; ------------------------------------ ERC ------------------------------------ ;; Server definitions and connection settings @@ -97,7 +99,7 @@ Change this value to use a different nickname.") (let ((server-buffers '())) (dolist (buf (erc-buffer-list)) (with-current-buffer buf - (when (eq (buffer-local-value 'erc-server-process buf) erc-server-process) + (when (and (erc-server-buffer-p) (erc-server-process-alive)) (unless (member (buffer-name) server-buffers) (push (buffer-name) server-buffers))))) @@ -222,7 +224,6 @@ Auto-adds # prefix if missing. Offers completion from configured channels." match move-to-prompt noncommands - notifications readonly services stamp diff --git a/tests/test-erc-config-connected-servers.el b/tests/test-erc-config-connected-servers.el new file mode 100644 index 000000000..7d4540d68 --- /dev/null +++ b/tests/test-erc-config-connected-servers.el @@ -0,0 +1,48 @@ +;;; test-erc-config-connected-servers.el --- cj/erc-connected-servers -*- lexical-binding: t; -*- + +;;; Commentary: +;; cj/erc-connected-servers must return only ERC *server* buffers with a live +;; process. The original test compared a buffer's own erc-server-process to the +;; same buffer-local value inside `with-current-buffer', which is always true, so +;; it returned every ERC buffer (channels, queries, dead connections). These +;; tests stub `erc-buffer-list' and the two ERC predicates so the classification +;; is exercised without a real IRC connection. + +;;; Code: + +(require 'ert) +(require 'cl-lib) + +(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory)) +(require 'erc-config) + +(ert-deftest test-erc-connected-servers-keeps-only-live-server-buffers () + "Normal: only buffers that are ERC server buffers with a live process are +returned; a channel buffer and a dead-connection server buffer are excluded." + (let ((b-server (generate-new-buffer " *erc-server*")) + (b-channel (generate-new-buffer " *erc-#chan*")) + (b-dead (generate-new-buffer " *erc-dead*"))) + (unwind-protect + (cl-letf (((symbol-function 'erc-buffer-list) + (lambda (&rest _) (list b-server b-channel b-dead))) + ((symbol-function 'erc-server-buffer-p) + (lambda (&rest _) (memq (current-buffer) (list b-server b-dead)))) + ((symbol-function 'erc-server-process-alive) + (lambda (&rest _) (eq (current-buffer) b-server)))) + (should (equal (cj/erc-connected-servers) + (list (buffer-name b-server))))) + (mapc #'kill-buffer (list b-server b-channel b-dead))))) + +(ert-deftest test-erc-connected-servers-empty-when-none-alive () + "Boundary: no live server buffers yields an empty list." + (let ((b-channel (generate-new-buffer " *erc-#chan*"))) + (unwind-protect + (cl-letf (((symbol-function 'erc-buffer-list) + (lambda (&rest _) (list b-channel))) + ((symbol-function 'erc-server-buffer-p) (lambda (&rest _) nil)) + ((symbol-function 'erc-server-process-alive) (lambda (&rest _) nil))) + (should (null (cj/erc-connected-servers)))) + (kill-buffer b-channel)))) + +(provide 'test-erc-config-connected-servers) +;;; test-erc-config-connected-servers.el ends here @@ -195,6 +195,14 @@ Spec draft: [[file:docs/theme-studio-palette-generator-spec.org][theme-studio-pa Build a constraint-first palette generator for Theme Studio: start from bg/fg, generate editable palette columns in OKLCH, preview candidate columns before applying them, and apply proposals by append/replace/regenerate modes while preserving stable column ids and existing assignments where possible. V1 is palette-only, not automatic face assignment; generator output becomes normal editable columns after apply. +** TODO [#B] theme-studio semantic theme architecture :feature:theme-studio:spec: +:PROPERTIES: +:LAST_REVIEWED: 2026-06-14 +:END: +Spec draft: [[file:docs/theme-studio-semantic-theme-architecture-spec.org][theme-studio-semantic-theme-architecture-spec.org]]. + +Design a Modus-inspired layered Theme Studio output path: palette data, semantic role mappings, face templates, and a generated theme wrapper. Keep the current flat JSON-to-theme converter as the compatibility/default path while proving a layered, self-contained generated theme. Include advisory semantic rules as a possible validation layer, not v1 enforcement. + *** TODO [#C] theme-studio palette generator source modes for base-only vs ground-aware palettes :feature: :PROPERTIES: :LAST_REVIEWED: 2026-06-14 @@ -970,11 +978,13 @@ From the 2026-06 config audit, =modules/calendar-sync.el=: - =:1284= — curl runs without =--fail=: an HTTP 404/500 error page exits 0 and the HTML proceeds into conversion. - =:1229-1233= — =--parse-ics= returns nil for both garbage and a valid calendar with zero in-window events, so healthy near-empty calendars report "parse failed" in =calendar-sync-status=. Distinguish the cases. -** TODO [#B] ERC: double mention notifications + tautological server list :bug:quick:solo: +** DONE [#B] ERC: double mention notifications + tautological server list :bug:quick:solo: +CLOSED: [2026-06-14 Sun] From the 2026-06 config audit, =modules/erc-config.el=: - =:281= — =erc-modules= includes the built-in =notifications= module AND :config adds =cj/erc-notify-on-mention= to the same hook — every mention fires two desktop notifications. Pick one path (keep the custom one, slated for messenger unification). - =:100= — =cj/erc-connected-servers=: inside =with-current-buffer=, the free =erc-server-process= is the buffer's own local value, so the eq test is tautologically true — returns ALL ERC buffers (channels, dead connections). Use =erc-server-buffer-p= + =erc-server-process-alive=. - =:238= — =user-whole-name= read at load but =user-constants= only required at compile time (same trap as auth-config/keyboard-macros). +Fixed 2026-06-14: removed =notifications= from =erc-modules= (kept the custom =cj/erc-notify-on-mention=, so one notification per mention); rewrote =cj/erc-connected-servers= to filter on =(erc-server-buffer-p)= + =(erc-server-process-alive)= instead of the tautological self-eq; moved =user-constants= to a runtime require. New test-erc-config-connected-servers.el (live-server-only + empty cases) 2 green; module byte-compiles. erc-config not reloaded into the daemon (live IRC session) — takes effect on restart. VERIFY for the one-notification + real-server-list behavior. ** TODO [#B] slack-config lifecycle gaps :bug:quick:solo: From the 2026-06 config audit, =modules/slack-config.el=: @@ -4441,6 +4451,12 @@ From the 2026-06-11 messenger-unification brainstorm. Google Voice has no offici ** TODO Manual testing and validation Exercised once the phases above land. +*** VERIFY ERC fires one mention notification and lists real servers +What we're verifying: a mention pops a single desktop notification (not two), and cj/erc-connected-servers lists only live server connections. Fixed in modules/erc-config.el; takes effect after an Emacs restart (not reloaded into the live IRC session). +- Restart Emacs and reconnect ERC +- Have someone mention your nick in a channel (or trigger erc-text-matched-hook) +- Run M-x cj/erc-connected-servers with one server connected and a few channels open +Expected: exactly one desktop notification per mention; cj/erc-connected-servers reports just the connected server(s), not every channel/query buffer. *** VERIFY modeline still shows the git branch and state What we're verifying: the VC-cache simplification didn't change what the modeline shows on a normal repo. Fixed in modules/modeline-config.el (live in the daemon after reload). - Open a file inside a git repo |
