diff options
Diffstat (limited to 'lisp/net/rcirc.el')
-rw-r--r-- | lisp/net/rcirc.el | 452 |
1 files changed, 296 insertions, 156 deletions
diff --git a/lisp/net/rcirc.el b/lisp/net/rcirc.el index 9d242c47cd5..bc67562d2d3 100644 --- a/lisp/net/rcirc.el +++ b/lisp/net/rcirc.el @@ -60,9 +60,9 @@ (defcustom rcirc-server-alist (if (gnutls-available-p) - '(("irc.libera.chat" :channels ("#rcirc") + '(("irc.libera.chat" :channels ("#emacs" "#rcirc") :port 6697 :encryption tls)) - '(("irc.libera.chat" :channels ("#rcirc")))) + '(("irc.libera.chat" :channels ("#emacs" "#rcirc")))) "An alist of IRC connections to establish when running `rcirc'. Each element looks like (SERVER-NAME PARAMETERS). @@ -194,16 +194,15 @@ If nil, no maximum is applied." "Responses which will be hidden when `rcirc-omit-mode' is enabled." :type '(repeat string)) -(defcustom rcirc-omit-after-reconnect - '("JOIN" "TOPIC" "NAMES") - "Types of messages to hide right after reconnecting." +(defcustom rcirc-omit-responses-after-join '() + "Types of messages to hide right after joining a channel." :type '(repeat string) :version "28.1") -(defvar-local rcirc-reconncting nil - "Non-nil means we have just reconnected. +(defvar-local rcirc-joined nil + "Non-nil means we have just connected. This is used to hide the message types enumerated in -`rcirc-supress-after-reconnect'.") +`rcirc-omit-responses-after-join'.") (defvar-local rcirc-prompt-start-marker nil "Marker indicating the beginning of the message prompt.") @@ -215,11 +214,8 @@ Uninteresting lines are those whose responses are listed in `rcirc-omit-responses'." :lighter " Omit" (if rcirc-omit-mode - (progn - (add-to-invisibility-spec '(rcirc-omit . nil)) - (message "Rcirc-Omit mode enabled")) - (remove-from-invisibility-spec '(rcirc-omit . nil)) - (message "Rcirc-Omit mode disabled")) + (add-to-invisibility-spec '(rcirc-omit . nil)) + (remove-from-invisibility-spec '(rcirc-omit . nil))) (dolist (window (get-buffer-window-list (current-buffer))) (with-selected-window window (recenter (when (> (point) rcirc-prompt-start-marker) -1))))) @@ -413,6 +409,21 @@ will be killed." :version "28.1" :type 'function) +(defcustom rcirc-channel-filter #'identity + "Function applied to channels before displaying." + :version "28.1" + :type 'function) + +(defcustom rcirc-track-ignore-server-buffer-flag nil + "Non-nil means activities in the server buffer are not traced." + :version "28.1" + :type 'boolean) + +(defcustom rcirc-display-server-buffer t + "Non-nil means the server buffer should be shown on connecting." + :version "28.1" + :type 'boolean) + (defvar-local rcirc-nick nil "The nickname used for the current connection.") @@ -512,10 +523,12 @@ If ARG is non-nil, instead prompt for connection parameters." :channels) " ")) "[, ]+" t)) - (encryption (rcirc-prompt-for-encryption server-plist))) - (rcirc-connect server port nick user-name - rcirc-default-full-name - channels password encryption)) + (encryption (rcirc-prompt-for-encryption server-plist)) + (process (rcirc-connect server port nick user-name + rcirc-default-full-name + channels password encryption))) + (when rcirc-display-server-buffer + (pop-to-buffer-same-window (process-buffer process)))) ;; connect to servers in `rcirc-server-alist' (let (connected-servers) (dolist (c rcirc-server-alist) @@ -544,9 +557,11 @@ If ARG is non-nil, instead prompt for connection parameters." (setq connected p))) (if (not connected) (condition-case nil - (rcirc-connect server port nick user-name - full-name channels password encryption - server-alias) + (let ((process (rcirc-connect server port nick user-name + full-name channels password encryption + server-alias))) + (when rcirc-display-server-buffer + (pop-to-buffer-same-window (process-buffer process)))) (quit (message "Quit connecting to %s" (or server-alias server)))) (with-current-buffer (process-buffer connected) @@ -595,6 +610,8 @@ FULL-NAME STARTUP-CHANNELS PASSWORD ENCRYPTION SERVER-ALIAS). See `rcirc-connect' for more details on these variables.") (defvar-local rcirc-process nil "Network process for the current connection.") +(defvar-local rcirc-last-connect-time nil + "The last time the buffer was connected.") ;;; IRCv3 capability negotiation (https://ircv3.net/specs/extensions/capability-negotiation) (defvar rcirc-implemented-capabilities @@ -604,6 +621,16 @@ See `rcirc-connect' for more details on these variables.") "message-ids" ;https://ircv3.net/specs/extensions/message-ids "invite-notify" ;https://ircv3.net/specs/extensions/invite-notify "sasl" ;https://ircv3.net/specs/extensions/sasl-3.1 + "multi-prefix" ;https://ircv3.net/specs/extensions/multi-prefix + "standard-replies" ;https://ircv3.net/specs/extensions/standard-replies + ;; The following capabilities should be implemented as soon as + ;; their specifications are undrafted: + ;; + ;; "reply" ;https://ircv3.net/specs/client-tags/reply + ;; "react" ;https://ircv3.net/specs/client-tags/react + ;; "multiline" ;https://ircv3.net/specs/extensions/multiline + ;; "chathistory" ;https://ircv3.net/specs/extensions/chathistory + ;; "channel-rename" ;https://ircv3.net/specs/extensions/channel-rename ) "A list of capabilities that rcirc supports.") (defvar-local rcirc-requested-capabilities nil @@ -611,7 +638,7 @@ See `rcirc-connect' for more details on these variables.") (defvar-local rcirc-acked-capabilities nil "A list of capabilities that the server supports.") (defvar-local rcirc-finished-sasl t - "Check whether SASL authentication has completed") + "Check whether SASL authentication has completed.") (defun rcirc-get-server-method (server) "Return authentication method for SERVER." @@ -644,69 +671,61 @@ that are joined after authentication." (message "Connecting to %s..." (or server-alias server)) (let* ((inhibit-eol-conversion) (port-number (if port - (if (stringp port) - (string-to-number port) - port) - rcirc-default-port)) - (nick (or nick rcirc-default-nick)) - (user-name (or user-name rcirc-default-user-name)) - (full-name (or full-name rcirc-default-full-name)) - (startup-channels startup-channels) - (use-sasl (eq (rcirc-get-server-method server) 'sasl)) - (process (open-network-stream + (if (stringp port) + (string-to-number port) + port) + rcirc-default-port)) + (nick (or nick rcirc-default-nick)) + (user-name (or user-name rcirc-default-user-name)) + (full-name (or full-name rcirc-default-full-name)) + (startup-channels startup-channels) + + process) + + ;; Ensure any previous process is killed + (when-let ((old-process (get-process (or server-alias server)))) + (set-process-sentinel old-process #'ignore) + (delete-process process)) + + ;; Set up process + (setq process (open-network-stream (or server-alias server) nil server port-number - :type (or encryption 'plain)))) - ;; set up process + :type (or encryption 'plain) + :nowait t)) (set-process-coding-system process 'raw-text 'raw-text) - (switch-to-buffer (rcirc-generate-new-buffer-name process nil)) - (set-process-buffer process (current-buffer)) - (unless (eq major-mode 'rcirc-mode) - (rcirc-mode process nil)) - (set-process-sentinel process 'rcirc-sentinel) - (set-process-filter process 'rcirc-filter) - - (setq rcirc-connection-info - (list server port nick user-name full-name startup-channels - password encryption server-alias)) - (setq rcirc-process process) - (setq rcirc-server server) - (setq rcirc-server-name (or server-alias server)) ; Update when we get 001 response. - (setq rcirc-nick-table (make-hash-table :test 'equal)) - (setq rcirc-nick nick) - (setq rcirc-startup-channels startup-channels) - (setq rcirc-last-server-message-time (current-time)) - - (setq rcirc-connecting t) - - (add-hook 'auto-save-hook 'rcirc-log-write) - (when use-sasl - (rcirc-send-string process "CAP REQ sasl")) - - (when use-sasl - (setq-local rcirc-finished-sasl nil)) - ;; identify - (dolist (cap rcirc-implemented-capabilities) - (rcirc-send-string process "CAP" "REQ" : cap) - (push cap rcirc-requested-capabilities)) - (unless (zerop (length password)) - (rcirc-send-string process "PASS" password)) - (rcirc-send-string process "NICK" nick) - (rcirc-send-string process "USER" user-name "0" "*" : full-name) - ;; Setup sasl, and initiate authentication. - (when (and rcirc-auto-authenticate-flag - use-sasl) - (rcirc-send-string process "AUTHENTICATE" "PLAIN")) - - ;; setup ping timer if necessary - (unless rcirc-keepalive-timer - (setq rcirc-keepalive-timer - (run-at-time 0 (/ rcirc-timeout-seconds 2) 'rcirc-keepalive))) - - (message "Connecting to %s...done" (or server-alias server)) - (setq mode-line-process nil) - - ;; return process object - process))) + (with-current-buffer (get-buffer-create (rcirc-generate-new-buffer-name process nil)) + (set-process-buffer process (current-buffer)) + (unless (eq major-mode 'rcirc-mode) + (rcirc-mode process nil)) + (set-process-sentinel process #'rcirc-sentinel) + (set-process-filter process #'rcirc-filter) + + (setq rcirc-connection-info + (list server port nick user-name full-name startup-channels + password encryption server-alias)) + (setq rcirc-process process) + (setq rcirc-server server) + (setq rcirc-server-name (or server-alias server)) ; Update when we get 001 response. + (setq rcirc-nick-table (make-hash-table :test 'equal)) + (setq rcirc-nick nick) + (setq rcirc-startup-channels startup-channels) + (setq rcirc-last-server-message-time (current-time)) + (setq rcirc-last-connect-time (current-time)) + + ;; Check if the immediate process state + (sit-for .1) + (cond + ((eq (process-status process) 'failed) + (setq mode-line-process ":disconnected") + (setq rcirc-connecting nil)) + ((eq (process-status process) 'connect) + (setq mode-line-process ":connecting") + (setq rcirc-connecting t))) + + (add-hook 'auto-save-hook #'rcirc-log-write) + + ;; return process object + process)))) (defmacro with-rcirc-process-buffer (process &rest body) "Evaluate BODY in the buffer of PROCESS." @@ -795,31 +814,112 @@ When 0, do not auto-reconnect." :version "25.1" :type 'integer) -(defvar-local rcirc-last-connect-time nil - "The last time the buffer was connected.") +(defcustom rcirc-reconnect-attempts 3 + "Number of times a reconnection should be attempted." + :version "28.1" + :type 'integer) + +(defvar-local rcirc-failed-attempts 0 + "Number of times reconnecting has failed.") + +(defvar-local rcirc-reconnection-timer nil + "Timer used for reconnecting.") + +(defun rcirc-reconnect (process &optional quiet) + "Attempt to reconnect connection to PROCESS. +If QUIET is non-nil, no not emit a message." + (with-rcirc-process-buffer process + (catch 'exit + (if (rcirc--connection-open-p process) + (throw 'exit (or quiet (message "Server process is alive"))) + (delete-process process)) + (let ((conn-info rcirc-connection-info)) + (setf (nth 5 conn-info) + (cl-remove-if-not #'rcirc-channel-p + (mapcar #'car rcirc-buffer-alist))) + (dolist (buffer (mapcar #'cdr rcirc-buffer-alist)) + (when (buffer-live-p buffer) + (with-current-buffer buffer + (setq mode-line-process ":connecting")))) + (let ((nprocess (apply #'rcirc-connect conn-info))) + (when (and (< rcirc-failed-attempts rcirc-reconnect-attempts) + (eq (process-status nprocess) 'failed)) + (setq rcirc-failed-attempts (1+ rcirc-failed-attempts)) + (rcirc-print nprocess "*rcirc*" "ERROR" nil + (format "Failed to reconnect (%d/%d)..." + rcirc-failed-attempts + rcirc-reconnect-attempts)) + (setq rcirc-reconnection-timer + (run-at-time rcirc-timeout-seconds nil + #'rcirc-reconnect process t)))))))) (defun rcirc-sentinel (process sentinel) "Called when PROCESS receives SENTINEL." (let ((sentinel (string-replace "\n" "" sentinel))) (rcirc-debug process (format "SENTINEL: %S %S\n" process sentinel)) (with-rcirc-process-buffer process - (dolist (buffer (cons nil (mapcar 'cdr rcirc-buffer-alist))) - (with-current-buffer (or buffer (current-buffer)) - (rcirc-print process "rcirc.el" "ERROR" rcirc-target - (format "%s: %s (%S)" - (process-name process) - sentinel - (process-status process)) - (not rcirc-target)) - (rcirc-disconnect-buffer))) - (when (and (string= sentinel "deleted") - (< 0 rcirc-reconnect-delay)) + (cond + ((string= sentinel "open") + (let* ((server (nth 0 rcirc-connection-info)) + (user-name (nth 3 rcirc-connection-info)) + (full-name (nth 4 rcirc-connection-info)) + (password (nth 6 rcirc-connection-info)) + (server-alias (nth 8 rcirc-connection-info)) + (use-sasl (eq (rcirc-get-server-method server) 'sasl))) + + ;; Prepare SASL authentication + (when use-sasl + (rcirc-send-string process "CAP REQ sasl") + (setq-local rcirc-finished-sasl nil)) + + ;; Capability negotiation + (dolist (cap rcirc-implemented-capabilities) + (rcirc-send-string process "CAP" "REQ" : cap) + (push cap rcirc-requested-capabilities)) + + ;; Identify user + (unless (zerop (length password)) + (rcirc-send-string process "PASS" password)) + (rcirc-send-string process "NICK" rcirc-nick) + (rcirc-send-string process "USER" user-name "0" "*" : full-name) + + ;; Setup sasl, and initiate authentication. + (when (and rcirc-auto-authenticate-flag + use-sasl) + (rcirc-send-string process "AUTHENTICATE" "PLAIN")) + + ;; Setup ping timer if necessary + (unless rcirc-keepalive-timer + (setq rcirc-keepalive-timer + (run-at-time 0 (/ rcirc-timeout-seconds 2) #'rcirc-keepalive))) + + ;; Reset previous reconnection attempts + (setq rcirc-failed-attempts 0) + (when rcirc-reconnection-timer + (cancel-timer rcirc-reconnection-timer) + (setq rcirc-reconnection-timer nil)) + + (message "Connecting to %s...done" (or server-alias server)) + (dolist (buffer (cons nil (mapcar 'cdr rcirc-buffer-alist))) + (with-current-buffer (or buffer (current-buffer)) + (setq mode-line-process nil))))) + ((string= sentinel "deleted") (let ((now (current-time))) - (when (or (null rcirc-last-connect-time) - (time-less-p rcirc-reconnect-delay - (time-subtract now rcirc-last-connect-time))) - (setq rcirc-last-connect-time now) - (rcirc-cmd-reconnect nil)))) + (with-rcirc-process-buffer process + (when (and (< 0 rcirc-reconnect-delay) + (time-less-p rcirc-reconnect-delay + (time-subtract now rcirc-last-connect-time))) + (setq rcirc-last-connect-time now) + (rcirc-reconnect process))))) + ((dolist (buffer (cons nil (mapcar 'cdr rcirc-buffer-alist))) + (with-current-buffer (or buffer (current-buffer)) + (rcirc-print process "*rcirc*" "ERROR" rcirc-target + (format "%s: %s (%S)" + (process-name process) + sentinel + (process-status process)) + (not rcirc-target)) + (rcirc-disconnect-buffer))))) (run-hook-with-args 'rcirc-sentinel-functions process sentinel)))) (defun rcirc-disconnect-buffer (&optional buffer) @@ -879,7 +979,7 @@ Function is called with PROCESS, COMMAND, SENDER, ARGS and LINE.") (condition-case err (rcirc-process-server-response-1 process text) (error - (rcirc-print process "RCIRC" "ERROR" nil + (rcirc-print process "*rcirc*" "ERROR" nil (format "\"%s\" %s" text err) t))) (rcirc-process-server-response-1 process text))) @@ -1054,7 +1154,7 @@ With no argument or nil as argument, use the current buffer." (let ((buffer (or buffer (and (buffer-live-p rcirc-server-buffer) rcirc-server-buffer)))) (if buffer - (with-current-buffer buffer rcirc-process) + (buffer-local-value 'rcirc-process buffer) rcirc-process))) (defun rcirc-server-name (process) @@ -1258,7 +1358,8 @@ Each element looks like (FILENAME . TEXT).") This number is independent of the number of lines in the buffer.") (defun rcirc-mode (process target) - "Major mode for IRC channel buffers. + "Initialize an IRC buffer for writing with TARGET. +PROCESS is the process object used for communication. \\{rcirc-mode-map}" ;; FIXME: Use define-derived-mode. @@ -1281,7 +1382,6 @@ This number is independent of the number of lines in the buffer.") (setq rcirc-last-post-time (current-time)) (setq-local fill-paragraph-function 'rcirc-fill-paragraph) (setq rcirc-current-line 0) - (setq rcirc-last-connect-time (current-time)) (use-hard-newlines t) @@ -1320,8 +1420,7 @@ This number is independent of the number of lines in the buffer.") (when target ; skip server buffer (let ((buffer (current-buffer))) (with-rcirc-process-buffer process - (setq rcirc-buffer-alist (cons (cons target buffer) - rcirc-buffer-alist)))) + (push (cons target buffer) rcirc-buffer-alist))) (rcirc-update-short-buffer-names)) (add-hook 'completion-at-point-functions @@ -1464,10 +1563,11 @@ Create the buffer if it doesn't exist." (rcirc-generate-new-buffer-name process target)))) (with-current-buffer new-buffer (unless (eq major-mode 'rcirc-mode) - (rcirc-mode process target))) + (rcirc-mode process target)) (setq mode-line-process nil) - (rcirc-put-nick-channel process (rcirc-nick process) target - rcirc-current-line) + (setq rcirc-joined (current-time))) + (rcirc-put-nick-channel process (rcirc-nick process) target + rcirc-current-line) new-buffer))))) (defun rcirc-send-input () @@ -1522,6 +1622,11 @@ The argument JUSTIFY is passed on to `fill-region'." (defun rcirc-process-message (line) "Process LINE as a message to be sent." + (when (and (null rcirc-target) + (string-match + (rx bos (group (+? nonl)) "@" (+ nonl) eos) + (buffer-name))) + (setq rcirc-target (match-string 1 (buffer-name)))) (if (not rcirc-target) (message "Not joined (no target)") (delete-region rcirc-prompt-end-marker (point)) @@ -1625,6 +1730,9 @@ extracted." ("ACTION" . "[%N %m]") ("COMMAND" . "%m") ("ERROR" . "%fw!!! %m") + ("FAIL" . "(%fwFAIL%f-) %m") + ("WARN" . "(%fwWARN%f-) %m") + ("NOTE" . "(%fwNOTE%f-) %m") (t . "%fp*** %fs%n %r %m")) "An alist of formats used for printing responses. The format is looked up using the response-type as a key; @@ -1742,8 +1850,9 @@ Returns nil if the information is not recorded. PROCESS is the process object for the current connection." (let ((chanbuf (rcirc-get-buffer process target))) (when chanbuf - (cdr (assoc-string nick (with-current-buffer chanbuf - rcirc-recent-quit-alist)))))) + (cdr (assoc-string nick (buffer-local-value + 'rcirc-recent-quit-alist + chanbuf)))))) (defun rcirc-last-line (process nick target) "Return the line from the last activity from NICK in TARGET. @@ -1858,9 +1967,9 @@ connection." (let ((last-activity-lines (rcirc-elapsed-lines process sender target))) (if (and (not (string= (rcirc-nick process) sender)) (or (member response rcirc-omit-responses) - (if (member response rcirc-omit-after-reconnect) - rcirc-reconncting - (setq rcirc-reconncting nil))) + (and (member response rcirc-omit-responses-after-join) + (< (time-to-seconds (time-since rcirc-joined)) + 1))) (or (not last-activity-lines) (< rcirc-omit-threshold last-activity-lines))) (put-text-property (point-min) (point-max) @@ -2008,7 +2117,8 @@ PROCESS is the process object for the current connection." "Return the nick from USER. Remove any non-nick junk." (save-match-data (if (string-match (concat "^[" rcirc-nick-prefix-chars - "]?\\([^! ]+\\)!?") (or user "")) + "]*\\([^! ]+\\)!?") + (or user "")) (match-string 1 user) user))) @@ -2119,6 +2229,11 @@ This function does not alter the INPUT string." map) "Keymap for rcirc track minor mode.") +(defcustom rcirc-track-abbrevate-flag t + "Non-nil means `rcirc-track-minor-mode' should abbreviate names." + :version "28.1" + :type 'boolean) + ;;;###autoload (define-minor-mode rcirc-track-minor-mode "Global minor mode for tracking activity in rcirc buffers." @@ -2176,7 +2291,7 @@ This function does not alter the INPUT string." "Bury all RCIRC buffers." (interactive) (dolist (buf (buffer-list)) - (when (eq 'rcirc-mode (with-current-buffer buf major-mode)) + (when (eq 'rcirc-mode (buffer-local-value 'major-mode buf)) (bury-buffer buf) ; buffers not shown (quit-windows-on buf)))) ; buffers shown in a window @@ -2216,13 +2331,15 @@ activity. Only run if the buffer is not visible and (with-current-buffer buffer (let ((old-activity rcirc-activity) (old-types rcirc-activity-types)) - (when (not (get-buffer-window (current-buffer) t)) + (when (and (not (get-buffer-window (current-buffer) t)) + (not (and rcirc-track-ignore-server-buffer-flag + (eq rcirc-server-buffer (current-buffer))))) (setq rcirc-activity (sort (if (memq (current-buffer) rcirc-activity) rcirc-activity (cons (current-buffer) rcirc-activity)) (lambda (b1 b2) - (let ((t1 (with-current-buffer b1 rcirc-last-post-time)) - (t2 (with-current-buffer b2 rcirc-last-post-time))) + (let ((t1 (buffer-local-value 'rcirc-last-post-time b1)) + (t2 (buffer-local-value 'rcirc-last-post-time b2))) (time-less-p t2 t1))))) (cl-pushnew type rcirc-activity-types) (unless (and (equal rcirc-activity old-activity) @@ -2299,7 +2416,12 @@ activity. Only run if the buffer is not visible and (defun rcirc-short-buffer-name (buffer) "Return a short name for BUFFER to use in the mode line indicator." (with-current-buffer buffer - (or rcirc-short-buffer-name (buffer-name)))) + (funcall rcirc-channel-filter + (replace-regexp-in-string + "@.*?\\'" "" + (or (and rcirc-track-abbrevate-flag + rcirc-short-buffer-name) + (buffer-name)))))) (defun rcirc-visible-buffers () "Return a list of the visible buffers that are in `rcirc-mode'." @@ -2408,7 +2530,7 @@ prefix with another element in PAIRS." (when (and (listp x) (listp (cadr x))) (setcdr x (if (> (length (cdr x)) 1) (rcirc-make-trees (cdr x)) - (setcdr x (list (cdadr x))))))) + (setcdr x (list (cdadr x))))))) alist))) ;;; /commands these are called with 3 args: PROCESS, TARGET, which is @@ -2441,23 +2563,23 @@ that, an interactive form can specified." (insert "\\(.*?\\)") (insert "[[:space:]]*\\'") (buffer-string))) - (argument (gensym)) + (argument (make-symbol "arglist")) documentation interactive-spec) (when (stringp (car body)) (setq documentation (pop body))) (when (eq (car-safe (car-safe body)) 'interactive) - (setq interactive-spec (cdr (pop body)))) + (setq interactive-spec (cadr (pop body)))) `(progn (defun ,fn-name (,argument &optional process target) ,(concat documentation "\n\nNote: If PROCESS or TARGET are nil, the values given" "\nby `rcirc-buffer-process' and `rcirc-target' will be used.") - (interactive (list ,@interactive-spec)) + (interactive ,interactive-spec) (unless (if (listp ,argument) (<= ,required (length ,argument) ,total) (string-match ,regexp ,argument)) - (user-error "Malformed input (%s): %S" ',command ',argument)) + (user-error "Malformed input (%s): %S" ',command ,argument)) (let ((process (or process (rcirc-buffer-process))) (target (or target rcirc-target))) (ignore target process) @@ -2533,18 +2655,8 @@ to `rcirc-default-part-reason'." (rcirc-define-command reconnect () "Reconnect to current server." (interactive "i") - (with-rcirc-server-buffer - (cond - (rcirc-connecting (message "Already connecting")) - ((process-live-p process) (message "Server process is alive")) - (t (let ((conn-info rcirc-connection-info)) - (setf (nth 5 conn-info) - (cl-remove-if-not #'rcirc-channel-p - (mapcar #'car rcirc-buffer-alist))) - (dolist (buf (nth 5 conn-info)) - (with-current-buffer (cdr (assoc buf rcirc-buffer-alist)) - (setq rcirc-reconncting t))) - (apply #'rcirc-connect conn-info)))))) + (setq rcirc-failed-attempts 0) + (rcirc-reconnect process)) (rcirc-define-command nick (nick) "Change nick to NICK." @@ -2564,8 +2676,8 @@ With a prefix arg, prompt for new topic." (interactive (list (and current-prefix-arg (read-string "List names in channel: ")))) (if (> (length topic) 0) - (rcirc-send-string process "TOPIC" : topic) - (rcirc-send-string process "TOPIC"))) + (rcirc-send-string process "TOPIC" target : topic) + (rcirc-send-string process "TOPIC" target))) (rcirc-define-command whois (nick) "Request information from server about NICK." @@ -3046,11 +3158,11 @@ connection." ;; already open buffer (after getting kicked e.g.) (setq mode-line-process nil)) - (rcirc-print process sender "JOIN" channel "") + (rcirc-print process sender "JOIN" (funcall rcirc-channel-filter channel) "") ;; print in private chat buffer if it exists (when (rcirc-get-buffer (rcirc-buffer-process) sender) - (rcirc-print process sender "JOIN" sender channel)))) + (rcirc-print process sender "JOIN" sender (funcall rcirc-channel-filter channel))))) ;; PART and KICK are handled the same way (defun rcirc-handler-PART-or-KICK (process _response channel _sender nick _args) @@ -3079,10 +3191,10 @@ PROCESS is the process object for the current connection." (let* ((channel (car args)) (reason (cadr args)) (message (concat channel " " reason))) - (rcirc-print process sender "PART" channel message) + (rcirc-print process sender "PART" (funcall rcirc-channel-filter channel) message) ;; print in private chat buffer if it exists (when (rcirc-get-buffer (rcirc-buffer-process) sender) - (rcirc-print process sender "PART" sender message)) + (rcirc-print process sender "PART" (funcall rcirc-channel-filter channel) message)) (rcirc-handler-PART-or-KICK process "PART" channel sender sender reason))) @@ -3094,7 +3206,7 @@ PROCESS is the process object for the current connection." (nick (cadr args)) (reason (nth 2 args)) (message (concat nick " " channel " " reason))) - (rcirc-print process sender "KICK" channel message t) + (rcirc-print process sender "KICK" (funcall rcirc-channel-filter channel) message t) ;; print in private chat buffer if it exists (when (rcirc-get-buffer (rcirc-buffer-process) nick) (rcirc-print process sender "KICK" nick message)) @@ -3124,7 +3236,7 @@ PROCESS is the process object for the current connection." (rcirc-ignore-update-automatic sender) (mapc (lambda (channel) ;; broadcast quit message each channel - (rcirc-print process sender "QUIT" channel (apply 'concat args)) + (rcirc-print process sender "QUIT" (funcall rcirc-channel-filter channel) (apply 'concat args)) ;; record nick in quit table if they recently spoke (rcirc-maybe-remember-nick-quit process sender channel)) (rcirc-nick-channels process sender)) @@ -3145,13 +3257,16 @@ PROCESS is the process object for the current connection." ;; print message to nick's channels (dolist (target channels) (rcirc-print process sender "NICK" target new-nick)) - ;; update private chat buffer, if it exists - (let ((chat-buffer (rcirc-get-buffer process old-nick))) - (when chat-buffer - (with-current-buffer chat-buffer - (rcirc-print process sender "NICK" old-nick new-nick) - (setq rcirc-target new-nick) - (rename-buffer (rcirc-generate-new-buffer-name process new-nick))))) + ;; update chat buffer, if it exists + (when-let ((chat-buffer (rcirc-get-buffer process old-nick))) + (with-current-buffer chat-buffer + (rcirc-print process sender "NICK" old-nick new-nick) + (setq rcirc-target new-nick) + (rename-buffer (rcirc-generate-new-buffer-name process new-nick))) + (setf rcirc-buffer-alist + (cons (cons new-nick chat-buffer) + (delq (assoc-string old-nick rcirc-buffer-alist t) + rcirc-buffer-alist)))) ;; remove old nick and add new one (with-rcirc-process-buffer process (let ((v (gethash old-nick rcirc-nick-table))) @@ -3234,7 +3349,7 @@ RFC1459." (with-current-buffer buffer (let ((setter (nth 2 args)) (time (current-time-string - (string-to-number (cadddr args))))) + (string-to-number (cadddr args))))) (rcirc-print process sender "TOPIC" (cadr args) (format "%s (%s on %s)" rcirc-topic setter time)))))) @@ -3344,7 +3459,7 @@ Passwords are stored in `rcirc-authinfo' (which see)." (server (car i)) (nick (nth 2 i)) (method (cadr i)) - (args (cdddr i))) + (args (cdddr i))) (when (and (string-match server rcirc-server)) (if (and (memq method '(nickserv chanserv bitlbee)) (string-match nick rcirc-nick)) @@ -3381,6 +3496,8 @@ process object for the current connection." (let ((self (buffer-local-value 'rcirc-nick rcirc-process)) (target (car args)) (chan (cadr args))) + ;; `rcirc-channel-filter' is not used here because joining + ;; requires an unfiltered name. (if (string= target self) (rcirc-print process sender "INVITE" nil (format "%s invited you to %s" @@ -3451,7 +3568,7 @@ is the process object for the current connection." (let ((subcmd (cadr args))) (dolist (cap (cddr args)) (cond ((string= subcmd "ACK") - (push cap rcirc-acked-capabilities) + (push (intern (downcase cap)) rcirc-acked-capabilities) (setq rcirc-requested-capabilities (delete cap rcirc-requested-capabilities))) ((string= subcmd "NAK") @@ -3525,13 +3642,36 @@ PROCESS is the process object for the current connection." "\0" (rcirc-get-server-password rcirc-server))))) (defun rcirc-handler-900 (process sender args _text) - "Respond to a successful authentication response." + "Respond to a successful authentication response. +SENDER is passed on to `rcirc-handler-generic'. PROCESS is the +process object for the current connection." (rcirc-handler-generic process "900" sender args nil) (when (not rcirc-finished-sasl) (setq-local rcirc-finished-sasl t) (rcirc-send-string process "CAP" "END")) (rcirc-join-channels-post-auth process)) +(defun rcirc-handler-FAIL (process _sender args _text) + "Display a FAIL message, as indicated by ARGS. +PROCESS is the process object for the current connection." + (rcirc-print process nil "FAIL" nil + (mapconcat #'identity args " ") + t)) + +(defun rcirc-handler-WARN (process _sender args _text) + "Display a WARN message, as indicated by ARGS. +PROCESS is the process object for the current connection." + (rcirc-print process nil "WARN" nil + (mapconcat #'identity args " ") + t)) + +(defun rcirc-handler-NOTE (process _sender args _text) + "Display a NOTE message, as indicated by ARGS. +PROCESS is the process object for the current connection." + (rcirc-print process nil "NOTE" nil + (mapconcat #'identity args " ") + t)) + (defgroup rcirc-faces nil "Faces for rcirc." |