From 7576926bea34c45ea9b035b59b8a9d3967311f60 Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Sun, 24 Dec 2023 11:49:26 -0800 Subject: [PATCH] Replace erc--get-inserted-msg-bounds with functions * lisp/erc/erc-fill.el (erc-fill--wrap-rejigger-region): Call `erc--get-inserted-msg-end' instead of `erc--get-inserted-msg-bounds' with `end' arg. * lisp/erc/erc-truncate.el (erc-truncate-buffer-to-size): Call `erc--get-inserted-msg-beg' with `point' instead of `erc--get-inserted-msg-bounds' with `beg' arg. * lisp/erc/erc.el (erc--get-inserted-msg-beg-at, erc--get-inserted-msg-end-at): New macros. (erc--get-inserted-msg-beg, erc--get-inserted-msg-end): New functions. (erc--get-inserted-msg-bounds): Convert to function with different signature, and refactor. This was introduced for the yet unreleased 5.6 (Emacs 30) by bug#60936. (erc--get-inserted-msg-prop): Use `erc--get-inserted-msg-beg' instead of `erc--get-inserted-msg-bounds' with `beg' arg. (erc--delete-inserted-message): Update call site of `erc--get-inserted-msg-bounds' to match new signature. (erc-cmd-CLEAR): Use `erc--get-inserted-msg-beg' instead of `erc--get-inserted-msg-bounds' with `beg' arg. * test/lisp/erc/erc-scenarios-match.el (erc-scenarios-match--stamp-right-fools-invisible): Call `erc--get-inserted-msg-end' instead of `erc--get-inserted-msg-bounds'. * test/lisp/erc/erc-tests.el (erc-tests--get-inserted-msg-setup, erc-tests--assert-get-inserted-msg, erc-tests--assert-get-inserted-msg/basic, erc-tests--assert-get-inserted-msg/stamp, erc-tests--assert-get-inserted-msg-readonly-with): New helper functions. (erc--get-inserted-msg-beg/basic, erc--get-inserted-msg-beg/readonly, erc--get-inserted-msg-beg/stamp, erc--get-inserted-msg-beg/readonly/stamp, erc--get-inserted-msg-end/basic, erc--get-inserted-msg-end/stamp, erc--get-inserted-msg-end/readonly, erc--get-inserted-msg-end/readonly/stamp, erc--get-inserted-msg-bounds/readonly, erc--get-inserted-msg-bounds/stamp, erc--get-inserted-msg-bounds/readonly/stamp): New tests. (erc--get-inserted-msg-bounds, erc--get-inserted-msg-bounds/basic): Move `beg' and `end' cases to separate test variants and rename former to latter. --- lisp/erc/erc-fill.el | 2 +- lisp/erc/erc-truncate.el | 2 +- lisp/erc/erc.el | 65 +++++++------ test/lisp/erc/erc-scenarios-match.el | 2 +- test/lisp/erc/erc-tests.el | 131 ++++++++++++++++++++------- 5 files changed, 139 insertions(+), 63 deletions(-) diff --git a/lisp/erc/erc-fill.el b/lisp/erc/erc-fill.el index 16ae5bae8d5..03d16c2fcce 100644 --- a/lisp/erc/erc-fill.el +++ b/lisp/erc/erc-fill.el @@ -768,7 +768,7 @@ With REPAIRP, destructively fill gaps and re-merge speakers." ;; Skip to end of message upon encountering accidental gaps ;; introduced by third parties (or bugs). (if-let (((/= ?\n (char-after end))) - (next (erc--get-inserted-msg-bounds 'end beg))) + (next (erc--get-inserted-msg-end beg))) (progn (cl-assert (= ?\n (char-after next))) (when repairp ; eol <= next diff --git a/lisp/erc/erc-truncate.el b/lisp/erc/erc-truncate.el index 3350cbd13b7..18c2396d58a 100644 --- a/lisp/erc/erc-truncate.el +++ b/lisp/erc/erc-truncate.el @@ -102,7 +102,7 @@ present in `erc-modules'." ;; Truncate at message boundary (formerly line boundary ;; before 5.6). (goto-char end) - (goto-char (or (erc--get-inserted-msg-bounds 'beg) + (goto-char (or (erc--get-inserted-msg-beg end) (pos-bol))) (setq end (point)) ;; try to save the current buffer using diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index ab9c769cbbf..02bfda143bc 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -3210,34 +3210,45 @@ stored value. Otherwise, return the stored value." (v (gethash prop erc--msg-props))) (if (consp val) (memq v val) (if val (eq v val) v)))) -(defmacro erc--get-inserted-msg-bounds (&optional only point) - "Return the bounds of a message in an ERC buffer. -Return ONLY one side when the first arg is `end' or `beg'. With -POINT, search from POINT instead of `point'." - ;; TODO add edebug spec. - `(let* ((point ,(or point '(point))) - (at-start-p (get-text-property point 'erc--msg))) - (and-let* - (,@(and (member only '(nil beg 'beg)) - '((b (or (and at-start-p point) - (and-let* - ((p (previous-single-property-change point - 'erc--msg))) - (if (= p (1- point)) - (if (get-text-property p 'erc--msg) p (1- p)) - (1- p))))))) - ,@(and (member only '(nil end 'end)) - '((e (1- (next-single-property-change - (if at-start-p (1+ point) point) - 'erc--msg nil erc-insert-marker)))))) - ,(pcase only - ('(quote beg) 'b) - ('(quote end) 'e) - (_ '(cons b e)))))) +(defmacro erc--get-inserted-msg-beg-at (point at-start-p) + (macroexp-let2* nil ((point point) + (at-start-p at-start-p)) + `(or (and ,at-start-p ,point) + (and-let* ((p (previous-single-property-change ,point 'erc--msg))) + (if (and (= p (1- ,point)) (get-text-property p 'erc--msg)) + p + (1- p)))))) + +(defmacro erc--get-inserted-msg-end-at (point at-start-p) + (macroexp-let2 nil point point + `(1- (next-single-property-change (if ,at-start-p (1+ ,point) ,point) + 'erc--msg nil erc-insert-marker)))) + +(defun erc--get-inserted-msg-beg (&optional point) + "Maybe return the start of message in an ERC buffer." + (erc--get-inserted-msg-beg-at (or point (setq point (point))) + (get-text-property point 'erc--msg))) + +(defun erc--get-inserted-msg-end (&optional point) + "Return the end of message in an ERC buffer. +Include any trailing white space before final newline. Expect +POINT to be less than `erc-insert-marker', and don't bother +considering `erc--insert-marker', for now." + (erc--get-inserted-msg-end-at (or point (setq point (point))) + (get-text-property point 'erc--msg))) + +(defun erc--get-inserted-msg-bounds (&optional point) + "Return bounds of message at POINT in an ERC buffer when found. +Search from POINT, when non-nil, instead of `point'. Return nil +if not found." + (let ((at-start-p (get-text-property (or point (setq point (point))) + 'erc--msg))) + (and-let* ((b (erc--get-inserted-msg-beg-at point at-start-p))) + (cons b (erc--get-inserted-msg-end-at point at-start-p))))) (defun erc--get-inserted-msg-prop (prop) "Return the value of text property PROP for some message at point." - (and-let* ((stack-pos (erc--get-inserted-msg-bounds 'beg))) + (and-let* ((stack-pos (erc--get-inserted-msg-beg (point)))) (get-text-property stack-pos prop))) (defmacro erc--with-inserted-msg (&rest body) @@ -3525,7 +3536,7 @@ subsequent message." (save-restriction (widen) (unless end - (setq end (erc--get-inserted-msg-bounds nil beg-or-point) + (setq end (erc--get-inserted-msg-bounds beg-or-point) beg (pop end))) (with-silent-modifications (if erc-legacy-invisible-bounds-p @@ -4167,7 +4178,7 @@ 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))))) + (or (erc--get-inserted-msg-beg (point)) (pos-bol))))) (run-hook-with-args 'erc--pre-clear-functions max) (delete-region (point-min) max))) t) diff --git a/test/lisp/erc/erc-scenarios-match.el b/test/lisp/erc/erc-scenarios-match.el index 0eed1853879..b18c0a4bd17 100644 --- a/test/lisp/erc/erc-scenarios-match.el +++ b/test/lisp/erc/erc-scenarios-match.el @@ -191,7 +191,7 @@ (should (= (next-single-property-change msg-end 'invisible) end))))) (lambda () - (let ((end (erc--get-inserted-msg-bounds 'end))) + (let ((end (erc--get-inserted-msg-end (point)))) ;; This message has a time stamp like all the others. (should (eq (field-at-pos (1- end)) 'erc-timestamp)) diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index 8a28d351b0f..1d2090e1027 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -1754,7 +1754,7 @@ (should-not calls)))))) -(ert-deftest erc--get-inserted-msg-bounds () +(defun erc-tests--get-inserted-msg-setup () (erc-mode) (erc--initialize-markers (point) nil) (let ((parsed (make-erc-response :unparsed ":bob PRIVMSG #chan :hi" @@ -1766,42 +1766,107 @@ (erc-display-message parsed nil (current-buffer) (erc-format-privmessage "bob" "hi" nil t))) (goto-char 3) - (should (looking-at " hi")) - (goto-char 11) - (should (looking-back " hi")) - - (ert-info ("Parameter `only' being `beg'") - (dolist (i (number-sequence 3 11)) - (goto-char i) - (ert-info ((format "At %d (%c)" i (char-after i))) - (should (= 3 (erc--get-inserted-msg-bounds 'beg))))) - - (ert-info ("Parameter `point'") - (dolist (i (number-sequence 3 11)) - (ert-info ((format "At %d (%c)" i (char-after i))) - (should (= 3 (erc--get-inserted-msg-bounds 'beg i))))))) + (should (looking-at " hi"))) - (ert-info ("Parameter `only' being `end'") - (dolist (i (number-sequence 3 11)) +;; All these bounds-finding functions take an optional POINT argument. +;; So run each case with and without it at each pos in the message. +(defun erc-tests--assert-get-inserted-msg (from to assert-fn) + (dolist (pt-arg '(nil t)) + (dolist (i (number-sequence from to)) (goto-char i) - (ert-info ((format "At %d (%c)" i (char-after i))) - (should (= 11 (erc--get-inserted-msg-bounds 'end))))) + (ert-info ((format "At %d (%c) %s param" i (char-after i) + (if pt-arg "with" ""))) + (funcall assert-fn (and pt-arg i)))))) - (ert-info ("Parameter `point'") - (dolist (i (number-sequence 3 11)) - (ert-info ((format "At %d (%c)" i (char-after i))) - (should (= 11 (erc--get-inserted-msg-bounds 'end i))))))) - - (ert-info ("Parameter `only' being nil") - (dolist (i (number-sequence 3 11)) - (goto-char i) - (ert-info ((format "At %d (%c)" i (char-after i))) - (should (equal '(3 . 11) (erc--get-inserted-msg-bounds nil))))) +(defun erc-tests--assert-get-inserted-msg/basic (test-fn) + (erc-tests--get-inserted-msg-setup) + (goto-char 11) + (should (looking-back " hi")) + (erc-tests--assert-get-inserted-msg 3 11 test-fn)) - (ert-info ("Parameter `point'") - (dolist (i (number-sequence 3 11)) - (ert-info ((format "At %d (%c)" i (char-after i))) - (should (equal '(3 . 11) (erc--get-inserted-msg-bounds nil i)))))))) +(defun erc-tests--assert-get-inserted-msg/stamp (test-fn) + (require 'erc-stamp) + (defvar erc-insert-timestamp-function) + (defvar erc-timestamp-format) + (defvar erc-timestamp-use-align-to) + (let ((erc-insert-modify-hook erc-insert-modify-hook) + (erc-insert-timestamp-function 'erc-insert-timestamp-right) + (erc-timestamp-use-align-to 0) + (erc-timestamp-format "[00:00]")) + (cl-pushnew 'erc-add-timestamp erc-insert-modify-hook) + (erc-tests--get-inserted-msg-setup)) + (goto-char 19) + (should (looking-back (rx " hi [00:00]"))) + (erc-tests--assert-get-inserted-msg 3 19 test-fn)) + +;; This is a "mixin" and requires a base assertion function to work. +(defun erc-tests--assert-get-inserted-msg-readonly-with (assert-fn test-fn) + (defvar erc-readonly-mode) + (defvar erc-readonly-mode-hook) + (let ((erc-readonly-mode nil) + (erc-readonly-mode-hook nil) + (erc-send-post-hook erc-send-post-hook) + (erc-insert-post-hook erc-insert-post-hook)) + (erc-readonly-mode +1) + (funcall assert-fn test-fn))) + +(ert-deftest erc--get-inserted-msg-beg/basic () + (erc-tests--assert-get-inserted-msg/basic + (lambda (arg) (should (= 3 (erc--get-inserted-msg-beg arg)))))) + +(ert-deftest erc--get-inserted-msg-beg/readonly () + (erc-tests--assert-get-inserted-msg-readonly-with + #'erc-tests--assert-get-inserted-msg/basic + (lambda (arg) (should (= 3 (erc--get-inserted-msg-beg arg)))))) + +(ert-deftest erc--get-inserted-msg-beg/stamp () + (erc-tests--assert-get-inserted-msg/stamp + (lambda (arg) (should (= 3 (erc--get-inserted-msg-beg arg)))))) + +(ert-deftest erc--get-inserted-msg-beg/readonly/stamp () + (erc-tests--assert-get-inserted-msg-readonly-with + #'erc-tests--assert-get-inserted-msg/stamp + (lambda (arg) (should (= 3 (erc--get-inserted-msg-beg arg)))))) + +(ert-deftest erc--get-inserted-msg-end/basic () + (erc-tests--assert-get-inserted-msg/basic + (lambda (arg) (should (= 11 (erc--get-inserted-msg-end arg)))))) + +(ert-deftest erc--get-inserted-msg-end/readonly () + (erc-tests--assert-get-inserted-msg-readonly-with + #'erc-tests--assert-get-inserted-msg/basic + (lambda (arg) (should (= 11 (erc--get-inserted-msg-end arg)))))) + +(ert-deftest erc--get-inserted-msg-end/stamp () + (erc-tests--assert-get-inserted-msg/stamp + (lambda (arg) (should (= 19 (erc--get-inserted-msg-end arg)))))) + +(ert-deftest erc--get-inserted-msg-end/readonly/stamp () + (erc-tests--assert-get-inserted-msg-readonly-with + #'erc-tests--assert-get-inserted-msg/stamp + (lambda (arg) (should (= 19 (erc--get-inserted-msg-end arg)))))) + +(ert-deftest erc--get-inserted-msg-bounds/basic () + (erc-tests--assert-get-inserted-msg/basic + (lambda (arg) + (should (equal '(3 . 11) (erc--get-inserted-msg-bounds arg)))))) + +(ert-deftest erc--get-inserted-msg-bounds/readonly () + (erc-tests--assert-get-inserted-msg-readonly-with + #'erc-tests--assert-get-inserted-msg/basic + (lambda (arg) + (should (equal '(3 . 11) (erc--get-inserted-msg-bounds arg)))))) + +(ert-deftest erc--get-inserted-msg-bounds/stamp () + (erc-tests--assert-get-inserted-msg/stamp + (lambda (arg) + (should (equal '(3 . 19) (erc--get-inserted-msg-bounds arg)))))) + +(ert-deftest erc--get-inserted-msg-bounds/readonly/stamp () + (erc-tests--assert-get-inserted-msg-readonly-with + #'erc-tests--assert-get-inserted-msg/stamp + (lambda (arg) + (should (equal '(3 . 19) (erc--get-inserted-msg-bounds arg)))))) (ert-deftest erc--delete-inserted-message () (erc-mode) -- 2.39.2