Fix overlapping logs from erc-truncate-buffer-on-save

* lisp/erc/erc-button.el (erc-button--display-error-notice-with-keys):
Currently, internal "error notices" do not have timestamps.  However,
this causes alignment issues for non-`fill-wrap' users of left-sided
stamps.  The heuristic used by this change for detecting such stamps
is weak and prone to false negatives.
* lisp/erc/erc-log.el (erc-log-mode, erc-log-enable): Set explicit
depth for `erc--pre-clear-functions' to 50.
(erc-save-buffer-in-logs): Fix partial regression in which redundant
text would appear in logs that have undergone truncation via an
interactive call to this command when the deprecated option
`erc-truncate-on-save' is non-nil.
* lisp/erc/erc-stamp.el (erc-stamp-mode, erc-stamp-enable): Set
depth for `erc--pre-clear-functions' to 40.
(erc-stamp--reset-on-clear): Only add `erc-stamp--insert-date-hook'
when `erc-stamp--date-mode' is active.
* lisp/erc/erc.el (erc-cmd-CLEAR): Rework to honor but improve upon
the old behavior when called from lisp.  Do this by attempting to find
the beginning of the current message and excluding it from the
truncated portion of the buffer.  A NEWS entry describing this
behavior already exists for 5.6.
* test/lisp/erc/erc-scenarios-log.el
(erc-scenarios-log--save-buffer-in-logs/truncate-on-save): New test.
These changes originate from bug#60936.
This commit is contained in:
F. Jason Park 2023-12-19 22:33:48 -08:00
parent 34fe0b5c87
commit 9cd47017c7
5 changed files with 77 additions and 13 deletions

View file

@ -829,6 +829,7 @@ argument when calling `erc-display-message'. Otherwise, add it
to STRINGS. If STRINGS contains any trailing non-nil
non-strings, concatenate leading string members before applying
`format'. Otherwise, just concatenate everything."
(defvar erc-stamp--skip)
(let* ((buffer (if (bufferp maybe-buffer)
maybe-buffer
(when (stringp maybe-buffer)
@ -844,8 +845,10 @@ non-strings, concatenate leading string members before applying
(push head strings))
#'format))
(string (apply op strings))
(erc-insert-modify-hook (remove 'erc-add-timestamp
erc-insert-modify-hook))
;; Avoid timestamps unless left-sided.
(erc-stamp--skip (or (bound-and-true-p erc-stamp--display-margin-mode)
(not (fboundp 'erc-timestamp-offset))
(zerop (erc-timestamp-offset))))
(erc-insert-post-hook
(cons (lambda ()
(setq string (buffer-substring (point-min)

View file

@ -231,7 +231,7 @@ also be a predicate function. To only log when you are not set away, use:
(add-hook 'erc-part-hook #'erc-conditional-save-buffer)
;; append, so that 'erc-initialize-log-marker runs first
(add-hook 'erc-connect-pre-hook #'erc-log-setup-logging 'append)
(add-hook 'erc--pre-clear-functions #'erc-save-buffer-in-logs)
(add-hook 'erc--pre-clear-functions #'erc-save-buffer-in-logs 50)
(dolist (buffer (erc-buffer-list))
(erc-log-setup-logging buffer))
(erc--modify-local-map t "C-c C-l" #'erc-save-buffer-in-logs))
@ -430,7 +430,8 @@ You can save every individual message by putting this function on
(if (and erc-truncate-buffer-on-save
(called-interactively-p 'interactive))
(let ((erc-log--save-in-progress-p t))
(erc-cmd-CLEAR)
(save-excursion (goto-char erc-insert-marker)
(erc-cmd-CLEAR))
(erc-button--display-error-notice-with-keys
(erc-server-buffer) "Option `%s' is deprecated."
" Use /CLEAR instead." 'erc-truncate-buffer-on-save))

View file

@ -182,7 +182,7 @@ from entering them and instead jump over them."
(add-hook 'erc-insert-modify-hook #'erc-add-timestamp 70)
(add-hook 'erc-send-modify-hook #'erc-add-timestamp 70)
(add-hook 'erc-mode-hook #'erc-stamp--recover-on-reconnect)
(add-hook 'erc--pre-clear-functions #'erc-stamp--reset-on-clear)
(add-hook 'erc--pre-clear-functions #'erc-stamp--reset-on-clear 40)
(unless erc--updating-modules-p (erc-buffer-do #'erc-stamp--setup)))
((remove-hook 'erc-mode-hook #'erc-munge-invisibility-spec)
(remove-hook 'erc-insert-modify-hook #'erc-add-timestamp)
@ -973,8 +973,9 @@ with the option `erc-echo-timestamps', see the companion option
(defun erc-stamp--reset-on-clear (pos)
"Forget last-inserted stamps when POS is at insert marker."
(when (= pos (1- erc-insert-marker))
(add-hook 'erc-stamp--insert-date-hook
#'erc-stamp--update-saved-position 0 t)
(when erc-stamp--date-mode
(add-hook 'erc-stamp--insert-date-hook
#'erc-stamp--update-saved-position 0 t))
(setq erc-timestamp-last-inserted nil
erc-timestamp-last-inserted-left nil
erc-timestamp-last-inserted-right nil)))

View file

@ -4160,12 +4160,16 @@ If no USER argument is specified, list the contents of `erc-ignore-list'."
Called with position indicating boundary of interval to be excised.")
(defun erc-cmd-CLEAR ()
"Clear the window content."
(let ((inhibit-read-only t))
(run-hook-with-args 'erc--pre-clear-functions (1- erc-insert-marker))
;; Ostensibly, `line-beginning-position' is for use in lisp code.
(delete-region (point-min) (min (line-beginning-position)
(1- erc-insert-marker))))
"Clear messages in current buffer after informing active modules.
Expect modules to perform housekeeping tasks to withstand the
disruption. When called from lisp code, only clear messages up
to but not including the one occupying the current line."
(with-silent-modifications
(let ((max (if (>= (point) erc-insert-marker)
(1- erc-insert-marker)
(or (erc--get-inserted-msg-bounds 'beg) (pos-bol)))))
(run-hook-with-args 'erc--pre-clear-functions max)
(delete-region (point-min) max)))
t)
(put 'erc-cmd-CLEAR 'process-not-needed t)

View file

@ -206,4 +206,59 @@
(erc-truncate-mode -1)
(when noninteractive (delete-directory tempdir :recursive))))
(defvar erc-insert-timestamp-function)
(declare-function erc-insert-timestamp-left "erc-stamp" (string))
(ert-deftest erc-scenarios-log--save-buffer-in-logs/truncate-on-save ()
:tags '(:expensive-test)
(erc-scenarios-common-with-cleanup
((erc-scenarios-common-dialog "base/assoc/bouncer-history")
(dumb-server (erc-d-run "localhost" t 'foonet))
(tempdir (make-temp-file "erc-tests-log." t nil nil))
(erc-log-channels-directory tempdir)
(erc-modules (cons 'log erc-modules))
(port (process-contact dumb-server :service))
(erc-truncate-buffer-on-save t)
(logchan (expand-file-name (format "#chan!tester@127.0.0.1:%d.txt" port)
tempdir))
(erc-server-flood-penalty 0.1)
(erc-insert-timestamp-function #'erc-insert-timestamp-left)
(expect (erc-d-t-make-expecter)))
(unless noninteractive
(add-hook 'kill-emacs-hook
(lambda () (delete-directory tempdir :recursive))))
(ert-info ("Connect to foonet")
(with-current-buffer (erc :server "127.0.0.1"
:port port
:nick "tester"
:password "foonet:changeme"
:full-name "tester")
(should (string= (buffer-name) (format "127.0.0.1:%d" port)))))
(with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan"))
(funcall expect 10 "<someone> [07:04:10] hi everyone")
(should-not (file-exists-p logchan))
;; Simulate an M-x erc-save-buffer-in-logs RET
(cl-letf (((symbol-function 'called-interactively-p) #'always))
(call-interactively #'erc-save-buffer-in-logs))
(should (file-exists-p logchan))
(funcall expect 10 "<alice> bob: As't please your lordship")
(erc-save-buffer-in-logs)
;; Not truncated when called by lisp code.
(should (> (buffer-size) 400)))
(ert-info ("No double entries")
(with-temp-buffer
(insert-file-contents logchan)
(funcall expect 0.1 "hi everyone")
(funcall expect -0.1 "hi everyone")
(funcall expect 0.1 "Playback Complete")
(funcall expect -0.1 "Playback Complete")
(funcall expect 10 "<alice> bob: As't")))
(erc-log-mode -1)
(when noninteractive (delete-directory tempdir :recursive))))
;;; erc-scenarios-log.el ends here