aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/erc
diff options
context:
space:
mode:
authorF. Jason Park2023-12-04 22:13:02 -0800
committerF. Jason Park2023-12-17 20:17:55 -0800
commit236a416be76cbb0b79ad46c06652f6cbf8788fcb (patch)
treecfa08aed176f7ceb3f95002e946d9e65a620ccff /lisp/erc
parentc1befaf0a8b19fdd3b22e824f4bfc10f8882db67 (diff)
downloademacs-236a416be76cbb0b79ad46c06652f6cbf8788fcb.tar.gz
emacs-236a416be76cbb0b79ad46c06652f6cbf8788fcb.zip
Add erc--spkr text property to chat messages
* etc/ERC-NEWS: Mention combined face ordering for "/me" messages. * lisp/erc/erc-backend.el (erc-server-PRIVMSG): Bind `erc--msg-prop-overrides' for the extent of this function's execution, which means a large amount of code will see this variable as being non-nil. However, no calls to `erc-display-message' or `erc-display-msg' should occur other than the one handling the final insertion. Code needing to influence the current message's "msg props" can push new pairs onto this value, which will override any existing collisions. * lisp/erc/erc-fill.el (erc-fill): Switch to `erc--spkr' as sentinel property. (erc-fill--wrap-continued-message-p): Look for `erc--spkr' property instead of `erc-speaker'. * lisp/erc/erc.el (erc--msg-props): Mention `erc--spkr' in doc. (erc--send-action-perform-ctcp): Add `erc--spkr' property. Fix bug in which `erc-my-nick-face' appeared below `erc-input-face' in the speaker portion. (erc--ensure-spkr-prop): New helper function to propagate speaker metadata. (erc--ranked-properties): Add `erc--spkr', `erc--ctcp', and `erc--ephemeral'. (erc-display-message): Use default hash table size when initializing. Remove unnecessary assignment of `msg' to `erc--msg' for PRIVMSG and NOTICE commands. Bind `string' below `erc--msg-props' so that implementers of the function form of the `erc-format-message' templating interface can read and write the current context's "msg props". (erc--own-property-names): Add all `erc--msg-props' props by subsumation. (erc--get-speaker-bounds): Use `erc--spkr' instead of `erc--msg' as a sentinel to detect a chat message guaranteed to have an `erc--speaker' text-property interval. (erc-format-privmessage, erc-format-my-nick, erc-ctcp-query-ACTION): Add `erc--spkr' to `erc--msg-prop-overrides' when available. * test/lisp/erc/erc-fill-tests.el: (erc-fill-tests--insert-privmsg): Bind `erc--msg-prop-overrides'. (erc-fill-tests--compare): Require environment variable value to match current test name exactly when saving snapshots. Add `erc--msg-props' individually to white list. * test/lisp/erc/erc-tests.el (erc--order-text-properties-from-hash): Include `erc--spkr'. (Bug#60936) (Bug#67677) ; * test/lisp/erc/resources/fill/snapshots/merge-01-start.eld: Update. ; * test/lisp/erc/resources/fill/snapshots/merge-02-right.eld: Update. ; * test/lisp/erc/resources/fill/snapshots/merge-wrap-01.eld: Update. ; * test/lisp/erc/resources/fill/snapshots/merge-wrap-indicator-post-01.eld: ; Update. ; * test/lisp/erc/resources/fill/snapshots/merge-wrap-indicator-pre-01.eld: ; Update. ; * test/lisp/erc/resources/fill/snapshots/monospace-01-start.eld: Update. ; * test/lisp/erc/resources/fill/snapshots/monospace-02-right.eld: Update. ; * test/lisp/erc/resources/fill/snapshots/monospace-03-left.eld: Update. ; * test/lisp/erc/resources/fill/snapshots/monospace-04-reset.eld: Update. ; * test/lisp/erc/resources/fill/snapshots/spacing-01-mono.eld: Update. ; * test/lisp/erc/resources/fill/snapshots/stamps-left-01.eld: Update.
Diffstat (limited to 'lisp/erc')
-rw-r--r--lisp/erc/erc-backend.el3
-rw-r--r--lisp/erc/erc-fill.el20
-rw-r--r--lisp/erc/erc.el85
3 files changed, 62 insertions, 46 deletions
diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el
index 1c29f49a129..0f6f7e2d4c3 100644
--- a/lisp/erc/erc-backend.el
+++ b/lisp/erc/erc-backend.el
@@ -1919,6 +1919,7 @@ add things to `%s' instead."
1919 (and erc-ignore-reply-list (erc-ignored-reply-p msg tgt proc))) 1919 (and erc-ignore-reply-list (erc-ignored-reply-p msg tgt proc)))
1920 (when erc-minibuffer-ignored 1920 (when erc-minibuffer-ignored
1921 (message "Ignored %s from %s to %s" cmd sender-spec tgt)) 1921 (message "Ignored %s from %s to %s" cmd sender-spec tgt))
1922 (defvar erc--msg-prop-overrides)
1922 (let* ((sndr (erc-parse-user sender-spec)) 1923 (let* ((sndr (erc-parse-user sender-spec))
1923 (nick (nth 0 sndr)) 1924 (nick (nth 0 sndr))
1924 (login (nth 1 sndr)) 1925 (login (nth 1 sndr))
@@ -1929,6 +1930,8 @@ add things to `%s' instead."
1929 (privp (erc-current-nick-p tgt)) 1930 (privp (erc-current-nick-p tgt))
1930 (erc--display-context `((erc-buffer-display . ,(intern cmd)) 1931 (erc--display-context `((erc-buffer-display . ,(intern cmd))
1931 ,@erc--display-context)) 1932 ,@erc--display-context))
1933 (erc--msg-prop-overrides `((erc--msg . msg)
1934 ,@erc--msg-prop-overrides))
1932 s buffer 1935 s buffer
1933 fnick) 1936 fnick)
1934 (setq buffer (erc-get-buffer (if privp nick tgt) proc)) 1937 (setq buffer (erc-get-buffer (if privp nick tgt) proc))
diff --git a/lisp/erc/erc-fill.el b/lisp/erc/erc-fill.el
index b1bbb5e19b9..0c2be4b5bc9 100644
--- a/lisp/erc/erc-fill.el
+++ b/lisp/erc/erc-fill.el
@@ -177,11 +177,10 @@ You can put this on `erc-insert-modify-hook' and/or `erc-send-modify-hook'."
177 (when-let ((erc-fill-line-spacing) 177 (when-let ((erc-fill-line-spacing)
178 (p (point-min))) 178 (p (point-min)))
179 (widen) 179 (widen)
180 (when (or (erc--check-msg-prop 'erc--msg 'msg) 180 (when (or (erc--check-msg-prop 'erc--spkr)
181 (and-let* ((m (save-excursion 181 (save-excursion
182 (forward-line -1) 182 (forward-line -1)
183 (erc--get-inserted-msg-prop 'erc--msg)))) 183 (erc--get-inserted-msg-prop 'erc--spkr)))
184 (eq 'msg m)))
185 (put-text-property (1- p) p 184 (put-text-property (1- p) p
186 'line-spacing erc-fill-line-spacing)))))))) 185 'line-spacing erc-fill-line-spacing))))))))
187 186
@@ -568,22 +567,19 @@ marked as being ephemeral."
568 (props (save-restriction 567 (props (save-restriction
569 (widen) 568 (widen)
570 (and-let* 569 (and-let*
571 (((eq 'msg (get-text-property m 'erc--msg))) 570 ((speaker (get-text-property m 'erc--spkr))
572 ((not (eq (get-text-property m 'erc--ctcp) 571 ((not (eq (get-text-property m 'erc--ctcp)
573 'ACTION))) 572 'ACTION)))
574 ((not (invisible-p m))) 573 ((not (invisible-p m))))
575 (spr (next-single-property-change m 'erc--speaker))) 574 (cons (get-text-property m 'erc--ts) speaker))))
576 (cons (get-text-property m 'erc--ts)
577 (get-text-property spr 'erc--speaker)))))
578 (ts (pop props)) 575 (ts (pop props))
579 (props) 576 (props)
580 ((not (time-less-p (erc-stamp--current-time) ts))) 577 ((not (time-less-p (erc-stamp--current-time) ts)))
581 ((time-less-p (time-subtract (erc-stamp--current-time) ts) 578 ((time-less-p (time-subtract (erc-stamp--current-time) ts)
582 erc-fill--wrap-max-lull)) 579 erc-fill--wrap-max-lull))
583 ;; Assume presence of leading angle bracket or hyphen. 580 ;; Assume presence of leading angle bracket or hyphen.
584 (speaker (next-single-property-change (point-min) 'erc--speaker)) 581 (nick (erc--check-msg-prop 'erc--spkr))
585 ((not (erc--check-msg-prop 'erc--ctcp 'ACTION))) 582 ((not (erc--check-msg-prop 'erc--ctcp 'ACTION)))
586 (nick (get-text-property speaker 'erc--speaker))
587 ((erc-nick-equal-p props nick)))) 583 ((erc-nick-equal-p props nick))))
588 (set-marker erc-fill--wrap-last-msg (point-min)))))) 584 (set-marker erc-fill--wrap-last-msg (point-min))))))
589 585
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index dad7ebab621..57194ed439e 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -167,6 +167,8 @@ as of ERC 5.6:
167 and help text, and on outgoing messages unless echoed back by 167 and help text, and on outgoing messages unless echoed back by
168 the server (assuming future support) 168 the server (assuming future support)
169 169
170 - `erc--spkr': a string, the nick of the person speaking
171
170 - `erc--ctcp': a CTCP command, like `ACTION' 172 - `erc--ctcp': a CTCP command, like `ACTION'
171 173
172 - `erc--ts': a timestamp, possibly provided by the server; as of 174 - `erc--ts': a timestamp, possibly provided by the server; as of
@@ -3018,13 +3020,16 @@ target, and an `erc-server-send' FORCE flag.")
3018(defun erc--send-action-display (string) 3020(defun erc--send-action-display (string)
3019 "Display STRING as an outgoing \"CTCP ACTION\" message." 3021 "Display STRING as an outgoing \"CTCP ACTION\" message."
3020 ;; Allow hooks acting on inserted PRIVMSG and NOTICES to process us. 3022 ;; Allow hooks acting on inserted PRIVMSG and NOTICES to process us.
3021 (let ((erc--msg-prop-overrides `((erc--msg . msg) 3023 (defvar erc--merge-prop-behind-p)
3022 (erc--ctcp . ACTION) 3024 (let* ((nick (erc-current-nick))
3023 ,@erc--msg-prop-overrides)) 3025 (erc--msg-prop-overrides `((erc--msg . msg)
3024 (nick (erc-current-nick))) 3026 (erc--ctcp . ACTION)
3027 (erc--spkr . ,nick)
3028 ,@erc--msg-prop-overrides))
3029 (erc--merge-prop-behind-p t))
3025 (setq nick (propertize nick 'erc--speaker nick 3030 (setq nick (propertize nick 'erc--speaker nick
3026 'font-lock-face 'erc-my-nick-face)) 3031 'font-lock-face 'erc-my-nick-face))
3027 (erc-display-message nil '(t action input) (current-buffer) 3032 (erc-display-message nil '(t input action) (current-buffer)
3028 'ACTION ?n nick ?a string ?u "" ?h ""))) 3033 'ACTION ?n nick ?a string ?u "" ?h "")))
3029 3034
3030(defun erc--send-action (target string force) 3035(defun erc--send-action (target string force)
@@ -3034,6 +3039,12 @@ target, and an `erc-server-send' FORCE flag.")
3034 3039
3035;; Display interface 3040;; Display interface
3036 3041
3042(defun erc--ensure-spkr-prop (nick)
3043 "Maybe add NICK to `erc--msg-props' or `erc--msg-prop-overrides'."
3044 (cond (erc--msg-props (puthash 'erc--spkr nick erc--msg-props))
3045 (erc--msg-prop-overrides
3046 (push (cons 'erc--spkr nick) erc--msg-prop-overrides))))
3047
3037(defun erc-string-invisible-p (string) 3048(defun erc-string-invisible-p (string)
3038 "Check whether STRING is invisible or not. 3049 "Check whether STRING is invisible or not.
3039I.e. any char in it has the `invisible' property set." 3050I.e. any char in it has the `invisible' property set."
@@ -3463,7 +3474,8 @@ subsequent message."
3463 (substring (delete-and-extract-region (1- (point)) (1+ end)) 3474 (substring (delete-and-extract-region (1- (point)) (1+ end))
3464 -1)))))))) 3475 -1))))))))
3465 3476
3466(defvar erc--ranked-properties '(erc--msg erc--ts erc--cmd)) 3477(defvar erc--ranked-properties
3478 '(erc--msg erc--spkr erc--ts erc--cmd erc--ctcp erc--ephemeral))
3467 3479
3468(defun erc--order-text-properties-from-hash (table) 3480(defun erc--order-text-properties-from-hash (table)
3469 "Return a plist of text props from items in TABLE. 3481 "Return a plist of text props from items in TABLE.
@@ -3729,32 +3741,29 @@ ERC to process arbitrary informative messages as if they'd been
3729sent from a server. That is, guarantee \"local\" messages, for 3741sent from a server. That is, guarantee \"local\" messages, for
3730which PARSED is typically nil, will be subject to buttonizing, 3742which PARSED is typically nil, will be subject to buttonizing,
3731filling, and other effects." 3743filling, and other effects."
3732 (let ((string (if (symbolp msg) 3744 (let* ((erc--msg-props
3733 (apply #'erc-format-message msg args) 3745 (or erc--msg-props
3734 msg)) 3746 (let ((table (make-hash-table))
3735 (erc--msg-props 3747 (cmd (and parsed (erc--get-eq-comparable-cmd
3736 (or erc--msg-props 3748 (erc-response.command parsed)))))
3737 (let ((table (make-hash-table :size 5)) 3749 (puthash 'erc--msg
3738 (cmd (and parsed (erc--get-eq-comparable-cmd 3750 (cond ((and msg (symbolp msg)) msg)
3739 (erc-response.command parsed))))) 3751 (type (pcase type
3740 (puthash 'erc--msg 3752 ((pred symbolp) type)
3741 (cond ((and msg (symbolp msg)) msg) 3753 ((pred listp)
3742 ((and cmd (memq cmd '(PRIVMSG NOTICE)) 'msg)) 3754 (intern (mapconcat #'prin1-to-string
3743 (type (pcase type 3755 type "-")))
3744 ((pred symbolp) type) 3756 (_ 'unknown)))
3745 ((pred listp) 3757 (t 'unknown))
3746 (intern (mapconcat #'prin1-to-string 3758 table)
3747 type "-"))) 3759 (when cmd
3748 (_ 'unknown))) 3760 (puthash 'erc--cmd cmd table))
3749 (t 'unknown)) 3761 (when erc--msg-prop-overrides
3750 table) 3762 (pcase-dolist (`(,k . ,v) (reverse erc--msg-prop-overrides))
3751 (when cmd 3763 (when v (puthash k v table))))
3752 (puthash 'erc--cmd cmd table)) 3764 table)))
3753 (and-let* ((ovs erc--msg-prop-overrides)) 3765 (erc-message-parsed parsed)
3754 (pcase-dolist (`(,k . ,v) (reverse ovs)) 3766 (string (if (symbolp msg) (apply #'erc-format-message msg args) msg)))
3755 (puthash k v table)))
3756 table)))
3757 (erc-message-parsed parsed))
3758 (setq string 3767 (setq string
3759 (cond 3768 (cond
3760 ((null type) 3769 ((null type)
@@ -4650,6 +4659,9 @@ See also `erc-message' and `erc-display-line'."
4650 (funcall erc--send-message-nested-function line force) 4659 (funcall erc--send-message-nested-function line force)
4651 (erc--send-message-external line force))) 4660 (erc--send-message-external line force)))
4652 4661
4662;; FIXME fully simulate `erc-display-msg'. This doesn't currently add
4663;; the correct text properties. For example, the LINE should have
4664;; `erc-default-face'.
4653(defun erc--send-message-external (line force) 4665(defun erc--send-message-external (line force)
4654 (erc-message "PRIVMSG" (concat (erc-default-target) " " line) force) 4666 (erc-message "PRIVMSG" (concat (erc-default-target) " " line) force)
4655 (erc-display-line 4667 (erc-display-line
@@ -5263,7 +5275,9 @@ Eventually add a # in front of it, if that turns it into a valid channel name."
5263 (concat "#" channel))) 5275 (concat "#" channel)))
5264 5276
5265(defvar erc--own-property-names 5277(defvar erc--own-property-names
5266 '( tags erc--speaker erc-parsed display ; core 5278 `( tags erc--speaker erc-parsed display ; core
5279 ;; `erc--msg-props'
5280 ,@erc--ranked-properties
5267 ;; `erc-display-prompt' 5281 ;; `erc-display-prompt'
5268 rear-nonsticky erc-prompt field front-sticky read-only 5282 rear-nonsticky erc-prompt field front-sticky read-only
5269 ;; stamp 5283 ;; stamp
@@ -5749,7 +5763,7 @@ and as second argument the event parsed as a vector."
5749(defun erc--get-speaker-bounds () 5763(defun erc--get-speaker-bounds ()
5750 "Return the bounds of `erc--speaker' text property when present. 5764 "Return the bounds of `erc--speaker' text property when present.
5751Assume buffer is narrowed to the confines of an inserted message." 5765Assume buffer is narrowed to the confines of an inserted message."
5752 (and-let* (((erc--check-msg-prop 'erc--msg 'msg)) 5766 (and-let* (((erc--check-msg-prop 'erc--spkr))
5753 (beg (text-property-not-all (point-min) (point-max) 5767 (beg (text-property-not-all (point-min) (point-max)
5754 'erc--speaker nil))) 5768 'erc--speaker nil)))
5755 (cons beg (next-single-property-change beg 'erc--speaker)))) 5769 (cons beg (next-single-property-change beg 'erc--speaker))))
@@ -5777,6 +5791,7 @@ NUH, and the current `erc-response' object.")
5777 nick-prefix-face nick)) 5791 nick-prefix-face nick))
5778 0)) 5792 0))
5779 (msg-face (if privp 'erc-direct-msg-face 'erc-default-face))) 5793 (msg-face (if privp 'erc-direct-msg-face 'erc-default-face)))
5794 (erc--ensure-spkr-prop nick)
5780 ;; add text properties to text before the nick, the nick and after the nick 5795 ;; add text properties to text before the nick, the nick and after the nick
5781 (erc-put-text-property 0 (length mark-s) 'font-lock-face msg-face str) 5796 (erc-put-text-property 0 (length mark-s) 'font-lock-face msg-face str)
5782 (erc-put-text-properties (+ (length mark-s) prefix-len) 5797 (erc-put-text-properties (+ (length mark-s) prefix-len)
@@ -5842,6 +5857,7 @@ also `erc-format-nick-function'."
5842 (close "> ") 5857 (close "> ")
5843 (nick (erc-current-nick)) 5858 (nick (erc-current-nick))
5844 (mode (erc-get-channel-membership-prefix nick))) 5859 (mode (erc-get-channel-membership-prefix nick)))
5860 (erc--ensure-spkr-prop nick)
5845 (concat 5861 (concat
5846 (propertize open 'font-lock-face 'erc-default-face) 5862 (propertize open 'font-lock-face 'erc-default-face)
5847 (propertize mode 'font-lock-face 'erc-my-nick-prefix-face) 5863 (propertize mode 'font-lock-face 'erc-my-nick-prefix-face)
@@ -6126,6 +6142,7 @@ See also `erc-display-message'."
6126 (buf (or (erc-get-buffer to proc) 6142 (buf (or (erc-get-buffer to proc)
6127 (erc-get-buffer nick proc) 6143 (erc-get-buffer nick proc)
6128 (process-buffer proc)))) 6144 (process-buffer proc))))
6145 (erc--ensure-spkr-prop nick)
6129 (setq nick (propertize nick 'erc--speaker nick)) 6146 (setq nick (propertize nick 'erc--speaker nick))
6130 (erc-display-message 6147 (erc-display-message
6131 parsed 'action buf 6148 parsed 'action buf