backport: erc bugfixes

This commit is contained in:
l3thal 2014-11-08 20:51:43 -05:00
parent 7d8205619a
commit d1036d288d
6 changed files with 2160 additions and 1976 deletions

View file

@ -1,17 +1,111 @@
2014-11-04 Stefan Monnier <monnier@iro.umontreal.ca> 2014-11-05 Stefan Monnier <monnier@iro.umontreal.ca>
* erc.el (erc-send-input): Bind `str' dynamically (bug#18936). * erc.el (erc-send-input): Bind `str' dynamically (bug#18936).
2014-10-29 Paul Eggert <eggert@cs.ucla.edu>
Simplify use of current-time and friends.
* erc-backend.el (TOPIC): Omit unnecessary call to current-time.
* erc.el (erc-emacs-time-to-erc-time): Simplify by using float-time.
(erc-current-time): Simplify by using erc-emacs-time-to-erc-time.
2014-10-20 Glenn Morris <rgm@gnu.org> 2014-10-20 Glenn Morris <rgm@gnu.org>
* Version 24.4 released. * Merge in all changes up to 24.4 release.
2014-09-24 Stefan Monnier <monnier@iro.umontreal.ca> 2014-10-15 Ivan Shmakov <ivan@siamics.net>
* erc-track.el (erc-modified-channels-display): Update mode line
more frequently (bug#18510).
2014-10-10 Kelvin White <kwhite@gnu.org>
* erc.el (erc-initialize-log-marker): Only initialize
erc-last-saved-position if not already a marker.
2014-10-04 Stefan Monnier <monnier@iro.umontreal.ca>
* erc.el (erc-channel-receive-names): Silence compiler warning.
(erc-format-@nick, erc-update-modes): Idem.
2014-10-03 Kelvin White <kwhite@gnu.org>
* erc.el (erc-rename-buffers): Use defcustom instead of defvar for
buffer renaming configuration option.
2014-10-02 Paul Eggert <eggert@cs.ucla.edu>
* erc.el (erc-nick-at-point): Fix format-string typo (Bug#17755).
2014-10-02 Kelvin White <kwhite@gnu.org>
* erc.el (erc-rename-buffer-p): When set to t buffers will be
renamed to the current irc network.
(erc-format-target-and/or-network): Use `erc-rename-buffer-p' when
renaming buffers.
* erc-ring.el (erc-input-ring-setup): Fixes Bug #18599
2014-09-30 Stefan Monnier <monnier@iro.umontreal.ca>
* erc-track.el (erc-modified-channels-display): Update all mode lines * erc-track.el (erc-modified-channels-display): Update all mode lines
if needed (bug#18510). Remove call to erc-modified-channels-object if needed (bug#18510). Remove call to erc-modified-channels-object
where we ignored the return value. where we ignored the return value.
(erc-modified-channels-update): Don't force-mode-line-update here any more. (erc-modified-channels-update): Don't force-mode-line-update here
any more.
2014-09-26 Kelvin White <kwhite@gnu.org>
* erc.el (erc-format-nick): Fix code regression - Bug #18551
2014-09-25 Kelvin White <kwhite@gnu.org>
* erc.el: Follow Emacs version instead of tracking it seperately.
(erc-quit/part-reason-default) : Clean up quit/part message
functions by abstracting repetitive code, change version string.
(erc-quit-reason-various, erc-quit-reason-normal, erc-quit-reason-zippy)
(erc-part-reason-normal, erc-part-reason-zippy, erc-part-reason-various)
(erc-cmd-SV, erc-ctcp-query-VERSION, erc-version, erc-version-string):
Change version string.
2014-08-13 Kelvin White <kwhite@gnu.org>
* erc.el (erc-send-input): Disable display commands in current buffer
(erc-format-target-and/or-network): Fix cases when buffer name is set
2014-08-12 Stefan Monnier <monnier@iro.umontreal.ca>
* erc-stamp.el (erc-timestamp-intangible): Disable by default because
`intangible' is evil.
2014-08-07 Kelvin White <kwhite@gnu.org>
* erc.el (erc-channel-receive-names): Fix variable names
(erc-format-target-and/or-network): Rename server-buffers to
network name if possible
2014-07-08 Stefan Monnier <monnier@iro.umontreal.ca>
* erc.el (erc-channel-receive-names): Reduce redundancy.
2014-06-19 Kelvin White <kwhite@gnu.org>
* erc-backend.el: Handle user modes in relevant server responses
* erc.el: Better user mode support.
(erc-channel-user): Add members for new modes.
(erc-channel-member-halfop-p, erc-channel-user-admin-p)
(erc-channel-user-owner-p): Use new struct members.
(erc-format-nick, erc-format-@nick): Display user modes as nick prefix.
(erc-nick-prefix-face, erc-my-nick-prefix-face): Add new faces
(erc-get-user-mode-prefix): Return symbol for mode prefix.
(erc-update-channel-member, erc-update-current-channel-member)
(erc-channel-receive-names): Update channel users.
(erc-nick-at-point): Return correct user info.
2014-04-04 Stefan Monnier <monnier@iro.umontreal.ca>
* erc.el (erc-invite-only-mode, erc-toggle-channel-mode): Simplify.
(erc-load-script): Tighten a regexp.
2014-02-25 Julien Danjou <julien@danjou.info> 2014-02-25 Julien Danjou <julien@danjou.info>
@ -360,9 +454,9 @@
2011-11-28 Mike Kazantsev <mk.fraggod@gmail.com> (tiny change) 2011-11-28 Mike Kazantsev <mk.fraggod@gmail.com> (tiny change)
* erc-dcc.el (erc-dcc-ctcp-query-send-regexp): Updated regexp to * erc-dcc.el (erc-dcc-ctcp-query-send-regexp): Update regexp to
match quoted filenames with spaces inside. match quoted filenames with spaces inside.
(erc-dcc-handle-ctcp-send): Updated regexp match group numbers, (erc-dcc-handle-ctcp-send): Update regexp match group numbers,
added processing of escaped quotes and backslashes if filename added processing of escaped quotes and backslashes if filename
itself was in quotes. itself was in quotes.
@ -625,4 +719,3 @@ See ChangeLog.08 for earlier changes.
;; coding: utf-8 ;; coding: utf-8
;; add-log-time-zone-rule: t ;; add-log-time-zone-rule: t
;; End: ;; End:

View file

@ -1208,7 +1208,6 @@ add things to `%s' instead."
parsed 'notice 'active parsed 'notice 'active
'INVITE ?n nick ?u login ?h host ?c chnl))))) 'INVITE ?n nick ?u login ?h host ?c chnl)))))
(define-erc-response-handler (JOIN) (define-erc-response-handler (JOIN)
"Handle join messages." "Handle join messages."
nil nil
@ -1244,7 +1243,7 @@ add things to `%s' instead."
(erc-format-message (erc-format-message
'JOIN ?n nick ?u login ?h host ?c chnl)))))) 'JOIN ?n nick ?u login ?h host ?c chnl))))))
(when buffer (set-buffer buffer)) (when buffer (set-buffer buffer))
(erc-update-channel-member chnl nick nick t nil nil host login) (erc-update-channel-member chnl nick nick t nil nil nil nil nil host login)
;; on join, we want to stay in the new channel buffer ;; on join, we want to stay in the new channel buffer
;;(set-buffer ob) ;;(set-buffer ob)
(erc-display-message parsed nil buffer str)))))) (erc-display-message parsed nil buffer str))))))
@ -1413,7 +1412,7 @@ add things to `%s' instead."
;; message. We will accumulate private identities indefinitely ;; message. We will accumulate private identities indefinitely
;; at this point. ;; at this point.
(erc-update-channel-member (if privp nick tgt) nick nick (erc-update-channel-member (if privp nick tgt) nick nick
privp nil nil host login nil nil t) privp nil nil nil nil nil host login nil nil t)
(let ((cdata (erc-get-channel-user nick))) (let ((cdata (erc-get-channel-user nick)))
(setq fnick (funcall erc-format-nick-function (setq fnick (funcall erc-format-nick-function
(car cdata) (cdr cdata)))))) (car cdata) (cdr cdata))))))
@ -1466,11 +1465,10 @@ add things to `%s' instead."
"The channel topic has changed." nil "The channel topic has changed." nil
(let* ((ch (car (erc-response.command-args parsed))) (let* ((ch (car (erc-response.command-args parsed)))
(topic (erc-trim-string (erc-response.contents parsed))) (topic (erc-trim-string (erc-response.contents parsed)))
(time (format-time-string erc-server-timestamp-format (time (format-time-string erc-server-timestamp-format)))
(current-time))))
(pcase-let ((`(,nick ,login ,host) (pcase-let ((`(,nick ,login ,host)
(erc-parse-user (erc-response.sender parsed)))) (erc-parse-user (erc-response.sender parsed))))
(erc-update-channel-member ch nick nick nil nil nil host login) (erc-update-channel-member ch nick nick nil nil nil nil nil nil host login)
(erc-update-channel-topic ch (format "%s\C-o (%s, %s)" topic nick time)) (erc-update-channel-topic ch (format "%s\C-o (%s, %s)" topic nick time))
(erc-display-message parsed 'notice (erc-get-buffer ch proc) (erc-display-message parsed 'notice (erc-get-buffer ch proc)
'TOPIC ?n nick ?u login ?h host 'TOPIC ?n nick ?u login ?h host
@ -1800,8 +1798,7 @@ See `erc-display-server-message'." nil
(when (string-match "\\(^[0-9]+ \\)\\(.*\\)$" full-name) (when (string-match "\\(^[0-9]+ \\)\\(.*\\)$" full-name)
(setq hopcount (match-string 1 full-name)) (setq hopcount (match-string 1 full-name))
(setq full-name (match-string 2 full-name))) (setq full-name (match-string 2 full-name)))
(erc-update-channel-member channel nick nick nil nil nil host (erc-update-channel-member channel nick nick nil nil nil nil nil nil host user full-name)
user full-name)
(erc-display-message parsed 'notice 'active 's352 (erc-display-message parsed 'notice 'active 's352
?c channel ?n nick ?a away-flag ?c channel ?n nick ?a away-flag
?u user ?h host ?f full-name)))) ?u user ?h host ?f full-name))))

View file

@ -67,7 +67,8 @@ variable.")
(defun erc-input-ring-setup () (defun erc-input-ring-setup ()
"Do the setup required so that we can use comint style input rings. "Do the setup required so that we can use comint style input rings.
Call this function when setting up the mode." Call this function when setting up the mode."
(setq erc-input-ring (make-ring comint-input-ring-size)) (unless (ring-p erc-input-ring)
(setq erc-input-ring (make-ring comint-input-ring-size)))
(setq erc-input-ring-index nil)) (setq erc-input-ring-index nil))
(defun erc-add-to-input-ring (s) (defun erc-add-to-input-ring (s)

View file

@ -147,10 +147,11 @@ the minibuffer."
:group 'erc-stamp :group 'erc-stamp
:type 'string) :type 'string)
(defcustom erc-timestamp-intangible t (defcustom erc-timestamp-intangible nil
"Whether the timestamps should be intangible, i.e. prevent the point "Whether the timestamps should be intangible, i.e. prevent the point
from entering them and instead jump over them." from entering them and instead jump over them."
:group 'erc-stamp :group 'erc-stamp
:version "25.1"
:type 'boolean) :type 'boolean)
(defface erc-timestamp-face '((t :weight bold :foreground "green")) (defface erc-timestamp-face '((t :weight bold :foreground "green"))

View file

@ -858,7 +858,7 @@ Use `erc-make-mode-line-buffer-name' to create buttons."
faces (cdr faces))) faces (cdr faces)))
strings))) strings)))
(newobject (erc-modified-channels-object strings))) (newobject (erc-modified-channels-object strings)))
(unless (equal oldobject newobject) (unless (equal-including-properties oldobject newobject)
(setq erc-modified-channels-object newobject) (setq erc-modified-channels-object newobject)
(force-mode-line-update t))))) (force-mode-line-update t)))))

View file

@ -9,9 +9,10 @@
;; Andreas Fuchs (afs@void.at) ;; Andreas Fuchs (afs@void.at)
;; Gergely Nagy (algernon@midgard.debian.net) ;; Gergely Nagy (algernon@midgard.debian.net)
;; David Edmondson (dme@dme.org) ;; David Edmondson (dme@dme.org)
;; Kelvin White (kwhite@gnu.org)
;; Maintainer: emacs-devel@gnu.org ;; Maintainer: emacs-devel@gnu.org
;; Keywords: IRC, chat, client, Internet ;; Keywords: IRC, chat, client, Internet
;; Version: 5.3
;; This file is part of GNU Emacs. ;; This file is part of GNU Emacs.
@ -62,11 +63,11 @@
;;; History: ;;; History:
;; ;;
;;; Code: (defconst erc-version-string (format "\C-bERC\C-b (IRC client for Emacs %s)" emacs-version)
(defconst erc-version-string "Version 5.3"
"ERC version. This is used by function `erc-version'.") "ERC version. This is used by function `erc-version'.")
;;; Code:
(eval-when-compile (require 'cl-lib)) (eval-when-compile (require 'cl-lib))
(require 'font-lock) (require 'font-lock)
(require 'pp) (require 'pp)
@ -195,6 +196,11 @@ parameters and authentication."
:set (lambda (sym val) :set (lambda (sym val)
(set sym (if (functionp val) (funcall val) val)))) (set sym (if (functionp val) (funcall val) val))))
(defcustom erc-rename-buffers nil
"When this is set to t, buffers will be renamed to network name if available"
:group 'erc
:type 'boolean)
(defvar erc-password nil (defvar erc-password nil
"Password to use when authenticating to an IRC server. "Password to use when authenticating to an IRC server.
It is not strictly necessary to provide this, since ERC will It is not strictly necessary to provide this, since ERC will
@ -370,7 +376,7 @@ If no server buffer exists, return nil."
) )
(cl-defstruct (erc-channel-user (:type vector) :named) (cl-defstruct (erc-channel-user (:type vector) :named)
op voice voice halfop op admin owner
;; Last message time (in the form of the return value of ;; Last message time (in the form of the return value of
;; (current-time) ;; (current-time)
;; ;;
@ -475,16 +481,40 @@ Removes all users in the current channel. This is called by
erc-channel-users) erc-channel-users)
(clrhash erc-channel-users))) (clrhash erc-channel-users)))
(defsubst erc-channel-user-owner-p (nick)
"Return non-nil if NICK is an owner of the current channel."
(and nick
(hash-table-p erc-channel-users)
(let ((cdata (erc-get-channel-user nick)))
(and cdata (cdr cdata)
(erc-channel-user-owner (cdr cdata))))))
(defsubst erc-channel-user-admin-p (nick)
"Return non-nil if NICK is an admin in the current channel."
(and nick
(hash-table-p erc-channel-users)
(let ((cdata (erc-get-channel-user nick)))
(and cdata (cdr cdata)
(erc-channel-user-admin (cdr cdata))))))
(defsubst erc-channel-user-op-p (nick) (defsubst erc-channel-user-op-p (nick)
"Return t if NICK is an operator in the current channel." "Return non-nil if NICK is an operator in the current channel."
(and nick (and nick
(hash-table-p erc-channel-users) (hash-table-p erc-channel-users)
(let ((cdata (erc-get-channel-user nick))) (let ((cdata (erc-get-channel-user nick)))
(and cdata (cdr cdata) (and cdata (cdr cdata)
(erc-channel-user-op (cdr cdata)))))) (erc-channel-user-op (cdr cdata))))))
(defsubst erc-channel-user-halfop-p (nick)
"Return non-nil if NICK is a half-operator in the current channel."
(and nick
(hash-table-p erc-channel-users)
(let ((cdata (erc-get-channel-user nick)))
(and cdata (cdr cdata)
(erc-channel-user-halfop (cdr cdata))))))
(defsubst erc-channel-user-voice-p (nick) (defsubst erc-channel-user-voice-p (nick)
"Return t if NICK has voice in the current channel." "Return non-nil if NICK has voice in the current channel."
(and nick (and nick
(hash-table-p erc-channel-users) (hash-table-p erc-channel-users)
(let ((cdata (erc-get-channel-user nick))) (let ((cdata (erc-get-channel-user nick)))
@ -1122,6 +1152,14 @@ which the local user typed."
"ERC default face." "ERC default face."
:group 'erc-faces) :group 'erc-faces)
(defface erc-nick-prefix-face '((t :inherit erc-nick-default-face :weight bold))
"ERC face used for user mode prefix."
:group 'erc-faces)
(defface erc-my-nick-prefix-face '((t :inherit erc-nick-default-face :weight bold))
"ERC face used for my user mode prefix."
:group 'erc-faces)
(defface erc-direct-msg-face '((t :foreground "IndianRed")) (defface erc-direct-msg-face '((t :foreground "IndianRed"))
"ERC face used for messages you receive in the main erc buffer." "ERC face used for messages you receive in the main erc buffer."
:group 'erc-faces) :group 'erc-faces)
@ -2019,9 +2057,10 @@ Returns the buffer for the given server or channel."
"Initialize the `erc-last-saved-position' marker to a sensible position. "Initialize the `erc-last-saved-position' marker to a sensible position.
BUFFER is the current buffer." BUFFER is the current buffer."
(with-current-buffer buffer (with-current-buffer buffer
(unless (markerp erc-last-saved-position)
(setq erc-last-saved-position (make-marker)) (setq erc-last-saved-position (make-marker))
(move-marker erc-last-saved-position (move-marker erc-last-saved-position
(1- (marker-position erc-insert-marker))))) (1- (marker-position erc-insert-marker))))))
;; interactive startup ;; interactive startup
@ -2764,7 +2803,8 @@ VALUE is computed by evaluating the rest of LINE in Lisp."
(concat "\n" (pp-to-string val)) (concat "\n" (pp-to-string val))
(format " %S\n" val))))) (format " %S\n" val)))))
(apropos-internal "^erc-" 'custom-variable-p)))) (apropos-internal "^erc-" 'custom-variable-p))))
(current-buffer)) t) (current-buffer))
t)
(t nil))) (t nil)))
(defalias 'erc-cmd-VAR 'erc-cmd-SET) (defalias 'erc-cmd-VAR 'erc-cmd-SET)
(defalias 'erc-cmd-VARIABLE 'erc-cmd-SET) (defalias 'erc-cmd-VARIABLE 'erc-cmd-SET)
@ -3346,14 +3386,16 @@ If USER is omitted, close the current query buffer if one exists
(signal 'wrong-number-of-arguments "")))) (signal 'wrong-number-of-arguments ""))))
(defalias 'erc-cmd-Q 'erc-cmd-QUERY) (defalias 'erc-cmd-Q 'erc-cmd-QUERY)
(defun erc-quit/part-reason-default ()
"Default quit/part message."
(format "\C-bERC\C-b (IRC client for Emacs %s)" emacs-version))
(defun erc-quit-reason-normal (&optional s) (defun erc-quit-reason-normal (&optional s)
"Normal quit message. "Normal quit message.
If S is non-nil, it will be used as the quit reason." If S is non-nil, it will be used as the quit reason."
(or s (or s (erc-quit/part-reason-default)))
(format "\C-bERC\C-b %s (IRC client for Emacs)"; - \C-b%s\C-b"
erc-version-string) ; erc-official-location)
))
(defun erc-quit-reason-zippy (&optional s) (defun erc-quit-reason-zippy (&optional s)
"Zippy quit message. "Zippy quit message.
@ -3362,7 +3404,7 @@ If S is non-nil, it will be used as the quit reason."
(or s (or s
(if (fboundp 'yow) (if (fboundp 'yow)
(erc-replace-regexp-in-string "\n" "" (yow)) (erc-replace-regexp-in-string "\n" "" (yow))
(erc-quit-reason-normal)))) (erc-quit/part-reason-default))))
(make-obsolete 'erc-quit-reason-zippy "it will be removed." "24.4") (make-obsolete 'erc-quit-reason-zippy "it will be removed." "24.4")
@ -3375,16 +3417,13 @@ If S is non-nil, it will be used as the quit reason."
((functionp res) (funcall res)) ((functionp res) (funcall res))
((stringp res) res) ((stringp res) res)
(s s) (s s)
(t (erc-quit-reason-normal))))) (t (erc-quit/part-reason-default)))))
(defun erc-part-reason-normal (&optional s) (defun erc-part-reason-normal (&optional s)
"Normal part message. "Normal part message.
If S is non-nil, it will be used as the quit reason." If S is non-nil, it will be used as the part reason."
(or s (or s (erc-quit/part-reason-default)))
(format "\C-bERC\C-b %s (IRC client for Emacs)"; - \C-b%s\C-b"
erc-version-string) ; erc-official-location)
))
(defun erc-part-reason-zippy (&optional s) (defun erc-part-reason-zippy (&optional s)
"Zippy part message. "Zippy part message.
@ -3393,7 +3432,7 @@ If S is non-nil, it will be used as the quit reason."
(or s (or s
(if (fboundp 'yow) (if (fboundp 'yow)
(erc-replace-regexp-in-string "\n" "" (yow)) (erc-replace-regexp-in-string "\n" "" (yow))
(erc-part-reason-normal)))) (erc-quit/part-reason-default))))
(make-obsolete 'erc-part-reason-zippy "it will be removed." "24.4") (make-obsolete 'erc-part-reason-zippy "it will be removed." "24.4")
@ -3406,7 +3445,7 @@ If S is non-nil, it will be used as the quit reason."
((functionp res) (funcall res)) ((functionp res) (funcall res))
((stringp res) res) ((stringp res) res)
(s s) (s s)
(t (erc-part-reason-normal))))) (t (erc-quit/part-reason-default)))))
(defun erc-cmd-QUIT (reason) (defun erc-cmd-QUIT (reason)
"Disconnect from the current server. "Disconnect from the current server.
@ -3500,8 +3539,7 @@ the message given by REASON."
(defun erc-cmd-SV () (defun erc-cmd-SV ()
"Say the current ERC and Emacs version into channel." "Say the current ERC and Emacs version into channel."
(erc-send-message (format "I'm using ERC %s with %s %s (%s%s) of %s." (erc-send-message (format "I'm using ERC with %s %s (%s%s) of %s."
erc-version-string
(if (featurep 'xemacs) "XEmacs" "GNU Emacs") (if (featurep 'xemacs) "XEmacs" "GNU Emacs")
emacs-version emacs-version
system-configuration system-configuration
@ -3841,7 +3879,8 @@ If FACE is non-nil, it will be used to propertize the prompt. If it is nil,
(insert (read-from-minibuffer "Message: " (insert (read-from-minibuffer "Message: "
(string (if (featurep 'xemacs) (string (if (featurep 'xemacs)
last-command-char last-command-char
last-command-event)) read-map)) last-command-event))
read-map))
(erc-send-current-line))) (erc-send-current-line)))
(defvar erc-action-history-list () (defvar erc-action-history-list ()
@ -4073,10 +4112,12 @@ E.g. \"Read error to Nick [user@some.host]: 110\" would be shortened to
host (regexp-quote host)) host (regexp-quote host))
(or (when (string-match (concat "^\\(Read error\\) to " (or (when (string-match (concat "^\\(Read error\\) to "
nick "\\[" host "\\]: " nick "\\[" host "\\]: "
"\\(.+\\)$") reason) "\\(.+\\)$")
reason)
(concat (match-string 1 reason) ": " (match-string 2 reason))) (concat (match-string 1 reason) ": " (match-string 2 reason)))
(when (string-match (concat "^\\(Ping timeout\\) for " (when (string-match (concat "^\\(Ping timeout\\) for "
nick "\\[" host "\\]$") reason) nick "\\[" host "\\]$")
reason)
(match-string 1 reason)) (match-string 1 reason))
reason)) reason))
@ -4192,24 +4233,43 @@ and as second argument the event parsed as a vector."
See also `erc-format-nick-function'." See also `erc-format-nick-function'."
(when user (erc-server-user-nickname user))) (when user (erc-server-user-nickname user)))
(defun erc-format-@nick (&optional user channel-data) (defun erc-get-user-mode-prefix (user)
"Format the nickname of USER showing if USER is an operator or has voice.
Operators have \"@\" and users with voice have \"+\" as a prefix.
Use CHANNEL-DATA to determine op and voice status.
See also `erc-format-nick-function'."
(when user (when user
(let ((op (and channel-data (erc-channel-user-op channel-data) "@")) (cond ((erc-channel-user-owner-p user)
(voice (and channel-data (erc-channel-user-voice channel-data) "+"))) (erc-propertize "~" 'help-echo "owner"))
(concat voice op (erc-server-user-nickname user))))) ((erc-channel-user-admin-p user)
(erc-propertize "&" 'help-echo "admin"))
((erc-channel-user-op-p user)
(erc-propertize "@" 'help-echo "operator"))
((erc-channel-user-halfop-p user)
(erc-propertize "%" 'help-echo "half-op"))
((erc-channel-user-voice-p user)
(erc-propertize "+" 'help-echo "voice"))
(t ""))))
(defun erc-format-@nick (&optional user _channel-data)
"Format the nickname of USER showing if USER has a voice, is an
operator, half-op, admin or owner. Owners have \"~\", admins have
\"&\", operators have \"@\" and users with voice have \"+\" as a
prefix. Use CHANNEL-DATA to determine op and voice status. See
also `erc-format-nick-function'."
(when user
(let ((nick (erc-server-user-nickname user)))
(concat (erc-propertize
(erc-get-user-mode-prefix nick)
'face 'erc-nick-prefix-face)
nick))))
(defun erc-format-my-nick () (defun erc-format-my-nick ()
"Return the beginning of this user's message, correctly propertized." "Return the beginning of this user's message, correctly propertized."
(if erc-show-my-nick (if erc-show-my-nick
(let ((open "<") (let* ((open "<")
(close "> ") (close "> ")
(nick (erc-current-nick))) (nick (erc-current-nick))
(mode (erc-get-user-mode-prefix nick)))
(concat (concat
(erc-propertize open 'face 'erc-default-face) (erc-propertize open 'face 'erc-default-face)
(erc-propertize mode 'face 'erc-my-nick-prefix-face)
(erc-propertize nick 'face 'erc-my-nick-face) (erc-propertize nick 'face 'erc-my-nick-face)
(erc-propertize close 'face 'erc-default-face))) (erc-propertize close 'face 'erc-default-face)))
(let ((prefix "> ")) (let ((prefix "> "))
@ -4534,8 +4594,8 @@ See also `erc-display-message'."
(unless erc-disable-ctcp-replies (unless erc-disable-ctcp-replies
(erc-send-ctcp-notice (erc-send-ctcp-notice
nick (format nick (format
"VERSION \C-bERC\C-b %s - an IRC client for emacs (\C-b%s\C-b)" "VERSION \C-bERC\C-b - an IRC client for Emacs %s (\C-b%s\C-b)"
erc-version-string emacs-version
erc-official-location))) erc-official-location)))
nil) nil)
@ -4685,7 +4745,7 @@ Example: (operator) o => @, (voiced) v => +."
(let ((str (or (cdr (assoc "PREFIX" (erc-with-server-buffer (let ((str (or (cdr (assoc "PREFIX" (erc-with-server-buffer
erc-server-parameters))) erc-server-parameters)))
;; provide a sane default ;; provide a sane default
"(ov)@+")) "(qaohv)~&@%+"))
types chars) types chars)
(when (string-match "^(\\([^)]+\\))\\(.+\\)$" str) (when (string-match "^(\\([^)]+\\))\\(.+\\)$" str)
(setq types (match-string 1 str) (setq types (match-string 1 str)
@ -4705,40 +4765,39 @@ Example: (operator) o => @, (voiced) v => +."
Update `erc-channel-users' according to NAMES-STRING. Update `erc-channel-users' according to NAMES-STRING.
NAMES-STRING is a string listing some of the names on the NAMES-STRING is a string listing some of the names on the
channel." channel."
(let (prefix op-ch voice-ch names name op voice) (let* ((prefix (erc-parse-prefix))
(setq prefix (erc-parse-prefix)) (voice-ch (cdr (assq ?v prefix)))
(setq op-ch (cdr (assq ?o prefix)) (op-ch (cdr (assq ?o prefix)))
voice-ch (cdr (assq ?v prefix))) (hop-ch (cdr (assq ?h prefix)))
;; We need to delete "" because in XEmacs, (split-string "a ") (adm-ch (cdr (assq ?a prefix)))
;; returns ("a" ""). (own-ch (cdr (assq ?q prefix)))
(setq names (delete "" (split-string names-string))) (names (delete "" (split-string names-string)))
name op voice halfop admin owner)
(let ((erc-channel-members-changed-hook nil)) (let ((erc-channel-members-changed-hook nil))
(dolist (item names) (dolist (item names)
(let ((updatep t)) (let ((updatep t)
(if (rassq (elt item 0) prefix) (ch (aref item 0)))
(cond ((= (length item) 1) (setq name item op 'off voice 'off halfop 'off admin 'off owner 'off)
(setq updatep nil)) (if (rassq ch prefix)
((eq (elt item 0) op-ch) (if (= (length item) 1)
(setq name (substring item 1) (setq updatep nil)
op 'on (setq name (substring item 1))
voice 'off)) (setf (pcase ch
((eq (elt item 0) voice-ch) ((pred (eq voice-ch)) voice)
(setq name (substring item 1) ((pred (eq hop-ch)) halfop)
op 'off ((pred (eq op-ch)) op)
voice 'on)) ((pred (eq adm-ch)) admin)
(t (setq name (substring item 1) ((pred (eq own-ch)) owner)
op 'off (_ (error "Unknown prefix char `%S'" ch) voice))
voice 'off))) 'on)))
(setq name item
op 'off
voice 'off))
(when updatep (when updatep
(puthash (erc-downcase name) t (puthash (erc-downcase name) t
erc-channel-new-member-names) erc-channel-new-member-names)
(erc-update-current-channel-member (erc-update-current-channel-member
name name t op voice))))) name name t voice halfop op admin owner)))))
(run-hooks 'erc-channel-members-changed-hook))) (run-hooks 'erc-channel-members-changed-hook)))
(defcustom erc-channel-members-changed-hook nil (defcustom erc-channel-members-changed-hook nil
"This hook is called every time the variable `channel-members' changes. "This hook is called every time the variable `channel-members' changes.
The buffer where the change happened is current while this hook is called." The buffer where the change happened is current while this hook is called."
@ -4795,16 +4854,15 @@ which USER is a member, and t is returned."
changed)) changed))
(defun erc-update-current-channel-member (defun erc-update-current-channel-member
(nick new-nick &optional add op voice host login full-name info (nick new-nick &optional add voice halfop op admin owner host login full-name info
update-message-time) update-message-time)
"Update the stored user information for the user with nickname NICK. "Update the stored user information for the user with nickname NICK.
`erc-update-user' is called to handle changes to nickname, `erc-update-user' is called to handle changes to nickname,
HOST, LOGIN, FULL-NAME, and INFO. If OP or VOICE are non-nil, HOST, LOGIN, FULL-NAME, and INFO. If VOICE HALFOP OP ADMIN or OWNER
they must be equal to either `on' or `off', in which case the are non-nil, they must be equal to either `on' or `off', in which
operator or voice status of the user in the current channel is case the status of the user in the current channel is changed accordingly.
changed accordingly. If UPDATE-MESSAGE-TIME is non-nil, the If UPDATE-MESSAGE-TIME is non-nil, the last-message-time of the user
last-message-time of the user in the current channel is set in the current channel is set to (current-time).
to (current-time).
If ADD is non-nil, the user will be added with the specified If ADD is non-nil, the user will be added with the specified
information if it is not already present in the user or channel information if it is not already present in the user or channel
@ -4822,13 +4880,6 @@ See also: `erc-update-user' and `erc-update-channel-member'."
(if cuser (if cuser
(progn (progn
(erc-log (format "update-member: user = %S, cuser = %S" user cuser)) (erc-log (format "update-member: user = %S, cuser = %S" user cuser))
(when (and op
(not (eq (erc-channel-user-op cuser) op)))
(setq changed t)
(setf (erc-channel-user-op cuser)
(cond ((eq op 'on) t)
((eq op 'off) nil)
(t op))))
(when (and voice (when (and voice
(not (eq (erc-channel-user-voice cuser) voice))) (not (eq (erc-channel-user-voice cuser) voice)))
(setq changed t) (setq changed t)
@ -4836,6 +4887,34 @@ See also: `erc-update-user' and `erc-update-channel-member'."
(cond ((eq voice 'on) t) (cond ((eq voice 'on) t)
((eq voice 'off) nil) ((eq voice 'off) nil)
(t voice)))) (t voice))))
(when (and halfop
(not (eq (erc-channel-user-halfop cuser) halfop)))
(setq changed t)
(setf (erc-channel-user-halfop cuser)
(cond ((eq halfop 'on) t)
((eq halfop 'off) nil)
(t halfop))))
(when (and op
(not (eq (erc-channel-user-op cuser) op)))
(setq changed t)
(setf (erc-channel-user-op cuser)
(cond ((eq op 'on) t)
((eq op 'off) nil)
(t op))))
(when (and admin
(not (eq (erc-channel-user-admin cuser) admin)))
(setq changed t)
(setf (erc-channel-user-admin cuser)
(cond ((eq admin 'on) t)
((eq admin 'off) nil)
(t admin))))
(when (and owner
(not (eq (erc-channel-user-owner cuser) owner)))
(setq changed t)
(setf (erc-channel-user-owner cuser)
(cond ((eq owner 'on) t)
((eq owner 'off) nil)
(t owner))))
(when update-message-time (when update-message-time
(setf (erc-channel-user-last-message-time cuser) (current-time))) (setf (erc-channel-user-last-message-time cuser) (current-time)))
(setq user-changed (setq user-changed
@ -4856,12 +4935,21 @@ See also: `erc-update-user' and `erc-update-channel-member'."
(cons (current-buffer) (cons (current-buffer)
(erc-server-user-buffers user)))) (erc-server-user-buffers user))))
(setq cuser (make-erc-channel-user (setq cuser (make-erc-channel-user
:op (cond ((eq op 'on) t)
((eq op 'off) nil)
(t op))
:voice (cond ((eq voice 'on) t) :voice (cond ((eq voice 'on) t)
((eq voice 'off) nil) ((eq voice 'off) nil)
(t voice)) (t voice))
:halfop (cond ((eq halfop 'on) t)
((eq halfop 'off) nil)
(t halfop))
:op (cond ((eq op 'on) t)
((eq op 'off) nil)
(t op))
:admin (cond ((eq admin 'on) t)
((eq admin 'off) nil)
(t admin))
:owner (cond ((eq owner 'on) t)
((eq owner 'off) nil)
(t owner))
:last-message-time :last-message-time
(if update-message-time (current-time)))) (if update-message-time (current-time))))
(puthash (erc-downcase nick) (cons user cuser) (puthash (erc-downcase nick) (cons user cuser)
@ -4872,7 +4960,7 @@ See also: `erc-update-user' and `erc-update-channel-member'."
(or changed user-changed add))) (or changed user-changed add)))
(defun erc-update-channel-member (channel nick new-nick (defun erc-update-channel-member (channel nick new-nick
&optional add op voice host login &optional add voice halfop op admin owner host login
full-name info update-message-time) full-name info update-message-time)
"Update user and channel information for the user with "Update user and channel information for the user with
nickname NICK in channel CHANNEL. nickname NICK in channel CHANNEL.
@ -4880,7 +4968,7 @@ nickname NICK in channel CHANNEL.
See also: `erc-update-current-channel-member'." See also: `erc-update-current-channel-member'."
(erc-with-buffer (erc-with-buffer
(channel) (channel)
(erc-update-current-channel-member nick new-nick add op voice host (erc-update-current-channel-member nick new-nick add voice halfop op admin owner host
login full-name info login full-name info
update-message-time))) update-message-time)))
@ -4979,7 +5067,7 @@ arg-modes is a list of triples of the form:
(while chars (while chars
(cond ((string= (car chars) "+") (setq add-p t)) (cond ((string= (car chars) "+") (setq add-p t))
((string= (car chars) "-") (setq add-p nil)) ((string= (car chars) "-") (setq add-p nil))
((string-match "^[ovbOVB]" (car chars)) ((string-match "^[qaovhbQAOVHB]" (car chars))
(setq arg-modes (cons (list (car chars) (setq arg-modes (cons (list (car chars)
(if add-p 'on 'off) (if add-p 'on 'off)
(if args (car args) nil)) (if args (car args) nil))
@ -5001,7 +5089,7 @@ arg-modes is a list of triples of the form:
(list add-modes remove-modes arg-modes)) (list add-modes remove-modes arg-modes))
nil)) nil))
(defun erc-update-modes (tgt mode-string &optional nick host login) (defun erc-update-modes (tgt mode-string &optional _nick _host _login)
"Update the mode information for TGT, provided as MODE-STRING. "Update the mode information for TGT, provided as MODE-STRING.
Optional arguments: NICK, HOST and LOGIN - the attributes of the Optional arguments: NICK, HOST and LOGIN - the attributes of the
person who changed the modes." person who changed the modes."
@ -5035,11 +5123,16 @@ person who changed the modes."
(let ((mode (nth 0 (car arg-modes))) (let ((mode (nth 0 (car arg-modes)))
(onoff (nth 1 (car arg-modes))) (onoff (nth 1 (car arg-modes)))
(arg (nth 2 (car arg-modes)))) (arg (nth 2 (car arg-modes))))
(cond ((string-match "^[oO]" mode) (cond ((string-match "^[Vv]" mode)
(erc-update-channel-member tgt arg arg nil onoff)) (erc-update-channel-member tgt arg arg nil onoff))
((string-match "^[Vv]" mode) ((string-match "^[hH]" mode)
(erc-update-channel-member tgt arg arg nil nil (erc-update-channel-member tgt arg arg nil nil onoff))
onoff)) ((string-match "^[oO]" mode)
(erc-update-channel-member tgt arg arg nil nil nil onoff))
((string-match "^[aA]" mode)
(erc-update-channel-member tgt arg arg nil nil nil nil onoff))
((string-match "^[qQ]" mode)
(erc-update-channel-member tgt arg arg nil nil nil nil nil onoff))
((string-match "^[Ll]" mode) ((string-match "^[Ll]" mode)
(erc-update-channel-limit tgt onoff arg)) (erc-update-channel-limit tgt onoff arg))
((string-match "^[Kk]" mode) ((string-match "^[Kk]" mode)
@ -5287,8 +5380,6 @@ This returns non-nil only if we actually send anything."
(or (and erc-flood-protect (erc-split-line line)) (or (and erc-flood-protect (erc-split-line line))
(list line)))) (list line))))
(split-string str "\n")) (split-string str "\n"))
;; Insert the prompt along with the command.
(erc-display-command str)
(erc-process-input-line (concat str "\n") t nil)) (erc-process-input-line (concat str "\n") t nil))
t))))) t)))))
@ -5543,12 +5634,11 @@ This command is sent even if excess flood is detected."
(interactive "P") (interactive "P")
(erc-set-active-buffer (current-buffer)) (erc-set-active-buffer (current-buffer))
(let ((tgt (erc-default-target))) (let ((tgt (erc-default-target)))
(cond ((or (not tgt) (not (erc-channel-p tgt))) (if (or (not tgt) (not (erc-channel-p tgt)))
(erc-display-message nil 'error (current-buffer) 'no-target)) (erc-display-message nil 'error (current-buffer) 'no-target)
(arg (erc-load-irc-script-lines (list (concat "/mode " tgt " -i")) (erc-load-irc-script-lines
t)) (list (concat "/mode " tgt (if arg " -i" " +i")))
(t (erc-load-irc-script-lines (list (concat "/mode " tgt " +i")) t))))
t)))))
(defun erc-get-channel-mode-from-keypress (key) (defun erc-get-channel-mode-from-keypress (key)
"Read a key sequence and call the corresponding channel mode function. "Read a key sequence and call the corresponding channel mode function.
@ -5580,15 +5670,14 @@ If CHANNEL is non-nil, toggle MODE for that channel, otherwise use
(interactive "P") (interactive "P")
(erc-set-active-buffer (current-buffer)) (erc-set-active-buffer (current-buffer))
(let ((tgt (or channel (erc-default-target)))) (let ((tgt (or channel (erc-default-target))))
(cond ((or (null tgt) (null (erc-channel-p tgt))) (if (or (null tgt) (null (erc-channel-p tgt)))
(erc-display-message nil 'error 'active 'no-target)) (erc-display-message nil 'error 'active 'no-target)
((member mode erc-channel-modes) (let* ((active (member mode erc-channel-modes))
(erc-log (format "%s: Toggle mode %s OFF" tgt mode)) (newstate (if active "OFF" "ON")))
(message "Toggle channel mode %s OFF" mode) (erc-log (format "%s: Toggle mode %s %s" tgt mode newstate))
(erc-server-send (format "MODE %s -%s" tgt mode))) (message "Toggle channel mode %s %s" mode newstate)
(t (erc-log (format "%s: Toggle channel mode %s ON" tgt mode)) (erc-server-send (format "MODE %s %s%s"
(message "Toggle channel mode %s ON" mode) tgt (if active "-" "+") mode))))))
(erc-server-send (format "MODE %s +%s" tgt mode))))))
(defun erc-insert-mode-command () (defun erc-insert-mode-command ()
"Insert the line \"/mode <current target> \" at `point'." "Insert the line \"/mode <current target> \" at `point'."
@ -5651,7 +5740,7 @@ as an Emacs Lisp program. Otherwise, treat it as a regular IRC
script." script."
(erc-log (concat "erc-load-script: " file)) (erc-log (concat "erc-load-script: " file))
(cond (cond
((string-match "\\.el$" file) ((string-match "\\.el\\'" file)
(load file)) (load file))
(t (t
(erc-load-irc-script file)))) (erc-load-irc-script file))))
@ -5868,17 +5957,10 @@ Returns a list of the form (HIGH LOW), compatible with Emacs time format."
(list (truncate (/ n 65536)) (list (truncate (/ n 65536))
(truncate (mod n 65536))))) (truncate (mod n 65536)))))
(defun erc-emacs-time-to-erc-time (time) (defalias 'erc-emacs-time-to-erc-time
"Convert Emacs TIME to a number of seconds since the epoch." (if (featurep 'xemacs) 'time-to-seconds 'float-time))
(when time
(+ (* (nth 0 time) 65536.0) (nth 1 time))))
; (round (+ (* (nth 0 tm) 65536.0) (nth 1 tm))))
(defun erc-current-time () (defalias 'erc-current-time 'erc-emacs-time-to-erc-time)
"Return the `current-time' as a number of seconds since the epoch.
See also `erc-emacs-time-to-erc-time'."
(erc-emacs-time-to-erc-time (current-time)))
(defun erc-time-diff (t1 t2) (defun erc-time-diff (t1 t2)
"Return the time difference in seconds between T1 and T2." "Return the time difference in seconds between T1 and T2."
@ -5981,26 +6063,32 @@ entry of `channel-members'."
(user (if channel-data (user (if channel-data
(car channel-data) (car channel-data)
(erc-get-server-user word))) (erc-get-server-user word)))
host login full-name nick op voice) host login full-name nick voice halfop op admin owner)
(when user (when user
(setq nick (erc-server-user-nickname user) (setq nick (erc-server-user-nickname user)
host (erc-server-user-host user) host (erc-server-user-host user)
login (erc-server-user-login user) login (erc-server-user-login user)
full-name (erc-server-user-full-name user)) full-name (erc-server-user-full-name user))
(if cuser (if cuser
(setq op (erc-channel-user-op cuser) (setq voice (erc-channel-user-voice cuser)
voice (erc-channel-user-voice cuser))) halfop (erc-channel-user-halfop cuser)
op (erc-channel-user-op cuser)
admin (erc-channel-user-admin cuser)
owner (erc-channel-user-owner cuser))))
(if (called-interactively-p 'interactive) (if (called-interactively-p 'interactive)
(message "%s is %s@%s%s%s" (message "%s is %s@%s%s%s"
nick login host nick login host
(if full-name (format " (%s)" full-name) "") (if full-name (format " (%s)" full-name) "")
(if (or op voice) (if (or voice halfop op admin owner)
(format " and is +%s%s on %s" (format " and is +%s%s%s%s%s on %s"
(if op "o" "")
(if voice "v" "") (if voice "v" "")
(if halfop "h" "")
(if op "o" "")
(if admin "a" "")
(if owner "q" "")
(erc-default-target)) (erc-default-target))
"")) ""))
user)))) user)))
(defun erc-away-time () (defun erc-away-time ()
"Return non-nil if the current ERC process is set away. "Return non-nil if the current ERC process is set away.
@ -6139,7 +6227,11 @@ shortened server name instead."
(cond ((erc-default-target) (cond ((erc-default-target)
(concat (erc-string-no-properties (erc-default-target)) (concat (erc-string-no-properties (erc-default-target))
"@" network-name)) "@" network-name))
(network-name network-name) ((and network-name
(not (get-buffer network-name)))
(when erc-rename-buffers
(rename-buffer network-name))
network-name)
(t (buffer-name (current-buffer)))))) (t (buffer-name (current-buffer))))))
(defun erc-format-away-status () (defun erc-format-away-status ()
@ -6278,7 +6370,7 @@ P may be an integer or a service name."
If optional argument HERE is non-nil, insert version number at point." If optional argument HERE is non-nil, insert version number at point."
(interactive "P") (interactive "P")
(let ((version-string (let ((version-string
(format "ERC %s (GNU Emacs %s)" erc-version-string emacs-version))) (format "ERC (IRC client for Emacs %s)" emacs-version)))
(if here (if here
(insert version-string) (insert version-string)
(if (called-interactively-p 'interactive) (if (called-interactively-p 'interactive)