]> git.eshelyaron.com Git - emacs.git/commitdiff
Restore deferred date-stamp insertions in ERC
authorF. Jason Park <jp@neverwas.me>
Wed, 5 Jun 2024 07:22:28 +0000 (00:22 -0700)
committerEshel Yaron <me@eshelyaron.com>
Sun, 9 Jun 2024 05:31:05 +0000 (07:31 +0200)
* 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)

lisp/erc/erc-stamp.el
test/lisp/erc/erc-scenarios-stamp.el

index a9ffdb18ba7c43084536288461a62e2d613ca425..7788f0b2d684e5cc10e3692757d455357ca0d8f1 100644 (file)
@@ -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
index 6f2fbc1b7e975b8382cf6b5c828b36cbef4a8038..2e836e163bc9f1604e1022bc8bf3e9568f7f68d8 100644 (file)
 
         (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