mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-15 10:30:25 -08:00
Tether query rolls to channel membership in ERC
* lisp/erc/erc-backend.el (erc-server-JOIN): Update query membership via `erc--ensure-query-member' when someone else joins a channel. (erc-server-NICK): Update query membership via `erc--ensure-query-member' after someone else changes their nick. (erc-server-PRIVMSG): After printing a query message from some other person, remove their nick's data from the query buffer's user table if they're "untracked," i.e., not a member of a channel. (erc-server-263, erc-server-263-functions): New function and variable, a default response handler and hook for "RPL_TRYAGAIN", which servers send for things like rejecting "WHO" and "WHOX" responses due to rate limiting. (erc-server-311): Fix call to `erc-update-user-nick' so the userhost login component is no longer supplied as the `info' parameter but rather, correctly, as the `login'. (erc--extract-352-full-name): Factor out trailing hop-count and GECOS parsing for use by overriding handlers or those for adjacent numerics. (erc-server-352): Refactor to handle asterisk as `channel' parameter, which indicates a nick rather than a channel target. (erc-server-366): Update membership in all query buffers via `erc--ensure-query-members' after all names have been received. (erc-server-401): Forget a known user completely when the server reports them as nonexistent. * lisp/erc/erc-common.el (erc--get-server-user): New function, a thin wrapper around `erc-get-server-user' for cases were inlining would require declaring symbols not defined in erc-common. * lisp/erc/erc.el (erc-channel-members): Mention that instances are used for query-participant tables as well. (erc--decouple-query-and-channel-membership-p): New variable, a compatibility flag to access pre-5.6 query bookkeeping behavior. (erc--ensure-query-member, erc--ensure-query-members): New functions. (erc-cmd-QUERY): Ensure parties are present in the query buffer's membership table if they're known to be on the server by simple virtue of being present in some joined channel. (erc-message-english-s352-you): New variable. * test/lisp/erc/erc-scenarios-base-query-participants.el (erc-scenarios-base-query-participants) (erc-scenarios-base-query-participants/legacy): Rename former to latter. Enable compat flag to activate legacy query behavior in which channel membership does not impact query membership. (erc-scenarios-base-query-participants/coupled): New test asserting new behavior in which channel membership dictates query membership. (Bug#70928)
This commit is contained in:
parent
75aefe6514
commit
04477cf97b
4 changed files with 183 additions and 26 deletions
|
|
@ -118,6 +118,8 @@
|
|||
(defvar erc-nick-change-attempt-count)
|
||||
(defvar erc-verbose-server-ping)
|
||||
|
||||
(declare-function erc--ensure-query-member "erc" (name))
|
||||
(declare-function erc--ensure-query-members "erc" ())
|
||||
(declare-function erc--init-channel-modes "erc" (channel raw-args))
|
||||
(declare-function erc--open-target "erc" (target))
|
||||
(declare-function erc--parse-nuh "erc" (string))
|
||||
|
|
@ -1781,6 +1783,8 @@ add things to `%s' instead."
|
|||
(list 'JOIN ?n nick ?u login ?h host ?c chnl)))))
|
||||
(when buffer (set-buffer buffer))
|
||||
(erc-update-channel-member chnl nick nick t nil nil nil nil nil host login)
|
||||
(unless (erc-current-nick-p nick)
|
||||
(erc--ensure-query-member nick))
|
||||
;; on join, we want to stay in the new channel buffer
|
||||
;;(set-buffer ob)
|
||||
(apply #'erc-display-message parsed 'notice buffer args))))))
|
||||
|
|
@ -1906,7 +1910,8 @@ Return a list of buffers in which to announce the change."
|
|||
(run-hook-with-args 'erc-nick-changed-functions nn nick))
|
||||
(t
|
||||
(when erc-server-connected
|
||||
(erc-networks--id-reload erc-networks--id proc parsed))
|
||||
(erc-networks--id-reload erc-networks--id proc parsed)
|
||||
(erc--ensure-query-member nn))
|
||||
(erc-handle-user-status-change 'nick (list nick login host) (list nn))
|
||||
(erc-display-message parsed 'notice bufs 'NICK ?n nick
|
||||
?u login ?h host ?N nn))))))
|
||||
|
|
@ -2054,7 +2059,7 @@ like `erc-insert-modify-hook'.")
|
|||
(erc--speaker-status-prefix-wanted-p nil)
|
||||
(erc-current-message-catalog erc--message-speaker-catalog)
|
||||
;;
|
||||
buffer statusmsg cmem-prefix fnick)
|
||||
finalize buffer statusmsg cmem-prefix fnick)
|
||||
(setq buffer (erc-get-buffer (if privp nick tgt) proc))
|
||||
;; Even worth checking for empty target here? (invalid anyway)
|
||||
(unless (or buffer noticep (string-empty-p tgt) (eq ?$ (aref tgt 0))
|
||||
|
|
@ -2081,10 +2086,14 @@ like `erc-insert-modify-hook'.")
|
|||
(setq buffer (erc--open-target tgt))))))
|
||||
(when buffer
|
||||
(with-current-buffer buffer
|
||||
(when privp (erc--unhide-prompt))
|
||||
;; update the chat partner info. Add to the list if private
|
||||
;; message. We will accumulate private identities indefinitely
|
||||
;; at this point.
|
||||
(when privp
|
||||
(erc--unhide-prompt)
|
||||
;; Remove untracked query partners after display.
|
||||
(defvar erc--decouple-query-and-channel-membership-p)
|
||||
(unless (or erc--decouple-query-and-channel-membership-p
|
||||
(erc--get-server-user nick))
|
||||
(setq finalize (lambda ()
|
||||
(erc-remove-channel-member buffer nick)))))
|
||||
(erc-update-channel-member (if privp nick tgt) nick nick
|
||||
privp nil nil nil nil nil host login nil nil t)
|
||||
(defvar erc--cmem-from-nick-function)
|
||||
|
|
@ -2123,7 +2132,9 @@ like `erc-insert-modify-hook'.")
|
|||
(run-hook-with-args 'erc-echo-notice-always-hook
|
||||
fmtmsg parsed buffer nick)
|
||||
(run-hook-with-args-until-success
|
||||
'erc-echo-notice-hook fmtmsg parsed buffer nick))))))))))
|
||||
'erc-echo-notice-hook fmtmsg parsed buffer nick)))))
|
||||
(when finalize (funcall finalize)))
|
||||
nil))))
|
||||
|
||||
(define-erc-response-handler (QUIT)
|
||||
"Another user has quit IRC." nil
|
||||
|
|
@ -2335,6 +2346,9 @@ A server may send more than one 005 message."
|
|||
See `erc-display-server-message'." nil
|
||||
(erc-display-server-message proc parsed))
|
||||
|
||||
(define-erc-response-handler (263) "RPL_TRYAGAIN." nil
|
||||
(erc-handle-unknown-server-response proc parsed))
|
||||
|
||||
(define-erc-response-handler (275)
|
||||
"Display secure connection message." nil
|
||||
(pcase-let ((`(,nick ,_user ,_message)
|
||||
|
|
@ -2387,7 +2401,7 @@ See `erc-display-server-message'." nil
|
|||
(catalog-entry (intern (format "s%s" (erc-response.command parsed)))))
|
||||
(pcase-let ((`(,nick ,user ,host)
|
||||
(cdr (erc-response.command-args parsed))))
|
||||
(erc-update-user-nick nick nick host nil fname user)
|
||||
(erc-update-user-nick nick nick host user fname)
|
||||
(erc-display-message
|
||||
parsed 'notice 'active catalog-entry
|
||||
?n nick ?f fname ?u user ?h host))))
|
||||
|
|
@ -2549,18 +2563,28 @@ See `erc-display-server-message'." nil
|
|||
(erc-display-message parsed 'notice (erc-get-buffer channel proc)
|
||||
's341 ?n nick ?c channel)))
|
||||
|
||||
;; FIXME update or add server user instead when channel is "*".
|
||||
(defun erc--extract-352-full-name (contents)
|
||||
"Return full name from 352 trailing param, discarding hop count."
|
||||
(pcase contents
|
||||
((rx (: bot (+ (any "0-9")) " ") (let full-name (group (* nonl))) eot)
|
||||
full-name)
|
||||
(_ contents)))
|
||||
|
||||
(define-erc-response-handler (352)
|
||||
"WHO notice." nil
|
||||
(pcase-let ((`(,channel ,user ,host ,_server ,nick ,away-flag)
|
||||
(cdr (erc-response.command-args parsed))))
|
||||
(let ((full-name (erc-response.contents parsed)))
|
||||
(when (string-match "\\(^[0-9]+ \\)\\(.*\\)$" full-name)
|
||||
(setq full-name (match-string 2 full-name)))
|
||||
(erc-update-channel-member channel nick nick nil nil nil nil nil nil host user full-name)
|
||||
(erc-display-message parsed 'notice 'active 's352
|
||||
?c channel ?n nick ?a away-flag
|
||||
?u user ?h host ?f full-name))))
|
||||
"RPL_WHOREPLY response." nil
|
||||
(pcase-let*
|
||||
((`(,_ ,channel ,user ,host ,_server ,nick ,flags, hop-real)
|
||||
(erc-response.command-args parsed))
|
||||
(full-name (erc--extract-352-full-name hop-real))
|
||||
(selfp (string= channel "*"))
|
||||
(template (if selfp 's352-you 's352)))
|
||||
(if selfp
|
||||
(erc-update-user-nick nick nick host user full-name)
|
||||
(erc-update-channel-member channel nick nick nil nil nil nil nil nil
|
||||
host user full-name))
|
||||
(erc-display-message parsed 'notice 'active template
|
||||
?c channel ?n nick ?a flags
|
||||
?u user ?h host ?f full-name)))
|
||||
|
||||
(define-erc-response-handler (353)
|
||||
"NAMES notice." nil
|
||||
|
|
@ -2575,7 +2599,9 @@ See `erc-display-server-message'." nil
|
|||
(define-erc-response-handler (366)
|
||||
"End of NAMES." nil
|
||||
(erc-with-buffer ((cadr (erc-response.command-args parsed)) proc)
|
||||
(erc-channel-end-receiving-names)))
|
||||
(erc-channel-end-receiving-names))
|
||||
(erc--ensure-query-members)
|
||||
nil)
|
||||
|
||||
(define-erc-response-handler (367)
|
||||
"Channel ban list entries." nil
|
||||
|
|
@ -2641,7 +2667,9 @@ See `erc-display-server-message'." nil
|
|||
(erc-log (format "cmd: WHOWAS: %s" nick/channel))
|
||||
(erc-server-send (format "WHOWAS %s 1" nick/channel)))
|
||||
(erc-display-message parsed '(notice error) 'active
|
||||
's401 ?n nick/channel)))
|
||||
's401 ?n nick/channel)
|
||||
(unless (erc-channel-p nick/channel)
|
||||
(erc-remove-user nick/channel))))
|
||||
|
||||
(define-erc-response-handler (402)
|
||||
"No such server." nil
|
||||
|
|
|
|||
|
|
@ -557,6 +557,9 @@ Use the CASEMAPPING ISUPPORT parameter to determine the style."
|
|||
(gethash (erc-downcase ,nick)
|
||||
(erc-with-server-buffer erc-server-users)))))
|
||||
|
||||
(defun erc--get-server-user (nick)
|
||||
(erc-get-server-user nick))
|
||||
|
||||
(defmacro erc--with-dependent-type-match (type &rest features)
|
||||
"Massage Custom :type TYPE with :match function that pre-loads FEATURES."
|
||||
`(backquote-list* ',(car type)
|
||||
|
|
|
|||
|
|
@ -509,7 +509,7 @@ Functions are passed a buffer as the first argument."
|
|||
|
||||
(defvaralias 'erc-channel-users 'erc-channel-members)
|
||||
(defvar-local erc-channel-members nil
|
||||
"Hash table of members in the current channel.
|
||||
"Hash table of members in the current channel or query buffer.
|
||||
It associates nicknames with cons cells of the form
|
||||
\(SERVER-USER . MEMBER-DATA), where SERVER-USER is a
|
||||
`erc-server-user' object and MEMBER-DATA is a `erc-channel-user'
|
||||
|
|
@ -549,6 +549,37 @@ Adds USER with nickname NICK to the `erc-server-users' hash table."
|
|||
(erc-with-server-buffer
|
||||
(puthash (erc-downcase nick) user erc-server-users)))
|
||||
|
||||
(defvar erc--decouple-query-and-channel-membership-p nil
|
||||
"When non-nil, don't tether query participation to channel membership.
|
||||
Specifically, add users to query tables when they speak, don't remove
|
||||
them when they leave all channels, and allow removing the client's own
|
||||
user from `erc-server-users'. Note that enabling this compatibility
|
||||
flag degrades the user experience and isn't guaranteed to correctly
|
||||
restore the described historical behavior.")
|
||||
|
||||
(defun erc--ensure-query-member (nick)
|
||||
"Populate membership table in query buffer for online NICK."
|
||||
(erc-with-buffer (nick)
|
||||
(when-let (((not erc--decouple-query-and-channel-membership-p))
|
||||
((zerop (hash-table-count erc-channel-users)))
|
||||
(user (erc-get-server-user nick)))
|
||||
(erc-update-current-channel-member nick nil t)
|
||||
(erc--unhide-prompt)
|
||||
t)))
|
||||
|
||||
(defun erc--ensure-query-members ()
|
||||
"Update membership tables in all query buffers.
|
||||
Ensure targets with an entry in `erc-server-users' are present in
|
||||
`erc-channel-members'."
|
||||
(erc-with-all-buffers-of-server erc-server-process #'erc-query-buffer-p
|
||||
(when-let (((not erc--decouple-query-and-channel-membership-p))
|
||||
((zerop (hash-table-count erc-channel-users)))
|
||||
(target (erc-target))
|
||||
((erc-get-server-user target)))
|
||||
(erc-update-current-channel-member target nil t)
|
||||
(erc--unhide-prompt))
|
||||
erc-server-process))
|
||||
|
||||
(defun erc-remove-server-user (nick)
|
||||
"This function is for internal use only.
|
||||
|
||||
|
|
@ -5155,8 +5186,7 @@ just as you provided it. Use this command with care!"
|
|||
|
||||
(defun erc-cmd-QUERY (&optional user)
|
||||
"Open a query with USER.
|
||||
How the query is displayed (in a new window, frame, etc.) depends
|
||||
on the value of `erc-interactive-display'."
|
||||
Display the query buffer in accordance with `erc-interactive-display'."
|
||||
;; FIXME: The doc string used to say at the end:
|
||||
;; "If USER is omitted, close the current query buffer if one exists
|
||||
;; - except this is broken now ;-)"
|
||||
|
|
@ -5172,7 +5202,11 @@ on the value of `erc-interactive-display'."
|
|||
(erc--display-context `((erc-interactive-display . /QUERY)
|
||||
,@erc--display-context)))
|
||||
(erc-with-server-buffer
|
||||
(erc--open-target user))))
|
||||
(if-let ((buffer (erc-get-buffer user erc-server-process)))
|
||||
(prog1 buffer
|
||||
(erc-setup-buffer buffer))
|
||||
(prog1 (erc--open-target user) ; becomes current buffer
|
||||
(erc--ensure-query-member user))))))
|
||||
|
||||
(defalias 'erc-cmd-Q #'erc-cmd-QUERY)
|
||||
|
||||
|
|
@ -9525,6 +9559,7 @@ SOFTP, only do so when defined as a variable."
|
|||
(s333 . "%c: topic set by %n, %t")
|
||||
(s341 . "Inviting %n to channel %c")
|
||||
(s352 . "%-11c %-10n %-4a %u@%h (%f)")
|
||||
(s352-you . "%n %a %u@%h (%f)")
|
||||
(s353 . "Users on %c: %u")
|
||||
(s367 . "Ban for %b on %c")
|
||||
(s367-set-by . "Ban for %b on %c set by %s on %t")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue