]> code.delx.au - gnu-emacs/blobdiff - lisp/erc/erc.el
(erc-noncommands-list, noncommands, erc-control-characters,
[gnu-emacs] / lisp / erc / erc.el
index fab8f7ca1b95504ba7313894189e81889bc931ee..cadc6fed22262e8a8b36620e87bc515b6d3edfdc 100644 (file)
@@ -1,7 +1,7 @@
 ;; erc.el --- An Emacs Internet Relay Chat client
 
 ;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-;;   2006, 2007 Free Software Foundation, Inc.
+;;   2006, 2007, 2008 Free Software Foundation, Inc.
 
 ;; Author: Alexander L. Belikoff (alexander@belikoff.net)
 ;; Contributors: Sergey Berezin (sergey.berezin@cs.cmu.edu),
@@ -66,7 +66,7 @@
 
 ;;; Code:
 
-(defconst erc-version-string "Version 5.3 (devel)"
+(defconst erc-version-string "Version 5.3"
   "ERC version.  This is used by function `erc-version'.")
 
 (eval-when-compile (require 'cl))
@@ -1110,6 +1110,7 @@ which the local user typed."
     (define-key map "\C-c\C-r" 'erc-remove-text-properties-region)
     (define-key map "\C-c\C-t" 'erc-set-topic)
     (define-key map "\C-c\C-u" 'erc-kill-input)
+    (define-key map "\C-c\C-x" 'erc-quit-server)
     (define-key map "\M-\t" 'ispell-complete-word)
     (define-key map "\t" 'erc-complete-word)
 
@@ -1167,7 +1168,13 @@ This will only be used if `erc-header-line-face-method' is non-nil."
 See the variable `erc-command-indicator'."
   :group 'erc-faces)
 
-(defface erc-notice-face '((t (:bold t :foreground "SlateBlue")))
+(defface erc-notice-face
+  (if (or (featurep 'xemacs)
+         (< emacs-major-version 22))
+      '((t (:bold t :foreground "blue")))
+    '((((class color) (min-colors 88))
+       (:bold t :foreground "SlateBlue"))
+      (t (:bold t :foreground "blue"))))
   "ERC face for notices."
   :group 'erc-faces)
 
@@ -1465,18 +1472,23 @@ Turning on `erc-mode' runs the hook `erc-mode-hook'."
   "IRC port to use if it cannot be detected otherwise.")
 
 (defcustom erc-join-buffer 'buffer
-  "Determines how to display the newly created IRC buffer.
-'window - in another window,
-'window-noselect - in another window, but don't select that one,
-'frame - in another frame,
-'bury - bury it in a new buffer,
-any other value - in place of the current buffer."
+  "Determines how to display a newly created IRC buffer.
+
+The available choices are:
+
+  'window          - in another window,
+  'window-noselect - in another window, but don't select that one,
+  'frame           - in another frame,
+  'bury            - bury it in a new buffer,
+  'buffer          - in place of the current buffer,
+  any other value  - in place of the current buffer."
   :group 'erc-buffers
-  :type '(choice (const window)
-                (const window-noselect)
-                (const frame)
-                (const bury)
-                (const buffer)))
+  :type '(choice (const :tag "Split window and select" window)
+                (const :tag "Split window, don't select" window-noselect)
+                (const :tag "New frame" frame)
+                (const :tag "Bury in new buffer" bury)
+                (const :tag "Use current buffer" buffer)
+                (const :tag "Use current buffer" t)))
 
 (defcustom erc-frame-alist nil
   "*Alist of frame parameters for creating erc frames.
@@ -1693,6 +1705,11 @@ nil."
 (put 'erc-with-all-buffers-of-server 'lisp-indent-function 1)
 (put 'erc-with-all-buffers-of-server 'edebug-form-spec '(form form body))
 
+;; (iswitchb-mode) will autoload iswitchb.el
+(defvar iswitchb-temp-buflist)
+(declare-function iswitchb-read-buffer "iswitchb"
+                (prompt &optional default require-match start matches-set))
+
 (defun erc-iswitchb (&optional arg)
   "Use `iswitchb-read-buffer' to prompt for a ERC buffer to switch to.
 When invoked with prefix argument, use all erc buffers.  Without prefix
@@ -1703,9 +1720,7 @@ If `erc-track-mode' is in enabled, put the last element of
 Due to some yet unresolved reason, global function `iswitchb-mode'
 needs to be active for this function to work."
   (interactive "P")
-  (eval-when-compile
-    (require 'iswitchb))
-  (let ((enabled iswitchb-mode))
+  (let ((enabled (bound-and-true-p iswitchb-mode)))
     (or enabled (iswitchb-mode 1))
     (unwind-protect
        (let ((iswitchb-make-buflist-hook
@@ -1801,8 +1816,8 @@ buffer rather than a server buffer.")
             mods))))
 
 (defcustom erc-modules '(netsplit fill button match track completion readonly
-                                 ring autojoin noncommands irccontrols
-                                 stamp menu)
+                        networks ring autojoin noncommands irccontrols
+                        move-to-prompt stamp menu 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
@@ -1834,14 +1849,20 @@ removed from the list will be disabled."
     (const :tag "completion: Complete nicknames and commands (programmable)"
           completion)
     (const :tag "hecomplete: Complete nicknames and commands (old)" hecomplete)
+    (const :tag "dcc: Provide Direct Client-to-Client support" dcc)
     (const :tag "fill: Wrap long lines" fill)
     (const :tag "identd: Launch an identd server on port 8113" identd)
     (const :tag "irccontrols: Highlight or remove IRC control characters"
           irccontrols)
+    (const :tag "keep-place: Leave point above un-viewed text" keep-place)
+    (const :tag "list: List channels in a separate buffer" list)
     (const :tag "log: Save buffers in logs" log)
     (const :tag "match: Highlight pals, fools, and other keywords" match)
     (const :tag "menu: Display a menu in ERC buffers" menu)
+    (const :tag "move-to-prompt: Move to the prompt when typing text"
+          move-to-prompt)
     (const :tag "netsplit: Detect netsplits" netsplit)
+    (const :tag "networks: Provide data about IRC networks" networks)
     (const :tag "noncommands: Don't display non-IRC commands after evaluation"
           noncommands)
     (const :tag
@@ -1863,6 +1884,7 @@ removed from the list will be disabled."
     (const :tag "track: Track channel activity in the mode-line" track)
     (const :tag "truncate: Truncate buffers to a certain size" truncate)
     (const :tag "unmorse: Translate morse code in messages" unmorse)
+    (const :tag "xdcc: Act as an XDCC file-server" xdcc)
     (repeat :tag "Others" :inline t symbol))
   :group 'erc)
 
@@ -1924,7 +1946,7 @@ already connected and just create a separate buffer for the new
 target CHANNEL.
 
 Use PASSWD as user password on the server.  If TGT-LIST is
-non-nil, use it to initialise `erc-default-recipients'.
+non-nil, use it to initialize `erc-default-recipients'.
 
 Returns the buffer for the given server or channel."
   (let ((server-announced-name (when (and (boundp 'erc-session-server)
@@ -2165,6 +2187,8 @@ Arguments are the same as for `erc'."
 
 (defalias 'erc-select-ssl 'erc-ssl)
 
+(declare-function open-ssl-stream "ext:ssl" (name buffer host service))
+
 (defun erc-open-ssl-stream (name buffer host port)
   "Open an SSL stream to an IRC server.
 The process will be given the name NAME, its target buffer will be
@@ -2189,6 +2213,8 @@ Arguments are the same as for `erc'."
   (let ((erc-server-connect-function 'erc-open-tls-stream))
     (apply 'erc r)))
 
+(declare-function open-tls-stream "tls" (name buffer host port))
+
 (defun erc-open-tls-stream (name buffer host port)
   "Open an TLS stream to an IRC server.
 The process will be given the name NAME, its target buffer will be
@@ -2225,6 +2251,8 @@ but you won't see it.
 WARNING: Do not set this variable directly!  Instead, use the
 function `erc-toggle-debug-irc-protocol' to toggle its value.")
 
+(declare-function erc-network-name "erc-networks" ())
+
 (defun erc-log-irc-protocol (string &optional outbound)
   "Append STRING to the buffer *erc-protocol*.
 
@@ -2315,6 +2343,15 @@ If ARG is non-nil, show the *erc-protocol* buffer."
 I.e. any char in it has the `invisible' property set."
   (text-property-any 0 (length string) 'invisible t string))
 
+(defcustom erc-remove-parsed-property t
+  "Whether to remove the erc-parsed text property after displaying a message.
+
+The default is to remove it, since it causes ERC to take up extra
+memory.  If you have code that relies on this property, then set
+this option to nil."
+  :type 'boolean
+  :group 'erc)
+
 (defun erc-display-line-1 (string buffer)
   "Display STRING in `erc-mode' BUFFER.
 Auxiliary function used in `erc-display-line'.  The line gets filtered to
@@ -2355,7 +2392,10 @@ If STRING is nil, the function does nothing."
                (save-restriction
                  (narrow-to-region insert-position (point))
                  (run-hooks 'erc-insert-modify-hook)
-                 (run-hooks 'erc-insert-post-hook))))))
+                 (run-hooks 'erc-insert-post-hook)
+                 (when erc-remove-parsed-property
+                   (remove-text-properties (point-min) (point-max)
+                                           '(erc-parsed nil))))))))
        (erc-update-undo-list (- (or (marker-position erc-insert-marker)
                                     (point-max))
                                 insert-position))))))
@@ -2388,7 +2428,7 @@ If STRING is nil, the function does nothing."
        (setq list (cdr list))))))
 
 (defvar erc-valid-nick-regexp "[]a-zA-Z^[;\\`_{}|][]^[;\\`_{}|a-zA-Z0-9-]*"
-  "Regexp which matches all legal characters in a IRC nickname.")
+  "Regexp which matches all valid characters in a IRC nickname.")
 
 (defun erc-is-valid-nick-p (nick)
   "Check if NICK is a valid IRC nickname."
@@ -3152,14 +3192,35 @@ just as you provided it.  Use this command with care!"
    (t nil)))
 (put 'erc-cmd-QUOTE 'do-not-parse-args t)
 
+(defcustom erc-query-display 'window
+  "Indicates how to display query buffers when using the /QUERY
+command to talk to someone.
+
+The default behavior is to display the message in a new window
+and bring it to the front.  See the documentation for
+`erc-join-buffer' for a description of the available choices.
+
+See also `erc-auto-query' to decide how private messages from
+other people should be displayed."
+  :group 'erc-query
+  :type '(choice (const :tag "Split window and select" window)
+                (const :tag "Split window, don't select" window-noselect)
+                (const :tag "New frame" frame)
+                (const :tag "Bury in new buffer" bury)
+                (const :tag "Use current buffer" buffer)
+                (const :tag "Use current buffer" t)))
+
 (defun erc-cmd-QUERY (&optional user)
   "Open a query with USER.
 The type of query window/frame/etc will depend on the value of
-`erc-join-buffer'.  If USER is omitted, close the current query buffer if one
-exists - except this is broken now ;-)"
+`erc-query-display'.
+
+If USER is omitted, close the current query buffer if one exists
+- except this is broken now ;-)"
   (interactive
    (list (read-from-minibuffer "Start a query with: " nil)))
-  (let ((session-buffer (erc-server-buffer)))
+  (let ((session-buffer (erc-server-buffer))
+       (erc-join-buffer erc-query-display))
     (if user
        (erc-query user session-buffer)
       ;; currently broken, evil hack to display help anyway
@@ -3698,8 +3759,9 @@ If `point' is at the beginning of a channel name, use that as default."
     (read-from-minibuffer
      (concat "Set topic of " (erc-default-target) ": ")
      (when erc-channel-topic
-       (cons (apply 'concat (butlast (split-string erc-channel-topic "\C-o")))
-            0)))))
+       (let ((ss (split-string erc-channel-topic "\C-o")))
+        (cons (apply 'concat (if (cdr ss) (butlast ss) ss))
+              0))))))
   (let ((topic-list (split-string topic "\C-o"))) ; strip off the topic setter
     (erc-cmd-TOPIC (concat (erc-default-target) " " (car topic-list)))))
 
@@ -3832,20 +3894,22 @@ To change how this query window is displayed, use `let' to bind
     (erc-update-mode-line)
     buf))
 
-(defcustom erc-auto-query 'bury
+(defcustom erc-auto-query 'window-noselect
   "If non-nil, create a query buffer each time you receive a private message.
+If the buffer doesn't already exist, it is created.
 
-If the buffer doesn't already exist it is created.  This can be
-set to a symbol, to control how the new query window should
-appear.  See the documentation for `erc-join-buffer' for
-available choices."
+This can be set to a symbol, to control how the new query window
+should appear.  The default behavior is to display the buffer in
+a new window, but not to select it.  See the documentation for
+`erc-join-buffer' for a description of the available choices."
   :group 'erc-query
-  :type '(choice (const nil)
-                (const buffer)
-                (const window)
-                (const window-noselect)
-                (const bury)
-                (const frame)))
+  :type '(choice (const :tag "Don't create query window" nil)
+                (const :tag "Split window and select" window)
+                (const :tag "Split window, don't select" window-noselect)
+                (const :tag "New frame" frame)
+                (const :tag "Bury in new buffer" bury)
+                (const :tag "Use current buffer" buffer)
+                (const :tag "Use current buffer" t)))
 
 (defcustom erc-query-on-unjoined-chan-privmsg t
   "If non-nil create query buffer on receiving any PRIVMSG at all.
@@ -3964,7 +4028,7 @@ and as second argument the event parsed as a vector."
               (string= target (erc-current-nick)))
           (not (erc-get-buffer query proc))
           (not (erc-is-message-ctcp-and-not-action-p msg))
-          (let ((erc-join-buffer erc-auto-query))
+          (let ((erc-query-display erc-auto-query))
             (erc-cmd-QUERY query))
           nil))))
 
@@ -4979,9 +5043,9 @@ each property to the corresponding value in VALUE-LIST."
     (setq value-list (mapcar (lambda (x)
                               t)
                             properties)))
-  (mapcar* (lambda (prop value)
-            (erc-put-text-property start end prop value object))
-          properties value-list))
+  (dotimes (i (min (length properties) (length value-list)))
+    (erc-put-text-property start end (nth i properties)
+                          (nth i value-list) object)))
 
 ;;; Input area handling:
 
@@ -5413,6 +5477,7 @@ If CHANNEL is non-nil, toggle MODE for that channel, otherwise use
   (save-excursion
     (let ((inhibit-read-only t))
       (set-text-properties start end nil object))))
+(put 'erc-remove-text-properties-region 'disabled t)
 
 ;; script execution and startup
 
@@ -5813,7 +5878,7 @@ See `current-time' for details on the time format."
 
 ;; Mode line handling
 
-(defcustom erc-mode-line-format "%s %a"
+(defcustom erc-mode-line-format "%S %a"
   "A string to be formatted and shown in the mode-line in `erc-mode'.
 
 The string is formatted using `format-spec' and the result is set as the value
@@ -5824,12 +5889,16 @@ The following characters are replaced:
 %l: The estimated lag time to the server
 %m: The modes of the channel
 %n: The current nick name
+%N: The name of the network
 %o: The topic of the channel
 %p: The session port
 %t: The name of the target (channel, nickname, or servername:port)
 %s: In the server-buffer, this gets filled with the value of
     `erc-server-announced-name', in a channel, the value of
-    (erc-default-target) also get concatenated."
+    (erc-default-target) also get concatenated.
+%S: In the server-buffer, this gets filled with the value of
+    `erc-network', in a channel, the value of (erc-default-target)
+    also get concatenated."
   :group 'erc-mode-line-and-header
   :type 'string)
 
@@ -5923,6 +5992,29 @@ This should be a string with substitution variables recognized by
          (server-name server-name)
          (t (buffer-name (current-buffer))))))
 
+(defun erc-format-network ()
+  "Return the name of the network we are currently on."
+  (let ((network (and (fboundp 'erc-network-name) (erc-network-name))))
+    (if (and network (symbolp network))
+       (symbol-name network)
+      "")))
+
+(defun erc-format-target-and/or-network ()
+  "Return the network or the current target and network combined.
+If the name of the network is not available, then use the
+shortened server name instead."
+  (let ((network-name (or (and (fboundp 'erc-network-name) (erc-network-name))
+                         (erc-shorten-server-name
+                          (or erc-server-announced-name
+                              erc-session-server)))))
+    (when (and network-name (symbolp network-name))
+      (setq network-name (symbol-name network-name)))
+    (cond ((erc-default-target)
+          (concat (erc-string-no-properties (erc-default-target))
+                  "@" network-name))
+         (network-name network-name)
+         (t (buffer-name (current-buffer))))))
+
 (defun erc-format-away-status ()
   "Return a formatted `erc-mode-line-away-status-format'
 if `erc-away' is non-nil."
@@ -5955,6 +6047,9 @@ if `erc-away' is non-nil."
     (cond (lag (format "lag:%.0f" lag))
          (t ""))))
 
+;; erc-goodies is required at end of this file.
+(declare-function erc-controls-strip "erc-goodies" (str))
+
 (defun erc-update-mode-line-buffer (buffer)
   "Update the mode line in a single ERC buffer BUFFER."
   (with-current-buffer buffer
@@ -5963,9 +6058,11 @@ if `erc-away' is non-nil."
                 ?l (erc-format-lag-time)
                 ?m (erc-format-channel-modes)
                 ?n (or (erc-current-nick) "")
+                ?N (erc-format-network)
                 ?o (erc-controls-strip erc-channel-topic)
                 ?p (erc-port-to-string erc-session-port)
                 ?s (erc-format-target-and/or-server)
+                ?S (erc-format-target-and/or-network)
                 ?t (erc-format-target)))
          (process-status (cond ((and (erc-server-process-alive)
                                      (not erc-server-connected))
@@ -6201,10 +6298,12 @@ All windows are opened in the current frame."
    (s252   . "%i operator(s) online")
    (s253   . "%i unknown connection(s)")
    (s254   . "%i channels formed")
+   (s275   . "%n %m")
    (s301   . "%n is AWAY: %r")
    (s303   . "Is online: %n")
    (s305   . "%m")
    (s306   . "%m")
+   (s307   . "%n %m")
    (s311   . "%n is %f (%u@%h)")
    (s312   . "%n is/was on server %s (%c)")
    (s313   . "%n is an IRC operator")