Merge changes from emacs-23
[bpt/emacs.git] / lisp / erc / erc-backend.el
index 1bb3e4a..46e9d6c 100644 (file)
@@ -1,6 +1,6 @@
 ;;; erc-backend.el --- Backend network communication for ERC
 
-;; Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+;; Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
 ;; Filename: erc-backend.el
 ;; Author: Lawrence Mitchell <wence@gmx.li>
@@ -9,10 +9,10 @@
 
 ;; This file is part of GNU Emacs.
 
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; 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 3, or (at your option)
-;; any later version.
+;; the Free Software Foundation, either version 3 of the License, 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
@@ -20,9 +20,7 @@
 ;; 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.
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 
@@ -132,6 +130,10 @@ Use `erc-current-nick' to access this.")
   "The server name used to connect to for this session.")
 (make-variable-buffer-local 'erc-session-server)
 
+(defvar erc-session-connector nil
+  "The function used to connect to this session (nil for the default).")
+(make-variable-buffer-local 'erc-session-connector)
+
 (defvar erc-session-port nil
   "The port used to connect to.")
 (make-variable-buffer-local 'erc-session-port)
@@ -540,8 +542,10 @@ Make sure you are in an ERC buffer when running this."
       (erc-set-active-buffer (current-buffer))
       (setq erc-server-last-sent-time 0)
       (setq erc-server-lines-sent 0)
-      (erc-open erc-session-server erc-session-port erc-server-current-nick
-                erc-session-user-full-name t erc-session-password))))
+      (let ((erc-server-connect-function (or erc-session-connector
+                                             'open-network-stream)))
+        (erc-open erc-session-server erc-session-port erc-server-current-nick
+                  erc-session-user-full-name t erc-session-password)))))
 
 (defun erc-server-filter-function (process string)
   "The process filter for the ERC server."
@@ -570,6 +574,7 @@ Make sure you are in an ERC buffer when running this."
                       nil
                     (substring erc-server-filter-data
                                (match-end 0))))
+            (erc-log-irc-protocol line nil)
             (erc-parse-server-response process line)))))))
 
 (defsubst erc-server-reconnect-p (event)
@@ -648,30 +653,31 @@ Conditionally try to reconnect and take appropriate action."
 
 (defun erc-process-sentinel (cproc event)
   "Sentinel function for ERC process."
-  (with-current-buffer (process-buffer cproc)
-    (erc-log (format
-              "SENTINEL: proc: %S       status: %S  event: %S (quitting: %S)"
-              cproc (process-status cproc) event erc-server-quitting))
-    (if (string-match "^open" event)
-        ;; newly opened connection (no wait)
-        (erc-login)
-      ;; assume event is 'failed
-      (let ((buf (process-buffer cproc)))
-        (erc-with-all-buffers-of-server cproc nil
-                                        (setq erc-server-connected nil))
-        (when erc-server-ping-handler
-          (progn (erc-cancel-timer erc-server-ping-handler)
-                 (setq erc-server-ping-handler nil)))
-        (run-hook-with-args 'erc-disconnected-hook
-                            (erc-current-nick) (system-name) "")
-        ;; Remove the prompt
-        (goto-char (or (marker-position erc-input-marker) (point-max)))
-        (forward-line 0)
-        (erc-remove-text-properties-region (point) (point-max))
-        (delete-region (point) (point-max))
-        ;; Decide what to do with the buffer
-        ;; Restart if disconnected
-        (erc-process-sentinel-1 event buf)))))
+  (let ((buf (process-buffer cproc)))
+    (when (buffer-live-p buf)
+      (with-current-buffer buf
+        (erc-log (format
+                  "SENTINEL: proc: %S   status: %S  event: %S (quitting: %S)"
+                  cproc (process-status cproc) event erc-server-quitting))
+        (if (string-match "^open" event)
+            ;; newly opened connection (no wait)
+            (erc-login)
+          ;; assume event is 'failed
+          (erc-with-all-buffers-of-server cproc nil
+                                          (setq erc-server-connected nil))
+          (when erc-server-ping-handler
+            (progn (erc-cancel-timer erc-server-ping-handler)
+                   (setq erc-server-ping-handler nil)))
+          (run-hook-with-args 'erc-disconnected-hook
+                              (erc-current-nick) (system-name) "")
+          ;; Remove the prompt
+          (goto-char (or (marker-position erc-input-marker) (point-max)))
+          (forward-line 0)
+          (erc-remove-text-properties-region (point) (point-max))
+          (delete-region (point) (point-max))
+          ;; Decide what to do with the buffer
+          ;; Restart if disconnected
+          (erc-process-sentinel-1 event buf))))))
 
 ;;;; Sending messages
 
@@ -1165,7 +1171,7 @@ add things to `%s' instead."
   (let ((target (first (erc-response.command-args parsed)))
         (chnl (erc-response.contents parsed)))
     (multiple-value-bind (nick login host)
-        (erc-parse-user (erc-response.sender parsed))
+        (values-list (erc-parse-user (erc-response.sender parsed)))
       (setq erc-invitation chnl)
       (when (string= target (erc-current-nick))
         (erc-display-message
@@ -1179,7 +1185,7 @@ add things to `%s' instead."
   (let ((chnl (erc-response.contents parsed))
         (buffer nil))
     (multiple-value-bind (nick login host)
-        (erc-parse-user (erc-response.sender parsed))
+        (values-list (erc-parse-user (erc-response.sender parsed)))
       ;; strip the stupid combined JOIN facility (IRC 2.9)
       (if (string-match "^\\(.*\\)?\^g.*$" chnl)
           (setq chnl (match-string 1 chnl)))
@@ -1190,7 +1196,7 @@ add things to `%s' instead."
                       (setq buffer (erc-open erc-session-server erc-session-port
                                              nick erc-session-user-full-name
                                              nil nil
-                                             erc-default-recipients chnl
+                                             (list chnl) chnl
                                              erc-server-process))
                       (when buffer
                         (set-buffer buffer)
@@ -1220,7 +1226,7 @@ add things to `%s' instead."
          (reason (erc-trim-string (erc-response.contents parsed)))
          (buffer (erc-get-buffer ch proc)))
     (multiple-value-bind (nick login host)
-        (erc-parse-user (erc-response.sender parsed))
+        (values-list (erc-parse-user (erc-response.sender parsed)))
       (erc-remove-channel-member buffer tgt)
       (cond
        ((string= tgt (erc-current-nick))
@@ -1247,7 +1253,7 @@ add things to `%s' instead."
         (mode (mapconcat 'identity (cdr (erc-response.command-args parsed))
                          " ")))
     (multiple-value-bind (nick login host)
-        (erc-parse-user (erc-response.sender parsed))
+        (values-list (erc-parse-user (erc-response.sender parsed)))
       (erc-log (format "MODE: %s -> %s: %s" nick tgt mode))
       ;; dirty hack
       (let ((buf (cond ((erc-channel-p tgt)
@@ -1272,7 +1278,7 @@ add things to `%s' instead."
   (let ((nn (erc-response.contents parsed))
         bufs)
     (multiple-value-bind (nick login host)
-        (erc-parse-user (erc-response.sender parsed))
+        (values-list (erc-parse-user (erc-response.sender parsed)))
       (setq bufs (erc-buffer-list-with-nick nick proc))
       (erc-log (format "NICK: %s -> %s" nick nn))
       ;; if we had a query with this user, make sure future messages will be
@@ -1310,7 +1316,7 @@ add things to `%s' instead."
          (reason (erc-trim-string (erc-response.contents parsed)))
          (buffer (erc-get-buffer chnl proc)))
     (multiple-value-bind (nick login host)
-        (erc-parse-user (erc-response.sender parsed))
+        (values-list (erc-parse-user (erc-response.sender parsed)))
       (erc-remove-channel-member buffer nick)
       (erc-display-message parsed 'notice buffer
                            'PART ?n nick ?u login
@@ -1418,7 +1424,7 @@ add things to `%s' instead."
   (let ((reason (erc-response.contents parsed))
         bufs)
     (multiple-value-bind (nick login host)
-        (erc-parse-user (erc-response.sender parsed))
+        (values-list (erc-parse-user (erc-response.sender parsed)))
       (setq bufs (erc-buffer-list-with-nick nick proc))
       (erc-remove-user nick)
       (setq reason (erc-wash-quit-reason reason nick login host))
@@ -1432,7 +1438,7 @@ add things to `%s' instead."
          (topic (erc-trim-string (erc-response.contents parsed)))
          (time (format-time-string "%T %m/%d/%y" (current-time))))
     (multiple-value-bind (nick login host)
-        (erc-parse-user (erc-response.sender parsed))
+        (values-list (erc-parse-user (erc-response.sender parsed)))
       (erc-update-channel-member ch nick nick nil nil nil host login)
       (erc-update-channel-topic ch (format "%s\C-o (%s, %s)" topic nick time))
       (erc-display-message parsed 'notice (erc-get-buffer ch proc)
@@ -1443,7 +1449,7 @@ add things to `%s' instead."
   "Display a WALLOPS message." nil
   (let ((message (erc-response.contents parsed)))
     (multiple-value-bind (nick login host)
-        (erc-parse-user (erc-response.sender parsed))
+        (values-list (erc-parse-user (erc-response.sender parsed)))
       (erc-display-message
        parsed 'notice nil
        'WALLOPS ?n nick ?m message))))
@@ -1473,7 +1479,7 @@ add things to `%s' instead."
 (define-erc-response-handler (004)
   "Display the server's identification." nil
   (multiple-value-bind (server-name server-version)
-      (cdr (erc-response.command-args parsed))
+      (values-list (cdr (erc-response.command-args parsed)))
     (setq erc-server-version server-version)
     (setq erc-server-announced-name server-name)
     (erc-update-mode-line-buffer (process-buffer proc))
@@ -1542,7 +1548,7 @@ See `erc-display-server-message'." nil
 (define-erc-response-handler (275)
   "Display secure connection message." nil
   (multiple-value-bind (nick user message)
-      (cdr (erc-response.command-args parsed))
+      (values-list (cdr (erc-response.command-args parsed)))
     (erc-display-message
      parsed 'notice 'active 's275
      ?n nick
@@ -1578,7 +1584,7 @@ See `erc-display-server-message'." nil
 (define-erc-response-handler (307)
   "Display nick-identified message." nil
   (multiple-value-bind (nick user message)
-      (cdr (erc-response.command-args parsed))
+      (values-list (cdr (erc-response.command-args parsed)))
     (erc-display-message
      parsed 'notice 'active 's307
      ?n nick
@@ -1590,7 +1596,7 @@ See `erc-display-server-message'." nil
   (let ((fname (erc-response.contents parsed))
         (catalog-entry (intern (format "s%s" (erc-response.command parsed)))))
     (multiple-value-bind (nick user host)
-        (cdr (erc-response.command-args parsed))
+        (values-list (cdr (erc-response.command-args parsed)))
       (erc-update-user-nick nick nick host nil fname user)
       (erc-display-message
        parsed 'notice 'active catalog-entry
@@ -1599,7 +1605,7 @@ See `erc-display-server-message'." nil
 (define-erc-response-handler (312)
   "Server name response in WHOIS." nil
   (multiple-value-bind (nick server-host)
-      (cdr (erc-response.command-args parsed))
+      (values-list (cdr (erc-response.command-args parsed)))
     (erc-display-message
      parsed 'notice 'active 's312
      ?n nick ?s server-host ?c (erc-response.contents parsed))))
@@ -1621,7 +1627,7 @@ See `erc-display-server-message'." nil
 (define-erc-response-handler (317)
   "IDLE notice." nil
   (multiple-value-bind (nick seconds-idle on-since time)
-      (cdr (erc-response.command-args parsed))
+      (values-list (cdr (erc-response.command-args parsed)))
     (setq time (when on-since
                  (format-time-string "%T %Y/%m/%d"
                                      (erc-string-to-emacs-time on-since))))
@@ -1662,7 +1668,7 @@ See `erc-display-server-message'." nil
   "LIST notice." nil
   (let ((topic (erc-response.contents parsed)))
     (multiple-value-bind (channel num-users)
-        (cdr (erc-response.command-args parsed))
+        (values-list (cdr (erc-response.command-args parsed)))
       (add-to-list 'erc-channel-list (list channel))
       (erc-update-channel-topic channel topic))))
 
@@ -1670,7 +1676,7 @@ See `erc-display-server-message'." nil
   "Display a message for the 322 event."
   (let ((topic (erc-response.contents parsed)))
     (multiple-value-bind (channel num-users)
-        (cdr (erc-response.command-args parsed))
+        (values-list (cdr (erc-response.command-args parsed)))
       (erc-display-message
        parsed 'notice proc 's322
        ?c channel ?u num-users ?t (or topic "")))))
@@ -1686,6 +1692,13 @@ See `erc-display-server-message'." nil
      parsed 'notice (erc-get-buffer channel proc)
      's324 ?c channel ?m modes)))
 
+(define-erc-response-handler (328)
+  "Channel URL (on freenode network)." nil
+  (let ((channel (second (erc-response.command-args parsed)))
+        (url (erc-response.contents parsed)))
+    (erc-display-message parsed 'notice (erc-get-buffer channel proc)
+                         's328 ?c channel ?u url)))
+
 (define-erc-response-handler (329)
   "Channel creation date." nil
   (let ((channel (second (erc-response.command-args parsed)))
@@ -1729,7 +1742,7 @@ See `erc-display-server-message'." nil
 (define-erc-response-handler (333)
   "Who set the topic, and when." nil
   (multiple-value-bind (channel nick time)
-      (cdr (erc-response.command-args parsed))
+      (values-list (cdr (erc-response.command-args parsed)))
     (setq time (format-time-string "%T %Y/%m/%d"
                                    (erc-string-to-emacs-time time)))
     (erc-update-channel-topic channel
@@ -1742,14 +1755,14 @@ See `erc-display-server-message'." nil
   "Let user know when an INVITE attempt has been sent successfully."
   nil
   (multiple-value-bind (nick channel)
-      (cdr (erc-response.command-args parsed))
+      (values-list (cdr (erc-response.command-args parsed)))
     (erc-display-message parsed 'notice (erc-get-buffer channel proc)
                          's341 ?n nick ?c channel)))
 
 (define-erc-response-handler (352)
   "WHO notice." nil
   (multiple-value-bind (channel user host server nick away-flag)
-      (cdr (erc-response.command-args parsed))
+      (values-list (cdr (erc-response.command-args parsed)))
     (let ((full-name (erc-response.contents parsed))
           hopcount)
       (when (string-match "\\(^[0-9]+ \\)\\(.*\\)$" full-name)
@@ -1779,7 +1792,7 @@ See `erc-display-server-message'." nil
 (define-erc-response-handler (367)
   "Channel ban list entries." nil
   (multiple-value-bind (channel banmask setter time)
-      (cdr (erc-response.command-args parsed))
+      (values-list (cdr (erc-response.command-args parsed)))
     ;; setter and time are not standard
     (if setter
         (erc-display-message parsed 'notice 'active 's367-set-by
@@ -1803,7 +1816,7 @@ See `erc-display-server-message'." nil
   ;; command takes two arguments, and doesn't have any "contents". --
   ;; Lawrence 2004/05/10
   (multiple-value-bind (from to)
-      (cdr (erc-response.command-args parsed))
+      (values-list (cdr (erc-response.command-args parsed)))
     (erc-display-message parsed 'notice 'active
                          's379 ?c from ?f to)))