changeset 75259:f45c5edf0be4

Merge from erc--main--0 Highlights: - Display messages starting with "/" but are not commands correctly. - Add erc-capab.el file, with capab-identify module. - Fix various ERC menu bugs and add "Current channel" submenu. - Make header-line display look nicer. - Fix warning when auto-authenticating to bitlbee. - New option erc-system-name allows the hostname next to your nick to be customized. Revision: emacs@sv.gnu.org/emacs--devo--0--patch-599 Creator: Michael Olson <mwolson@gnu.org>
author Miles Bader <miles@gnu.org>
date Wed, 17 Jan 2007 18:17:25 +0000
parents 38cd68f9ba51
children 864a6f6648e2
files etc/ChangeLog etc/ERC-NEWS lisp/erc/ChangeLog lisp/erc/erc-backend.el lisp/erc/erc-capab.el lisp/erc/erc-dcc.el lisp/erc/erc-menu.el lisp/erc/erc-services.el lisp/erc/erc-track.el lisp/erc/erc.el man/ChangeLog man/erc.texi
diffstat 12 files changed, 600 insertions(+), 139 deletions(-) [+]
line wrap: on
line diff
--- a/etc/ChangeLog	Wed Jan 17 13:20:47 2007 +0000
+++ b/etc/ChangeLog	Wed Jan 17 18:17:25 2007 +0000
@@ -1,3 +1,7 @@
+2007-01-13  Michael Olson  <mwolson@gnu.org>
+
+	* ERC-NEWS: Mention new erc-capab.el file.
+
 2007-01-13  Glenn Morris  <rgm@gnu.org>
 
 	* MACHINES: Add information on compiling 32-bit Emacs on 64-bit
--- a/etc/ERC-NEWS	Wed Jan 17 13:20:47 2007 +0000
+++ b/etc/ERC-NEWS	Wed Jan 17 18:17:25 2007 +0000
@@ -22,6 +22,17 @@
 amount of time, in seconds, that ERC will wait between successive
 reconnect attempts.
 
+** New face: `erc-my-nick-face'
+This helps make it easier to distinguish messages sent by yourself
+from messages sent by other users when the value of the variable
+`erc-show-my-nick' is non-nil.
+
+** New modules
+
+*** Capab identify (erc-capab.el)
+Mark users who haven't identified to NickServ on servers supporting
+CAPAB IDENTIFY-MSG.
+
 ** Changes and additions to modules
 
 *** Channel lists (erc-list.el)
--- a/lisp/erc/ChangeLog	Wed Jan 17 13:20:47 2007 +0000
+++ b/lisp/erc/ChangeLog	Wed Jan 17 18:17:25 2007 +0000
@@ -1,3 +1,94 @@
+2007-01-13  Michael Olson  <mwolson@gnu.org>
+
+	* erc.el (erc-command-regexp): New variable that is used to match
+	a command.
+	(erc-send-input): Use it.  This fixes a bug where paths --
+	"/usr/bin/foo", for example -- were being displayed as commands,
+	but still sent correctly.
+	(erc-extract-command-from-line): Use it.
+
+	* erc.texi (Modules): Document erc-capab-identify.
+
+2007-01-11  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc.el (erc-find-parsed-property): Moved here from erc-track.el
+	since it can be useful in general.
+
+	* erc-track.el (erc-find-parsed-property): Removed.
+
+	* erc-capab.el (erc-capab-find-parsed): Removed.
+	(erc-capab-identify-add-prefix): Use `erc-find-parsed-property'.
+
+	* erc.el (erc-open): Run `erc-before-connect' hook here.  This
+	makes sure the hook always gets called before a connection is
+	made, as some functions, like `erc-handle-irc-url', use `erc-open'
+	instead of `erc'.
+	(erc): Removed `erc-before-connect' hook.
+
+	* erc-menu.el (erc-menu-definition): Put items specific to
+	channels in a "Current channel" submenu.
+
+	* erc-backend.el (321, 323): Display channel list in server buffer
+	when not using the channel list module.
+
+	* erc.el: Updated copyright years.
+	(erc-version-string): Set to 5.2 (devel).
+	(erc-format-lag-time): Fixed to work when `erc-server-lag' is nil.
+	(erc-update-mode-line-buffer): Set the header face.
+
+2007-01-11  Michael Olson  <mwolson@gnu.org>
+
+	* erc-bbdb.el (erc-bbdb-popup-type): Fix customization type and
+	documentation.
+
+	* erc-services.el (erc-nickserv-identify-mode): Improve
+	documentation for nick-change option and move higher to fix
+	compiler warning.  Avoid a recursive load error.
+	(erc-nickserv-alist): Add simple entry for BitlBee, to avoid
+	"NickServ is AWAY: User is offline" error.  Oddly enough, bitlbee
+	was smart enough to recognize that as an authentication request
+	and log in regardless, which is why I didn't notice this earlier.
+	(erc-nickserv-alist-sender, erc-nickserv-alist-regexp)
+	(erc-nickserv-alist-nickserv, erc-nickserv-alist-ident-keyword)
+	(erc-nickserv-alist-use-nick-p)
+	(erc-nickserv-alist-ident-command): New accessors for
+	erc-nickserv-alist.  Using nth is unwieldy.
+	(erc-nickserv-identify-autodetect)
+	(erc-nickserv-identify-on-connect)
+	(erc-nickserv-identify-on-nick-change, erc-nickserv-identify): Use
+	the new accessors.
+
+2007-01-11  Diane Murray  <disumu@x3y2z1.net>
+
+	* NEWS: Added note for `erc-my-nick-face'.  Fixed capab-identify
+	wording.
+
+2007-01-10  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc.el (erc-mode-line-format): Added %l to documentation.
+	(erc-header-line-format): Removed "[IRC]".  Use the new %l
+	replacement character.  Doc fix.
+	(erc-format-channel-modes): Removed lag code.  Removed parentheses
+	from mode string.
+	(erc-format-lag-time): New function.
+	(erc-update-mode-line-buffer): Use it.
+
+2007-01-09  Michael Olson  <mwolson@gnu.org>
+
+	* erc.el (erc-system-name): New option that determines the system
+	name to use when logging in.  The default is to figure this out by
+	calling `system-name'.
+	(erc-login): Use it.
+
+2007-01-07  Michael Olson  <mwolson@gnu.org>
+
+	* erc.el (erc-modules): Add the menu module.  This should fix a
+	bug with incorrect ERC submenus being displayed.
+
+	* erc-menu.el: Turn this into a module.
+	(erc-menu-add, erc-menu-remove): New functions that add and remove
+	the ERC menu.
+
 2006-12-28  Michael Olson  <mwolson@gnu.org>
 
 	* erc-list.el: Change header to mention that this is part of ERC,
@@ -645,8 +736,30 @@
 	<C-tab> for `erc-button-previous' as it is a more standard key
 	binding for this type of function.
 
+2006-02-28  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc-capab.el: Removed things that were accidentally committed on
+	2006-02-20.  Removed Todo section.
+	(erc-capab-unidentified): Removed.
+
+2006-02-26  Michael Olson  <mwolson@gnu.org>
+
+	* erc-capab.el: Use (eval-when-compile (require 'cl)).
+	(erc-capab-unidentified): Fix compiler warning by specifying
+	group.
+
+2006-02-20  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc-capab.el (erc-capab-send-identify-messages): Fixed comment
+	to explain thoughts better.  `erc-server-parameters' is an
+	associated list when it's set, not a string.
+
 2006-02-19  Michael Olson  <mwolson@gnu.org>
 
+	* erc-capab.el (erc-capab-send-identify-messages): Make sure some
+	parameters are strings before using them.  Thanks to Alejandro
+	Benitez for the report.
+
 	* erc.el (erc-version-string): Release ERC 5.1.2.
 
 2006-02-19  Diane Murray  <disumu@x3y2z1.net>
@@ -696,8 +809,13 @@
 
 2006-02-11  Michael Olson  <mwolson@gnu.org>
 
-	* erc.el (erc-update-modules): Make some requirements shorter, so
-	that it's easier to see why they are needed.
+	* erc.el (erc-update-modules): Handle erc-capab-identify
+	correctly.  Make some requirements shorter, so that it's easier to
+	see why they are needed.
+
+	* erc-capab.el: Add autoload cookie for capab-identify.
+	(erc-capab-send-identify-messages, erc-capab-identify-activate):
+	Minor whitespace fix in code.
 
 	* erc-stamp.el (erc-timestamp-use-align-to): Renamed from
 	`erc-timestamp-right-align-by-pixel'.  Set the default based on
@@ -721,11 +839,21 @@
 	(erc-list-channels): Was `erc-cmd-LIST', renamed.
 	(erc-list-channels-simple): New function.
 
-	* erc.el (erc-modules): Added `list' to enabled modules.  Moved
-	customization options left in source code.
+	* erc.el (erc-modules): Added `list' to enabled modules.  Changed
+	`capab-identify' description.  Moved customization options left in
+	source code.
 
 	* erc-menu.el (erc-menu-definition): Use `erc-list-channels'.
 
+	* erc-capab.el: Put a little more detail into Usage section.
+	(define-erc-module): Run `erc-capab-identify-setup' in all open
+	server buffers when enabling.
+	(erc-capab-identify-setup): Make PROC and PARSED optional
+	arguments.
+	(erc-capab-identify-add-prefix): Simplified nickname regexp.  This
+	should now also match nicknames that are formatted differently
+	than the default.
+
 	* erc-spelling.el (define-erc-module): Make sure there's a buffer
 	before calling `with-current-buffer'.
 
@@ -742,12 +870,34 @@
 2006-02-09  Diane Murray  <disumu@x3y2z1.net>
 
 	* erc.el (erc-get-parsed-vector, erc-get-parsed-vector-nick)
+	* erc-capab.el: Require erc.
+	(erc-capab-send-identify-messages): Use `erc-server-send'.
+	(erc-capab-identify-remove/set-identified-flag): Use 1 and 0 as
+	the flags so we can also check whether the `erc-identified' text
+	property is there at all.
+	(erc-capab-identify-add-prefix): Use `erc-capab-find-parsed'.
+	This fixes a bug where the prefix wasn't inserted when timestamps
+	are inserted on the right.  Tweaked nickname regexp.
+	(erc-capab-find-parsed): New function.
+	(erc-capab-get-unidentified-nickname): Updated to check for 0
+	flag.  Only get nickname if there's a nickuserhost associated with
+	this message.
+
+	* erc-capab.el: New file.  Adds the new module
+	`erc-capab-identify', which allows flagging of unidentified users
+	on servers running an ircd based on dancer - irc.freenode.net, for
+	example.
+
+	* erc.el (erc-modules): Added `capab-identify' to options.
+	(erc-get-parsed-vector, erc-get-parsed-vector-nick)
 	(erc-get-parsed-vector-type): Moved here from erc-match.el.
 
 	* erc-match.el (erc-get-parsed-vector, erc-get-parsed-vector-nick)
 	(erc-get-parsed-vector-type): Moved these functions to erc.el
 	since they can be useful outside of the text matching module.
 
+	* NEWS: Added erc-capab.el.
+
 	* erc-dcc.el, erc-stamp.el, erc-xdcc.el: Changed "Emacs IRC Client"
 	to "ERC".
 
--- a/lisp/erc/erc-backend.el	Wed Jan 17 13:20:47 2007 +0000
+++ b/lisp/erc/erc-backend.el	Wed Jan 17 18:17:25 2007 +0000
@@ -1535,7 +1535,7 @@
 (define-erc-response-handler (321)
   "LIST header." nil
   (setq erc-channel-list nil)
-  (erc-display-message parsed 'notice 'active 's321))
+  (erc-display-message parsed 'notice proc 's321))
 
 (define-erc-response-handler (322)
   "LIST notice." nil
@@ -1545,7 +1545,7 @@
       (add-to-list 'erc-channel-list (list channel))
       (erc-update-channel-topic channel topic)
       (erc-display-message
-       parsed 'notice 'active 's322
+       parsed 'notice proc 's322
        ?c channel ?u num-users ?t (or topic "")))))
 
 (define-erc-response-handler (324)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc-capab.el	Wed Jan 17 18:17:25 2007 +0000
@@ -0,0 +1,202 @@
+;;; erc-capab.el --- support for dancer-ircd and hyperion's CAPAB
+
+;; Copyright (C) 2006 Free Software Foundation, Inc.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; This file defines the ERC module `erc-capab-identify', which allows
+;; flagging of unidentified users on servers running dancer-ircd or
+;; hyperion.  freenode.net supports this capability, for example.
+
+;; With CAPAB IDENTIFY-MSG and IDENTIFY-CTCP enabled, messages from
+;; users who have identified themselves to NickServ will have a plus
+;; sign and messages from unidentified users will have a minus sign
+;; added as a prefix.  Note that it is not necessary for your nickname
+;; to be identified in order to receive these marked messages.
+
+;; The plus or minus sign is removed from the message, and a prefix,
+;; `erc-capab-identify-prefix', is inserted in the front of the user's
+;; nickname if the nickname is not identified.
+
+;; Please note that once this has been enabled on a server, there is no
+;; way to tell the server to stop sending marked messages.  If you
+;; disable this module, it will continue removing message flags, but the
+;; unidentified nickname prefix will not be added to messages.
+
+;; Visit <http://freenode.net/faq.shtml#spoofing> and
+;; <http://freenode.net/faq.shtml#registering> to find further
+;; explanations of this capability.
+
+;; From freenode.net's web site (not there anymore) on how to mark
+;; unidentified users:
+;; "We recommend that you add an asterisk before the nick, and
+;;  optionally either highlight or colourize the line in some
+;;  appropriate fashion, if the user is not identified."
+
+;;; Usage:
+
+;; Put the following in your ~/.emacs file.
+
+;; (require 'erc-capab)
+;; (erc-capab-identify-mode 1)
+
+;; `erc-capab-identify-prefix' will now be added to the beginning of
+;; unidentified users' nicknames.  The default is an asterisk, "*".  If
+;; the value of this variable is nil or you disable this module (see
+;; `erc-capab-identify-disable'), no prefix will be inserted, but the
+;; flag sent by the server will still be stripped.
+
+;;; Code:
+
+(require 'erc)
+(eval-when-compile (require 'cl))
+
+;;; Customization:
+
+(defgroup erc-capab nil
+  "Support for dancer-ircd's CAPAB settings."
+  :group 'erc)
+
+(defcustom erc-capab-identify-prefix "*"
+  "The prefix used for unidentified users."
+  :group 'erc-capab
+  :type '(choice string (const nil)))
+
+;;; Define module:
+
+(define-erc-response-handler (290)
+  "Handle dancer-ircd CAPAB messages." nil nil)
+
+;;;###autoload (autoload 'erc-capab-identify-mode "erc-capab" nil t)
+(define-erc-module capab-identify nil
+  "Handle dancer-ircd's CAPAB IDENTIFY-MSG and IDENTIFY-CTCP."
+  ;; append so that `erc-server-parameters' is already set by `erc-server-005'
+  ((add-hook 'erc-server-005-functions 'erc-capab-identify-setup t)
+   (add-hook 'erc-server-290-functions 'erc-capab-identify-activate)
+   (add-hook 'erc-server-PRIVMSG-functions
+             'erc-capab-identify-remove/set-identified-flag)
+   (add-hook 'erc-server-NOTICE-functions
+             'erc-capab-identify-remove/set-identified-flag)
+   (add-hook 'erc-insert-modify-hook 'erc-capab-identify-add-prefix t)
+   (mapc (lambda (buffer)
+           (when buffer
+             (with-current-buffer buffer (erc-capab-identify-setup))))
+         (erc-buffer-list 'erc-open-server-buffer-p)))
+  ((remove-hook 'erc-server-005-functions 'erc-capab-identify-setup)
+   (remove-hook 'erc-server-290-functions 'erc-capab-identify-activate)
+   ;; we don't remove the `erc-capab-identify-remove/set-identified-flag' hooks
+   ;; because there doesn't seem to be a way to tell the server to turn it off
+   (remove-hook 'erc-insert-modify-hook 'erc-capab-identify-add-prefix)))
+
+;;; Variables:
+
+(defvar erc-capab-identify-activated nil
+  "CAPAB IDENTIFY-MSG has been activated.")
+(make-variable-buffer-local 'erc-capab-identify-activated)
+
+(defvar erc-capab-identify-sent nil
+  "CAPAB IDENTIFY-MSG and IDENTIFY-CTCP messages have been sent.")
+(make-variable-buffer-local 'erc-capab-identify-sent)
+
+;;; Functions:
+
+(defun erc-capab-identify-setup (&optional proc parsed)
+  "Set up CAPAB IDENTIFY on the current server.
+
+Optional argument PROC is the current server's process.
+Optional argument PARSED is the current message, a response struct.
+
+These arguments are sent to this function when called as a hook in
+`erc-server-005-functions'."
+  (unless erc-capab-identify-sent
+    (erc-capab-send-identify-messages)))
+
+(defun erc-capab-send-identify-messages ()
+  "Send CAPAB IDENTIFY messages if the server supports it."
+  (when (and (stringp erc-server-version)
+             (string-match "^\\(dancer-ircd\\|hyperion\\)" erc-server-version)
+             ;; could possibly check for '("IRCD" . "dancer") in
+             ;; `erc-server-parameters' instead of looking for a specific name
+             ;; in `erc-server-version'
+             (assoc "CAPAB" erc-server-parameters))
+    (erc-log "Sending CAPAB IDENTIFY-MSG and IDENTIFY-CTCP")
+    (erc-server-send "CAPAB IDENTIFY-MSG")
+    (erc-server-send "CAPAB IDENTIFY-CTCP")
+    (setq erc-capab-identify-sent t)))
+
+
+(defun erc-capab-identify-activate (proc parsed)
+  "Set `erc-capab-identify-activated' and display an activation message.
+
+PROC is the current server's process.
+PARSED is an `erc-parsed' response struct."
+  (when (or (string= "IDENTIFY-MSG" (erc-response.contents parsed))
+            (string= "IDENTIFY-CTCP" (erc-response.contents parsed)))
+    (setq erc-capab-identify-activated t)
+    (erc-display-message
+     parsed 'notice 'active (format "%s activated"
+                                    (erc-response.contents parsed)))))
+
+(defun erc-capab-identify-remove/set-identified-flag (proc parsed)
+  "Remove PARSED message's id flag and add the `erc-identified' text property.
+
+PROC is the current server's process.
+PARSED is an `erc-parsed' response struct."
+  (let ((msg (erc-response.contents parsed)))
+    (when (and erc-capab-identify-activated
+               (string-match "^\\([-\\+]\\)\\(.+\\)$" msg))
+      (setf (erc-response.contents parsed)
+            (if erc-capab-identify-mode
+                (erc-propertize (match-string 2 msg)
+                                'erc-identified
+                                (if (string= (match-string 1 msg) "+")
+                                    1
+                                  0))
+              (match-string 2 msg)))
+      nil)))
+
+(defun erc-capab-identify-add-prefix ()
+  "Add `erc-capab-identify-prefix' to nickname if user is unidentified."
+  (when (and erc-capab-identify-prefix
+             (erc-with-server-buffer erc-capab-identify-activated))
+    (goto-char (or (erc-find-parsed-property) (point-min)))
+    (let ((nickname (erc-capab-get-unidentified-nickname
+                     (erc-get-parsed-vector (point)))))
+      (when (and nickname
+                 (goto-char (point-min))
+                 ;; assuming the first use of `nickname' is the sender's nick
+                 (re-search-forward (regexp-quote nickname) nil t))
+        (goto-char (match-beginning 0))
+        (insert (erc-propertize erc-capab-identify-prefix
+                                'face (get-char-property (- (point) 1)
+                                                         'face)))))))
+
+(defun erc-capab-get-unidentified-nickname (parsed)
+  "Return the nickname of the user if unidentified.
+PARSED is an `erc-parsed' response struct."
+  (when (and (erc-response-p parsed)
+             (equal 0 (get-text-property 0 'erc-identified
+                                     (erc-response.contents parsed))))
+    (let ((nickuserhost (erc-get-parsed-vector-nick parsed)))
+      (when nickuserhost
+       (nth 0 (erc-parse-user nickuserhost))))))
+
+(provide 'erc-capab)
+
+;; arch-tag: 27b6d668-7ee5-4e47-b9f0-27d7a4362062
+;;; erc-capab.el ends here
--- a/lisp/erc/erc-dcc.el	Wed Jan 17 13:20:47 2007 +0000
+++ b/lisp/erc/erc-dcc.el	Wed Jan 17 18:17:25 2007 +0000
@@ -863,29 +863,29 @@
 protocol spec.  Well not really.  We write back a reply after each read,
 rather than every 1024 byte block, but nobody seems to care."
   (with-current-buffer (process-buffer proc)
-    (setq buffer-read-only nil) ;; FIXME
-    (goto-char (point-max))
-    (insert (string-make-unibyte str))
+    (let ((inhibit-read-only t))
+      (goto-char (point-max))
+      (insert (string-make-unibyte str))
 
-    (setq erc-dcc-byte-count (+ (length str) erc-dcc-byte-count))
-    (erc-assert (= erc-dcc-byte-count (1- (point-max))))
-    (and erc-verbose-dcc
-         (erc-display-message
-          nil 'notice erc-server-process
-          'dcc-get-bytes-received
-          ?f (file-name-nondirectory buffer-file-name)
-          ?b (number-to-string erc-dcc-byte-count)))
-    (cond
-     ((and (> (plist-get erc-dcc-entry-data :size) 0)
-           (> erc-dcc-byte-count (plist-get erc-dcc-entry-data :size)))
-      (erc-display-message
-       nil '(error notice) 'active
-       'dcc-get-file-too-long
-       ?f (file-name-nondirectory buffer-file-name))
-      (delete-process proc))
-     (t
-      (process-send-string
-       proc (erc-pack-int erc-dcc-byte-count 4))))))
+      (setq erc-dcc-byte-count (+ (length str) erc-dcc-byte-count))
+      (erc-assert (= erc-dcc-byte-count (1- (point-max))))
+      (and erc-verbose-dcc
+           (erc-display-message
+            nil 'notice erc-server-process
+            'dcc-get-bytes-received
+            ?f (file-name-nondirectory buffer-file-name)
+            ?b (number-to-string erc-dcc-byte-count)))
+      (cond
+       ((and (> (plist-get erc-dcc-entry-data :size) 0)
+             (> erc-dcc-byte-count (plist-get erc-dcc-entry-data :size)))
+        (erc-display-message
+         nil '(error notice) 'active
+         'dcc-get-file-too-long
+         ?f (file-name-nondirectory buffer-file-name))
+        (delete-process proc))
+       (t
+        (process-send-string
+         proc (erc-pack-int erc-dcc-byte-count 4)))))))
 
 
 (defun erc-dcc-get-sentinel (proc event)
--- a/lisp/erc/erc-menu.el	Wed Jan 17 13:20:47 2007 +0000
+++ b/lisp/erc/erc-menu.el	Wed Jan 17 18:17:25 2007 +0000
@@ -28,7 +28,7 @@
 
 ;;; Code:
 
-;(require 'erc)
+(require 'erc)
 (require 'easymenu)
 
 (defvar erc-menu-definition
@@ -40,41 +40,43 @@
 	 (and erc-server-connected (fboundp 'erc-list-channels))]
 	["Join channel..." erc-join-channel erc-server-connected]
 	["Start a query..." erc-cmd-QUERY erc-server-connected]
+	["Input action..." erc-input-action (erc-default-target)]
 	"-"
-	["List users in channel" erc-channel-names erc-channel-users]
-	["List channel operators" erc-cmd-OPS erc-channel-users]
-	["Input action..." erc-input-action (erc-default-target)]
-	["Set topic..." erc-set-topic
-	 (and (and (erc-default-target) (not (erc-query-buffer-p)))
-	      (or (not (member "t" erc-channel-modes))
-		  (erc-channel-user-op-p (erc-current-nick))))]
-	(list "Channel modes"
-	      ["Change mode..." erc-insert-mode-command
-	       (erc-channel-user-op-p (erc-current-nick))]
-	      ["No external send" (erc-toggle-channel-mode "n")
-	       :active (erc-channel-user-op-p (erc-current-nick))
-	       :style toggle :selected (member "n" erc-channel-modes)]
-	      ["Topic set by channel operator" (erc-toggle-channel-mode "t")
-	       :style toggle :selected (member "t" erc-channel-modes)
-	       :active (erc-channel-user-op-p (erc-current-nick))]
-	      ["Invite only" (erc-toggle-channel-mode "i")
-	       :style toggle :selected (member "i" erc-channel-modes)
-	       :active (erc-channel-user-op-p (erc-current-nick))]
-	      ["Private" (erc-toggle-channel-mode "p")
-	       :style toggle :selected (member "p" erc-channel-modes)
-	       :active (erc-channel-user-op-p (erc-current-nick))]
-	      ["Secret" (erc-toggle-channel-mode "s")
-	       :style toggle :selected (member "s" erc-channel-modes)
-	       :active (erc-channel-user-op-p (erc-current-nick))]
-	      ["Moderated" (erc-toggle-channel-mode "m")
-	       :style toggle :selected (member "m" erc-channel-modes)
-	       :active (erc-channel-user-op-p (erc-current-nick))]
-	      ["Set a limit..." erc-set-channel-limit
-	       (erc-channel-user-op-p (erc-current-nick))]
-	      ["Set a key..." erc-set-channel-key
-	       (erc-channel-user-op-p (erc-current-nick))])
-	["Leave this channel..." erc-part-from-channel erc-channel-users]
-	"-"
+	(list
+	 "Current channel"
+	 ["List users in channel" erc-channel-names erc-channel-users]
+	 ["List channel operators" erc-cmd-OPS erc-channel-users]
+	 ["Set topic..." erc-set-topic
+	  (and (and (erc-default-target) (not (erc-query-buffer-p)))
+	       (or (not (member "t" erc-channel-modes))
+		   (erc-channel-user-op-p (erc-current-nick))))]
+	 (list "Channel modes"
+	       ["Change mode..." erc-insert-mode-command
+		(erc-channel-user-op-p (erc-current-nick))]
+	       ["No external send" (erc-toggle-channel-mode "n")
+		:active (erc-channel-user-op-p (erc-current-nick))
+		:style toggle :selected (member "n" erc-channel-modes)]
+	       ["Topic set by channel operator" (erc-toggle-channel-mode "t")
+		:style toggle :selected (member "t" erc-channel-modes)
+		:active (erc-channel-user-op-p (erc-current-nick))]
+	       ["Invite only" (erc-toggle-channel-mode "i")
+		:style toggle :selected (member "i" erc-channel-modes)
+		:active (erc-channel-user-op-p (erc-current-nick))]
+	       ["Private" (erc-toggle-channel-mode "p")
+		:style toggle :selected (member "p" erc-channel-modes)
+		:active (erc-channel-user-op-p (erc-current-nick))]
+	       ["Secret" (erc-toggle-channel-mode "s")
+		:style toggle :selected (member "s" erc-channel-modes)
+		:active (erc-channel-user-op-p (erc-current-nick))]
+	       ["Moderated" (erc-toggle-channel-mode "m")
+		:style toggle :selected (member "m" erc-channel-modes)
+		:active (erc-channel-user-op-p (erc-current-nick))]
+	       ["Set a limit..." erc-set-channel-limit
+		(erc-channel-user-op-p (erc-current-nick))]
+	       ["Set a key..." erc-set-channel-key
+		(erc-channel-user-op-p (erc-current-nick))])
+	 ["Leave this channel..." erc-part-from-channel erc-channel-users]
+	 "-")
 	(list "Pals, fools and other keywords"
 	      ["Add pal..." erc-add-pal]
 	      ["Delete pal..." erc-delete-pal]
@@ -98,16 +100,46 @@
 	["Show ERC version" erc-version t])
   "ERC menu definition.")
 
-;; `erc-mode-map' must be defined before doing this
-(eval-after-load "erc"
-  '(progn
+(defvar erc-menu-defined nil
+  "Internal variable used to keep track of whether we've defined the
+ERC menu yet.")
+
+;;;###autoload (autoload 'erc-menu-mode "erc-menu" nil t)
+(define-erc-module menu nil
+  "Enable a menu in ERC buffers."
+  ((unless erc-menu-defined
+     ;; make sure the menu only gets defined once, since Emacs 22
+     ;; activates it immediately
      (easy-menu-define erc-menu erc-mode-map "ERC menu" erc-menu-definition)
-     (easy-menu-add erc-menu erc-mode-map)
+     (setq erc-menu-defined t))
+   (if (featurep 'xemacs)
+       (progn
+	 ;; the menu isn't automatically added to the menu bar in
+	 ;; XEmacs
+	 (add-hook 'erc-mode-hook 'erc-menu-add)
+	 (dolist (buffer (erc-buffer-list))
+	   (with-current-buffer buffer (erc-menu-add))))
+     (erc-menu-add)))
+  ((if (featurep 'xemacs)
+       (progn
+	 (remove-hook 'erc-mode-hook 'erc-menu-add)
+	 (dolist (buffer (erc-buffer-list))
+	   (with-current-buffer buffer (erc-menu-remove))))
+     (erc-menu-remove)
+     ;; `easy-menu-remove' is a no-op in Emacs 22
+     (message "You might have to restart Emacs to remove the ERC menu"))))
 
-     ;; for some reason the menu isn't automatically added to the menu bar
-     (when (featurep 'xemacs)
-       (add-hook 'erc-mode-hook
-		 (lambda () (easy-menu-add erc-menu erc-mode-map))))))
+;; silence byte-compiler warning
+(eval-when-compile
+  (defvar erc-menu nil))
+
+(defun erc-menu-add ()
+  "Add the ERC menu to the current buffer."
+  (easy-menu-add erc-menu erc-mode-map))
+
+(defun erc-menu-remove ()
+  "Remove the ERC menu from the current buffer."
+  (easy-menu-remove erc-menu))
 
 (provide 'erc-menu)
 
--- a/lisp/erc/erc-services.el	Wed Jan 17 13:20:47 2007 +0000
+++ b/lisp/erc/erc-services.el	Wed Jan 17 18:17:25 2007 +0000
@@ -77,6 +77,29 @@
 communication with those Services."
   :group 'erc)
 
+(defcustom erc-nickserv-identify-mode 'both
+  "The mode which is used when identifying to Nickserv.
+
+Possible settings are:.
+
+'autodetect  - Identify when the real Nickserv sends an identify request.
+'nick-change - Identify when you log in or change your nickname.
+'both        - Do the former if the network supports it, otherwise do the
+               latter.
+nil          - Disables automatic Nickserv identification.
+
+You can also use M-x erc-nickserv-identify-mode to change modes."
+  :group 'erc-services
+  :type '(choice (const autodetect)
+		 (const nick-change)
+		 (const both)
+		 (const nil))
+  :set (lambda (sym val)
+	 (set sym val)
+	 ;; avoid recursive load at startup
+	 (when (featurep 'erc-services)
+	   (erc-nickserv-identify-mode val))))
+
 ;;;###autoload (autoload 'erc-services-mode "erc-services" nil t)
 (define-erc-module services nickserv
   "This mode automates communication with services."
@@ -128,27 +151,6 @@
 	 (remove-hook 'erc-nick-changed-functions
 		      'erc-nickserv-identify-on-nick-change))))
 
-(defcustom erc-nickserv-identify-mode 'both
-  "The mode which is used when identifying to Nickserv.
-
-Possible settings are:.
-
-'autodetect  - Identify when the real Nickserv sends an identify request.
-'nick-change - Identify when you change your nickname.
-'both        - Do the former if the network supports it, otherwise do the
-               latter.
-nil          - Disables automatic Nickserv identification.
-
-You can also use M-x erc-nickserv-identify-mode to change modes."
-  :group 'erc-services
-  :type '(choice (const autodetect)
-		 (const nick-change)
-		 (const both)
-		 (const nil))
-  :set (lambda (sym val)
-	 (set sym val)
-	 (erc-nickserv-identify-mode val)))
-
 (defcustom erc-prompt-for-nickserv-password t
   "Ask for the password when identifying to NickServ."
   :group 'erc-services
@@ -184,7 +186,13 @@
 ;; Variables:
 
 (defcustom erc-nickserv-alist
-  '((DALnet
+  '((BitlBee
+     nil
+     nil
+     "&bitlbee"
+     "identify"
+     nil)
+    (DALnet
      "NickServ!service@dal.net"
      "/msg\\s-NickServ@services.dal.net\\s-IDENTIFY\\s-<password>"
      "NickServ@services.dal.net"
@@ -266,6 +274,24 @@
 		  (string :tag "Command")
 		  (const :tag "No special command necessary" nil)))))
 
+(defsubst erc-nickserv-alist-sender (network &optional entry)
+  (nth 1 (or entry (assoc network erc-nickserv-alist))))
+
+(defsubst erc-nickserv-alist-regexp (network &optional entry)
+  (nth 2 (or entry (assoc network erc-nickserv-alist))))
+
+(defsubst erc-nickserv-alist-nickserv (network &optional entry)
+  (nth 3 (or entry (assoc network erc-nickserv-alist))))
+
+(defsubst erc-nickserv-alist-ident-keyword (network &optional entry)
+  (nth 4 (or entry (assoc network erc-nickserv-alist))))
+
+(defsubst erc-nickserv-alist-use-nick-p (network &optional entry)
+  (nth 5 (or entry (assoc network erc-nickserv-alist))))
+
+(defsubst erc-nickserv-alist-ident-command (network &optional entry)
+  (nth 6 (or entry (assoc network erc-nickserv-alist))))
+
 ;; Functions:
 
 (defun erc-nickserv-identify-autodetect (proc parsed)
@@ -277,14 +303,14 @@
   (unless (and (null erc-nickserv-passwords)
 	       (null erc-prompt-for-nickserv-password))
     (let* ((network (erc-network))
-	   (nickserv (nth 1 (assoc network erc-nickserv-alist)))
-	   (identify-regex (nth 2 (assoc network erc-nickserv-alist)))
+	   (sender (erc-nickserv-alist-sender network))
+	   (identify-regex (erc-nickserv-alist-regexp network))
 	   (sspec (erc-response.sender parsed))
 	   (nick (car (erc-response.command-args parsed)))
 	   (msg (erc-response.contents parsed)))
       ;; continue only if we're sure it's the real nickserv for this network
       ;; and it's asked us to identify
-      (when (and nickserv (equal sspec nickserv)
+      (when (and sender (equal sspec sender)
 		 (string-match identify-regex msg))
 	(erc-log "NickServ IDENTIFY request detected")
 	(erc-nickserv-call-identify-function nick)
@@ -295,7 +321,7 @@
   (unless (or (and (null erc-nickserv-passwords)
 		   (null erc-prompt-for-nickserv-password))
 	      (and (eq erc-nickserv-identify-mode 'both)
-		   (nth 2 (assoc (erc-network) erc-nickserv-alist))))
+		   (erc-nickserv-alist-regexp (erc-network))))
     (erc-nickserv-call-identify-function nick)))
 
 (defun erc-nickserv-identify-on-nick-change (nick old-nick)
@@ -303,7 +329,7 @@
   (unless (or (and (null erc-nickserv-passwords)
 		   (null erc-prompt-for-nickserv-password))
 	      (and (eq erc-nickserv-identify-mode 'both)
-		   (nth 2 (assoc (erc-network) erc-nickserv-alist))))
+		   (erc-nickserv-alist-regexp (erc-network))))
     (erc-nickserv-call-identify-function nick)))
 
 (defun erc-nickserv-call-identify-function (nickname)
@@ -333,12 +359,16 @@
     (let* ((erc-auto-discard-away nil)
 	   (network (erc-network))
 	   (nickserv-info (assoc network erc-nickserv-alist))
-	   (nickserv (or (nth 3 nickserv-info) "NickServ"))
-	   (identify-word (or (nth 4 nickserv-info) "IDENTIFY"))
-	   (nick (if (nth 5 nickserv-info)
+	   (nickserv (or (erc-nickserv-alist-nickserv nil nickserv-info)
+			 "NickServ"))
+	   (identify-word (or (erc-nickserv-alist-ident-keyword
+			       nil nickserv-info)
+			      "IDENTIFY"))
+	   (nick (if (erc-nickserv-alist-use-nick-p nil nickserv-info)
 		     (concat (erc-current-nick) " ")
 		   ""))
-	   (msgtype (or (nth 6 nickserv-info) "PRIVMSG")))
+	   (msgtype (or (erc-nickserv-alist-ident-command nil nickserv-info)
+			"PRIVMSG")))
       (erc-message msgtype
 		   (concat nickserv " " identify-word " " nick password)))))
 
--- a/lisp/erc/erc-track.el	Wed Jan 17 13:20:47 2007 +0000
+++ b/lisp/erc/erc-track.el	Wed Jan 17 18:17:25 2007 +0000
@@ -773,10 +773,6 @@
 		      str)
    (erc-faces-in str)))
 
-(defun erc-find-parsed-property ()
-  "Find the next occurrence of the `erc-parsed' text property."
-  (text-property-not-all (point-min) (point-max) 'erc-parsed nil))
-
 ;;; Buffer switching
 
 (defvar erc-track-last-non-erc-buffer nil
--- a/lisp/erc/erc.el	Wed Jan 17 13:20:47 2007 +0000
+++ b/lisp/erc/erc.el	Wed Jan 17 18:17:25 2007 +0000
@@ -1,7 +1,7 @@
 ;; erc.el --- An Emacs Internet Relay Chat client
 
 ;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-;;   2006 Free Software Foundation, Inc.
+;;   2006, 2007 Free Software Foundation, Inc.
 
 ;; Author: Alexander L. Belikoff (alexander@belikoff.net)
 ;; Contributors: Sergey Berezin (sergey.berezin@cs.cmu.edu),
@@ -74,7 +74,6 @@
 (require 'pp)
 (require 'thingatpt)
 (require 'erc-compat)
-(require 'erc-menu)
 
 (defvar erc-official-location
   "http://emacswiki.org/cgi-bin/wiki/ERC (mailing list: erc-discuss@gnu.org)"
@@ -782,6 +781,13 @@
   :group 'erc
   :type 'string)
 
+(defcustom erc-system-name nil
+  "Use this as the name of your system.
+If nil, ERC will call `system-name' to get this information."
+  :group 'erc
+  :type '(choice (const :tag "Default system name" nil)
+		 string))
+
 (defcustom erc-ignore-list nil
   "*List of regexps matching user identifiers to ignore.
 
@@ -1764,7 +1770,7 @@
 
 (defcustom erc-modules '(netsplit fill button match track completion readonly
 				  ring autojoin noncommands irccontrols
-				  stamp)
+				  stamp menu)
   "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
@@ -1791,17 +1797,21 @@
     (const :tag "Set away status automatically" autoaway)
     (const :tag "Join channels automatically" autojoin)
     (const :tag "Buttonize URLs, nicknames, and other text" button)
+    (const
+     :tag
+     "Mark unidentified users on freenode and other servers supporting CAPAB"
+     capab-identify)
     (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 "Save buffers in logs" log)
     (const :tag "Highlight pals, fools, and other keywords" match)
+    (const :tag "Display a menu in ERC buffers" menu)
     (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"
+    (const :tag "Notify when the online status of certain users changes"
 	   notify)
     (const :tag "Complete nicknames and commands (programmable)"
 	   completion)
@@ -1831,6 +1841,8 @@
       (setq req (concat "erc-" (symbol-name mod)))
       (cond
        ;; yuck. perhaps we should bring the filenames into sync?
+       ((string= req "erc-capab-identify")
+	(setq req "erc-capab"))
        ((string= req "erc-completion")
 	(setq req "erc-pcomplete"))
        ((string= req "erc-pcomplete")
@@ -1891,6 +1903,7 @@
 	(old-buffer (current-buffer))
 	old-point
 	continued-session)
+    (when connect (run-hook-with-args 'erc-before-connect server port nick))
     (erc-update-modules)
     (set-buffer buffer)
     (setq old-point (point))
@@ -2104,8 +2117,6 @@
 `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)
   (erc-open server port nick full-name t password))
 
 (defalias 'erc-select 'erc)
@@ -4300,8 +4311,10 @@
   nil)
 
 (defun erc-process-away (proc away-p)
-  ;; FIXME: This docstring is AWFUL -- Lawrence 2004-01-08
-  "Process the user being away, or returning from an away break."
+  "Toggle the away status of the user depending on the value of AWAY-P.
+
+If nil, set the user as away.
+If non-nil, return from being away."
   (let ((sessionbuf (process-buffer proc)))
     (when sessionbuf
       (with-current-buffer sessionbuf
@@ -4881,6 +4894,9 @@
    erc-input-marker
    (erc-end-of-input-line)))
 
+(defvar erc-command-regexp "^/\\([A-Za-z]+\\)\\(\\s-+.*\\|\\s-*\\)$"
+  "Regular expression used for matching commands in ERC.")
+
 (defun erc-send-input (input)
   "Treat INPUT as typed in by the user. It is assumed that the input
 and the prompt is already deleted.
@@ -4902,7 +4918,7 @@
       (run-hook-with-args 'erc-send-pre-hook input)
       (when erc-send-this
 	(if (or (string-match "\n" str)
-		(not (char-equal (aref str 0) ?/)))
+		(not (string-match erc-command-regexp str)))
 	    (mapc
 	     (lambda (line)
 	       (mapc
@@ -4967,7 +4983,7 @@
   "Extract command and args from the input LINE.
 If no command was given, return nil.  If command matches, return a
 list of the form: (command args) where both elements are strings."
-  (when (string-match "^/\\([A-Za-z]+\\)\\(\\s-+.*\\|\\s-*\\)$" line)
+  (when (string-match erc-command-regexp line)
     (let* ((cmd (erc-command-symbol (match-string 1 line)))
 	   ;; note: return is nil, we apply this simply for side effects
 	   (canon-defun (while (and cmd (symbolp (symbol-function cmd)))
@@ -5406,7 +5422,7 @@
   (erc-log (format "login: nick: %s, user: %s %s %s :%s"
 		   (erc-current-nick)
 		   (user-login-name)
-		   (system-name)
+		   (or erc-system-name (system-name))
 		   erc-session-server
 		   erc-session-user-full-name))
   (if erc-session-password
@@ -5655,6 +5671,7 @@
 
 The following characters are replaced:
 %a: String indicating away status or \"\" if you are not away
+%l: The estimated lag time to the server
 %m: The modes of the channel
 %n: The current nick name
 %o: The topic of the channel
@@ -5666,9 +5683,9 @@
   :group 'erc-mode-line-and-header
   :type 'string)
 
-(defcustom erc-header-line-format "[IRC] %n on %t %m %o"
+(defcustom erc-header-line-format "%n on %t (%m,%l) %o"
   "A string to be formatted and shown in the header-line in `erc-mode'.
-Only used in Emacs 21.
+Only used starting in Emacs 21.
 
 See `erc-mode-line-format' for which characters are can be used."
   :group 'erc-mode-line-and-header
@@ -5758,33 +5775,37 @@
       "")))
 
 (defun erc-format-channel-modes ()
-  "Return the current channel's modes and the estimated lag."
+  "Return the current channel's modes."
+  (concat (apply 'concat
+		 "+" erc-channel-modes)
+	  (cond ((and erc-channel-user-limit erc-channel-key)
+		 (if erc-show-channel-key-p
+		     (format "lk %.0f %s" erc-channel-user-limit
+			     erc-channel-key)
+		   (format "kl %.0f" erc-channel-user-limit)))
+		(erc-channel-user-limit
+		 ;; Emacs has no bignums
+		 (format "l %.0f" erc-channel-user-limit))
+		(erc-channel-key
+		 (if erc-show-channel-key-p
+		     (format "k %s" erc-channel-key)
+		   "k"))
+		(t nil))))
+
+(defun erc-format-lag-time ()
+  "Return the estimated lag time to server, `erc-server-lag'."
   (let ((lag (when (erc-server-buffer-live-p)
 	       (with-current-buffer (process-buffer erc-server-process)
 		 erc-server-lag))))
-    (concat (apply 'concat
-		   "(+" erc-channel-modes)
-	    (cond ((and erc-channel-user-limit erc-channel-key)
-		   (if erc-show-channel-key-p
-		       (format "lk %.0f %s" erc-channel-user-limit
-			       erc-channel-key)
-		     (format "kl %.0f" erc-channel-user-limit)))
-		  (erc-channel-user-limit
-		   ;; Emacs has no bignums
-		   (format "l %.0f" erc-channel-user-limit))
-		  (erc-channel-key
-		   (if erc-show-channel-key-p
-		       (format "k %s" erc-channel-key)
-		     "k"))
-		  (t ""))
-	    (if lag (format ",lag:%.0f" lag) "")
-	    ")")))
+    (cond (lag (format "lag:%.0f" lag))
+	  (t ""))))
 
 (defun erc-update-mode-line-buffer (buffer)
   "Update the mode line in a single ERC buffer BUFFER."
   (with-current-buffer buffer
     (let ((spec (format-spec-make
 		 ?a (erc-format-away-status)
+		 ?l (erc-format-lag-time)
 		 ?m (erc-format-channel-modes)
 		 ?n (or (erc-current-nick) "")
 		 ?o (erc-controls-strip erc-channel-topic)
@@ -5831,7 +5852,10 @@
 			      (erc-propertize header 'help-echo help-echo
 					      'face face)
 			    (erc-propertize header 'help-echo help-echo))))))
-		(t (setq header-line-format header))))))
+		(t (setq header-line-format
+			 (if face
+			     (erc-propertize header 'face face)
+			   header)))))))
     (if (featurep 'xemacs)
 	(redraw-modeline)
       (force-mode-line-update))))
@@ -6185,6 +6209,10 @@
 
 ;;; Dealing with `erc-parsed'
 
+(defun erc-find-parsed-property ()
+  "Find the next occurrence of the `erc-parsed' text property."
+  (text-property-not-all (point-min) (point-max) 'erc-parsed nil))
+
 (defun erc-get-parsed-vector (point)
   "Return the whole parsed vector on POINT."
   (get-text-property point 'erc-parsed))
--- a/man/ChangeLog	Wed Jan 17 13:20:47 2007 +0000
+++ b/man/ChangeLog	Wed Jan 17 18:17:25 2007 +0000
@@ -1,3 +1,7 @@
+2007-01-13  Michael Olson  <mwolson@gnu.org>
+
+	* erc.texi (Modules): Mention capab-identify module.
+
 2007-01-16  Glenn Morris  <rgm@gnu.org>
 
 	* abbrevs.texi (Editing Abbrevs): Describe how to disable a system
--- a/man/erc.texi	Wed Jan 17 13:20:47 2007 +0000
+++ b/man/erc.texi	Wed Jan 17 18:17:25 2007 +0000
@@ -406,6 +406,10 @@
 @item button
 Buttonize URLs, nicknames, and other text
 
+@cindex modules, capab-identify
+@item capab-identify
+Mark unidentified users on freenode and other servers supporting CAPAB.
+
 @cindex modules, completion
 @item pcomplete
 Complete nicknames and commands (programmable)