diff options
| author | F. Jason Park | 2023-12-04 22:13:02 -0800 |
|---|---|---|
| committer | F. Jason Park | 2023-12-17 20:17:55 -0800 |
| commit | 236a416be76cbb0b79ad46c06652f6cbf8788fcb (patch) | |
| tree | cfa08aed176f7ceb3f95002e946d9e65a620ccff /lisp/erc | |
| parent | c1befaf0a8b19fdd3b22e824f4bfc10f8882db67 (diff) | |
| download | emacs-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.el | 3 | ||||
| -rw-r--r-- | lisp/erc/erc-fill.el | 20 | ||||
| -rw-r--r-- | lisp/erc/erc.el | 85 |
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. |
| 3039 | I.e. any char in it has the `invisible' property set." | 3050 | I.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 | |||
| 3729 | sent from a server. That is, guarantee \"local\" messages, for | 3741 | sent from a server. That is, guarantee \"local\" messages, for |
| 3730 | which PARSED is typically nil, will be subject to buttonizing, | 3742 | which PARSED is typically nil, will be subject to buttonizing, |
| 3731 | filling, and other effects." | 3743 | filling, 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. |
| 5751 | Assume buffer is narrowed to the confines of an inserted message." | 5765 | Assume 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 |