]> code.delx.au - gnu-emacs/blobdiff - lisp/erc/erc.el
Add "add-log-time-zone-rule: t" to Local Variables section.
[gnu-emacs] / lisp / erc / erc.el
index cc9dc8bf1b9843022e1098a5b8918187b4a250cf..1944bb1a8322db0b2dff9c53ce9e0e82bb08f35e 100644 (file)
@@ -11,7 +11,7 @@
 ;;               Andreas Fuchs (afs@void.at)
 ;;               Gergely Nagy (algernon@midgard.debian.net)
 ;;               David Edmondson (dme@dme.org)
-;; Maintainer: Mario Lang (mlang@delysid.org)
+;; Maintainer: Michael Olson (mwolson@gnu.org)
 ;; Keywords: IRC, chat, client, Internet
 
 ;; This file is part of GNU Emacs.
 ;; ERC is an IRC client for Emacs.
 
 ;; For more information, see the following URLs:
-;; * http://sf.net/projects/erc/
+;; * http://sv.gnu.org/projects/erc/
 ;; * http://www.emacswiki.org/cgi-bin/wiki.pl?EmacsIRCClient
 
-;; Jul-26-2001. erc.el is now in CVS on SourceForge.  I invite everyone
-;; who wants to hack it to contact me <mlang@delysid.org> in order to
-;; get write access on the CVS.
+;; As of 2006-06-13, ERC development is now hosted on Savannah
+;; (http://sv.gnu.org/projects/erc).  I invite everyone who wants to
+;; hack on it to contact me <mwolson@gnu.org> in order to get write
+;; access to the shared Arch archive.
 
 ;; Installation:
 
@@ -66,7 +67,7 @@
 
 ;;; Code:
 
-(defconst erc-version-string "Version 5.1"
+(defconst erc-version-string "Version 5.1.4"
   "ERC version.  This is used by function `erc-version'.")
 
 (eval-when-compile (require 'cl))
 (require 'erc-menu)
 
 (defvar erc-official-location
-  "http://erc.sf.net (comments mailto://mlang@delysid.org)"
+  "http://emacswiki.org/cgi-bin/wiki/ERC (mailing list: erc-discuss@gnu.org)"
   "Location of the ERC client on the Internet.")
 
 (defgroup erc nil
   "Emacs Internet Relay Chat client."
-  :link '(url-link "http://www.emacswiki.org/cgi-bin/wiki.pl?EmacsIRCClient")
+  :link '(url-link "http://www.emacswiki.org/cgi-bin/wiki/ERC")
   :prefix "erc-"
   :group 'applications)
 
 ;; tunable connection and authentication parameters
 
 (defcustom erc-server nil
-  "IRC server to use.
+  "IRC server to use if one is not provided.
 See function `erc-compute-server' for more details on connection
 parameters and authentication."
   :group 'erc
-  :type '(choice (const nil) string))
+  :type '(choice (const :tag "None" nil)
+                (string :tag "Server")))
 
 (defcustom erc-port nil
-  "IRC port to use."
+  "IRC port to use if not specified.
+
+This can be either a string or a number."
   :group 'erc
-  :type '(choice (const nil) number string))
+  :type '(choice (const :tag "None" nil)
+                (integer :tag "Port number")
+                (string :tag "Port string")))
 
 (defcustom erc-nick nil
-  "Nickname to use.
+  "Nickname to use if one is not provided.
 
-Can be either a string, or a list of strings.
+This can be either a string, or a list of strings.
 In the latter case, if the first nick in the list is already in use,
 other nicks are tried in the list order.
 
 See function `erc-compute-nick' for more details on connection
 parameters and authentication."
   :group 'erc
-  :type '(choice (const nil)
+  :type '(choice (const :tag "None" nil)
                 (string :tag "Nickname")
-                (repeat string)))
+                (repeat (string :tag "Nickname"))))
 
 (defcustom erc-nick-uniquifier "`"
-  "The character to append to the nick if it is already in use."
+  "The string to append to the nick if it is already in use."
   :group 'erc
   :type 'string)
 
-(defcustom erc-manual-set-nick-on-bad-nick-p nil
-  "If the nickname you chose isn't available, ERC should not automatically
-attempt to set another nickname.  You can manually set another nickname with
-the /NICK command."
+(defcustom erc-try-new-nick-p t
+  "If the nickname you chose isn't available, and this option is non-nil,
+ERC should automatically attempt to connect with another nickname.
+
+You can manually set another nickname with the /NICK command."
   :group 'erc
   :type 'boolean)
 
 (defcustom erc-user-full-name nil
   "User full name.
 
+This can be either a string or a function to call.
+
 See function `erc-compute-full-name' for more details on connection
 parameters and authentication."
   :group 'erc
-  :type '(choice (const nil) string function)
+  :type '(choice (const :tag "No name" nil)
+                (string :tag "Name")
+                (function :tag "Get from function"))
   :set (lambda (sym val)
         (if (functionp val)
             (set sym (funcall val))
           (set sym val))))
 
 (defvar erc-password nil
-  "ERC password to use in authentication (not necessary).")
+  "Password to use when authenticating to an IRC server.
+It is not strictly necessary to provide this, since ERC will
+prompt you for it.")
 
 (defcustom erc-user-mode nil
   "Initial user modes to be set after a connection is established."
@@ -809,7 +822,8 @@ See `erc-server-flood-margin' for other flood-related parameters.")
 ;; Script parameters
 
 (defcustom erc-startup-file-list
-  '("~/.ercrc.el" "~/.ercrc" ".ercrc.el" ".ercrc")
+  '("~/.emacs.d/.ercrc.el" "~/.emacs.d/.ercrc"
+    "~/.ercrc.el" "~/.ercrc" ".ercrc.el" ".ercrc")
   "List of files to try for a startup script.
 The first existent and readable one will get executed.
 
@@ -871,7 +885,7 @@ As an example:
        (\"xmms\" dme:now-playing)
        (\"version\" erc-quit-reason-normal)
        (\"home\" \"Gone home !\")
-       (\"\" \"Default Reason\")))
+       (\"^$\" \"Default Reason\")))
 If the user types \"/quit zippy\", then a Zippy the Pinhead quotation
 will be used as the quit message."
   :group 'erc-quit-and-part
@@ -895,7 +909,7 @@ As an example:
        (\"xmms\" dme:now-playing)
        (\"version\" erc-part-reason-normal)
        (\"home\" \"Gone home !\")
-       (\"\" \"Default Reason\")))
+       (\"^$\" \"Default Reason\")))
 If the user types \"/part zippy\", then a Zippy the Pinhead quotation
 will be used as the part message."
   :group 'erc-quit-and-part
@@ -1116,12 +1130,19 @@ which the local user typed."
   "ERC face used for messages you receive in the main erc buffer."
   :group 'erc-faces)
 
+(defface erc-header-line
+  '((t (:foreground "grey20" :background "grey90")))
+  "ERC face used for the header line.
+
+This will only be used if `erc-header-line-face-method' is non-nil."
+  :group 'erc-faces)
+
 (defface erc-input-face '((t (:foreground "brown")))
   "ERC face used for your input."
   :group 'erc-faces)
 
 (defface erc-prompt-face
-  '((t (:bold t :foreground "Black" :background"lightBlue2")))
+  '((t (:bold t :foreground "Black" :background "lightBlue2")))
   "ERC face for the prompt."
   :group 'erc-faces)
 
@@ -1223,7 +1244,11 @@ With arg, turn ERC %S mode on if and only if arg is positive.
                (format "erc-%s-mode"
                        (downcase (symbol-name alias)))))
             (quote
-             ,mode))))))
+             ,mode)))
+       ;; For find-function and find-variable.
+       (put ',mode    'definition-name ',name)
+       (put ',enable  'definition-name ',name)
+       (put ',disable 'definition-name ',name))))
 
 (put 'define-erc-module 'doc-string-elt 3)
 
@@ -1366,7 +1391,10 @@ server buffer")
 (defun erc-active-buffer ()
   "Return the value of `erc-active-buffer' for the current server.
 Defaults to the server buffer."
-  (with-current-buffer (erc-server-buffer) erc-active-buffer))
+  (with-current-buffer (erc-server-buffer)
+    (if (buffer-live-p erc-active-buffer)
+       erc-active-buffer
+      (setq erc-active-buffer (current-buffer)))))
 
 (defun erc-set-active-buffer (buffer)
   "Set the value of `erc-active-buffer' to BUFFER."
@@ -1588,12 +1616,13 @@ server connection, or nil which means all open connections."
     (delq
      nil
      (mapcar (lambda (buf)
-              (with-current-buffer buf
-                (and (eq major-mode 'erc-mode)
-                     (or (not proc)
-                         (eq proc erc-server-process))
-                     (funcall predicate)
-                     buf)))
+              (when (buffer-live-p buf)
+                (with-current-buffer buf
+                  (and (eq major-mode 'erc-mode)
+                       (or (not proc)
+                           (eq proc erc-server-process))
+                       (funcall predicate)
+                       buf))))
             (buffer-list)))))
 
 (defun erc-buffer-list (&optional predicate proc)
@@ -1716,13 +1745,25 @@ all channel buffers on all servers."
   "Used to keep track of how many times an attempt at changing nick is made.")
 (make-variable-buffer-local 'erc-nick-change-attempt-count)
 
-(defcustom erc-modules '(netsplit fill button match track pcomplete readonly
+(defun erc-migrate-modules (mods)
+  "Migrate old names of ERC modules to new ones."
+  ;; modify `transforms' to specify what needs to be changed
+  ;; each item is in the format '(old . new)
+  (let ((transforms '((pcomplete . completion))))
+    (erc-delete-dups
+     (mapcar (lambda (m) (or (cdr (assoc m transforms)) m))
+            mods))))
+
+(defcustom erc-modules '(netsplit fill button match track completion readonly
                                  ring autojoin noncommands irccontrols
-                                 stamp)
+                                 stamp list)
   "A list of modules which erc should enable.
 If you set the value of this without using `customize' remember to call
 \(erc-update-modules) after you change it.  When using `customize', modules
 removed from the list will be disabled."
+  :get (lambda (sym)
+        ;; replace outdated names with their newer equivalents
+        (erc-migrate-modules (symbol-value sym)))
   :set (lambda (sym val)
         ;; disable modules which have just been removed
         (when (and (boundp 'erc-modules) erc-modules val)
@@ -1732,44 +1773,48 @@ removed from the list will be disabled."
                 (when (and (fboundp f) (boundp f) (symbol-value f))
                   (message "Disabling `erc-%s'" module)
                   (funcall f 0))))))
-        (set-default sym val)
+        (set sym val)
         ;; this test is for the case where erc hasn't been loaded yet
         (when (fboundp 'erc-update-modules)
           (erc-update-modules)))
-  :type '(set :greedy t
-             (const :tag "Set away status automatically" autoaway)
-             (const :tag "Join channels automatically" autojoin)
-             (const :tag "Integrate with Big Brother Database" bbdb)
-             (const :tag "Buttonize URLs, nicknames, and other text" button)
-             (const :tag "Wrap long lines" fill)
-             (const :tag "Highlight or remove IRC control characters"
-                    irccontrols)
-             (const :tag "Save buffers in logs" log)
-             (const :tag "Highlight pals, fools, and other keywords" match)
-             (const :tag "Detect netsplits" netsplit)
-             (const :tag "Don't display non-IRC commands after evaluation"
-                    noncommands)
-             (const :tag
-                    "Notify when the online status of certain users changes"
-                    notify)
-             (const :tag "Complete nicknames and commands (programmable)"
-                    pcomplete)
-             (const :tag "Complete nicknames and commands (old)" completion)
-             (const :tag "Make displayed lines read-only" readonly)
-             (const :tag "Replace text in messages" replace)
-             (const :tag "Enable an input history" ring)
-             (const :tag "Scroll to the bottom of the buffer" scrolltobottom)
-             (const :tag "Identify to Nickserv (IRC Services) automatically"
-                    services)
-             (const :tag "Convert smileys to pretty icons" smiley)
-             (const :tag "Play sounds when you receive CTCP SOUND requests"
-                    sound)
-             (const :tag "Add timestamps to messages" stamp)
-             (const :tag "Check spelling" spelling)
-             (const :tag "Track channel activity in the mode-line" track)
-             (const :tag "Truncate buffers to a certain size" truncate)
-             (const :tag "Translate morse code in messages" unmorse)
-             (repeat :tag "Others" :inline t symbol))
+  :type
+  '(set
+    :greedy t
+    (const :tag "Set away status automatically" autoaway)
+    (const :tag "Join channels automatically" autojoin)
+    (const :tag "Buttonize URLs, nicknames, and other text" button)
+    (const :tag "Wrap long lines" fill)
+    (const :tag "Launch an identd server on port 8113" identd)
+    (const :tag "Highlight or remove IRC control characters"
+          irccontrols)
+    (const :tag "List channels in a separate buffer" list)
+    (const :tag "Save buffers in logs" log)
+    (const :tag "Highlight pals, fools, and other keywords" match)
+    (const :tag "Detect netsplits" netsplit)
+    (const :tag "Don't display non-IRC commands after evaluation"
+          noncommands)
+    (const :tag
+          "Notify when the online status of certain users changes"
+          notify)
+    (const :tag "Complete nicknames and commands (programmable)"
+          completion)
+    (const :tag "Complete nicknames and commands (old)" hecomplete)
+    (const :tag "Process CTCP PAGE requests from IRC" page)
+    (const :tag "Make displayed lines read-only" readonly)
+    (const :tag "Replace text in messages" replace)
+    (const :tag "Enable an input history" ring)
+    (const :tag "Scroll to the bottom of the buffer" scrolltobottom)
+    (const :tag "Identify to Nickserv (IRC Services) automatically"
+          services)
+    (const :tag "Convert smileys to pretty icons" smiley)
+    (const :tag "Play sounds when you receive CTCP SOUND requests"
+          sound)
+    (const :tag "Add timestamps to messages" stamp)
+    (const :tag "Check spelling" spelling)
+    (const :tag "Track channel activity in the mode-line" track)
+    (const :tag "Truncate buffers to a certain size" truncate)
+    (const :tag "Translate morse code in messages" unmorse)
+    (repeat :tag "Others" :inline t symbol))
   :group 'erc)
 
 (defun erc-update-modules ()
@@ -1780,11 +1825,11 @@ removed from the list will be disabled."
       (cond
        ;; yuck. perhaps we should bring the filenames into sync?
        ((string= req "erc-completion")
-       (setq req "erc-pcomplete")
-       (setq mod 'pcomplete))
-       ((string= req "erc-services")
-       (setq req "erc-nickserv")
-       (setq mod 'services)))
+       (setq req "erc-pcomplete"))
+       ((string= req "erc-pcomplete")
+       (setq mod 'completion))
+       ((string= req "erc-autojoin")
+       (setq req "erc-join")))
       (condition-case nil
          (require (intern req))
        (error nil))
@@ -1913,7 +1958,8 @@ Returns the buffer for the given server or channel."
       (goto-char (point-max))
       (insert "\n"))
     (set-marker (process-mark erc-server-process) (point))
-    (unless continued-session
+    (if continued-session
+       (goto-char (point-max))
       (set-marker erc-insert-marker (point))
       (erc-display-prompt)
       (goto-char (point-max)))
@@ -1956,7 +2002,7 @@ If no buffer matches, return nil."
 
 (if (not (fboundp 'read-passwd))
     (defun read-passwd (prompt)
-      "Substitute for read-passwd in early emacsen"
+      "Substitute for `read-passwd' in early emacsen."
       (read-from-minibuffer prompt)))
 
 (defcustom erc-before-connect nil
@@ -2041,10 +2087,12 @@ Non-interactively, it takes keyword arguments
    (full-name (erc-compute-full-name)))
 
 That is, if called with
+
    (erc-select :server \"irc.freenode.net\" :full-name \"Harry S Truman\")
+
 server and full-name will be set to those values, whereas
-erc-compute-port, erc-compute-nick and erc-compute-full-name will
-be invoked for those parameters' values"
+`erc-compute-port', `erc-compute-nick' and `erc-compute-full-name' will
+be invoked for the values of the other parameters."
   (interactive (erc-select-read-args))
 
   (run-hook-with-args 'erc-before-connect server port nick)
@@ -2315,6 +2363,8 @@ See also `erc-format-message' and `erc-display-line'."
                  msg)))
     (setq string
          (cond
+          ((null type)
+           string)
           ((listp type)
            (mapc (lambda (type)
                    (setq string
@@ -2327,7 +2377,7 @@ See also `erc-format-message' and `erc-display-line'."
     (if (not (erc-response-p parsed))
        (erc-display-line string buffer)
       (unless (member (erc-response.command parsed) erc-hide-list)
-      (erc-put-text-property 0 (length string) 'erc-parsed parsed string)
+       (erc-put-text-property 0 (length string) 'erc-parsed parsed string)
        (erc-put-text-property 0 (length string) 'rear-sticky t string)
        (erc-display-line string buffer)))))
 
@@ -2981,7 +3031,7 @@ Otherwise leave the channel indicated by LINE."
 All the text given as argument is sent to the sever as unmodified,
 just as you provided it.  Use this command with care!"
   (cond
-   ((string-match "^\\s-\\(.+\\)$" line)
+   ((string-match "^ ?\\(.+\\)$" line)
     (erc-server-send (match-string 1 line)))
    (t nil)))
 (put 'erc-cmd-QUOTE 'do-not-parse-args t)
@@ -3025,8 +3075,8 @@ If S is non-nil, it will be used as the quit reason."
     (cond
      ((functionp res) (funcall res))
      ((stringp res) res)
-     ;; hopefully never reached
-     (s))))
+     (s s)
+     (t (erc-quit-reason-normal)))))
 
 (defun erc-part-reason-normal (&optional s)
   "Normal part message.
@@ -3052,7 +3102,8 @@ If S is non-nil, it will be used as the quit reason."
     (cond
      ((functionp res) (funcall res))
      ((stringp res) res)
-     (s))))
+     (s s)
+     (t (erc-part-reason-normal)))))
 
 (defun erc-cmd-QUIT (reason)
   "Disconnect from the current server.
@@ -3110,7 +3161,7 @@ the message given by REASON."
 
 (defun erc-cmd-SV ()
   "Say the current ERC and Emacs version into channel."
-  (erc-send-message (format "I'm using ERC %s with %s %s (%s%s%s)!"
+  (erc-send-message (format "I'm using ERC %s with %s %s (%s%s) of %s."
                            erc-version-string
                            (if (featurep 'xemacs) "XEmacs" "GNU Emacs")
                            emacs-version
@@ -3133,7 +3184,7 @@ the message given by REASON."
                                                      x-toolkit-scroll-bars)))
                               "")
                             (if (featurep 'multi-tty) ", multi-tty" ""))
-                           (concat ", built " erc-emacs-build-time)))
+                           erc-emacs-build-time))
   t)
 
 (defun erc-cmd-SM ()
@@ -3142,12 +3193,6 @@ the message given by REASON."
                            (erc-modes)))
   t)
 
-(defun erc-cmd-SMV ()
-  "Say the current ERC module versions into channel."
-  (erc-send-message (format "I'm using the following module revisions: %s!"
-                           (erc-version-modules)))
-  t)
-
 (defun erc-cmd-DEOP (&rest people)
   "Remove the operator setting from user(s) given in PEOPLE."
   (when (> (length people) 0)
@@ -3474,7 +3519,7 @@ If FACE is non-nil, it will be used to propertize the prompt.  If it is nil,
 If `point' is at the beginning of a channel name, use that as default."
   (interactive
    (list
-    (let ((chnl (if (looking-at "\\([&#+!][^ ]+\\)") (match-string 1) ""))
+    (let ((chnl (if (looking-at "\\([&#+!][^ \n]+\\)") (match-string 1) ""))
          (table (when (erc-server-buffer-live-p)
                   (set-buffer (process-buffer erc-server-process))
                   erc-channel-list)))
@@ -3697,7 +3742,7 @@ E.g. \"Read error to Nick [user@some.host]: 110\" would be shortened to
   "If NICK is unavailable, tell the user the REASON.
 
 See also `erc-display-error-notice'."
-  (if (or erc-manual-set-nick-on-bad-nick-p
+  (if (or (not erc-try-new-nick-p)
          ;; how many default-nicks are left + one more try...
          (eq erc-nick-change-attempt-count
              (if (consp erc-nick)
@@ -3719,12 +3764,13 @@ See also `erc-display-error-notice'."
          (setq newnick (concat (truncate-string-to-width
                                 nick
                                 (if (and erc-server-connected nicklen)
-                                    (- (string-to-number nicklen) 1)
+                                    (- (string-to-number nicklen)
+                                       (length erc-nick-uniquifier))
                                   ;; rfc2812 max nick length = 9
                                   ;; we must assume this is the
                                   ;; server's setting if we haven't
                                   ;; established a connection yet
-                                  8))
+                                  (- 9 (length erc-nick-uniquifier))))
                                erc-nick-uniquifier)))
       (erc-cmd-NICK newnick)
       (erc-display-error-notice
@@ -4718,12 +4764,12 @@ EmacsSpeak support."
 
 Return a list of the three separate tokens."
   (cond
-   ((string-match "^\\([^!]*\\)!\\([^@]*\\)@\\(.*\\)$" string)
+   ((string-match "^\\([^!\n]*\\)!\\([^@\n]*\\)@\\(.*\\)$" string)
     (list (match-string 1 string)
          (match-string 2 string)
          (match-string 3 string)))
    ;; Some bogus bouncers send Nick!(null), try to live with that.
-   ((string-match "^\\([^!]*\\)!\\(.*\\)$" string)
+   ((string-match "^\\([^!\n]*\\)!\\(.*\\)$" string)
     (list (match-string 1 string)
          ""
          (match-string 2 string)))
@@ -4841,7 +4887,8 @@ This returns non-nil only iff we actually send anything."
                  (erc-display-msg line)
                  (erc-process-input-line (concat line "\n")
                                          (null erc-flood-protect) t))
-               (erc-split-line line)))
+               (or (and erc-flood-protect (erc-split-line line))
+                   (list line))))
             (split-string str "\n"))
          ;; Insert the prompt along with the command.
          (erc-display-command str)
@@ -5036,7 +5083,7 @@ user matches any regexp in `erc-ignore-reply-list'."
   "Return the addressed target in MSG.
 
 The addressed target is the string before the first colon in MSG."
-  (if (string-match "^\\([^: ]*\\):" msg)
+  (if (string-match "^\\([^: \n]*\\):" msg)
       (match-string 1 msg)
     nil))
 
@@ -5081,13 +5128,16 @@ If ARG is non-nil and not positive, turns CTCP replies off."
 (defun erc-toggle-flood-control (&optional arg)
   "Toggle use of flood control on sent messages.
 
-If ARG is non-nil, use flood control.
-If ARG is nil, do not use flood control.
+If ARG is positive, use flood control.
+If ARG is non-nil and not positive, do not use flood control.
 
 See `erc-server-flood-margin' for an explanation of the available
 flood control parameters."
   (interactive "P")
-  (setq erc-flood-protect arg)
+  (cond ((and (numberp arg) (> arg 0))
+        (setq erc-flood-protect t))
+       (arg (setq erc-flood-protect nil))
+       (t (setq erc-flood-protect (not erc-flood-protect))))
   (message "ERC flood control is %s"
           (cond (erc-flood-protect "ON")
                 (t "OFF"))))
@@ -5113,10 +5163,10 @@ This command is sent even if excess flood is detected."
 
 (defun erc-get-channel-mode-from-keypress (key)
   "Read a key sequence and call the corresponding channel mode function.
-After doing C-c C-o type in a channel mode letter.
+After doing C-c C-o, type in a channel mode letter.
 
 C-g means quit.
-RET let's you type more than one mode at a time.
+RET lets you type more than one mode at a time.
 If \"l\" is pressed, `erc-set-channel-limit' gets called.
 If \"k\" is pressed, `erc-set-channel-key' gets called.
 Anything else will be sent to `erc-toggle-channel-mode'."
@@ -5194,13 +5244,11 @@ If FILE is found, return the path to it."
 (defun erc-select-startup-file ()
   "Select an ERC startup file.
 See also `erc-startup-file-list'."
-  (let ((l erc-startup-file-list)
-       (f nil))
-    (while (and (not f) l)
-      (if (file-readable-p (car l))
-         (setq f (car l)))
-      (setq l (cdr l)))
-    f))
+  (catch 'found
+    (dolist (f erc-startup-file-list)
+      (setq f (convert-standard-filename f))
+      (when (file-readable-p f)
+       (throw 'found f)))))
 
 (defun erc-find-script-file (file)
   "Search for FILE in `default-directory', and any in `erc-script-path'."
@@ -5367,28 +5415,28 @@ Sets the buffer local variables:
 (defun erc-compute-server (&optional server)
   "Return an IRC server name.
 
-Tries a number of increasingly more default methods until a non-nil value is
-found:
+This tries a number of increasingly more default methods until a
+non-nil value is found.
 
-- SERVER
-- `erc-server'
+- SERVER (the argument passwd to this function)
+- The `erc-server' option
 - The value of the IRCSERVER environment variable
-- `erc-default-server'."
+- The `erc-default-server' variable"
   (or server
       erc-server
       (getenv "IRCSERVER")
       erc-default-server))
 
 (defun erc-compute-nick (&optional nick)
-  "Return user's NICK.
+  "Return user's IRC nick.
 
-Tries a number of increasingly more default methods until a non-nil value is
-found:
+This tries a number of increasingly more default methods until a
+non-nil value is found.
 
-- NICK
-- `erc-nick'
+- NICK (the argument passed to this function)
+- The `erc-nick' option
 - The value of the IRCNICK environment variable
-- via the function `user-login-name'."
+- The result from the `user-login-name' function"
   (or nick
       (if (consp erc-nick) (car erc-nick) erc-nick)
       (getenv "IRCNICK")
@@ -5396,15 +5444,15 @@ found:
 
 
 (defun erc-compute-full-name (&optional full-name)
-  "Return user's FULL-NAME.
+  "Return user's full name.
 
-Tries a number of increasingly more default methods until a non-nil value is
-found:
+This tries a number of increasingly more default methods until a
+non-nil value is found.
 
-- FULL-NAME
-- `erc-user-full-name'
+- FULL-NAME (the argument passed to this function)
+- The `erc-user-full-name' option
 - The value of the IRCNAME environment variable
-- via the function `user-full-name'."
+- The result from the `user-full-name' function"
   (or full-name
       erc-user-full-name
       (getenv "IRCNAME")
@@ -5414,12 +5462,13 @@ found:
 (defun erc-compute-port (&optional port)
   "Return a port for an IRC server.
 
-Tries a number of increasingly more default methods until a non-nil
-value is found:
+This tries a number of increasingly more default methods until a
+non-nil value is found.
 
-- PORT
-- \"ircd\"."
-  (or port erc-port "ircd"))
+- PORT (the argument passed to this function)
+- The `erc-port' option
+- The `erc-default-port' variable"
+  (or port erc-port erc-default-port))
 
 ;; time routines
 
@@ -5607,6 +5656,17 @@ when you move point into the header line."
   :group 'erc-mode-line-and-header
   :type 'boolean)
 
+(defcustom erc-header-line-face-method nil
+  "Determine what method to use when colorizing the header line text.
+
+If nil, don't colorize the header text.
+If given a function, call it and use the resulting face name.
+Otherwise, use the `erc-header-line' face."
+  :group 'erc-mode-line-and-header
+  :type '(choice (const :tag "Don't colorize" nil)
+                (const :tag "Use the erc-header-line face" t)
+                (function :tag "Call a function")))
+
 (defcustom erc-show-channel-key-p t
   "Show the the channel key in the header line."
   :group 'erc-paranoia
@@ -5713,7 +5773,13 @@ if `erc-away' is non-nil."
                                ((erc-server-process-alive)
                                 "")
                                (t
-                                ": CLOSED"))))
+                                ": CLOSED")))
+         (face (cond ((eq erc-header-line-face-method nil)
+                      nil)
+                     ((functionp erc-header-line-face-method)
+                      (funcall erc-header-line-face-method))
+                     (t
+                      'erc-header-line))))
       (cond ((featurep 'xemacs)
             (setq modeline-buffer-identification
                   (list (format-spec erc-mode-line-format spec)))
@@ -5737,7 +5803,10 @@ if `erc-away' is non-nil."
                         (erc-replace-regexp-in-string
                          "%"
                          "%%"
-                         (erc-propertize header 'help-echo help-echo)))))
+                         (if face
+                             (erc-propertize header 'help-echo help-echo
+                                             'face face)
+                           (erc-propertize header 'help-echo help-echo))))))
                (t (setq header-line-format header))))))
     (if (featurep 'xemacs)
        (redraw-modeline)
@@ -5781,26 +5850,6 @@ If optional argument HERE is non-nil, insert version number at point."
          (message "%s" version-string)
        version-string))))
 
-(defun erc-version-modules (&optional here)
-  "Show the version numbers of all loaded ERC modules in the minibuffer.
-If optional argument HERE is non-nil, insert version number at point."
-  (interactive "P")
-  (let ((version-string
-        (mapconcat 'identity
-                   (let (versions (case-fold-search nil))
-                     (dolist (var (apropos-internal "^erc-.*version$"))
-                       (when (and (boundp var)
-                                  (stringp (symbol-value var)))
-                         (setq versions (cons (format "%S: %s"
-                                                      var (symbol-value var))
-                                              versions))))
-                     versions) ", ")))
-    (if here
-       (insert version-string)
-      (if (interactive-p)
-         (message "%s" version-string)
-       version-string))))
-
 (defun erc-modes (&optional here)
   "Show the active ERC modes in the minibuffer.
 If optional argument HERE is non-nil, insert version number at point."
@@ -5821,32 +5870,6 @@ If optional argument HERE is non-nil, insert version number at point."
          (message "%s" string)
        string))))
 
-(defun erc-latest-version ()
-  "Retrieve the latest erc.el version from CVS."
-  (interactive)
-  (if (ignore-errors (require 'url))
-      (progn
-       (switch-to-buffer (get-buffer-create "*erc.el latest version*"))
-       (delete-region (point-min) (point-max))
-       (kill-all-local-variables)
-       (url-insert-file-contents (concat
-                                  "http://cvs.sourceforge.net/viewcvs.py/"
-                                  "*checkout*/erc/erc/erc.el?content-type"
-                                  "=text%2Fplain&rev=HEAD"))
-       (emacs-lisp-mode)
-       (current-buffer))
-    (error "URL needs to be installed")))
-
-(defun erc-ediff-latest-version ()
-  "Ediff your installed erc.el with the latest CVS version.
-See also `erc-latest-version'."
-  (interactive)
-  (let ((current (locate-library "erc.el")))
-    (if current
-       (ediff-buffers (find-file current)
-                      (erc-latest-version))
-      (error "You do not appear to have the uncompiled erc.el file"))))
-
 (defun erc-trim-string (s)
   "Trim leading and trailing spaces off S."
   (cond
@@ -5872,7 +5895,8 @@ All windows are opened in the current frame."
       (setq bufs (cdr bufs))
       (while bufs
        (split-window)
-       (switch-to-buffer-other-window (car bufs))
+       (other-window 1)
+       (switch-to-buffer (car bufs))
        (setq bufs (cdr bufs))
        (balance-windows)))))
 
@@ -5924,12 +5948,17 @@ All windows are opened in the current frame."
    (ctcp-request-to . "==> CTCP request from %n (%u@%h) to %t: %r")
    (ctcp-too-many . "Too many CTCP queries in single message. Ignoring")
    (flood-ctcp-off . "FLOOD PROTECTION: Automatic CTCP responses turned off.")
-   (flood-strict-mode . "FLOOD PROTECTION: Switched to Strict Flood Control mode.")
-   (disconnected . "Connection failed!  Re-establishing connection...")
-   (disconnected-noreconnect . "Connection failed!  Not re-establishing connection.")
+   (flood-strict-mode
+    . "FLOOD PROTECTION: Switched to Strict Flood Control mode.")
+   (disconnected . "\n\nConnection failed!  Re-establishing connection...\n")
+   (disconnected-noreconnect
+    . "\n\nConnection failed!  Not re-establishing connection.\n")
+   (finished . "\n\n*** ERC finished ***\n")
+   (terminated . "\n\n*** ERC terminated: %e\n")
    (login . "Logging in as \'%n\'...")
    (nick-in-use . "%n is in use. Choose new nickname: ")
-   (nick-too-long . "WARNING: Nick length (%i) exceeds max NICKLEN(%l) defined by server")
+   (nick-too-long
+    . "WARNING: Nick length (%i) exceeds max NICKLEN(%l) defined by server")
    (no-default-channel . "No default channel")
    (no-invitation . "You've got no invitation")
    (no-target . "No target")
@@ -6127,6 +6156,49 @@ This function should be on `erc-kill-channel-hook'."
                               (funcall erc-part-reason nil))
                       nil tgt))))
 
+;;; Dealing with `erc-parsed'
+
+(defun erc-get-parsed-vector (point)
+  "Return the whole parsed vector on POINT."
+  (get-text-property point 'erc-parsed))
+
+(defun erc-get-parsed-vector-nick (vect)
+  "Return nickname in the parsed vector VECT."
+  (let* ((untreated-nick (and vect (erc-response.sender vect)))
+        (maybe-nick (when untreated-nick
+                      (car (split-string untreated-nick "!")))))
+    (when (and (not (null maybe-nick))
+              (erc-is-valid-nick-p maybe-nick))
+      untreated-nick)))
+
+(defun erc-get-parsed-vector-type (vect)
+  "Return message type in the parsed vector VECT."
+  (and vect
+       (erc-response.command vect)))
+
+;; Teach url.el how to open irc:// URLs with ERC.
+;; To activate, customize `url-irc-function' to `url-irc-erc'.
+
+;;;###autoload
+(defun erc-handle-irc-url (host port channel user password)
+  "Use ERC to IRC on HOST:PORT in CHANNEL as USER with PASSWORD.
+If ERC is already connected to HOST:PORT, simply /join CHANNEL.
+Otherwise, connect to HOST:PORT as USER and /join CHANNEL."
+  (let ((server-buffer
+        (car (erc-buffer-filter
+              (lambda ()
+                (and (string-equal erc-session-server host)
+                     (= erc-session-port port)
+                     erc-server-connected
+                     (eq (erc-server-buffer) (current-buffer))))))))
+    (with-current-buffer (or server-buffer (current-buffer))
+      (if (and server-buffer channel)
+         (erc-cmd-JOIN channel)
+       (erc host port (or user (erc-compute-nick)) (erc-compute-full-name)
+            (not server-buffer) password nil channel
+            (when server-buffer
+              (get-buffer-process server-buffer)))))))
+
 (provide 'erc)
 
 ;;; Deprecated. We might eventually stop requiring the goodies automatically.