(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)
(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
(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)
(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"
(erc-display-message parsed nil (current-buffer)
(erc-format-privmessage "bob" "hi" nil t)))
(goto-char 3)
- (should (looking-at "<bob> hi"))
- (goto-char 11)
- (should (looking-back "<bob> 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 "<bob> 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 "<bob> 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 "<bob> 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)