• Home
  • History
  • Annotate
  • Raw
  • Download
  • only in /macosx-10.10.1/emacs-93/emacs/lisp/erc/

Lines Matching +defs:erc +defs:with +defs:server +defs:buffer

0 ;; erc.el --- An Emacs Internet Relay Chat client
29 ;; along with GNU Emacs; see the file COPYING. If not, write to the
38 ;; * http://sv.gnu.org/projects/erc/
42 ;; (http://sv.gnu.org/projects/erc). I invite everyone who wants to
48 ;; Put erc.el in your load-path, and put (require 'erc) in your .emacs.
52 ;; Use M-x customize-group RET erc RET to get an overview
57 ;; To connect to an IRC server, do
59 ;; M-x erc RET
61 ;; After you are connected to a server, you can use C-h m or have a look at
69 (defconst erc-version-string "Version 5.2"
70 "ERC version. This is used by function `erc-version'.")
76 (require 'erc-compat)
78 (defvar erc-official-location
79 "http://emacswiki.org/cgi-bin/wiki/ERC (mailing list: erc-discuss@gnu.org)"
82 (defgroup erc nil
85 :prefix "erc-"
88 (defgroup erc-buffers nil
90 :group 'erc)
92 (defgroup erc-display nil
94 :group 'erc)
96 (defgroup erc-mode-line-and-header nil
98 :group 'erc-display)
100 (defgroup erc-ignore nil
102 :group 'erc)
104 (defgroup erc-query nil
106 :group 'erc)
108 (defgroup erc-quit-and-part nil
110 :group 'erc)
112 (defgroup erc-paranoia nil
114 :group 'erc)
116 (defgroup erc-scripts nil
117 "Running scripts at startup and with /LOAD"
118 :group 'erc)
120 (require 'erc-backend)
122 ;; compatibility with older ERC releases
126 (defvaralias 'erc-announced-server-name 'erc-server-announced-name)
127 (erc-make-obsolete-variable 'erc-announced-server-name
128 'erc-server-announced-name
130 (defvaralias 'erc-process 'erc-server-process)
131 (erc-make-obsolete-variable 'erc-process 'erc-server-process "ERC 5.1")
132 (defvaralias 'erc-default-coding-system 'erc-server-coding-system)
133 (erc-make-obsolete-variable 'erc-default-coding-system
134 'erc-server-coding-system
139 (defalias 'erc-send-command 'erc-server-send)
140 (erc-make-obsolete 'erc-send-command 'erc-server-send "ERC 5.1")
144 (defcustom erc-server nil
145 "IRC server to use if one is not provided.
146 See function `erc-compute-server' for more details on connection
148 :group 'erc
152 (defcustom erc-port nil
156 :group 'erc
161 (defcustom erc-nick nil
168 See function `erc-compute-nick' for more details on connection
170 :group 'erc
175 (defcustom erc-nick-uniquifier "`"
177 :group 'erc
180 (defcustom erc-try-new-nick-p t
182 ERC should automatically attempt to connect with another nickname.
184 You can manually set another nickname with the /NICK command."
185 :group 'erc
188 (defcustom erc-user-full-name nil
193 See function `erc-compute-full-name' for more details on connection
195 :group 'erc
204 (defvar erc-password nil
205 "Password to use when authenticating to an IRC server.
209 (defcustom erc-user-mode nil
211 :group 'erc
215 (defcustom erc-prompt-for-password t
217 :group 'erc
220 (defcustom erc-warn-about-blank-lines t
222 :group 'erc
225 (defcustom erc-send-whitespace-lines nil
227 :group 'erc
230 (defcustom erc-hide-prompt nil
233 \(A command is any input starting with a '/').
235 See also the variables `erc-prompt' and `erc-command-indicator'."
236 :group 'erc-display
241 (defcustom erc-show-my-nick t
246 :group 'erc-display
249 (define-widget 'erc-message-type 'set
259 (defcustom erc-hide-list nil
262 :group 'erc-ignore
263 :type 'erc-message-type)
265 (defvar erc-session-password nil
267 (make-variable-buffer-local 'erc-session-password)
269 (defcustom erc-disconnected-hook nil
270 "Run this hook with arguments (NICK IP REASON) when disconnected.
272 `erc-server-QUIT-functions' might not be run when we disconnect,
274 :group 'erc-hooks
277 (defcustom erc-complete-functions nil
281 :group 'erc-hooks
284 (defcustom erc-join-hook nil
286 without arguments, with the current buffer set to the buffer of
289 See also `erc-server-JOIN-functions', `erc-part-hook'."
290 :group 'erc-hooks
293 (defcustom erc-quit-hook nil
297 See also `erc-server-QUIT-functions' and `erc-disconnected-hook'."
298 :group 'erc-hooks
301 (defcustom erc-part-hook nil
305 See also `erc-server-QUIT-functions', `erc-quit-hook' and
306 `erc-disconnected-hook'."
307 :group 'erc-hooks
310 (defcustom erc-kick-hook nil
314 See also `erc-server-PART-functions' and `erc-part-hook'."
315 :group 'erc-hooks
318 (defcustom erc-nick-changed-functions nil
322 :group 'erc-hooks
325 (defcustom erc-connect-pre-hook '(erc-initialize-log-marker)
326 "Hook called just before `erc' calls `erc-connect'.
327 Functions are passed a buffer as the first argument."
328 :group 'erc-hooks
332 (defvar erc-channel-users nil
334 associates nicknames with cons cells of the form:
336 erc-server-user struct, and MEMBER-DATA is a pointer to an
337 erc-channel-user struct.")
338 (make-variable-buffer-local 'erc-channel-users)
340 (defvar erc-server-users nil
341 "A hash table of users on the current server, which associates
342 nicknames with erc-server-user struct instances.")
343 (make-variable-buffer-local 'erc-server-users)
345 (defun erc-downcase (string)
358 (defmacro erc-with-server-buffer (&rest body)
359 "Execute BODY in the current ERC server buffer.
360 If no server buffer exists, return nil."
361 (let ((buffer (make-symbol "buffer")))
362 `(let ((,buffer (erc-server-buffer)))
363 (when (buffer-live-p ,buffer)
364 (with-current-buffer ,buffer
366 (put 'erc-with-server-buffer 'lisp-indent-function 0)
367 (put 'erc-with-server-buffer 'edebug-form-spec '(body))
369 (defstruct (erc-server-user (:type vector) :named)
375 ;; CHANNEL-DATA is either nil or an erc-channel-user struct.
379 (defstruct (erc-channel-user (:type vector) :named)
387 (defsubst erc-get-channel-user (nick)
389 in the current buffer's `erc-channel-users' hash table."
390 (gethash (erc-downcase nick) erc-channel-users))
392 (defsubst erc-get-server-user (nick)
393 "Finds the USER corresponding to NICK in the current server's
394 `erc-server-users' hash table."
395 (erc-with-server-buffer
396 (gethash (erc-downcase nick) erc-server-users)))
398 (defsubst erc-add-server-user (nick user)
401 Adds USER with nickname NICK to the `erc-server-users' hash table."
402 (erc-with-server-buffer
403 (puthash (erc-downcase nick) user erc-server-users)))
405 (defsubst erc-remove-server-user (nick)
408 Removes the user with nickname NICK from the `erc-server-users'
410 `erc-channel-users' lists of other buffers.
412 See also: `erc-remove-user'."
413 (erc-with-server-buffer
414 (remhash (erc-downcase nick) erc-server-users)))
416 (defun erc-change-user-nickname (user new-nick)
420 `erc-server-users' hash table. The `erc-channel-users' lists of
422 (let ((nick (erc-server-user-nickname user)))
423 (setf (erc-server-user-nickname user) new-nick)
424 (erc-with-server-buffer
425 (remhash (erc-downcase nick) erc-server-users)
426 (puthash (erc-downcase new-nick) user erc-server-users))
427 (dolist (buf (erc-server-user-buffers user))
428 (if (buffer-live-p buf)
429 (with-current-buffer buf
430 (let ((cdata (erc-get-channel-user nick)))
431 (remhash (erc-downcase nick) erc-channel-users)
432 (puthash (erc-downcase new-nick) cdata
433 erc-channel-users)))))))
435 (defun erc-remove-channel-user (nick)
438 Removes the user with nickname NICK from the `erc-channel-users'
440 `erc-channel-users' list of any other buffers, the user is also
441 removed from the server's `erc-server-users' list.
443 See also: `erc-remove-server-user' and `erc-remove-user'."
444 (let ((channel-data (erc-get-channel-user nick)))
447 (setf (erc-server-user-buffers user)
448 (delq (current-buffer)
449 (erc-server-user-buffers user)))
450 (remhash (erc-downcase nick) erc-channel-users)
451 (if (null (erc-server-user-buffers user))
452 (erc-remove-server-user nick))))))
454 (defun erc-remove-user (nick)
457 Removes the user with nickname NICK from the `erc-server-users'
458 list as well as from all `erc-channel-users' lists.
460 See also: `erc-remove-server-user' and
461 `erc-remove-channel-user'."
462 (let ((user (erc-get-server-user nick)))
464 (let ((buffers (erc-server-user-buffers user)))
466 (if (buffer-live-p buf)
467 (with-current-buffer buf
468 (remhash (erc-downcase nick) erc-channel-users)
469 (run-hooks 'erc-channel-members-changed-hook)))))
470 (erc-remove-server-user nick))))
472 (defun erc-remove-channel-users ()
476 `erc-server-PART' and `erc-server-QUIT'."
477 (when (and erc-server-connected
478 (erc-server-process-alive)
479 (hash-table-p erc-channel-users))
481 (erc-remove-channel-user nick))
482 erc-channel-users)
483 (clrhash erc-channel-users)))
485 (defsubst erc-channel-user-op-p (nick)
488 (hash-table-p erc-channel-users)
489 (let ((cdata (erc-get-channel-user nick)))
491 (erc-channel-user-op (cdr cdata))))))
493 (defsubst erc-channel-user-voice-p (nick)
496 (hash-table-p erc-channel-users)
497 (let ((cdata (erc-get-channel-user nick)))
499 (erc-channel-user-voice (cdr cdata))))))
501 (defun erc-get-channel-user-list ()
504 an erc-server-user struct, and CHANNEL-DATA is either `nil' or an
505 erc-channel-user struct.
507 See also: `erc-sort-channel-users-by-activity'"
509 (if (hash-table-p erc-channel-users)
512 erc-channel-users))
515 (defun erc-get-server-nickname-list ()
516 "Returns a list of known nicknames on the current server."
517 (erc-with-server-buffer
519 (when (hash-table-p erc-server-users)
522 (cons (erc-server-user-nickname user)
524 erc-server-users)
527 (defun erc-get-channel-nickname-list ()
530 (when (hash-table-p erc-channel-users)
533 (cons (erc-server-user-nickname (car cdata))
535 erc-channel-users)
538 (defun erc-get-server-nickname-alist ()
539 "Returns an alist of known nicknames on the current server."
540 (erc-with-server-buffer
542 (when (hash-table-p erc-server-users)
545 (cons (cons (erc-server-user-nickname user) nil)
547 erc-server-users)
550 (defun erc-get-channel-nickname-alist ()
553 (when (hash-table-p erc-channel-users)
556 (cons (cons (erc-server-user-nickname (car cdata)) nil)
558 erc-channel-users)
561 (defun erc-sort-channel-users-by-activity (list)
565 See also: `erc-get-channel-user-list'."
570 (let ((tx (erc-channel-user-last-message-time (cdr x)))
571 (ty (erc-channel-user-last-message-time (cdr y))))
578 (defun erc-sort-channel-users-alphabetically (list)
582 See also: `erc-get-channel-user-list'."
587 (let ((nickx (downcase (erc-server-user-nickname (car x))))
588 (nicky (downcase (erc-server-user-nickname (car y)))))
595 (defvar erc-channel-topic nil
597 (make-variable-buffer-local 'erc-channel-topic)
599 (defvar erc-channel-modes nil
603 (make-variable-buffer-local 'erc-channel-modes)
605 (defvar erc-insert-marker nil
606 "The place where insertion of new text in erc buffers should happen.")
607 (make-variable-buffer-local 'erc-insert-marker)
609 (defvar erc-input-marker nil
611 (make-variable-buffer-local 'erc-input-marker)
613 (defun erc-string-no-properties (string)
619 (defcustom erc-prompt "ERC>"
621 :group 'erc-display
624 (defun erc-prompt ()
627 See also the variable `erc-prompt'."
628 (let ((prompt (if (functionp erc-prompt)
629 (funcall erc-prompt)
630 erc-prompt)))
635 (defcustom erc-command-indicator nil
638 If non-nil, this will be used in the ERC buffer to indicate
639 commands (i.e., input starting with a '/').
641 If nil, the prompt will be constructed from the variable `erc-prompt'."
642 :group 'erc-display
645 (defun erc-command-indicator ()
648 This only has any meaning if the variable `erc-command-indicator' is non-nil."
649 (and erc-command-indicator
650 (let ((prompt (if (functionp erc-command-indicator)
651 (funcall erc-command-indicator)
652 erc-command-indicator)))
657 (defcustom erc-notice-prefix "*** "
659 :group 'erc-display
662 (defcustom erc-notice-highlight-type 'all
664 See `erc-notice-prefix'.
672 :group 'erc-display
677 (defcustom erc-echo-notice-hook nil
679 notice. Each function is called with four arguments, the string
680 to display, the parsed server message, the target buffer (or
683 those specified in `erc-echo-notice-always-hook'.
685 See also: `erc-echo-notice-always-hook',
686 `erc-echo-notice-in-default-buffer',
687 `erc-echo-notice-in-target-buffer',
688 `erc-echo-notice-in-minibuffer',
689 `erc-echo-notice-in-server-buffer',
690 `erc-echo-notice-in-active-non-server-buffer',
691 `erc-echo-notice-in-active-buffer',
692 `erc-echo-notice-in-user-buffers',
693 `erc-echo-notice-in-user-and-target-buffers',
694 `erc-echo-notice-in-first-user-buffer'"
695 :group 'erc-hooks
697 :options '(erc-echo-notice-in-default-buffer
698 erc-echo-notice-in-target-buffer
699 erc-echo-notice-in-minibuffer
700 erc-echo-notice-in-server-buffer
701 erc-echo-notice-in-active-non-server-buffer
702 erc-echo-notice-in-active-buffer
703 erc-echo-notice-in-user-buffers
704 erc-echo-notice-in-user-and-target-buffers
705 erc-echo-notice-in-first-user-buffer))
707 (defcustom erc-echo-notice-always-hook
708 '(erc-echo-notice-in-default-buffer)
710 notice. Each function is called with four arguments, the string
711 to display, the parsed server message, the target buffer (or
714 specified in `erc-echo-notice-hook'.
716 See also: `erc-echo-notice-hook',
717 `erc-echo-notice-in-default-buffer',
718 `erc-echo-notice-in-target-buffer',
719 `erc-echo-notice-in-minibuffer',
720 `erc-echo-notice-in-server-buffer',
721 `erc-echo-notice-in-active-non-server-buffer',
722 `erc-echo-notice-in-active-buffer',
723 `erc-echo-notice-in-user-buffers',
724 `erc-echo-notice-in-user-and-target-buffers',
725 `erc-echo-notice-in-first-user-buffer'"
726 :group 'erc-hooks
728 :options '(erc-echo-notice-in-default-buffer
729 erc-echo-notice-in-target-buffer
730 erc-echo-notice-in-minibuffer
731 erc-echo-notice-in-server-buffer
732 erc-echo-notice-in-active-non-server-buffer
733 erc-echo-notice-in-active-buffer
734 erc-echo-notice-in-user-buffers
735 erc-echo-notice-in-user-and-target-buffers
736 erc-echo-notice-in-first-user-buffer))
740 (defcustom erc-whowas-on-nosuchnick nil
742 :group 'erc
745 (defcustom erc-verbose-server-ping nil
746 "*If non-nil, show every time you get a PING or PONG from the server."
747 :group 'erc-paranoia
750 (defcustom erc-public-away-p nil
756 :group 'erc
759 (defcustom erc-away-nickname nil
761 :group 'erc
765 (defcustom erc-paranoid nil
767 :group 'erc-paranoia
770 (defcustom erc-disable-ctcp-replies nil
775 :group 'erc-paranoia
778 (defcustom erc-anonymous-login t
780 :group 'erc-paranoia
783 (defcustom erc-prompt-for-channel-key nil
784 "Prompt for channel key when using `erc-join-channel' interactively."
785 :group 'erc
788 (defcustom erc-email-userid "user"
790 :group 'erc
793 (defcustom erc-system-name nil
796 :group 'erc
800 (defcustom erc-ignore-list nil
806 :group 'erc-ignore
808 (make-variable-buffer-local 'erc-ignore-list)
810 (defcustom erc-ignore-reply-list nil
813 This differs from `erc-ignore-list' in that it also ignores any
825 :group 'erc-ignore
828 (defvar erc-flood-protect t
830 Flooding is sending too much information to the server in too
831 short of an interval, which may cause the server to terminate the
834 See `erc-server-flood-margin' for other flood-related parameters.")
838 (defcustom erc-startup-file-list
844 If the filename ends with `.el' it is presumed to be an Emacs Lisp
847 :group 'erc-scripts
850 (defcustom erc-script-path nil
854 :group 'erc-scripts
857 (defcustom erc-script-echo t
859 :group 'erc-scripts
862 (defvar erc-last-saved-position nil
863 "A marker containing the position the current buffer was last saved at.")
864 (make-variable-buffer-local 'erc-last-saved-position)
866 (defcustom erc-kill-buffer-on-part nil
867 "Kill the channel buffer on PART.
870 :group 'erc-quit-and-part
873 (defcustom erc-kill-queries-on-quit nil
874 "Kill all query (also channel) buffers of this server on QUIT.
875 See the variable `erc-kill-buffer-on-part' for details."
876 :group 'erc-quit-and-part
879 (defcustom erc-kill-server-buffer-on-quit nil
880 "Kill the server buffer of the process on QUIT."
881 :group 'erc-quit-and-part
884 (defcustom erc-quit-reason-various-alist nil
897 (setq erc-quit-reason-various-alist
898 '((\"zippy\" erc-quit-reason-zippy)
900 (\"version\" erc-quit-reason-normal)
905 :group 'erc-quit-and-part
908 (defcustom erc-part-reason-various-alist nil
921 (setq erc-part-reason-various-alist
922 '((\"zippy\" erc-part-reason-zippy)
924 (\"version\" erc-part-reason-normal)
929 :group 'erc-quit-and-part
932 (defcustom erc-quit-reason 'erc-quit-reason-normal
937 :group 'erc-quit-and-part
938 :type '(choice (const erc-quit-reason-normal)
939 (const erc-quit-reason-zippy)
940 (const erc-quit-reason-various)
943 (defcustom erc-part-reason 'erc-part-reason-normal
948 :group 'erc-quit-and-part
949 :type '(choice (const erc-part-reason-normal)
950 (const erc-part-reason-zippy)
951 (const erc-part-reason-various)
954 (defvar erc-grab-buffer-name "*erc-grab*"
955 "The name of the buffer created by `erc-grab-region'.")
959 (defvar erc-user-information "ERC User"
964 (defgroup erc-hooks nil
966 :group 'erc)
968 (defcustom erc-mode-hook nil
969 "Hook run after `erc-mode' setup is finished."
970 :group 'erc-hooks
972 :options '(erc-add-scroll-to-bottom))
974 (defcustom erc-timer-hook nil
976 The idea is that servers always play ping pong with the client, and so there
977 is no need for any idle-timer games with Emacs."
978 :group 'erc-hooks
981 (defcustom erc-insert-pre-hook nil
982 "Hook called first when some text is inserted through `erc-display-line'.
983 It gets called with one argument, STRING.
984 To be able to modify the inserted text, use `erc-insert-modify-hook' instead.
985 Filtering functions can set `erc-insert-this' to nil to avoid
987 :group 'erc-hooks
990 (defcustom erc-send-pre-hook nil
991 "Hook called first when some text is sent through `erc-send-current-line'.
992 It gets called with one argument, STRING.
995 used in `erc-send-current-line'.
997 To change the text inserted into the buffer without changing the text
998 that will be sent, use `erc-send-modify-hook' instead.
1000 Filtering functions can set `erc-send-this' to nil to avoid sending of
1001 that particular string at all and `erc-insert-this' to prevent
1002 inserting that particular string into the buffer.
1004 Note that it's useless to set `erc-send-this' to nil and
1005 `erc-insert-this' to t. ERC is sane enough to not insert the text
1007 :group 'erc-hooks
1010 (defvar erc-insert-this t
1011 "Insert the text into the target buffer or not.
1012 Functions on `erc-insert-pre-hook' can set this variable to nil
1015 (defvar erc-send-this t
1017 Functions on `erc-send-pre-hook' can set this variable to nil
1020 (defcustom erc-insert-modify-hook ()
1022 This hook is called just after `erc-insert-pre-hook' when the value
1023 of `erc-insert-this' is t.
1024 While this hook is run, narrowing is in effect and `current-buffer' is
1025 the buffer where the text got inserted. One possible value to add here
1026 is `erc-fill'."
1027 :group 'erc-hooks
1030 (defcustom erc-insert-post-hook nil
1031 "This hook is called just after `erc-insert-modify-hook'.
1033 :group 'erc-hooks
1035 :options '(erc-truncate-buffer
1036 erc-make-read-only
1037 erc-save-buffer-in-logs))
1039 (defcustom erc-send-modify-hook nil
1041 This hook is called just after `erc-send-pre-hook' when the values
1042 of `erc-send-this' and `erc-insert-this' are both t.
1043 While this hook is run, narrowing is in effect and `current-buffer' is
1044 the buffer where the text got inserted.
1049 is `erc-fill'."
1050 :group 'erc-hooks
1053 (defcustom erc-send-post-hook nil
1054 "This hook is called just after `erc-send-modify-hook'.
1057 to the server.
1059 This function is called with narrowing, ala `erc-send-modify-hook'."
1060 :group 'erc-hooks
1062 :options '(erc-make-read-only))
1064 (defcustom erc-send-completed-hook
1073 :group 'erc-hooks
1077 (defvar erc-mode-syntax-table
1088 (defvar erc-mode-abbrev-table nil
1090 (define-abbrev-table 'erc-mode-abbrev-table ())
1092 (defvar erc-mode-map
1094 (define-key map "\C-m" 'erc-send-current-line)
1095 (define-key map "\C-a" 'erc-bol)
1096 (define-key map [home] 'erc-bol)
1097 (define-key map "\C-c\C-a" 'erc-bol)
1098 (define-key map "\C-c\C-b" 'erc-iswitchb)
1099 (define-key map "\C-c\C-c" 'erc-toggle-interpret-controls)
1100 (define-key map "\C-c\C-d" 'erc-input-action)
1101 (define-key map "\C-c\C-e" 'erc-toggle-ctcp-autoresponse)
1102 (define-key map "\C-c\C-f" 'erc-toggle-flood-control)
1103 (define-key map "\C-c\C-i" 'erc-invite-only-mode)
1104 (define-key map "\C-c\C-j" 'erc-join-channel)
1105 (define-key map "\C-c\C-n" 'erc-channel-names)
1106 (define-key map "\C-c\C-o" 'erc-get-channel-mode-from-keypress)
1107 (define-key map "\C-c\C-p" 'erc-part-from-channel)
1108 (define-key map "\C-c\C-q" 'erc-quit-server)
1109 (define-key map "\C-c\C-r" 'erc-remove-text-properties-region)
1110 (define-key map "\C-c\C-t" 'erc-set-topic)
1111 (define-key map "\C-c\C-u" 'erc-kill-input)
1113 (define-key map "\t" 'erc-complete-word)
1135 (defgroup erc-faces nil
1137 :group 'erc)
1139 (defface erc-default-face '((t))
1141 :group 'erc-faces)
1143 (defface erc-direct-msg-face '((t (:foreground "IndianRed")))
1144 "ERC face used for messages you receive in the main erc buffer."
1145 :group 'erc-faces)
1147 (defface erc-header-line
1151 This will only be used if `erc-header-line-face-method' is non-nil."
1152 :group 'erc-faces)
1154 (defface erc-input-face '((t (:foreground "brown")))
1156 :group 'erc-faces)
1158 (defface erc-prompt-face
1161 :group 'erc-faces)
1163 (defface erc-command-indicator-face
1166 See the variable `erc-command-indicator'."
1167 :group 'erc-faces)
1169 (defface erc-notice-face '((t (:bold t :foreground "SlateBlue")))
1171 :group 'erc-faces)
1173 (defface erc-action-face '((t (:bold t)))
1175 :group 'erc-faces)
1177 (defface erc-error-face '((t (:foreground "red")))
1179 :group 'erc-faces)
1181 ;; same default color as `erc-input-face'
1182 (defface erc-my-nick-face '((t (:bold t :foreground "brown")))
1184 See also `erc-show-my-nick'."
1185 :group 'erc-faces)
1187 (defface erc-nick-default-face '((t (:bold t)))
1189 :group 'erc-faces)
1191 (defface erc-nick-msg-face '((t (:bold t :foreground "IndianRed")))
1193 :group 'erc-faces)
1197 (defvar erc-log-p nil
1198 "When set to t, generate debug messages in a separate debug buffer.")
1200 (defvar erc-debug-log-file (expand-file-name "ERC.debug")
1203 (defvar erc-dbuf nil)
1204 (make-variable-buffer-local 'erc-dbuf)
1206 (defmacro define-erc-module (name alias doc enable-body disable-body
1214 If LOCAL-P is non-nil, the mode will be created as a buffer-local
1217 This will define a minor mode called erc-NAME-mode, possibly
1218 an alias erc-ALIAS-mode, as well as the helper functions
1219 erc-NAME-enable, and erc-NAME-disable.
1223 ;;;###autoload (autoload 'erc-replace-mode \"erc-replace\")
1224 (define-erc-module replace nil
1225 \"This mode replaces incoming text according to `erc-replace-alist'.\"
1226 ((add-hook 'erc-insert-modify-hook
1227 'erc-replace-insert))
1228 ((remove-hook 'erc-insert-modify-hook
1229 'erc-replace-insert)))"
1231 (mode (intern (format "erc-%s-mode" (downcase sn))))
1232 (group (intern (format "erc-%s" (downcase sn))))
1233 (enable (intern (format "erc-%s-enable" (downcase sn))))
1234 (disable (intern (format "erc-%s-disable" (downcase sn)))))
1236 (erc-define-minor-mode
1250 (add-to-list 'erc-modules (quote ,name))
1257 (setq erc-modules (delq (quote ,name) erc-modules))
1264 (format "erc-%s-mode"
1273 (put 'define-erc-module 'doc-string-elt 3)
1275 (defun erc-once-with-server-event (event &rest forms)
1276 "Execute FORMS the next time EVENT occurs in the `current-buffer'.
1278 You should make sure that `current-buffer' is a server buffer.
1287 Please be sure to use this function in server-buffers. In
1291 (unless (erc-server-buffer-p)
1293 "You should only run `erc-once-with-server-event' in a server buffer"))
1295 (hook (erc-get-hook event)))
1296 (put fun 'erc-original-buffer (current-buffer))
1298 (with-current-buffer (get ',fun 'erc-original-buffer)
1305 (defun erc-once-with-server-event-global (event &rest forms)
1306 "Execute FORMS the next time EVENT occurs in any server buffer.
1315 When FORMS execute, the current buffer is the server buffer associated with the
1318 (hook (erc-get-hook event)))
1326 (defmacro erc-log (string)
1327 "Logs STRING if logging is on (see `erc-log-p')."
1328 `(when erc-log-p
1329 (erc-log-aux ,string)))
1331 (defun erc-server-buffer ()
1332 "Return the server buffer for the current buffer's process.
1333 The buffer-local variable `erc-server-process' is used to find
1334 the process buffer."
1335 (and (erc-server-buffer-live-p)
1336 (process-buffer erc-server-process)))
1338 (defun erc-server-buffer-live-p ()
1339 "Return t if the server buffer has not been killed."
1340 (and (processp erc-server-process)
1341 (buffer-live-p (process-buffer erc-server-process))))
1343 (defun erc-server-buffer-p (&optional buffer)
1344 "Return non-nil if argument BUFFER is an ERC server buffer.
1346 If BUFFER is nil, the current buffer is used."
1347 (with-current-buffer (or buffer (current-buffer))
1348 (and (eq major-mode 'erc-mode)
1349 (null (erc-default-target)))))
1351 (defun erc-open-server-buffer-p (&optional buffer)
1352 "Return non-nil if argument BUFFER is an ERC server buffer that
1355 If BUFFER is nil, the current buffer is used."
1356 (and (erc-server-buffer-p)
1357 (erc-server-process-alive)))
1359 (defun erc-query-buffer-p (&optional buffer)
1360 "Return non-nil if BUFFER is an ERC query buffer.
1361 If BUFFER is nil, the current buffer is used."
1362 (with-current-buffer (or buffer (current-buffer))
1363 (let ((target (erc-default-target)))
1364 (and (eq major-mode 'erc-mode)
1368 (defun erc-ison-p (nick)
1371 (erc-with-server-buffer
1372 (let ((erc-online-p 'unknown))
1373 (erc-once-with-server-event
1376 (setq erc-online-p (car (erc-member-ignore-case ,nick ison)))
1378 (erc-server-send (format "ISON %s" nick))
1379 (while (eq erc-online-p 'unknown) (accept-process-output))
1382 (or erc-online-p nick)
1383 (if erc-online-p "" "not "))
1384 erc-online-p))))
1386 (defun erc-log-aux (string)
1388 (let ((cb (current-buffer))
1391 (session-buffer (erc-server-buffer)))
1392 (if session-buffer
1394 (set-buffer session-buffer)
1395 (if (not (and erc-dbuf (bufferp erc-dbuf) (buffer-live-p erc-dbuf)))
1397 (setq erc-dbuf (get-buffer-create
1399 erc-session-server "*")))))
1400 (set-buffer erc-dbuf)
1407 (set-buffer cb))
1410 ;; Last active buffer, to print server messages in the right place
1412 (defvar erc-active-buffer nil
1413 "The current active buffer, the one where the user typed the last command.
1414 Defaults to the server buffer, and should only be set in the
1415 server buffer.")
1416 (make-variable-buffer-local 'erc-active-buffer)
1418 (defun erc-active-buffer ()
1419 "Return the value of `erc-active-buffer' for the current server.
1420 Defaults to the server buffer."
1421 (erc-with-server-buffer
1422 (if (buffer-live-p erc-active-buffer)
1423 erc-active-buffer
1424 (setq erc-active-buffer (current-buffer)))))
1426 (defun erc-set-active-buffer (buffer)
1427 "Set the value of `erc-active-buffer' to BUFFER."
1428 (cond ((erc-server-buffer)
1429 (with-current-buffer (erc-server-buffer)
1430 (setq erc-active-buffer buffer)))
1431 (t (setq erc-active-buffer buffer))))
1435 (defun erc-mode ()
1439 \\{erc-mode-map}
1441 Turning on `erc-mode' runs the hook `erc-mode-hook'."
1443 (use-local-map erc-mode-map)
1445 major-mode 'erc-mode
1446 local-abbrev-table erc-mode-abbrev-table)
1447 (set-syntax-table erc-mode-syntax-table)
1452 (concat "\C-l\\|\\(^" (regexp-quote (erc-prompt)) "\\)"))
1454 (concat "\\(" (regexp-quote (erc-prompt)) "\\)"))
1456 (run-hooks 'erc-mode-hook))
1460 (defconst erc-default-server "irc.freenode.net"
1461 "IRC server to use if it cannot be detected otherwise.")
1463 (defconst erc-default-port "6667"
1466 (defcustom erc-join-buffer 'buffer
1467 "Determines how to display the newly created IRC buffer.
1471 'bury - bury it in a new buffer,
1472 any other value - in place of the current buffer."
1473 :group 'erc-buffers
1478 (const buffer)))
1480 (defcustom erc-frame-alist nil
1481 "*Alist of frame parameters for creating erc frames.
1483 :group 'erc-buffers
1488 (defcustom erc-frame-dedicated-flag nil
1489 "*Non-nil means the erc frames are dedicated to that buffer.
1490 This only has effect when `erc-join-buffer' is set to `frame'."
1491 :group 'erc-buffers
1494 (defun erc-channel-p (channel)
1498 ((and (bufferp channel) (buffer-live-p channel))
1499 (with-current-buffer channel
1500 (erc-channel-p (erc-default-target))))
1503 (defcustom erc-reuse-buffers t
1505 If non-nil, a new buffer will only be created when you join
1506 channels with same names on different servers, or have query buffers
1507 open with nicks of the same name on different servers. Otherwise,
1509 :group 'erc-buffers
1512 (defun erc-normalize-port (port)
1522 (erc-normalize-port (symbol-name port)))
1543 (defun erc-port-equal (a b)
1545 (= (erc-normalize-port a) (erc-normalize-port b)))
1547 (defun erc-generate-new-buffer-name (server port target &optional proc)
1548 "Create a new buffer name based on the arguments."
1551 (or (let ((name (concat server ":" port)))
1555 "*erc-server-buffer*"))))
1556 ;; Reuse existing buffers, but not if the buffer is a connected server
1557 ;; buffer and not if its associated with a different server than the
1558 ;; current ERC buffer.
1559 (if (and erc-reuse-buffers
1560 (get-buffer buf-name)
1562 (with-current-buffer (get-buffer buf-name)
1563 (and (erc-server-buffer-p)
1564 (not (erc-server-process-alive)))))
1565 (with-current-buffer (get-buffer buf-name)
1566 (and (string= erc-session-server server)
1567 (erc-port-equal erc-session-port port))))
1569 (generate-new-buffer-name buf-name))))
1571 (defun erc-get-buffer-create (server port target &optional proc)
1572 "Create a new buffer based on the arguments."
1573 (get-buffer-create (erc-generate-new-buffer-name server port target proc)))
1576 (defun erc-member-ignore-case (string list)
1580 `erc-downcase'."
1581 (setq string (erc-downcase string))
1584 (if (string= string (erc-downcase (car list)))
1588 (defmacro erc-with-buffer (spec &rest body)
1589 "Execute BODY in the buffer associated with SPEC.
1595 If TARGET is a buffer, use it. Otherwise, use the buffer
1598 If PROCESS is nil, use the current `erc-server-process'.
1599 See `erc-get-buffer' for details.
1601 See also `with-current-buffer'.
1613 (and (processp erc-server-process)
1614 erc-server-process))))
1616 (erc-get-buffer ,target ,proc))))))
1617 (when (buffer-live-p ,buf)
1618 (with-current-buffer ,buf
1620 (put 'erc-with-buffer 'lisp-indent-function 1)
1621 (put 'erc-with-buffer 'edebug-form-spec '((form &optional form) body))
1623 (defun erc-get-buffer (target &optional proc)
1624 "Return the buffer matching TARGET in the process PROC.
1626 (let ((downcased-target (erc-downcase target)))
1627 (catch 'buffer
1628 (erc-buffer-filter
1630 (let ((current (erc-default-target)))
1632 (string-equal downcased-target (erc-downcase current))
1633 (throw 'buffer (current-buffer)))))
1636 (defun erc-buffer-filter (predicate &optional proc)
1637 "Return a list of `erc-mode' buffers matching certain criteria.
1638 PREDICATE is a function executed with each buffer, if it returns t, that buffer
1641 PROC is either an `erc-server-process', identifying a certain
1642 server connection, or nil which means all open connections."
1647 (when (buffer-live-p buf)
1648 (with-current-buffer buf
1649 (and (eq major-mode 'erc-mode)
1651 (eq proc erc-server-process))
1654 (buffer-list)))))
1656 (defun erc-buffer-list (&optional predicate proc)
1658 PREDICATE is a function which executes with every buffer satisfying
1660 buffers. If PROC is given, the buffers local variable `erc-server-process'
1664 (erc-buffer-filter predicate proc))
1666 (defmacro erc-with-all-buffers-of-server (process pred &rest forms)
1667 "Execute FORMS in all buffers which have same process as this server.
1669 where PRED matches or in all buffers of the server process if PRED is
1676 (mapcar (lambda (buffer)
1677 (with-current-buffer buffer
1679 (erc-buffer-list ,pre
1681 (put 'erc-with-all-buffers-of-server 'lisp-indent-function 1)
1682 (put 'erc-with-all-buffers-of-server 'edebug-form-spec '(form form body))
1684 (defun erc-iswitchb (&optional arg)
1685 "Use `iswitchb-read-buffer' to prompt for a ERC buffer to switch to.
1686 When invoked with prefix argument, use all erc buffers. Without prefix
1687 ARG, allow only buffers related to same session server.
1688 If `erc-track-mode' is in enabled, put the last element of
1689 `erc-modified-channels-alist' in front of the buffer list.
1702 (mapcar 'buffer-name
1703 (erc-buffer-list
1705 (when arg erc-server-process)))))))
1706 (switch-to-buffer
1707 (iswitchb-read-buffer
1709 (if (boundp 'erc-modified-channels-alist)
1710 (buffer-name (caar (last erc-modified-channels-alist)))
1715 (defun erc-channel-list (proc)
1717 PROC is the process for the server connection. If PROC is nil, return
1719 (erc-buffer-filter
1721 (and (erc-default-target)
1722 (erc-channel-p (erc-default-target))))
1725 (defun erc-buffer-list-with-nick (nick proc)
1726 "Return buffers containing NICK in the `erc-channel-users' list."
1727 (with-current-buffer (process-buffer proc)
1728 (let ((user (gethash (erc-downcase nick) erc-server-users)))
1730 (erc-server-user-buffers user)
1735 (defvar erc-default-recipients nil
1736 "List of default recipients of the current buffer.")
1737 (make-variable-buffer-local 'erc-default-recipients)
1739 (defvar erc-session-user-full-name nil
1740 "Full name of the user on the current server.")
1741 (make-variable-buffer-local 'erc-session-user-full-name)
1743 (defvar erc-channel-user-limit nil
1745 (make-variable-buffer-local 'erc-channel-user-limit)
1747 (defvar erc-channel-key nil
1749 (make-variable-buffer-local 'erc-channel-key)
1751 (defvar erc-invitation nil
1753 (make-variable-buffer-local 'erc-invitation)
1755 (defvar erc-away nil
1758 Use `erc-away-time' to access this if you might be in a channel
1759 buffer rather than a server buffer.")
1760 (make-variable-buffer-local 'erc-away)
1762 (defvar erc-channel-list nil
1764 (make-variable-buffer-local 'erc-channel-list)
1766 (defvar erc-bad-nick nil
1768 (make-variable-buffer-local 'erc-bad-nick)
1770 (defvar erc-logged-in nil
1772 (make-variable-buffer-local 'erc-logged-in)
1774 (defvar erc-default-nicks nil
1775 "The local copy of `erc-nick' - the list of nicks to choose from.")
1776 (make-variable-buffer-local 'erc-default-nicks)
1778 (defvar erc-nick-change-attempt-count 0
1780 (make-variable-buffer-local 'erc-nick-change-attempt-count)
1782 (defun erc-migrate-modules (mods)
1787 (erc-delete-dups
1791 (defcustom erc-modules '(netsplit fill button match track completion readonly
1796 \(erc-update-modules) after you change it. When using `customize', modules
1799 ;; replace outdated names with their newer equivalents
1800 (erc-migrate-modules (symbol-value sym)))
1803 (when (and (boundp 'erc-modules) erc-modules val)
1804 (dolist (module erc-modules)
1806 (let ((f (intern-soft (format "erc-%s-mode" module))))
1808 (message "Disabling `erc-%s'" module)
1811 ;; this test is for the case where erc hasn't been loaded yet
1812 (when (fboundp 'erc-update-modules)
1813 (erc-update-modules)))
1826 (const :tag "identd: Launch an identd server on port 8113" identd)
1842 (const :tag "scrolltobottom: Scroll to the bottom of the buffer"
1855 :group 'erc)
1857 (defun erc-update-modules ()
1858 "Run this to enable erc-foo-mode for all modules in `erc-modules'."
1860 (dolist (mod erc-modules)
1861 (setq req (concat "erc-" (symbol-name mod)))
1864 ((string= req "erc-capab-identify")
1865 (setq req "erc-capab"))
1866 ((string= req "erc-completion")
1867 (setq req "erc-pcomplete"))
1868 ((string= req "erc-pcomplete")
1870 ((string= req "erc-autojoin")
1871 (setq req "erc-join")))
1875 (let ((sym (intern-soft (concat "erc-" (symbol-name mod) "-mode"))))
1880 (defun erc-setup-buffer (buffer)
1881 "Consults `erc-join-buffer' to find out how to display `BUFFER'."
1882 (cond ((eq erc-join-buffer 'window)
1884 (display-buffer buffer)
1885 (switch-to-buffer-other-window buffer)))
1886 ((eq erc-join-buffer 'window-noselect)
1887 (display-buffer buffer))
1888 ((eq erc-join-buffer 'bury)
1890 ((eq erc-join-buffer 'frame)
1894 (make-frame (or erc-frame-alist
1896 (switch-to-buffer buffer)
1897 (when erc-frame-dedicated-flag
1901 (display-buffer buffer)
1902 (switch-to-buffer buffer)))))
1904 (defun erc-open (&optional server port nick full-name
1906 "Connect to SERVER on PORT as NICK with FULL-NAME.
1908 If CONNECT is non-nil, connect to the server. Otherwise assume
1909 already connected and just create a separate buffer for the new
1912 Use PASSWD as user password on the server. If TGT-LIST is
1913 non-nil, use it to initialise `erc-default-recipients'.
1915 Returns the buffer for the given server or channel."
1916 (let ((server-announced-name (when (and (boundp 'erc-session-server)
1917 (string= server erc-session-server))
1918 erc-server-announced-name))
1919 (connected-p (unless connect erc-server-connected))
1920 (buffer (erc-get-buffer-create server port channel))
1921 (old-buffer (current-buffer))
1924 (when connect (run-hook-with-args 'erc-before-connect server port nick))
1925 (erc-update-modules)
1926 (set-buffer buffer)
1928 (erc-mode)
1929 (setq erc-server-announced-name server-announced-name)
1930 (setq erc-server-connected connected-p)
1932 (setq erc-server-process process)
1933 (setq erc-insert-marker (make-marker))
1934 (setq erc-input-marker (make-marker))
1935 ;; go to the end of the buffer and open a new line
1936 ;; (the buffer may have existed)
1939 (when (get-text-property (point) 'erc-prompt)
1941 (set-marker erc-input-marker
1942 (or (next-single-property-change (point) 'erc-prompt)
1947 (set-marker erc-insert-marker (point))
1949 (setq erc-default-recipients tgt-list)
1950 (setq erc-server-current-nick nil)
1951 ;; Initialize erc-server-users and erc-channel-users
1953 (progn ;; server buffer
1954 (setq erc-server-users
1956 (setq erc-channel-users nil))
1957 (progn ;; target buffer
1958 (setq erc-server-users nil)
1959 (setq erc-channel-users
1962 (setq erc-server-filter-data nil)
1963 (setq erc-channel-topic "")
1965 (setq erc-channel-user-limit nil)
1966 (setq erc-channel-key nil)
1967 ;; last active buffer, defaults to this one
1968 (erc-set-active-buffer buffer)
1970 (setq erc-invitation nil)
1972 (setq erc-channel-list ())
1974 (setq erc-bad-nick nil)
1976 (setq erc-logged-in nil)
1977 ;; The local copy of `erc-nick' - the list of nicks to choose
1978 (setq erc-default-nicks (if (consp erc-nick) erc-nick (list erc-nick)))
1980 (setq erc-session-password passwd)
1981 ;; debug output buffer
1982 (setq erc-dbuf
1983 (when erc-log-p
1984 (get-buffer-create (concat "*ERC-DEBUG: " server "*"))))
1991 (set-marker erc-insert-marker (point))
1992 (erc-display-prompt)
1995 (erc-determine-parameters server port nick full-name)
1998 (run-hook-with-args 'erc-connect-pre-hook buffer)
2001 (erc-server-connect erc-session-server erc-session-port buffer))
2002 (erc-update-mode-line)
2004 ;; Now display the buffer in a window as per user wishes.
2005 (unless (eq buffer old-buffer)
2006 (when erc-log-p
2007 ;; we can't log to debug buffer, it may not exist yet
2008 (message "erc: old buffer %s, switching to %s"
2009 old-buffer buffer))
2010 (erc-setup-buffer buffer))
2012 buffer))
2014 (defun erc-initialize-log-marker (buffer)
2015 "Initialize the `erc-last-saved-position' marker to a sensible position.
2016 BUFFER is the current buffer."
2017 (with-current-buffer buffer
2018 (setq erc-last-saved-position (make-marker))
2019 (move-marker erc-last-saved-position
2020 (1- (marker-position erc-insert-marker)))))
2024 (defvar erc-server-history-list nil
2025 "IRC server interactive selection history list.")
2027 (defvar erc-nick-history-list nil
2030 (defun erc-already-logged-in (server port nick)
2032 This is determined by looking for the appropriate buffer and checking
2034 If no buffer matches, return nil."
2035 (erc-buffer-list
2037 (and (erc-server-process-alive)
2038 (string= erc-session-server server)
2039 (erc-port-equal erc-session-port port)
2040 (erc-current-nick-p nick)))))
2047 (defcustom erc-before-connect nil
2048 "Hook called before connecting to a server.
2049 This hook gets executed before `erc' actually invokes `erc-mode'
2050 with your input data. The functions in here get called with three
2052 :group 'erc-hooks
2055 (defcustom erc-after-connect nil
2056 "Hook called after connecting to a server.
2058 functions in here get called with the parameters SERVER and NICK."
2059 :group 'erc-hooks
2063 (defun erc-select-read-args ()
2064 "Prompt the user for values of nick, server, port, and password."
2065 (let (user-input server port nick passwd)
2067 "IRC server: "
2068 (erc-compute-server) nil nil 'erc-server-history-list))
2071 (setq port (erc-string-to-port (match-string 2 user-input))
2074 (erc-string-to-port (read-from-minibuffer
2075 "IRC port: " (erc-port-to-string
2076 (erc-compute-port))))))
2082 (if (erc-already-logged-in server port nick)
2084 (erc-format-message 'nick-in-use ?n nick)
2086 nil nil 'erc-nick-history-list)
2088 "Nickname: " (erc-compute-nick nick)
2089 nil nil 'erc-nick-history-list))))
2091 (setq server user-input)
2093 (setq passwd (if erc-prompt-for-password
2094 (if (and erc-password
2096 erc-password
2098 erc-password))
2102 (while (erc-already-logged-in server port nick)
2104 ;; with the same nick. Currently this code prevents using more than one
2105 ;; bnc with the same nick. actually it would be nice to have
2106 ;; bncs transparent, so that erc-compute-buffer-name displays
2107 ;; the server one is connected to.
2109 (erc-format-message 'nick-in-use ?n nick)
2111 nil nil 'erc-nick-history-list)))
2112 (list :server server :port port :nick nick :password passwd)))
2115 (defun* erc (&key (server (erc-compute-server))
2116 (port (erc-compute-port))
2117 (nick (erc-compute-nick))
2119 (full-name (erc-compute-full-name)))
2126 (server (erc-compute-server))
2127 (port (erc-compute-port))
2128 (nick (erc-compute-nick))
2130 (full-name (erc-compute-full-name)))
2132 That is, if called with
2134 (erc :server \"irc.freenode.net\" :full-name \"Harry S Truman\")
2136 then the server and full-name will be set to those values, whereas
2137 `erc-compute-port', `erc-compute-nick' and `erc-compute-full-name' will
2139 (interactive (erc-select-read-args))
2140 (erc-open server port nick full-name t password))
2143 (defalias 'erc-select 'erc)
2145 (defun erc-ssl (&rest r)
2147 Arguments are the same as for `erc'."
2148 (interactive (erc-select-read-args))
2149 (let ((erc-server-connect-function 'erc-open-ssl-stream))
2150 (apply 'erc r)))
2152 (defalias 'erc-select-ssl 'erc-ssl)
2154 (defun erc-open-ssl-stream (name buffer host port)
2155 "Open an SSL stream to an IRC server.
2156 The process will be given the name NAME, its target buffer will be
2159 (let ((proc (open-tls-stream name buffer host port)))
2170 (defvar erc-debug-irc-protocol nil
2171 "If non-nil, log all IRC protocol traffic to the buffer \"*erc-protocol*\".
2173 The buffer is created if it doesn't exist.
2176 visible \"*erc-protocol*\" buffer, it will be recreated shortly,
2180 function `erc-toggle-debug-irc-protocol' to toggle its value.")
2182 (defun erc-log-irc-protocol (string &optional outbound)
2183 "Append STRING to the buffer *erc-protocol*.
2185 This only has any effect if `erc-debug-irc-protocol' is non-nil.
2187 The buffer is created if it doesn't exist.
2189 If OUTBOUND is non-nil, STRING is being sent to the IRC server
2190 and appears in face `erc-input-face' in the buffer."
2191 (when erc-debug-irc-protocol
2192 (let ((network-name (or (ignore-errors (erc-network-name))
2194 (with-current-buffer (get-buffer-create "*erc-protocol*")
2199 ;; Cope with the fact that string might
2208 (erc-propertize
2214 'face 'erc-input-face)))))
2216 (debug-buffer-window (get-buffer-window (current-buffer) t)))
2217 (when debug-buffer-window
2218 (select-window debug-buffer-window)
2224 (defun erc-toggle-debug-irc-protocol (&optional arg)
2225 "Toggle the value of `erc-debug-irc-protocol'.
2227 If ARG is non-nil, show the *erc-protocol* buffer."
2229 (let* ((buf (get-buffer-create "*erc-protocol*")))
2230 (with-current-buffer buf
2231 (erc-view-mode-enter 1)
2234 (insert (erc-make-notice "This buffer displays all IRC protocol traffic exchanged with each server.\n"))
2235 (insert (erc-make-notice "Kill this buffer to terminate protocol logging.\n\n")))
2237 (local-set-key (kbd "RET") 'erc-toggle-debug-irc-protocol))
2238 (add-hook 'kill-buffer-hook
2239 #'(lambda () (setq erc-debug-irc-protocol nil))
2243 (insert (erc-make-notice
2245 (if erc-debug-irc-protocol "disabled" "enabled")
2247 (setq erc-debug-irc-protocol (not erc-debug-irc-protocol))
2249 (not (get-buffer-window "*erc-protocol*" t)))
2250 (display-buffer buf t))
2251 (message "IRC protocol traffic logging %s (see buffer *erc-protocol*)."
2252 (if erc-debug-irc-protocol "enabled" "disabled"))))
2258 (defun erc-send-action (tgt str &optional force)
2260 (erc-send-ctcp-message tgt (format "ACTION %s" str) force)
2261 (erc-display-message
2262 nil 'input (current-buffer)
2263 'ACTION ?n (erc-current-nick) ?a str ?u "" ?h ""))
2267 (defun erc-string-invisible-p (string)
2272 (defun erc-display-line-1 (string buffer)
2273 "Display STRING in `erc-mode' BUFFER.
2274 Auxiliary function used in `erc-display-line'. The line gets filtered to
2275 interpret the control characters. Then, `erc-insert-pre-hook' gets called.
2276 If `erc-insert-this' is still t, STRING gets inserted into the buffer.
2277 Afterwards, `erc-insert-modify' and `erc-insert-post-hook' get called.
2281 (set-buffer (or buffer (process-buffer erc-server-process)))
2282 (let ((insert-position (or (marker-position erc-insert-marker)
2285 (buffer-undo-list t)
2289 (when (erc-string-invisible-p string)
2290 (erc-put-text-properties 0 (length string) string
2292 (erc-log (concat "erc-display-line: " string
2293 (format "(%S)" string) " in buffer "
2294 (format "%s" buffer)))
2295 (setq erc-insert-this t)
2296 (run-hook-with-args 'erc-insert-pre-hook string)
2297 (if (null erc-insert-this)
2298 ;; Leave erc-insert-this set to t as much as possible. Fran
2299 ;; Litterio <franl> has seen erc-insert-this set to nil while
2300 ;; erc-send-pre-hook is running, which should never happen. This
2302 (setq erc-insert-this t)
2303 (save-excursion ;; to restore point in the new buffer
2308 ;; run insertion hook, with point at restored location
2311 (run-hooks 'erc-insert-modify-hook)
2312 (run-hooks 'erc-insert-post-hook))))))
2313 (erc-update-undo-list (- (or (marker-position erc-insert-marker)
2317 (defun erc-update-undo-list (shift)
2318 ;; Translate buffer positions in buffer-undo-list by SHIFT.
2319 (unless (or (zerop shift) (atom buffer-undo-list))
2320 (let ((list buffer-undo-list) elt)
2344 (defvar erc-valid-nick-regexp "[]a-zA-Z^[;\\`_{}|][]^[;\\`_{}|a-zA-Z0-9-]*"
2347 (defun erc-is-valid-nick-p (nick)
2349 (string-match (concat "^" erc-valid-nick-regexp "$") nick))
2351 (defun erc-display-line (string &optional buffer)
2354 or omitted, the default ERC buffer for the `erc-session-server' is used.
2355 The BUFFER can be an actual buffer, a list of buffers, 'all or 'active.
2357 current session. 'active means the current active buffer
2358 \(`erc-active-buffer'). If the buffer can't be resolved, the current
2359 buffer is used. `erc-display-line-1' is used to display STRING.
2365 ((bufferp buffer) (list buffer))
2366 ((listp buffer) buffer)
2367 ((processp buffer) (list (process-buffer buffer)))
2368 ((eq 'all buffer)
2369 ;; Hmm, or all of the same session server?
2370 (erc-buffer-list nil erc-server-process))
2371 ((and (eq 'active buffer) (erc-active-buffer))
2372 (list (erc-active-buffer)))
2373 ((erc-server-buffer-live-p)
2374 (list (process-buffer erc-server-process)))
2375 (t (list (current-buffer)))))
2376 (when (buffer-live-p buf)
2377 (erc-display-line-1 string buf)
2380 (if (erc-server-buffer-live-p)
2381 (erc-display-line-1 string (process-buffer erc-server-process))
2382 (erc-display-line-1 string (current-buffer))))))
2384 (defun erc-display-message-highlight (type string)
2385 "Highlight STRING according to TYPE, where erc-TYPE-face is an ERC face.
2387 See also `erc-make-notice'."
2389 (erc-make-notice string))
2391 (erc-put-text-property
2394 (concat "erc-" (symbol-name type) "-face"))
2395 "erc-default-face")
2399 (defun erc-display-message (parsed type buffer msg &rest args)
2404 See also `erc-format-message' and `erc-display-line'."
2406 (apply 'erc-format-message msg args)
2415 (erc-display-message-highlight type string)))
2419 (erc-display-message-highlight type string))))
2421 (if (not (erc-response-p parsed))
2422 (erc-display-line string buffer)
2423 (unless (member (erc-response.command parsed) erc-hide-list)
2424 (erc-put-text-property 0 (length string) 'erc-parsed parsed string)
2425 (erc-put-text-property 0 (length string) 'rear-sticky t string)
2426 (erc-display-line string buffer)))))
2428 (defun erc-message-type-member (position list)
2429 "Return non-nil if the erc-parsed text-property at POSITION is in LIST.
2431 This function relies on the erc-parsed text-property being
2433 (let ((prop-val (erc-get-parsed-vector position)))
2434 (and prop-val (member (erc-response.command prop-val) list))))
2436 (defvar erc-send-input-line-function 'erc-send-input-line)
2437 (make-variable-buffer-local 'erc-send-input-line-function)
2439 (defun erc-send-input-line (target line &optional force)
2442 See also `erc-server-send'."
2450 (erc-server-send line force target))
2452 (defun erc-get-arglist (fun)
2454 (let ((arglist (format "%S" (erc-function-arglist fun))))
2459 (defun erc-command-name (cmd)
2461 erc-cmd-FOO, this returns a string /FOO."
2463 (if (string-match "^erc-cmd-\\(.*\\)$" command-name)
2467 (defun erc-process-input-line (line &optional force no-command)
2469 Returns non-nil if the command is actually sent to the server, and nil
2472 If the command in the LINE is not bound as a function `erc-cmd-<COMMAND>',
2473 it is passed to `erc-cmd-default'. If LINE is not a command (i.e. doesn't
2474 start with /<COMMAND>) then it is sent as a message.
2479 (let ((command-list (erc-extract-command-from-line line)))
2489 (erc-display-message nil 'error (current-buffer) 'incorrect-args
2490 ?c (erc-command-name cmd)
2491 ?u (or (erc-get-arglist cmd)
2496 (let ((r (erc-default-target)))
2498 (funcall erc-send-input-line-function r line force)
2499 (erc-display-message nil 'error (current-buffer) 'no-target)
2506 (defun erc-cmd-AMSG (line)
2507 "Send LINE to all channels of the current server that you are on."
2509 (setq line (erc-trim-string line))
2510 (erc-with-all-buffers-of-server nil
2512 (erc-channel-p (erc-default-target)))
2513 (erc-send-message line)))
2514 (put 'erc-cmd-AMSG 'do-not-parse-args t)
2516 (defun erc-cmd-SAY (line)
2519 Use this when you want to send a message with a leading '/'. Note
2525 (erc-process-input-line (match-string 1 line) nil t)))
2526 (put 'erc-cmd-SAY 'do-not-parse-args t)
2528 (defun erc-cmd-SET (line)
2533 (let ((var (read (concat "erc-" (match-string 1 line))))
2538 (erc-display-message
2545 (erc-display-message
2548 (erc-display-message nil 'error 'active 'variable-not-bound)
2551 (erc-display-line
2562 (apropos-internal "^erc-" 'user-variable-p))))
2563 (current-buffer)) t)
2565 (defalias 'erc-cmd-VAR 'erc-cmd-SET)
2566 (defalias 'erc-cmd-VARIABLE 'erc-cmd-SET)
2567 (put 'erc-cmd-SET 'do-not-parse-args t)
2569 (defun erc-cmd-default (line)
2572 Commands for which no erc-cmd-xxx exists, are tunnelled through
2573 this function. LINE is sent to the server verbatim, and
2575 (erc-log (format "cmd: DEFAULT: %s" line))
2576 (erc-server-send (substring line 1))
2579 (defun erc-cmd-IGNORE (&optional user)
2581 If no USER argument is specified, list the contents of `erc-ignore-list'."
2588 (erc-display-line
2589 (erc-make-notice (format "Now ignoring %s" user))
2591 (erc-with-server-buffer (add-to-list 'erc-ignore-list user)))
2592 (if (null (erc-with-server-buffer erc-ignore-list))
2593 (erc-display-line (erc-make-notice "Ignore list is empty") 'active)
2594 (erc-display-line (erc-make-notice "Ignore list:") 'active)
2596 (erc-display-line (erc-make-notice item)
2598 (erc-with-server-buffer erc-ignore-list))))
2601 (defun erc-cmd-UNIGNORE (user)
2603 (let ((ignored-nick (car (erc-with-server-buffer
2604 (erc-member-ignore-case (regexp-quote user)
2605 erc-ignore-list)))))
2607 (if (setq ignored-nick (erc-ignored-user-p user))
2611 (erc-display-line
2612 (erc-make-notice (format "%s is not currently ignored!" user))
2615 (erc-display-line
2616 (erc-make-notice (format "No longer ignoring %s" user))
2618 (erc-with-server-buffer
2619 (setq erc-ignore-list (delete ignored-nick erc-ignore-list)))))
2622 (defun erc-cmd-CLEAR ()
2627 (defun erc-cmd-OPS ()
2631 (if erc-channel-users
2635 (erc-channel-user-op cuser))
2636 (setq ops (cons (erc-server-user-nickname
2639 erc-channel-users))
2642 (erc-display-message
2643 nil 'notice (current-buffer) 'ops
2646 (erc-display-message nil 'notice (current-buffer) 'ops-none)))
2649 (defun erc-cmd-COUNTRY (tld)
2650 "Display the country associated with the top level domain TLD."
2654 (erc-display-message
2656 (erc-display-message
2660 (defun erc-cmd-AWAY (line)
2665 (erc-log (format "cmd: AWAY: %s" reason))
2666 (erc-server-send
2671 (put 'erc-cmd-AWAY 'do-not-parse-args t)
2673 (defun erc-cmd-GAWAY (line)
2675 ;; on all server buffers.
2676 (erc-with-all-buffers-of-server nil
2677 #'erc-open-server-buffer-p
2678 (erc-cmd-AWAY line)))
2679 (put 'erc-cmd-GAWAY 'do-not-parse-args t)
2681 (defun erc-cmd-CTCP (nick cmd &rest args)
2685 VERSION and so on. It is called with ARGS."
2689 (erc-log (format "cmd: CTCP [%s]: [%s]" nick str))
2690 (erc-send-ctcp-message nick str)
2693 (defun erc-cmd-HELP (&optional func)
2699 \(\"erc-.*LINE\"\).
2702 To find out about erc and bbdb, do
2712 (concat "erc-cmd-" (upcase func)))))
2720 (let ((sym (intern-soft (concat "erc-" func))))
2729 (apropos-command (concat "erc-.*" func) nil
2734 (apropos "erc-cmd-")
2738 (defalias 'erc-cmd-H 'erc-cmd-HELP)
2740 (defun erc-cmd-JOIN (channel &optional key)
2741 "Join the channel given in CHANNEL, optionally with KEY.
2746 (if erc-invitation
2747 (setq chnl erc-invitation)
2748 (erc-display-message nil 'error (current-buffer) 'no-invitation))
2749 (setq chnl (erc-ensure-channel-name channel)))
2751 ;; Prevent double joining of same channel on same server.
2754 (with-current-buffer chanbuf (erc-default-target)))
2755 (erc-channel-list erc-server-process))))
2756 (if (erc-member-ignore-case chnl joined-channels)
2757 (switch-to-buffer (car (erc-member-ignore-case chnl
2759 (erc-log (format "cmd: JOIN: %s" chnl))
2761 (erc-server-send (format "JOIN %s %s" chnl key))
2762 (erc-server-send (format "JOIN %s" chnl)))))))
2765 (defalias 'erc-cmd-CHANNEL 'erc-cmd-JOIN)
2766 (defalias 'erc-cmd-J 'erc-cmd-JOIN)
2768 (defvar erc-channel-new-member-names nil
2772 received nicks with t.")
2773 (make-variable-buffer-local 'erc-channel-new-member-names)
2775 (defun erc-cmd-NAMES (&optional channel)
2780 (let ((tgt (or (and (erc-channel-p channel) channel)
2781 (erc-default-target))))
2782 (if (and tgt (erc-channel-p tgt))
2784 (erc-log (format "cmd: DEFAULT: NAMES %s" tgt))
2785 (erc-with-buffer
2787 (erc-channel-begin-receiving-names))
2788 (erc-server-send (concat "NAMES " tgt)))
2789 (erc-display-message nil 'error (current-buffer) 'no-default-channel)))
2791 (defalias 'erc-cmd-N 'erc-cmd-NAMES)
2793 (defun erc-cmd-KICK (target &optional reason-or-nick &rest reasonwords)
2798 (setq reasonstring (format "Kicked by %s" (erc-current-nick))))
2799 (if (erc-channel-p target)
2801 (erc-log (format "cmd: KICK: %s/%s: %s" nick target reasonstring))
2802 (erc-server-send (format "KICK %s %s :%s" target nick reasonstring)
2806 (let ((ch (erc-default-target)))
2812 (erc-log
2814 (erc-server-send
2816 (erc-display-message nil 'error (current-buffer)
2820 (defvar erc-script-args nil)
2822 (defun erc-cmd-LOAD (line)
2825 it is put in a (local) variable `erc-script-args',
2833 (erc-script-args (match-string 2 line))
2834 (file (erc-find-file file-to-find erc-script-path)))
2835 (erc-log (format "cmd: LOAD: %s" file-to-find))
2838 (erc-display-message nil 'error (current-buffer)
2841 (erc-display-message nil 'error (current-buffer)
2845 (erc-load-script file)
2850 (defun erc-cmd-WHOIS (user &optional server)
2853 If SERVER is non-nil, use that, rather than the current server."
2855 (let ((send (if server
2856 (format "WHOIS %s %s" user server)
2858 (erc-log (format "cmd: %s" send))
2859 (erc-server-send send)
2861 (defalias 'erc-cmd-WI 'erc-cmd-WHOIS)
2863 (defun erc-cmd-WHOAMI ()
2865 (erc-cmd-WHOIS (erc-current-nick))
2868 (defun erc-cmd-IDLE (nick)
2870 (let ((origbuf (current-buffer))
2872 (erc-with-server-buffer
2874 (cons (erc-once-with-server-event
2877 (erc-response.command-args parsed))))
2878 'erc-server-311-functions))
2880 (cons (erc-once-with-server-event
2883 (erc-response.command-args parsed))))
2884 'erc-server-312-functions))
2886 (cons (erc-once-with-server-event
2889 (erc-response.command-args parsed))))
2890 'erc-server-318-functions))
2892 (cons (erc-once-with-server-event
2895 (erc-response.command-args parsed))))
2896 'erc-server-319-functions))
2898 (cons (erc-once-with-server-event
2901 (erc-response.command-args parsed))))
2902 'erc-server-320-functions))
2904 (cons (erc-once-with-server-event
2907 (erc-response.command-args parsed))))
2908 'erc-server-330-functions))
2910 (cons (erc-once-with-server-event
2915 (erc-response.command-args parsed)))))
2916 (erc-display-line
2917 (erc-make-notice
2919 (erc-string-no-properties ,nick)
2920 (erc-seconds-to-string idleseconds)))
2923 'erc-server-317-functions))
2926 (erc-cmd-WHOIS nick)
2928 ;; Remove the uninterned symbols from the server hooks that did not run.
2930 (with-current-buffer ,(current-buffer)
2937 (defun erc-cmd-DESCRIBE (line)
2945 (erc-log (format "cmd: DESCRIBE: [%s] %s" dst s))
2946 (erc-send-action dst s))
2949 (put 'erc-cmd-DESCRIBE 'do-not-parse-args t)
2951 (defun erc-cmd-ME (line)
2956 (erc-log (format "cmd: ME: %s" s))
2957 (erc-send-action (erc-default-target) s))
2960 (put 'erc-cmd-ME 'do-not-parse-args t)
2962 (defun erc-cmd-LASTLOG (line)
2963 "Show all lines in the current buffer matching the regexp LINE.
2967 The lines are shown in a buffer named `*Occur*'.
2968 It serves as a menu to find any of the occurrences in this buffer.
2969 \\[describe-mode] in that buffer will explain how.
2975 (put 'erc-cmd-LASTLOG 'do-not-parse-args t)
2977 (defun erc-send-message (line &optional force)
2980 See also `erc-message' and `erc-display-line'."
2981 (erc-message "PRIVMSG" (concat (erc-default-target) " " line) force)
2982 (erc-display-line
2983 (concat (erc-format-my-nick) line)
2984 (current-buffer))
2988 (defun erc-cmd-MODE (line)
3000 (erc-log (format "cmd: MODE: %s" s))
3001 (erc-server-send (concat "MODE " line)))
3004 (put 'erc-cmd-MODE 'do-not-parse-args t)
3006 (defun erc-cmd-NOTICE (channel-or-user &rest message)
3009 (erc-message "NOTICE" (concat channel-or-user " "
3012 (defun erc-cmd-MSG (line)
3016 (erc-message "PRIVMSG" line))
3018 (defalias 'erc-cmd-M 'erc-cmd-MSG)
3019 (put 'erc-cmd-MSG 'do-not-parse-args t)
3021 (defun erc-cmd-SQUERY (line)
3025 (erc-message "SQUERY" line))
3027 (defun erc-cmd-NICK (nick)
3029 (erc-log (format "cmd: NICK: %s (erc-bad-nick: %S)" nick erc-bad-nick))
3030 (let ((nicklen (cdr (assoc "NICKLEN" (erc-with-server-buffer
3031 erc-server-parameters)))))
3033 (erc-display-message
3036 (erc-server-send (format "NICK %s" nick))
3037 (cond (erc-bad-nick
3038 (erc-set-current-nick nick)
3039 (erc-update-mode-line)
3040 (setq erc-bad-nick nil)))
3043 (defun erc-cmd-PART (line)
3050 (reason (funcall erc-part-reason (if (equal msg "") nil msg))))
3051 (erc-log (format "cmd: PART: %s: %s" ch reason))
3052 (erc-server-send (if (string= reason "")
3058 (let* ((ch (erc-default-target))
3060 (reason (funcall erc-part-reason (if (equal msg "") nil msg))))
3061 (if (and ch (erc-channel-p ch))
3063 (erc-log (format "cmd: PART: %s: %s" ch reason))
3064 (erc-server-send (if (string= reason "")
3068 (erc-display-message nil 'error (current-buffer) 'no-target)))
3071 (put 'erc-cmd-PART 'do-not-parse-args t)
3073 (defalias 'erc-cmd-LEAVE 'erc-cmd-PART)
3075 (defun erc-cmd-PING (recipient)
3077 (let ((time (format "%f" (erc-current-time))))
3078 (erc-log (format "cmd: PING: %s" time))
3079 (erc-cmd-CTCP recipient "PING" time)))
3081 (defun erc-cmd-QUOTE (line)
3082 "Send LINE directly to the server.
3084 just as you provided it. Use this command with care!"
3087 (erc-server-send (match-string 1 line)))
3089 (put 'erc-cmd-QUOTE 'do-not-parse-args t)
3091 (defun erc-cmd-QUERY (&optional user)
3092 "Open a query with USER.
3094 `erc-join-buffer'. If USER is omitted, close the current query buffer if one
3097 (list (read-from-minibuffer "Start a query with: " nil)))
3098 (let ((session-buffer (erc-server-buffer)))
3100 (erc-query user session-buffer)
3102 ;(erc-delete-query))))
3104 (defalias 'erc-cmd-Q 'erc-cmd-QUERY)
3106 (defun erc-quit-reason-normal (&optional s)
3112 erc-version-string) ; erc-official-location)
3115 (defun erc-quit-reason-zippy (&optional s)
3120 (erc-replace-regexp-in-string "\n" "" (yow))))
3122 (defun erc-quit-reason-various (s)
3126 erc-quit-reason-various-alist 'string-match))))
3131 (t (erc-quit-reason-normal)))))
3133 (defun erc-part-reason-normal (&optional s)
3139 erc-version-string) ; erc-official-location)
3142 (defun erc-part-reason-zippy (&optional s)
3147 (erc-replace-regexp-in-string "\n" "" (yow))))
3149 (defun erc-part-reason-various (s)
3153 erc-part-reason-various-alist 'string-match))))
3158 (t (erc-part-reason-normal)))))
3160 (defun erc-cmd-QUIT (reason)
3161 "Disconnect from the current server.
3169 (buffer (erc-server-buffer))
3170 (reason (funcall erc-quit-reason (if (equal s "") nil s)))
3171 server-proc)
3172 (with-current-buffer (if (and buffer
3173 (bufferp buffer))
3174 buffer
3175 (current-buffer))
3176 (erc-log (format "cmd: QUIT: %s" reason))
3177 (setq erc-server-quitting t)
3178 (erc-set-active-buffer (erc-server-buffer))
3179 (setq server-proc erc-server-process)
3180 (erc-server-send (format "QUIT :%s" reason)))
3181 (run-hook-with-args 'erc-quit-hook server-proc)
3182 (when erc-kill-queries-on-quit
3183 (erc-kill-query-buffers server-proc))
3190 server-proc))
3194 (defalias 'erc-cmd-BYE 'erc-cmd-QUIT)
3195 (defalias 'erc-cmd-EXIT 'erc-cmd-QUIT)
3196 (defalias 'erc-cmd-SIGNOFF 'erc-cmd-QUIT)
3197 (put 'erc-cmd-QUIT 'do-not-parse-args t)
3199 (defun erc-cmd-GQUIT (reason)
3200 "Disconnect from all servers at once with the same quit REASON."
3201 (erc-with-all-buffers-of-server nil #'erc-open-server-buffer-p
3202 (erc-cmd-QUIT reason)))
3204 (defalias 'erc-cmd-GQ 'erc-cmd-GQUIT)
3205 (put 'erc-cmd-GQUIT 'do-not-parse-args t)
3207 (defun erc-cmd-RECONNECT ()
3208 "Try to reconnect to the current IRC server."
3209 (let ((buffer (or (erc-server-buffer) (current-buffer)))
3211 (with-current-buffer (if (bufferp buffer) buffer (current-buffer))
3212 (setq erc-server-quitting nil)
3213 (setq erc-server-reconnecting t)
3214 (setq erc-server-reconnect-count 0)
3215 (setq process (get-buffer-process (erc-server-buffer)))
3218 (erc-server-reconnect))
3219 (setq erc-server-reconnecting nil)))
3222 (defun erc-cmd-SERVER (server)
3224 (erc-log (format "cmd: SERVER: %s" server))
3226 (erc :server server :nick (erc-current-nick))
3228 (message "Cannot find host %s." server)
3236 (defun erc-cmd-SV ()
3238 (erc-send-message (format "I'm using ERC %s with %s %s (%s%s) of %s."
3239 erc-version-string
3261 erc-emacs-build-time))
3264 (defun erc-cmd-SM ()
3266 (erc-send-message (format "I'm using the following modules: %s!"
3267 (erc-modes)))
3270 (defun erc-cmd-DEOP (&rest people)
3273 (erc-server-send (concat "MODE " (erc-default-target)
3280 (defun erc-cmd-OP (&rest people)
3283 (erc-server-send (concat "MODE " (erc-default-target)
3290 (defun erc-cmd-TIME (&optional line)
3291 "Request the current time and date from the current server."
3295 (erc-log (format "cmd: TIME: %s" args))
3296 (erc-server-send (concat "TIME " args)))
3298 (t (erc-server-send "TIME"))))
3299 (defalias 'erc-cmd-DATE 'erc-cmd-TIME)
3301 (defun erc-cmd-TOPIC (topic)
3314 (erc-log (format "cmd: TOPIC [%s]: %s" ch topic))
3315 (erc-server-send (format "TOPIC %s :%s" ch topic) nil ch))
3320 (erc-server-send (format "TOPIC %s" ch) nil ch)
3324 (let ((ch (erc-default-target)))
3325 (erc-server-send (format "TOPIC %s" ch) nil ch)
3329 (let ((ch (erc-default-target))
3331 (if (and ch (erc-channel-p ch))
3333 (erc-log (format "cmd: TOPIC [%s]: %s" ch topic))
3334 (erc-server-send (format "TOPIC %s :%s" ch topic) nil ch))
3335 (erc-display-message nil 'error (current-buffer) 'no-target)))
3338 (defalias 'erc-cmd-T 'erc-cmd-TOPIC)
3339 (put 'erc-cmd-TOPIC 'do-not-parse-args t)
3341 (defun erc-cmd-APPENDTOPIC (topic)
3343 (let ((oldtopic erc-channel-topic))
3349 (erc-cmd-TOPIC (concat (match-string 1 oldtopic) topic)))))
3350 (defalias 'erc-cmd-AT 'erc-cmd-APPENDTOPIC)
3351 (put 'erc-cmd-APPENDTOPIC 'do-not-parse-args t)
3353 (defun erc-cmd-CLEARTOPIC (&optional channel)
3357 (let ((chnl (or (and (erc-channel-p channel) channel) (erc-default-target))))
3359 (erc-server-send (format "TOPIC %s :" chnl))
3364 (defvar erc-channel-banlist nil
3370 The property `received-from-server' indicates whether
3371 or not the ban list has been requested from the server.")
3372 (make-variable-buffer-local 'erc-channel-banlist)
3373 (put 'erc-channel-banlist 'received-from-server nil)
3375 (defun erc-cmd-BANLIST ()
3376 "Pretty-print the contents of `erc-channel-banlist'.
3378 The ban list is fetched from the server if necessary."
3379 (let ((chnl (erc-default-target))
3380 (chnl-name (buffer-name)))
3383 ((not (erc-channel-p chnl))
3384 (erc-display-line (erc-make-notice "You're not on a channel\n")
3387 ((not (get 'erc-channel-banlist 'received-from-server))
3388 (let ((old-367-hook erc-server-367-functions))
3389 (setq erc-server-367-functions 'erc-banlist-store
3390 erc-channel-banlist nil)
3392 (erc-with-server-buffer
3393 (erc-once-with-server-event
3395 `(with-current-buffer ,chnl-name
3396 (put 'erc-channel-banlist 'received-from-server t)
3397 (setq erc-server-367-functions ',old-367-hook)
3398 (erc-cmd-BANLIST)
3400 (erc-server-send (format "MODE %s b" chnl)))))
3402 ((null erc-channel-banlist)
3403 (erc-display-line (erc-make-notice
3406 (put 'erc-channel-banlist 'received-from-server nil))
3409 (let* ((erc-fill-column (or (and (boundp 'erc-fill-column)
3410 erc-fill-column)
3414 (separator (make-string erc-fill-column ?=))
3416 "%-" (number-to-string (/ erc-fill-column 2)) "s"
3417 "%" (number-to-string (/ erc-fill-column 2)) "s")))
3419 (erc-display-line
3420 (erc-make-notice (format "Ban list for channel: %s\n"
3421 (erc-default-target)))
3424 (erc-display-line separator 'active)
3425 (erc-display-line (format fmt "Ban Mask" "Banned By") 'active)
3426 (erc-display-line separator 'active)
3430 (erc-display-line
3432 (truncate-string-to-width (cdr x) (/ erc-fill-column 2))
3434 (truncate-string-to-width (car x) (/ erc-fill-column 2))
3437 erc-channel-banlist)
3439 (erc-display-line (erc-make-notice "End of Ban list")
3441 (put 'erc-channel-banlist 'received-from-server nil)))))
3444 (defalias 'erc-cmd-BL 'erc-cmd-BANLIST)
3446 (defun erc-cmd-MASSUNBAN ()
3450 (let ((chnl (erc-default-target)))
3453 ((not (erc-channel-p chnl))
3454 (erc-display-line
3455 (erc-make-notice "You're not on a channel\n")
3458 ((not (get 'erc-channel-banlist 'received-from-server))
3459 (let ((old-367-hook erc-server-367-functions))
3460 (setq erc-server-367-functions 'erc-banlist-store)
3462 (erc-with-server-buffer
3463 (erc-once-with-server-event
3465 `(with-current-buffer ,chnl
3466 (put 'erc-channel-banlist 'received-from-server t)
3467 (setq erc-server-367-functions ,old-367-hook)
3468 (erc-cmd-MASSUNBAN)
3470 (erc-server-send (format "MODE %s b" chnl)))))
3472 (t (let ((bans (mapcar 'cdr erc-channel-banlist)))
3478 (erc-server-send
3479 (format "MODE %s -%s %s" (erc-default-target)
3482 (erc-group-list bans 3))))
3485 (defalias 'erc-cmd-MUB 'erc-cmd-MASSUNBAN)
3489 (defun erc-ensure-channel-name (channel)
3492 (if (erc-channel-p channel)
3496 (defun erc-grab-region (start end)
3500 into control codes and writes them to a separate buffer. The
3504 (erc-set-active-buffer (current-buffer))
3506 (let* ((cb (current-buffer))
3507 (buf (generate-new-buffer erc-grab-buffer-name))
3508 (region (buffer-substring start end))
3509 (lines (erc-split-multiline-safe region)))
3510 (set-buffer buf)
3513 (set-buffer cb)
3514 (switch-to-buffer-other-window buf)))
3515 (message "erc-grab-region doesn't grab colors etc. anymore. If you use this, please tell the maintainers.")
3518 (defun erc-display-prompt (&optional buffer pos prompt face)
3522 If PROMPT is nil, one is constructed with the function `erc-prompt'.
3523 If BUFFER is nil, the `current-buffer' is used.
3526 `erc-prompt-face' will be used."
3527 (let* ((prompt (or prompt (erc-prompt)))
3529 (ob (current-buffer)))
3532 (when (and buffer (bufferp buffer))
3533 (set-buffer buffer))
3536 ;; in the current buffer
3544 (setq prompt (erc-propertize prompt
3547 'erc-prompt t
3550 (erc-put-text-property 0 (1- (length prompt))
3551 'face (or face 'erc-prompt-face)
3555 (set-marker erc-input-marker (point)))
3562 ;; Clear the undo buffer now, so the user can undo his stuff,
3564 (setq buffer-undo-list nil)
3565 (set-buffer ob)))
3569 (defun erc-input-message ()
3576 (erc-send-current-line)))
3578 (defvar erc-action-history-list ()
3581 (defun erc-input-action ()
3584 (erc-set-active-buffer (current-buffer))
3586 "Action: " nil nil nil 'erc-action-history-list)))
3588 (erc-send-action (erc-default-target) action))))
3590 (defun erc-join-channel (channel &optional key)
3597 (table (when (erc-server-buffer-live-p)
3598 (set-buffer (process-buffer erc-server-process))
3599 erc-channel-list)))
3601 (when erc-prompt-for-channel-key
3603 (erc-cmd-JOIN channel (when (>= (length key) 1) key)))
3605 (defun erc-part-from-channel (reason)
3611 (read-from-minibuffer (concat "Reason for leaving " (erc-default-target)
3613 (erc-cmd-PART (concat (erc-default-target)" " reason)))
3615 (defun erc-set-topic (topic)
3620 (concat "Set topic of " (erc-default-target) ": ")
3621 (when erc-channel-topic
3622 (cons (apply 'concat (butlast (split-string erc-channel-topic "\C-o")))
3625 (erc-cmd-TOPIC (concat (erc-default-target) " " (car topic-list)))))
3627 (defun erc-set-channel-limit (&optional limit)
3632 (erc-default-target)))))
3633 (let ((tgt (erc-default-target)))
3635 (erc-server-send (format "MODE %s +l %s" tgt limit))
3636 (erc-server-send (format "MODE %s -l" tgt)))))
3638 (defun erc-set-channel-key (&optional key)
3643 (erc-default-target)))))
3644 (let ((tgt (erc-default-target)))
3646 (erc-server-send (format "MODE %s +k %s" tgt key))
3647 (erc-server-send (format "MODE %s -k" tgt)))))
3649 (defun erc-quit-server (reason)
3650 "Disconnect from current server after prompting for REASON.
3651 `erc-quit-reason' works with this just like with `erc-cmd-QUIT'."
3654 (or erc-server-announced-name
3655 erc-session-server)))))
3656 (erc-cmd-QUIT reason))
3660 (defun erc-bol ()
3666 (when (get-text-property (point) 'erc-prompt)
3667 (goto-char erc-input-marker))
3670 (defun erc-kill-input ()
3671 "Kill current input line using `erc-bol' followed by `kill-line'."
3673 (when (and (erc-bol)
3676 (if (boundp 'erc-input-ring-index)
3677 (setq erc-input-ring-index nil))
3680 (defun erc-complete-word ()
3683 This function uses `erc-complete-functions'."
3685 (unless (run-hook-with-args-until-success 'erc-complete-functions)
3699 (defcustom erc-default-server-hook '(erc-debug-missing-hooks
3700 erc-default-server-handler)
3701 "*Default for server messages which aren't covered by `erc-server-hooks'."
3702 :group 'erc-server-hooks
3705 (defun erc-default-server-handler (proc parsed)
3706 "Default server handler.
3708 Displays PROC and PARSED appropriately using `erc-display-message'."
3709 (erc-display-message
3721 (defvar erc-server-vectors
3723 "List of received server messages which ERC does not specifically handle.
3724 See `erc-debug-missing-hooks'.")
3725 ;(make-variable-buffer-local 'erc-server-vectors)
3727 (defun erc-debug-missing-hooks (proc parsed)
3728 "Add PARSED server message ERC does not yet handle to `erc-server-vectors'.
3729 These vectors can be helpful when adding new server message handlers to ERC.
3730 See `erc-default-server-hook'."
3731 (nconc erc-server-vectors (list parsed))
3734 (defun erc-query (target server)
3735 "Open a query buffer on TARGET, using SERVER.
3737 `erc-join-buffer' before calling this."
3738 (unless (and server
3739 (buffer-live-p server)
3740 (set-buffer server))
3741 (error "Couldn't switch to server buffer"))
3742 (let ((buf (erc-open erc-session-server
3743 erc-session-port
3744 (erc-current-nick)
3745 erc-session-user-full-name
3750 erc-server-process)))
3753 (erc-update-mode-line)
3756 (defcustom erc-auto-query 'bury
3757 "If non-nil, create a query buffer each time you receive a private message.
3759 If the buffer doesn't already exist it is created. This can be
3761 appear. See the documentation for `erc-join-buffer' for
3763 :group 'erc-query
3765 (const buffer)
3771 (defcustom erc-query-on-unjoined-chan-privmsg t
3772 "If non-nil create query buffer on receiving any PRIVMSG at all.
3776 :group 'erc-query
3779 (defcustom erc-format-query-as-channel-p t
3780 "If non-nil, format text from others in a query buffer like in a channel,
3782 :group 'erc-query
3785 (defcustom erc-minibuffer-notice nil
3787 Only happens when the session buffer isn't visible."
3788 :group 'erc-display
3791 (defcustom erc-minibuffer-ignored nil
3793 :group 'erc-ignore
3796 (defun erc-wash-quit-reason (reason nick login host)
3814 (defun erc-nickname-in-use (nick reason)
3817 See also `erc-display-error-notice'."
3818 (if (or (not erc-try-new-nick-p)
3820 (eq erc-nick-change-attempt-count
3821 (if (consp erc-nick)
3822 (+ (length erc-nick) 1)
3824 (erc-display-error-notice
3827 (setq erc-nick-change-attempt-count (+ erc-nick-change-attempt-count 1))
3828 (let ((newnick (nth 1 erc-default-nicks))
3830 (erc-with-server-buffer
3831 erc-server-parameters)))))
3832 (setq erc-bad-nick t)
3834 (if erc-default-nicks
3835 (setq erc-default-nicks (cdr erc-default-nicks)))
3839 (if (and erc-server-connected nicklen)
3841 (length erc-nick-uniquifier))
3844 ;; server's setting if we haven't
3846 (- 9 (length erc-nick-uniquifier))))
3847 erc-nick-uniquifier)))
3848 (erc-cmd-NICK newnick)
3849 (erc-display-error-notice
3856 (defgroup erc-server-hooks nil
3858 Every server event - like numeric replies - has its own hook.
3859 Those hooks are all called using `run-hook-with-args-until-success'.
3863 :group 'erc-hooks)
3865 (defun erc-display-server-message (proc parsed)
3866 "Display the message sent by the server as a notice."
3867 (erc-display-message
3868 parsed 'notice 'active (erc-response.contents parsed)))
3870 (defun erc-auto-query (proc parsed)
3873 "Put this on `erc-server-PRIVMSG-functions'."
3874 (when erc-auto-query
3875 (let* ((nick (car (erc-parse-user (erc-response.sender parsed))))
3876 (target (car (erc-response.command-args parsed)))
3877 (msg (erc-response.contents parsed))
3878 (query (if (not erc-query-on-unjoined-chan-privmsg)
3880 (if (erc-current-nick-p target)
3883 (and (not (erc-ignored-user-p (erc-response.sender parsed)))
3884 (or erc-query-on-unjoined-chan-privmsg
3885 (string= target (erc-current-nick)))
3886 (not (erc-get-buffer query proc))
3887 (not (erc-is-message-ctcp-and-not-action-p msg))
3888 (let ((erc-join-buffer erc-auto-query))
3889 (erc-cmd-QUERY query))
3892 (defun erc-is-message-ctcp-p (message)
3896 (defun erc-is-message-ctcp-and-not-action-p (message)
3898 (and (erc-is-message-ctcp-p message)
3901 (defun erc-format-privmessage (nick msg privp msgp)
3906 (nick-face (if privp 'erc-nick-msg-face 'erc-nick-default-face))
3907 (msg-face (if privp 'erc-direct-msg-face 'erc-default-face)))
3909 (erc-put-text-property 0 (length mark-s) 'face msg-face str)
3910 (erc-put-text-property (length mark-s) (+ (length mark-s) (length nick))
3912 (erc-put-text-property (+ (length mark-s) (length nick)) (length str)
3916 (defcustom erc-format-nick-function 'erc-format-nick
3918 :group 'erc-display
3921 (defun erc-format-nick (&optional user channel-data)
3923 See also `erc-format-nick-function'."
3924 (when user (erc-server-user-nickname user)))
3926 (defun erc-format-@nick (&optional user channel-data)
3928 Operators have \"@\" and users with voice have \"+\" as a prefix.
3930 See also `erc-format-nick-function'."
3932 (let ((op (and channel-data (erc-channel-user-op channel-data) "@"))
3933 (voice (and channel-data (erc-channel-user-voice channel-data) "+")))
3934 (concat voice op (erc-server-user-nickname user)))))
3936 (defun erc-format-my-nick ()
3938 (if erc-show-my-nick
3941 (nick (erc-current-nick)))
3943 (erc-propertize open 'face 'erc-default-face)
3944 (erc-propertize nick 'face 'erc-my-nick-face)
3945 (erc-propertize close 'face 'erc-default-face)))
3947 (erc-propertize prefix 'face 'erc-default-face))))
3949 (defun erc-echo-notice-in-default-buffer (s parsed buffer sender)
3950 "Echos a private notice in the default buffer, namely the
3951 target buffer specified by BUFFER, or there is no target buffer,
3952 the server buffer. This function is designed to be added to
3953 either `erc-echo-notice-hook' or `erc-echo-notice-always-hook',
3955 (erc-display-message parsed nil buffer s)
3958 (defun erc-echo-notice-in-target-buffer (s parsed buffer sender)
3960 function is designed to be added to either `erc-echo-notice-hook'
3961 or `erc-echo-notice-always-hook', and returns non-nil iff BUFFER
3963 (if buffer
3964 (progn (erc-display-message parsed nil buffer s) t)
3967 (defun erc-echo-notice-in-minibuffer (s parsed buffer sender)
3969 designed to be added to either `erc-echo-notice-hook' or
3970 `erc-echo-notice-always-hook', and always returns t."
3974 (defun erc-echo-notice-in-server-buffer (s parsed buffer sender)
3975 "Echos a private notice in the server buffer. This function is
3976 designed to be added to either `erc-echo-notice-hook' or
3977 `erc-echo-notice-always-hook', and always returns t."
3978 (erc-display-message parsed nil nil s)
3981 (defun erc-echo-notice-in-active-non-server-buffer (s parsed buffer sender)
3982 "Echos a private notice in the active buffer if the active
3983 buffer is not the server buffer. This function is designed to be
3984 added to either `erc-echo-notice-hook' or
3985 `erc-echo-notice-always-hook', and returns non-nil iff the active
3986 buffer is not the server buffer."
3987 (if (not (eq (erc-server-buffer) (erc-active-buffer)))
3988 (progn (erc-display-message parsed nil 'active s) t)
3991 (defun erc-echo-notice-in-active-buffer (s parsed buffer sender)
3992 "Echos a private notice in the active buffer. This function is
3993 designed to be added to either `erc-echo-notice-hook' or
3994 `erc-echo-notice-always-hook', and always returns t."
3995 (erc-display-message parsed nil 'active s)
3998 (defun erc-echo-notice-in-user-buffers (s parsed buffer sender)
4001 `erc-echo-notice-hook' or `erc-echo-notice-always-hook', and
4002 returns non-nil iff there is at least one buffer for which the
4005 See also: `erc-echo-notice-in-first-user-buffer',
4006 `erc-buffer-list-with-nick'."
4007 (let ((buffers (erc-buffer-list-with-nick sender erc-server-process)))
4009 (progn (erc-display-message parsed nil buffers s) t)
4012 (defun erc-echo-notice-in-user-and-target-buffers (s parsed buffer sender)
4015 to either `erc-echo-notice-hook' or
4016 `erc-echo-notice-always-hook', and returns non-nil iff there is
4017 at least one buffer for which the sender is a member or the
4020 See also: `erc-echo-notice-in-user-buffers',
4021 `erc-buffer-list-with-nick'."
4022 (let ((buffers (erc-buffer-list-with-nick sender erc-server-process)))
4023 (add-to-list 'buffers buffer)
4025 (progn (erc-display-message parsed nil buffers s) t)
4028 (defun erc-echo-notice-in-first-user-buffer (s parsed buffer sender)
4031 `erc-echo-notice-hook' or `erc-echo-notice-always-hook', and
4032 returns non-nil iff there is at least one buffer for which the
4035 See also: `erc-echo-notice-in-user-buffers',
4036 `erc-buffer-list-with-nick'."
4037 (let ((buffers (erc-buffer-list-with-nick sender erc-server-process)))
4039 (progn (erc-display-message parsed nil (car buffers) s) t)
4044 (defun erc-banlist-store (proc parsed)
4047 (cdr (erc-response.command-args parsed))
4048 ;; Determine to which buffer the message corresponds
4049 (let ((buffer (erc-get-buffer channel proc)))
4050 (with-current-buffer buffer
4051 (unless (member (cons whoset mask) erc-channel-banlist)
4052 (setq erc-channel-banlist (cons (cons whoset mask)
4053 erc-channel-banlist))))))
4056 (defun erc-banlist-finished (proc parsed)
4058 (let* ((channel (second (erc-response.command-args parsed)))
4059 (buffer (erc-get-buffer channel proc)))
4060 (with-current-buffer buffer
4061 (put 'erc-channel-banlist 'received-from-server t)))
4064 (defun erc-banlist-update (proc parsed)
4067 (let* ((tgt (first (erc-response.command-args parsed)))
4068 (mode (erc-response.contents parsed))
4069 (whoset (erc-response.sender parsed))
4070 (buffer (erc-get-buffer tgt proc)))
4071 (when buffer
4072 (with-current-buffer buffer
4073 (cond ((not (get 'erc-channel-banlist 'received-from-server)) nil)
4079 (setq erc-channel-banlist
4080 (erc-delete-if
4085 erc-channel-banlist)))
4090 (unless (member (cons whoset mask) erc-channel-banlist)
4091 (setq erc-channel-banlist
4092 (cons (cons whoset mask) erc-channel-banlist))))
4097 (defun erc-group-list (list n)
4101 (t (cons (erc-subseq list 0 n) (erc-group-list (nthcdr n list) n)))))
4106 (defun erc-handle-login ()
4108 (unless erc-logged-in
4109 (setq erc-logged-in t)
4110 (message "Logging in as \'%s\'... done" (erc-current-nick))
4112 (let ((f (erc-select-startup-file)))
4114 (erc-load-script f)))))
4116 (defun erc-connection-established (proc parsed)
4119 Set user modes and run `erc-after-connect' hook."
4120 (with-current-buffer (process-buffer proc)
4121 (unless erc-server-connected ; only once per session
4122 (let ((server (or erc-server-announced-name
4123 (erc-response.sender parsed)))
4124 (nick (car (erc-response.command-args parsed)))
4125 (buffer (process-buffer proc)))
4126 (setq erc-server-connected t)
4127 (erc-update-mode-line)
4128 (erc-set-initial-user-mode nick buffer)
4129 (erc-server-setup-periodical-ping buffer)
4130 (run-hook-with-args 'erc-after-connect server nick)))))
4132 (defun erc-set-initial-user-mode (nick buffer)
4133 "If `erc-user-mode' is non-nil for NICK, set the user modes.
4134 The server buffer is given by BUFFER."
4135 (with-current-buffer buffer
4136 (when erc-user-mode
4137 (let ((mode (if (functionp erc-user-mode)
4138 (funcall erc-user-mode)
4139 erc-user-mode)))
4141 (erc-log (format "changing mode for %s to %s" nick mode))
4142 (erc-server-send (format "MODE %s %s" nick mode)))))))
4144 (defun erc-display-error-notice (parsed string)
4147 See also `erc-display-message'."
4148 (erc-display-message
4151 (defun erc-process-ctcp-query (proc parsed nick login host)
4154 (let ((queries (delete "" (split-string (erc-response.contents parsed)
4157 (erc-display-message
4160 (erc-display-message
4165 (hook (intern-soft (concat "erc-ctcp-query-" type "-hook"))))
4168 (run-hook-with-args-until-success
4170 (car (erc-response.command-args parsed))
4172 (when erc-paranoid
4173 (if (erc-current-nick-p
4174 (car (erc-response.command-args parsed)))
4175 (erc-display-message
4178 (erc-display-message
4181 ?t (car (erc-response.command-args parsed)))))
4182 (run-hook-with-args-until-success
4184 (car (erc-response.command-args parsed))
4186 (erc-display-message
4191 (defvar erc-ctcp-query-ACTION-hook '(erc-ctcp-query-ACTION))
4193 (defun erc-ctcp-query-ACTION (proc parsed nick login host to msg)
4197 (buf (or (erc-get-buffer to proc)
4198 (erc-get-buffer nick proc)
4199 (process-buffer proc))))
4200 (erc-display-message
4204 (defvar erc-ctcp-query-CLIENTINFO-hook '(erc-ctcp-query-CLIENTINFO))
4206 (defun erc-ctcp-query-CLIENTINFO (proc nick login host to msg)
4209 (let ((s (erc-client-info (erc-trim-string (match-string 1 msg)))))
4210 (unless erc-disable-ctcp-replies
4211 (erc-send-ctcp-notice nick (format "CLIENTINFO %s" s)))))
4214 (defvar erc-ctcp-query-ECHO-hook '(erc-ctcp-query-ECHO))
4215 (defun erc-ctcp-query-ECHO (proc nick login host to msg)
4219 (unless erc-disable-ctcp-replies
4220 (erc-send-ctcp-notice nick (format "ECHO %s" s)))))
4223 (defvar erc-ctcp-query-FINGER-hook '(erc-ctcp-query-FINGER))
4224 (defun erc-ctcp-query-FINGER (proc nick login host to msg)
4226 (unless erc-disable-ctcp-replies
4227 (let ((s (if erc-anonymous-login
4228 (format "FINGER I'm %s." (erc-current-nick))
4233 (ns (erc-time-diff erc-server-last-sent-time (erc-current-time))))
4235 (setq s (concat s " Idle for " (erc-sec-to-time ns))))
4236 (erc-send-ctcp-notice nick s)))
4239 (defvar erc-ctcp-query-PING-hook '(erc-ctcp-query-PING))
4240 (defun erc-ctcp-query-PING (proc nick login host to msg)
4243 (unless erc-disable-ctcp-replies
4245 (erc-send-ctcp-notice nick (format "PING %s" arg)))))
4248 (defvar erc-ctcp-query-TIME-hook '(erc-ctcp-query-TIME))
4249 (defun erc-ctcp-query-TIME (proc nick login host to msg)
4251 (unless erc-disable-ctcp-replies
4252 (erc-send-ctcp-notice nick (format "TIME %s" (current-time-string))))
4255 (defvar erc-ctcp-query-USERINFO-hook '(erc-ctcp-query-USERINFO))
4256 (defun erc-ctcp-query-USERINFO (proc nick login host to msg)
4258 (unless erc-disable-ctcp-replies
4259 (erc-send-ctcp-notice nick (format "USERINFO %s" erc-user-information)))
4262 (defvar erc-ctcp-query-VERSION-hook '(erc-ctcp-query-VERSION))
4263 (defun erc-ctcp-query-VERSION (proc nick login host to msg)
4265 (unless erc-disable-ctcp-replies
4266 (erc-send-ctcp-notice
4269 erc-version-string
4270 erc-official-location)))
4273 (defun erc-process-ctcp-reply (proc parsed nick login host msg)
4276 (hook (intern (concat "erc-ctcp-reply-" type "-hook"))))
4278 (run-hook-with-args-until-success
4280 (car (erc-response.command-args parsed)) msg)
4281 (erc-display-message
4285 (defvar erc-ctcp-reply-ECHO-hook '(erc-ctcp-reply-ECHO))
4286 (defun erc-ctcp-reply-ECHO (proc nick login host to msg)
4290 (erc-display-message
4295 (defvar erc-ctcp-reply-CLIENTINFO-hook '(erc-ctcp-reply-CLIENTINFO))
4296 (defun erc-ctcp-reply-CLIENTINFO (proc nick login host to msg)
4300 (erc-display-message
4305 (defvar erc-ctcp-reply-FINGER-hook '(erc-ctcp-reply-FINGER))
4306 (defun erc-ctcp-reply-FINGER (proc nick login host to msg)
4310 (erc-display-message
4315 (defvar erc-ctcp-reply-PING-hook '(erc-ctcp-reply-PING))
4316 (defun erc-ctcp-reply-PING (proc nick login host to msg)
4322 (let ((delta (erc-time-diff (string-to-number time)
4323 (erc-current-time))))
4324 (erc-display-message
4327 ?t (erc-sec-to-time delta)))
4329 (erc-display-message
4333 (defvar erc-ctcp-reply-TIME-hook '(erc-ctcp-reply-TIME))
4334 (defun erc-ctcp-reply-TIME (proc nick login host to msg)
4338 (erc-display-message
4343 (defvar erc-ctcp-reply-VERSION-hook '(erc-ctcp-reply-VERSION))
4344 (defun erc-ctcp-reply-VERSION (proc nick login host to msg)
4348 (erc-display-message
4353 (defun erc-process-away (proc away-p)
4358 (let ((sessionbuf (process-buffer proc)))
4360 (with-current-buffer sessionbuf
4361 (when erc-away-nickname
4362 (erc-log (format "erc-process-away: away-nick: %s, away-p: %s"
4363 erc-away-nickname away-p))
4364 (erc-cmd-NICK (if away-p
4365 erc-away-nickname
4366 erc-nick)))
4369 (setq erc-away (current-time)))
4371 (let ((away-time erc-away))
4374 (setq erc-away nil)
4376 (set-buffer (erc-active-buffer))
4377 (when erc-public-away-p
4378 (erc-send-action
4379 (erc-default-target)
4382 (erc-sec-to-time
4383 (erc-time-diff
4384 (erc-emacs-time-to-erc-time away-time)
4385 (erc-current-time))))
4387 (erc-update-mode-line)))
4391 (defun erc-channel-begin-receiving-names ()
4395 be called with the current buffer set to the channel buffer.
4397 See also `erc-channel-end-receiving-names'."
4398 (setq erc-channel-new-member-names (make-hash-table :test 'equal)))
4400 (defun erc-channel-end-receiving-names ()
4403 Used to fix `erc-channel-users' after a channel names list has been
4404 received. Should be called with the current buffer set to the
4405 channel buffer.
4407 See also `erc-channel-begin-receiving-names'."
4409 (if (null (gethash nick erc-channel-new-member-names))
4410 (erc-remove-channel-user nick)))
4411 erc-channel-users)
4412 (setq erc-channel-new-member-names nil))
4414 (defun erc-channel-receive-names (names-string)
4417 Update `erc-channel-users' according to NAMES-STRING.
4424 (let ((erc-channel-members-changed-hook nil))
4437 (puthash (erc-downcase name) t
4438 erc-channel-new-member-names)
4439 (erc-update-current-channel-member
4441 (run-hooks 'erc-channel-members-changed-hook)))
4443 (defcustom erc-channel-members-changed-hook nil
4445 The buffer where the change happened is current while this hook is called."
4446 :group 'erc-hooks
4449 (defun erc-update-user-nick (nick &optional new-nick
4451 "Updates the stored user information for the user with nickname
4454 See also: `erc-update-user'."
4455 (erc-update-user (erc-get-server-user nick) new-nick
4458 (defun erc-update-user (user &optional new-nick
4460 "Update user info for USER. USER must be an erc-server-user
4466 `erc-channel-members-changed-hook' is run for each channel for
4471 (not (equal (erc-server-user-nickname user)
4474 (erc-change-user-nickname user new-nick))
4476 (not (equal (erc-server-user-host user) host)))
4478 (setf (erc-server-user-host user) host))
4480 (not (equal (erc-server-user-login user) login)))
4482 (setf (erc-server-user-login user) login))
4484 (not (equal (erc-server-user-full-name user)
4487 (setf (erc-server-user-full-name user) full-name))
4489 (not (equal (erc-server-user-info user) info)))
4491 (setf (erc-server-user-info user) info))
4493 (dolist (buf (erc-server-user-buffers user))
4494 (if (buffer-live-p buf)
4495 (with-current-buffer buf
4496 (run-hooks 'erc-channel-members-changed-hook))))))
4499 (defun erc-update-current-channel-member
4502 "Updates the stored user information for the user with nickname
4503 NICK. `erc-update-user' is called to handle changes to nickname,
4511 If ADD is non-nil, the user will be added with the specified
4516 `erc-channel-members-updated-hook' is run, and t is returned.
4518 See also: `erc-update-user' and `erc-update-channel-member'."
4520 (channel-data (erc-get-channel-user nick))
4523 (erc-get-server-user nick))))
4526 (erc-log (format "update-member: user = %S, cuser = %S" user cuser))
4528 (not (eq (erc-channel-user-op cuser) op)))
4530 (setf (erc-channel-user-op cuser)
4535 (not (eq (erc-channel-user-voice cuser) voice)))
4537 (setf (erc-channel-user-voice cuser)
4542 (setf (erc-channel-user-last-message-time cuser) (current-time)))
4544 (erc-update-user user new-nick
4549 (setq user (make-erc-server-user
4555 :buffers (list (current-buffer))))
4556 (erc-add-server-user nick user))
4557 (setf (erc-server-user-buffers user)
4558 (cons (current-buffer)
4559 (erc-server-user-buffers user))))
4560 (setq cuser (make-erc-channel-user
4569 (puthash (erc-downcase nick) (cons user cuser)
4570 erc-channel-users)
4573 (run-hooks 'erc-channel-members-changed-hook))
4576 (defun erc-update-channel-member (channel nick new-nick
4579 "Updates user and channel information for the user with
4582 See also: `erc-update-current-channel-member'."
4583 (erc-with-buffer
4585 (erc-update-current-channel-member nick new-nick add op voice host
4589 (defun erc-remove-current-channel-member (nick)
4591 Runs `erc-channel-members-changed-hook'."
4592 (let ((channel-data (erc-get-channel-user nick)))
4594 (erc-remove-channel-user nick)
4595 (run-hooks 'erc-channel-members-changed-hook))))
4597 (defun erc-remove-channel-member (channel nick)
4600 See also `erc-remove-current-channel-member'."
4601 (erc-with-buffer
4603 (erc-remove-current-channel-member nick)))
4605 (defun erc-update-channel-topic (channel topic &optional modify)
4606 "Find a buffer for CHANNEL and set the TOPIC for it.
4610 (erc-with-buffer (channel)
4612 (setq erc-channel-topic (concat erc-channel-topic topic)))
4614 (setq erc-channel-topic (concat topic erc-channel-topic)))
4615 (t (setq erc-channel-topic topic)))
4616 (erc-update-mode-line-buffer (current-buffer))))
4618 (defun erc-set-modes (tgt mode-string)
4620 (let* ((modes (erc-parse-modes mode-string))
4625 (cond ((erc-channel-p tgt); channel modes
4626 (let ((buf (and erc-server-process
4627 (erc-get-buffer tgt erc-server-process))))
4629 (with-current-buffer buf
4630 (setq erc-channel-modes add-modes)
4631 (setq erc-channel-user-limit nil)
4632 (setq erc-channel-key nil)
4638 (erc-update-channel-limit tgt onoff arg))
4640 (erc-update-channel-key tgt onoff arg))
4643 (erc-update-mode-line-buffer buf)))))
4645 ;;(t (setq erc-user-modes add-modes))
4649 (defun erc-sort-strings (list-of-strings)
4655 (defun erc-parse-modes (mode-string)
4681 ;; collect what modes changed, and match them with arguments
4707 (defun erc-update-modes (tgt mode-string &optional nick host login)
4711 (let* ((modes (erc-parse-modes mode-string))
4717 (cond ((erc-channel-p tgt); channel modes
4718 (let ((buf (and erc-server-process
4719 (erc-get-buffer tgt erc-server-process))))
4721 ;; FIXME! This used to have an original buffer
4723 ;; buffer. Is this wanted behavior?
4724 (set-buffer buf)
4725 (if (not (boundp 'erc-channel-modes))
4726 (setq erc-channel-modes nil))
4728 (setq erc-channel-modes (delete (car remove-modes)
4729 erc-channel-modes)
4732 (setq erc-channel-modes (cons (car add-modes)
4733 erc-channel-modes)
4735 (setq erc-channel-modes (erc-sort-strings erc-channel-modes))
4741 (erc-update-channel-member tgt arg arg nil onoff))
4743 (erc-update-channel-member tgt arg arg nil nil
4746 (erc-update-channel-limit tgt onoff arg))
4748 (erc-update-channel-key tgt onoff arg))
4751 (erc-update-mode-line buf))))
4755 (defun erc-update-channel-limit (channel onoff n)
4760 (erc-with-buffer
4762 (cond ((eq onoff 'on) (setq erc-channel-user-limit (string-to-number n)))
4763 (t (setq erc-channel-user-limit nil))))))
4765 (defun erc-update-channel-key (channel onoff key)
4767 (erc-with-buffer
4769 (cond ((eq onoff 'on) (setq erc-channel-key key))
4770 (t (setq erc-channel-key nil)))))
4772 (defun erc-handle-user-status-change (type nlh &optional l)
4786 (erc-log (format "user-change: type: %S nlh: %S l: %S" type nlh l))
4794 (defun erc-highlight-notice (s)
4796 See also variable `erc-notice-highlight-type'."
4798 ((eq erc-notice-highlight-type 'prefix)
4799 (erc-put-text-property 0 (length erc-notice-prefix)
4800 'face 'erc-notice-face s)
4802 ((eq erc-notice-highlight-type 'all)
4803 (erc-put-text-property 0 (length s) 'face 'erc-notice-face s)
4807 (defun erc-make-notice (message)
4809 (when erc-minibuffer-notice
4811 (erc-highlight-notice (concat erc-notice-prefix message)))
4813 (defun erc-highlight-error (s)
4815 (erc-put-text-property 0 (length s) 'face 'erc-error-face s)
4818 (defun erc-put-text-property (start end property value &optional object)
4823 the face `bold' or `erc-pal-face'.
4831 (defun erc-list (thing)
4832 "Return THING if THING is a list, or a list with THING as its element."
4837 (defun erc-parse-user (string)
4846 ;; Some bogus bouncers send Nick!(null), try to live with that.
4854 (defun erc-extract-nick (string)
4857 See also `erc-parse-user'."
4858 (car (erc-parse-user string)))
4860 (defun erc-put-text-properties (start end properties
4872 (erc-put-text-property start end prop value object))
4877 (defun erc-beg-of-input-line ()
4880 Specifically, return the position of `erc-insert-marker'."
4881 (or (and (boundp 'erc-insert-marker)
4882 (markerp erc-insert-marker))
4883 (error "erc-insert-marker has no value, please report a bug"))
4884 (marker-position erc-insert-marker))
4886 (defun erc-end-of-input-line ()
4890 (defun erc-send-current-line ()
4896 ((< (point) (erc-beg-of-input-line))
4899 ((not (erc-server-buffer-live-p))
4903 (erc-set-active-buffer (current-buffer))
4905 (str (erc-user-input))
4906 (old-buf (current-buffer)))
4909 (delete-region (erc-beg-of-input-line)
4910 (erc-end-of-input-line))
4913 (erc-send-input str)
4914 ;; Fix the buffer if the command didn't kill it
4915 (when (buffer-live-p old-buf)
4916 (with-current-buffer old-buf
4920 (set-marker (process-mark erc-server-process) (point))
4921 (set-marker erc-insert-marker (point))
4922 (let ((buffer-modified (buffer-modified-p)))
4923 (erc-display-prompt)
4924 (set-buffer-modified-p buffer-modified))))))
4927 (run-hook-with-args 'erc-send-completed-hook str))))))
4929 (defun erc-user-input ()
4930 "Return the input of the user in the current buffer."
4931 (buffer-substring
4932 erc-input-marker
4933 (erc-end-of-input-line)))
4935 (defvar erc-command-regexp "^/\\([A-Za-z]+\\)\\(\\s-+.*\\|\\s-*\\)$"
4938 (defun erc-send-input (input)
4945 ((if erc-send-whitespace-lines
4948 (when erc-warn-about-blank-lines
4954 (erc-insert-this t))
4955 (setq erc-send-this t)
4956 (run-hook-with-args 'erc-send-pre-hook input)
4957 (when erc-send-this
4959 (not (string-match erc-command-regexp str)))
4965 (erc-display-msg line)
4966 (erc-process-input-line (concat line "\n")
4967 (null erc-flood-protect) t))
4968 (or (and erc-flood-protect (erc-split-line line))
4971 ;; Insert the prompt along with the command.
4972 (erc-display-command str)
4973 (erc-process-input-line (concat str "\n") t nil))
4976 (defun erc-display-command (line)
4977 (when erc-insert-this
4979 (unless erc-hide-prompt
4980 (erc-display-prompt nil nil (erc-command-indicator)
4981 (and (erc-command-indicator)
4982 'erc-command-indicator-face)))
4985 (erc-put-text-property beg (point)
4986 'face 'erc-command-indicator-face)
4988 (set-marker (process-mark erc-server-process) (point))
4989 (set-marker erc-insert-marker (point))
4993 (run-hooks 'erc-send-modify-hook)
4994 (run-hooks 'erc-send-post-hook))))))
4996 (defun erc-display-msg (line)
4999 (when erc-insert-this
5001 (insert (erc-format-my-nick))
5004 (erc-put-text-property beg (point)
5005 'face 'erc-input-face))
5007 (set-marker (process-mark erc-server-process) (point))
5008 (set-marker erc-insert-marker (point))
5012 (run-hooks 'erc-send-modify-hook)
5013 (run-hooks 'erc-send-post-hook))))))
5015 (defun erc-command-symbol (command)
5017 (let ((cmd (intern-soft (format "erc-cmd-%s" (upcase command)))))
5020 (defun erc-extract-command-from-line (line)
5024 (when (string-match erc-command-regexp line)
5025 (let* ((cmd (erc-command-symbol (match-string 1 line)))
5029 (cmd-fun (or cmd #'erc-cmd-default))
5033 (delete "" (split-string (erc-trim-string
5038 (defun erc-split-multiline-safe (string)
5057 (defun erc-set-current-nick (nick)
5059 (with-current-buffer (if (buffer-live-p (erc-server-buffer))
5060 (erc-server-buffer)
5061 (current-buffer))
5062 (setq erc-server-current-nick nick)))
5064 (defun erc-current-nick ()
5066 (with-current-buffer (if (buffer-live-p (erc-server-buffer))
5067 (erc-server-buffer)
5068 (current-buffer))
5069 erc-server-current-nick))
5071 (defun erc-current-nick-p (nick)
5073 (erc-nick-equal-p nick (erc-current-nick)))
5075 (defun erc-nick-equal-p (nick1 nick2)
5080 See also `erc-downcase'."
5081 (string= (erc-downcase nick1)
5082 (erc-downcase nick2)))
5086 (defun erc-default-target ()
5088 (let ((tgt (car erc-default-recipients)))
5094 (defun erc-add-default-channel (channel)
5097 (let ((d1 (car erc-default-recipients))
5098 (d2 (cdr erc-default-recipients))
5100 (setq erc-default-recipients
5101 (cons chl erc-default-recipients))))
5103 (defun erc-delete-default-channel (channel &optional buffer)
5105 (let ((ob (current-buffer)))
5106 (with-current-buffer (if (and buffer
5107 (bufferp buffer))
5108 buffer
5109 (current-buffer))
5110 (setq erc-default-recipients (delete (downcase channel)
5111 erc-default-recipients)))))
5113 (defun erc-add-query (nickname)
5117 (let ((d1 (car erc-default-recipients))
5118 (d2 (cdr erc-default-recipients))
5122 (setq erc-default-recipients (cons qt d2))
5123 (setq erc-default-recipients (cons qt erc-default-recipients)))))
5125 (defun erc-delete-query ()
5128 (let ((d1 (car erc-default-recipients))
5129 (d2 (cdr erc-default-recipients)))
5132 (setq erc-default-recipients d2)
5135 (defun erc-ignored-user-p (spec)
5136 "Return non-nil if SPEC matches something in `erc-ignore-list'.
5139 matches against all the regexp's in `erc-ignore-list'. If any
5142 (dolist (ignored (erc-with-server-buffer erc-ignore-list))
5146 (defun erc-ignored-reply-p (msg tgt proc)
5148 "Return non-nil if MSG matches something in `erc-ignore-reply-list'.
5151 user matches any regexp in `erc-ignore-reply-list'."
5152 (let ((target-nick (erc-message-target msg)))
5155 (erc-with-buffer (tgt proc)
5156 (let ((user (erc-get-server-user target-nick)))
5158 (erc-list-match erc-ignore-reply-list
5159 (erc-user-spec user))))))))
5161 (defun erc-message-target (msg)
5169 (defun erc-user-spec (user)
5171 (let ((nick (erc-server-user-nickname user))
5172 (host (erc-server-user-host user))
5173 (login (erc-server-user-login user)))
5186 (defun erc-list-match (lst str)
5194 (defun erc-toggle-ctcp-autoresponse (&optional arg)
5202 (setq erc-disable-ctcp-replies t))
5203 (arg (setq erc-disable-ctcp-replies nil))
5204 (t (setq erc-disable-ctcp-replies (not erc-disable-ctcp-replies))))
5205 (message "ERC CTCP replies are %s" (if erc-disable-ctcp-replies "OFF" "ON")))
5207 (defun erc-toggle-flood-control (&optional arg)
5213 See `erc-server-flood-margin' for an explanation of the available
5217 (setq erc-flood-protect t))
5218 (arg (setq erc-flood-protect nil))
5219 (t (setq erc-flood-protect (not erc-flood-protect))))
5221 (cond (erc-flood-protect "ON")
5226 (defun erc-invite-only-mode (&optional arg)
5233 (erc-set-active-buffer (current-buffer))
5234 (let ((tgt (erc-default-target))
5235 (erc-force-send t))
5236 (cond ((or (not tgt) (not (erc-channel-p tgt)))
5237 (erc-display-message nil 'error (current-buffer) 'no-target))
5238 (arg (erc-load-irc-script-lines (list (concat "/mode " tgt " -i"))
5240 (t (erc-load-irc-script-lines (list (concat "/mode " tgt " +i"))
5243 (defun erc-get-channel-mode-from-keypress (key)
5249 If \"l\" is pressed, `erc-set-channel-limit' gets called.
5250 If \"k\" is pressed, `erc-set-channel-key' gets called.
5251 Anything else will be sent to `erc-toggle-channel-mode'."
5258 (erc-insert-mode-command))
5260 (call-interactively 'erc-set-channel-limit))
5262 (call-interactively 'erc-set-channel-key))
5263 (t (erc-toggle-channel-mode key))))
5265 (defun erc-toggle-channel-mode (mode &optional channel)
5269 `erc-default-target'."
5271 (erc-set-active-buffer (current-buffer))
5272 (let ((tgt (or channel (erc-default-target)))
5273 (erc-force-send t))
5274 (cond ((or (null tgt) (null (erc-channel-p tgt)))
5275 (erc-display-message nil 'error 'active 'no-target))
5276 ((member mode erc-channel-modes)
5277 (erc-log (format "%s: Toggle mode %s OFF" tgt mode))
5279 (erc-server-send (format "MODE %s -%s" tgt mode)))
5280 (t (erc-log (format "%s: Toggle channel mode %s ON" tgt mode))
5282 (erc-server-send (format "MODE %s +%s" tgt mode))))))
5284 (defun erc-insert-mode-command ()
5287 (let ((tgt (erc-default-target)))
5289 (erc-display-message nil 'error (current-buffer) 'no-target))))
5291 (defun erc-channel-names ()
5294 (erc-set-active-buffer (current-buffer))
5295 (let ((tgt (erc-default-target)))
5296 (if tgt (erc-load-irc-script-lines (list (concat "/names " tgt)))
5297 (erc-display-message nil 'error (current-buffer) 'no-target))))
5299 (defun erc-remove-text-properties-region (start end &optional object)
5308 (defun erc-find-file (file &optional path)
5323 (defun erc-select-startup-file ()
5325 See also `erc-startup-file-list'."
5327 (dolist (f erc-startup-file-list)
5332 (defun erc-find-script-file (file)
5333 "Search for FILE in `default-directory', and any in `erc-script-path'."
5334 (erc-find-file file erc-script-path))
5336 (defun erc-load-script (file)
5340 `erc-script-path'. If the filename ends with `.el', then load it
5343 (erc-log (concat "erc-load-script: " file))
5348 (erc-load-irc-script file))))
5350 (defun erc-process-script-line (line &optional args)
5354 server, etc.) in LINE and returns it.
5357 %S %s = current server, %N %n = my current nick, and %x is x verbatim,
5365 (tgt (erc-default-target))
5366 (server (and (boundp 'erc-session-server) erc-session-server))
5367 (nick (erc-current-nick))
5373 (if (not server) (setq server ""))
5406 ((string-match "^%[Ss]$" esc) server)
5409 (t (erc-log (format "BUG in erc-process-script-line: bad escape sequence: %S\n" esc))
5420 (defun erc-load-irc-script (file &optional force)
5422 (erc-log (concat "erc-load-script: " file))
5423 (let ((str (with-temp-buffer
5425 (buffer-string))))
5426 (erc-load-irc-script-lines (erc-split-multiline-safe str) force)))
5428 (defun erc-load-irc-script-lines (lines &optional force noexpand)
5434 (let* ((cb (current-buffer))
5437 (sp (or (erc-command-indicator) (erc-prompt)))
5438 (args (and (boundp 'erc-script-args) erc-script-args)))
5442 (erc-put-text-property 0 (length sp)
5443 'face 'erc-command-indicator-face sp)
5446 (erc-log (concat "erc-load-script: CMD: " s))
5448 (let ((line (if noexpand s (erc-process-script-line s args))))
5449 (if (and (erc-process-input-line line force)
5450 erc-script-echo)
5452 (erc-put-text-property 0 (length line)
5453 'face 'erc-input-face line)
5454 (erc-display-line (concat sp line) cb)))))
5459 (defun erc-login ()
5460 "Perform user authentication at the IRC server."
5461 (erc-log (format "login: nick: %s, user: %s %s %s :%s"
5462 (erc-current-nick)
5464 (or erc-system-name (system-name))
5465 erc-session-server
5466 erc-session-user-full-name))
5467 (if erc-session-password
5468 (erc-server-send (format "PASS %s" erc-session-password))
5470 (erc-server-send (format "NICK %s" (erc-current-nick)))
5471 (erc-server-send
5474 (if erc-anonymous-login erc-email-userid (user-login-name))
5476 erc-session-user-full-name))
5477 (erc-update-mode-line))
5481 (defun erc-determine-parameters (&optional server port nick name)
5483 Sets the buffer local variables:
5485 - `erc-session-server'
5486 - `erc-session-port'
5487 - `erc-session-full-name'
5488 - `erc-server-current-nick'"
5489 (setq erc-session-server (erc-compute-server server)
5490 erc-session-port (or port erc-default-port)
5491 erc-session-user-full-name (erc-compute-full-name name))
5492 (erc-set-current-nick (erc-compute-nick nick)))
5494 (defun erc-compute-server (&optional server)
5495 "Return an IRC server name.
5501 - The `erc-server' option
5503 - The `erc-default-server' variable"
5504 (or server
5505 erc-server
5507 erc-default-server))
5509 (defun erc-compute-nick (&optional nick)
5516 - The `erc-nick' option
5520 (if (consp erc-nick) (car erc-nick) erc-nick)
5525 (defun erc-compute-full-name (&optional full-name)
5532 - The `erc-user-full-name' option
5536 erc-user-full-name
5538 (if erc-anonymous-login "unknown" nil)
5541 (defun erc-compute-port (&optional port)
5542 "Return a port for an IRC server.
5548 - The `erc-port' option
5549 - The `erc-default-port' variable"
5550 (or port erc-port erc-default-port))
5554 (defun erc-string-to-emacs-time (string)
5556 Returns a list of the form (HIGH LOW), compatible with Emacs time format."
5561 (defun erc-emacs-time-to-erc-time (time)
5567 (defun erc-current-time ()
5570 See also `erc-emacs-time-to-erc-time'."
5571 (erc-emacs-time-to-erc-time (current-time)))
5573 (defun erc-time-diff (t1 t2)
5577 (defun erc-time-gt (t1 t2)
5581 (defun erc-sec-to-time (ns)
5589 (defun erc-seconds-to-string (seconds)
5610 (setq output (erc-replace-match-subexpression-in-string
5617 (defconst erc-clientinfo-alist
5628 (defun erc-client-info (s)
5636 erc-clientinfo-alist))
5638 (let ((h (assoc (upcase s) erc-clientinfo-alist)))
5645 (defun erc-directory-writable-p (dir)
5651 (defun erc-kill-query-buffers (process)
5655 (erc-with-all-buffers-of-server process
5657 (not (erc-server-buffer-p)))
5658 (kill-buffer (current-buffer))))
5660 (defun erc-nick-at-point ()
5669 (channel-data (erc-get-channel-user word))
5673 (erc-get-server-user word)))
5676 (setq nick (erc-server-user-nickname user)
5677 host (erc-server-user-host user)
5678 login (erc-server-user-login user)
5679 full-name (erc-server-user-full-name user)
5680 info (erc-server-user-info user))
5682 (setq op (erc-channel-user-op cuser)
5683 voice (erc-channel-user-voice cuser)))
5692 (erc-default-target))
5696 (defun erc-away-time ()
5701 (erc-with-server-buffer erc-away))
5705 (defcustom erc-mode-line-format "%s %a"
5706 "A string to be formatted and shown in the mode-line in `erc-mode'.
5709 of `mode-line-buffer-identification'.
5713 %l: The estimated lag time to the server
5719 %s: In the server-buffer, this gets filled with the value of
5720 `erc-server-announced-name', in a channel, the value of
5721 (erc-default-target) also get concatenated."
5722 :group 'erc-mode-line-and-header
5725 (defcustom erc-header-line-format "%n on %t (%m,%l) %o"
5726 "A string to be formatted and shown in the header-line in `erc-mode'.
5732 See `erc-mode-line-format' for which characters are can be used."
5733 :group 'erc-mode-line-and-header
5736 (when (fboundp 'erc-update-mode-line)
5737 (erc-update-mode-line nil)))
5741 (defcustom erc-header-line-uses-help-echo-p t
5744 :group 'erc-mode-line-and-header
5747 (defcustom erc-header-line-face-method nil
5752 Otherwise, use the `erc-header-line' face."
5753 :group 'erc-mode-line-and-header
5755 (const :tag "Use the erc-header-line face" t)
5758 (defcustom erc-show-channel-key-p t
5760 :group 'erc-paranoia
5763 (defcustom erc-common-server-suffixes
5767 "Alist of common server name suffixes.
5771 :group 'erc-mode-line-and-header
5774 (defcustom erc-mode-line-away-status-format
5776 "When you're away on a server, this is shown in the mode line.
5777 This should be a string with substitution variables recognized by
5779 :group 'erc-mode-line-and-header
5782 (defun erc-shorten-server-name (server-name)
5783 "Shorten SERVER-NAME according to `erc-common-server-suffixes'."
5784 (if (stringp server-name)
5785 (with-temp-buffer
5786 (insert server-name)
5787 (let ((alist erc-common-server-suffixes))
5793 (buffer-string))))
5795 (defun erc-format-target ()
5797 (let ((target (erc-default-target)))
5799 (concat (erc-shorten-server-name
5800 (or erc-server-announced-name
5801 erc-session-server))
5802 ":" (erc-port-to-string erc-session-port)))))
5804 (defun erc-format-target-and/or-server ()
5805 "Return the server name or the current target and server name combined."
5806 (let ((server-name (erc-shorten-server-name
5807 (or erc-server-announced-name
5808 erc-session-server))))
5809 (cond ((erc-default-target)
5810 (concat (erc-string-no-properties (erc-default-target))
5811 "@" server-name))
5812 (server-name server-name)
5813 (t (buffer-name (current-buffer))))))
5815 (defun erc-format-away-status ()
5816 "Return a formatted `erc-mode-line-away-status-format'
5817 if `erc-away' is non-nil."
5818 (let ((a (erc-away-time)))
5820 (format-time-string erc-mode-line-away-status-format a)
5823 (defun erc-format-channel-modes ()
5826 "+" erc-channel-modes)
5827 (cond ((and erc-channel-user-limit erc-channel-key)
5828 (if erc-show-channel-key-p
5829 (format "lk %.0f %s" erc-channel-user-limit
5830 erc-channel-key)
5831 (format "kl %.0f" erc-channel-user-limit)))
5832 (erc-channel-user-limit
5834 (format "l %.0f" erc-channel-user-limit))
5835 (erc-channel-key
5836 (if erc-show-channel-key-p
5837 (format "k %s" erc-channel-key)
5841 (defun erc-format-lag-time ()
5842 "Return the estimated lag time to server, `erc-server-lag'."
5843 (let ((lag (erc-with-server-buffer erc-server-lag)))
5847 (defun erc-update-mode-line-buffer (buffer)
5848 "Update the mode line in a single ERC buffer BUFFER."
5849 (with-current-buffer buffer
5851 ?a (erc-format-away-status)
5852 ?l (erc-format-lag-time)
5853 ?m (erc-format-channel-modes)
5854 ?n (or (erc-current-nick) "")
5855 ?o (erc-controls-strip erc-channel-topic)
5856 ?p (erc-port-to-string erc-session-port)
5857 ?s (erc-format-target-and/or-server)
5858 ?t (erc-format-target)))
5859 (process-status (cond ((and (erc-server-process-alive)
5860 (not erc-server-connected))
5862 ((erc-server-process-alive)
5866 (face (cond ((eq erc-header-line-face-method nil)
5868 ((functionp erc-header-line-face-method)
5869 (funcall erc-header-line-face-method))
5871 'erc-header-line))))
5873 (setq modeline-buffer-identification
5874 (list (format-spec erc-mode-line-format spec)))
5877 (setq mode-line-buffer-identification
5878 (list (format-spec erc-mode-line-format spec)))
5881 (let ((header (if erc-header-line-format
5882 (format-spec erc-header-line-format spec)
5886 (erc-header-line-uses-help-echo-p
5887 (let ((help-echo (with-temp-buffer
5890 (buffer-string))))
5892 (erc-replace-regexp-in-string
5896 (erc-propertize header 'help-echo help-echo
5898 (erc-propertize header 'help-echo help-echo))))))
5901 (erc-propertize header 'face face)
5907 (defun erc-update-mode-line (&optional buffer)
5911 (if (and buffer (bufferp buffer))
5912 (erc-update-mode-line-buffer buffer)
5913 (dolist (buf (erc-buffer-list))
5914 (when (buffer-live-p buf)
5915 (erc-update-mode-line-buffer buf)))))
5919 (defun erc-port-to-string (p)
5926 (defun erc-string-to-port (s)
5935 (defun erc-version (&optional here)
5940 (format "ERC %s (GNU Emacs %s)" erc-version-string emacs-version)))
5947 (defun erc-modes (&optional here)
5954 (dolist (var (apropos-internal "^erc-.*mode$"))
5967 (defun erc-trim-string (s)
5978 (defun erc-arrange-session-in-multiple-windows ()
5979 "Open a window for every non-server buffer related to `erc-session-server'.
5983 (unless erc-server-process
5984 (error "No erc-server-process found in current buffer"))
5985 (let ((bufs (erc-buffer-list nil erc-server-process)))
5988 (switch-to-buffer (car bufs))
5993 (switch-to-buffer (car bufs))
5997 (defun erc-popup-input-buffer ()
5998 "Provide an input buffer."
6000 (let ((buffer-name (generate-new-buffer-name "*ERC input*"))
6008 (pop-to-buffer (make-indirect-buffer (current-buffer) buffer-name))
6011 (shrink-window-if-larger-than-buffer)))
6015 (defun erc-make-message-variable-name (catalog entry)
6017 (intern (concat "erc-message-"
6020 (defun erc-define-catalog-entry (catalog entry format-spec)
6022 (set (erc-make-message-variable-name catalog entry)
6025 (defun erc-define-catalog (catalog entries)
6028 (erc-define-catalog-entry catalog (car entry) (cdr entry))))
6030 (erc-define-catalog
6055 . "WARNING: Nick length (%i) exceeds max NICKLEN(%l) defined by server")
6082 (PART . erc-message-english-PART)
6083 (PING . "PING from server (last: %s sec. ago)")
6098 (s312 . "%n is/was on server %s (%c)")
6138 (s465 . "You are banned from this server")
6143 (s483 . "You can't kill a server!")
6150 (defun erc-message-english-PART (&rest args)
6153 This function is an example on what could be done with formatting
6160 (if (string= nick (erc-current-nick))
6166 (erc-replace-regexp-in-string "%" "%%" reason))
6170 (defvar erc-current-message-catalog 'english)
6171 (make-variable-buffer-local 'erc-current-message-catalog)
6173 (defun erc-retrieve-catalog-entry (entry &optional catalog)
6176 If CATALOG is nil, `erc-current-message-catalog' is used.
6180 (unless catalog (setq catalog erc-current-message-catalog))
6181 (let ((var (erc-make-message-variable-name catalog entry)))
6184 (when (boundp (erc-make-message-variable-name 'english entry))
6185 (symbol-value (erc-make-message-variable-name 'english entry))))))
6187 (defun erc-format-message (msg &rest args)
6193 (let ((entry (erc-retrieve-catalog-entry msg)))
6202 (add-hook 'kill-buffer-hook 'erc-kill-buffer-function)
6204 (defcustom erc-kill-server-hook '(erc-kill-server)
6205 "*Invoked whenever a server-buffer is killed via `kill-buffer'."
6206 :group 'erc-hooks
6209 (defcustom erc-kill-channel-hook '(erc-kill-channel)
6210 "*Invoked whenever a channel-buffer is killed via `kill-buffer'."
6211 :group 'erc-hooks
6214 (defcustom erc-kill-buffer-hook nil
6215 "*Hook run whenever a non-server or channel buffer is killed.
6217 See also `kill-buffer'."
6218 :group 'erc-hooks
6221 (defun erc-kill-buffer-function ()
6222 "Function to call when an ERC buffer is killed.
6223 This function should be on `kill-buffer-hook'.
6224 When the current buffer is in `erc-mode', this function will run
6226 `erc-kill-server-hook' if the server buffer was killed,
6227 `erc-kill-channel-hook' if a channel buffer was killed,
6228 or `erc-kill-buffer-hook' if any other buffer."
6229 (when (eq major-mode 'erc-mode)
6230 (erc-remove-channel-users)
6232 ((eq (erc-server-buffer) (current-buffer))
6233 (run-hooks 'erc-kill-server-hook))
6234 ((erc-channel-p (erc-default-target))
6235 (run-hooks 'erc-kill-channel-hook))
6237 (run-hooks 'erc-kill-buffer-hook)))))
6239 (defun erc-kill-server ()
6240 "Sends a QUIT command to the server when the server buffer is killed.
6241 This function should be on `erc-kill-server-hook'."
6242 (when (erc-server-process-alive)
6243 (setq erc-server-quitting t)
6244 (erc-server-send (format "QUIT :%s" (funcall erc-quit-reason nil)))))
6246 (defun erc-kill-channel ()
6247 "Sends a PART command to the server when the channel buffer is killed.
6248 This function should be on `erc-kill-channel-hook'."
6249 (when (erc-server-process-alive)
6250 (let ((tgt (erc-default-target)))
6251 (erc-server-send (format "PART %s :%s" tgt
6252 (funcall erc-part-reason nil))
6255 ;;; Dealing with `erc-parsed'
6257 (defun erc-find-parsed-property ()
6258 "Find the next occurrence of the `erc-parsed' text property."
6259 (text-property-not-all (point-min) (point-max) 'erc-parsed nil))
6261 (defun erc-restore-text-properties ()
6262 "Restore the property 'erc-parsed for the region."
6263 (let ((parsed-posn (erc-find-parsed-property)))
6266 'erc-parsed (when parsed-posn (erc-get-parsed-vector parsed-posn)))))
6268 (defun erc-get-parsed-vector (point)
6270 (get-text-property point 'erc-parsed))
6272 (defun erc-get-parsed-vector-nick (vect)
6274 (let* ((untreated-nick (and vect (erc-response.sender vect)))
6278 (erc-is-valid-nick-p maybe-nick))
6281 (defun erc-get-parsed-vector-type (vect)
6284 (erc-response.command vect)))
6286 ;; Teach url.el how to open irc:// URLs with ERC.
6287 ;; To activate, customize `url-irc-function' to `url-irc-erc'.
6290 (defun erc-handle-irc-url (host port channel user password)
6291 "Use ERC to IRC on HOST:PORT in CHANNEL as USER with PASSWORD.
6294 (let ((server-buffer
6295 (car (erc-buffer-filter
6297 (and (string-equal erc-session-server host)
6298 (= erc-session-port port)
6299 (erc-open-server-buffer-p)))))))
6300 (with-current-buffer (or server-buffer (current-buffer))
6301 (if (and server-buffer channel)
6302 (erc-cmd-JOIN channel)
6303 (erc-open host port (or user (erc-compute-nick)) (erc-compute-full-name)
6304 (not server-buffer) password nil channel
6305 (when server-buffer
6306 (get-buffer-process server-buffer)))))))
6308 (provide 'erc)
6311 ;;; IMPORTANT: This require must appear _after_ the above (provide 'erc) to
6313 (require 'erc-goodies)
6315 ;;; erc.el ends here