From: F. Jason Park Date: Wed, 5 Jun 2024 07:22:28 +0000 (-0700) Subject: Restore deferred date-stamp insertions in ERC X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=e976769ed996e218f6f1d5f52b8c7a738f02bc83;p=emacs.git Restore deferred date-stamp insertions in ERC * lisp/erc/erc-stamp.el (erc-stamp--recover-on-reconnect): Treat `erc-stamp--deferred-date-stamp' as a permanent-local variable. (erc-stamp--date): Document expected possible values for `fn' slot. (erc-stamp--defer-date-insertion-on-post-modify): Use the function `ignore' to mean a new `erc-timer-hook' member has been requested. Use nil to mean one has already run. Deferred date stamps are new in ERC 5.6 and Emacs 30. (erc-stamp--date-mode): Improve doc string. * test/lisp/erc/erc-scenarios-stamp.el (erc-scenarios-stamp--date-mode/reconnect): New test. (cherry picked from commit f6bfa1844b53d6ccd24fd02092ae482d481fc5a5) --- diff --git a/lisp/erc/erc-stamp.el b/lisp/erc/erc-stamp.el index a9ffdb18ba7..7788f0b2d68 100644 --- a/lisp/erc/erc-stamp.el +++ b/lisp/erc/erc-stamp.el @@ -203,6 +203,7 @@ from entering them and instead jump over them." (dolist (var '(erc-timestamp-last-inserted erc-timestamp-last-inserted-left erc-timestamp-last-inserted-right + erc-stamp--deferred-date-stamp erc-stamp--date-stamps)) (when-let (existing (alist-get var priors)) (set var existing))))) @@ -668,7 +669,9 @@ value of t means the option's value doesn't require trimming.") :documentation "Time recorded by `erc-insert-timestamp-left-and-right'.") ( str (error "Missing `str' field") :type string :documentation "Stamp rendered by `erc-insert-timestamp-left-and-right'.") - ( fn nil :type (or null function) + ( fn #'ignore :type (or null function) + ;; Use `ignore' as a third state to mean the creation of a bespoke + ;; date-insertion function has been requested but not completed. :documentation "Deferred insertion function created by post-modify hook.") ( marker (make-marker) :type marker :documentation "Insertion marker.")) @@ -701,6 +704,9 @@ Non-nil between insertion-modification and \"done\" (or timer) hook.") (defun erc-stamp--find-insertion-point (p target-time) "Scan buffer backwards from P looking for TARGET-TIME. Return P or, if found, a position less than P." + ;; Continue searching after encountering a message without a + ;; timestamp because date stamps must be unique, and + ;; "Re-establishing connection" messages should have stamps. (while-let ((q (previous-single-property-change (1- p) 'erc--ts)) (qq (erc--get-inserted-msg-beg q)) (ts (get-text-property qq 'erc--ts)) @@ -720,7 +726,7 @@ inserted is a date stamp." Do so when `erc-stamp--deferred-date-stamp' and its `fn' slot are non-nil." (when-let ((data erc-stamp--deferred-date-stamp) - ((null (erc-stamp--date-fn data))) + ((eq (erc-stamp--date-fn data) #'ignore)) (ct (erc-stamp--date-ts data)) (rendered (erc-stamp--date-str data)) (buffer (current-buffer)) @@ -730,7 +736,7 @@ non-nil." (fset symbol (lambda (&rest _) (remove-hook hook-var symbol) - (setf (erc-stamp--date-fn data) #'ignore) + (setf (erc-stamp--date-fn data) nil) (when (buffer-live-p buffer) (with-current-buffer buffer (setq erc-stamp--date-stamps @@ -770,7 +776,21 @@ non-nil." ;; a standalone module to allow completely decoupling from and ;; possibly deprecating `erc-insert-timestamp-left-and-right'. (define-minor-mode erc-stamp--date-mode - "Insert date stamps as standalone messages." + "When enabled, insert date stamps as standalone messages. +Only do so when `erc-insert-timestamp-function' is set to +`erc-insert-timestamp-left-and-right'. On `erc-insert-modify-hook', +hold off on inserting a date stamp immediately because that would force +other members of the hook to rely on heuristics and implementation +details to detect a prepended stamp's presence, not to mention +compromise the integrity of the `erc-parsed' text property. Instead, +tell `erc-insert-post-hook', via `erc-stamp--deferred-date-stamp', to +schedule a date stamp for insertion on the next go around of +`erc-timer-hook', which only runs on server-sent messages. Expect users +to know that non-server-sent messages, such as local informational +messages, won't induce a date stamp's insertion but will instead defer +it until the next arrival, which can include \"PING\"s or messages that +otherwise don't insert anything, such as those skipped on account of +`erc-ignore'." :interactive nil (if erc-stamp--date-mode (progn diff --git a/test/lisp/erc/erc-scenarios-stamp.el b/test/lisp/erc/erc-scenarios-stamp.el index 6f2fbc1b7e9..2e836e163bc 100644 --- a/test/lisp/erc/erc-scenarios-stamp.el +++ b/test/lisp/erc/erc-scenarios-stamp.el @@ -180,4 +180,50 @@ (funcall expect 5 "This server is in debug mode"))))) +;; Assert that only one date stamp per day appears in the server +;; buffer when reconnecting. +(ert-deftest erc-scenarios-stamp--date-mode/reconnect () + :tags '(:expensive-test) + (erc-scenarios-common-with-cleanup + ((erc-scenarios-common-dialog "base/reconnect") + (erc-server-flood-penalty 0.1) + (erc-stamp--tz t) + (erc-server-auto-reconnect t) + ;; Start close to midnight: 2024-06-02T23:58:11.055Z + (erc-stamp--current-time (if (< emacs-major-version 29) + '(26205 1811 55000 0) + '(1717372691055 . 1000))) + (erc-insert-post-hook (cons (lambda () + (setq erc-stamp--current-time + (time-add erc-stamp--current-time 0.1))) + erc-insert-post-hook)) + (dumb-server (erc-d-run "localhost" t + 'unexpected-disconnect 'unexpected-disconnect)) + ;; Define overriding formatting function for catalog entry + ;; `disconnected' to spoof time progressing past midnight. + (erc-message-english-disconnected + (let ((orig erc-message-english-disconnected)) + (lambda (&rest _) + (setq erc-stamp--current-time + (time-add erc-stamp--current-time 120)) + orig))) + (port (process-contact dumb-server :service)) + (expect (erc-d-t-make-expecter))) + + (ert-info ("Connect") + (with-current-buffer (erc :server "127.0.0.1" + :port port + :nick "tester" + :full-name "tester") + (funcall expect 10 "debug mode"))) + + ;; Ensure date stamps are unique per server buffer. + (with-current-buffer "FooNet" + (funcall expect 10 "[Mon Jun 3 2024]") + (funcall expect -0.1 "[Mon Jun 3 2024]") ; no duplicates + (funcall expect 10 "[00:00]") + (funcall expect -0.1 "[00:00]") + (funcall expect 10 "Welcome to the foonet") + (delete-process erc-server-process)))) + ;;; erc-scenarios-stamp.el ends here