Add 2010 to copyright years.
[bpt/emacs.git] / lisp / erc / erc-log.el
index 194f8ae..98e58a3 100644 (file)
@@ -1,6 +1,6 @@
 ;;; erc-log.el --- Logging facilities for ERC.
 
-;; Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
 ;; Author: Lawrence Mitchell <wence@gmx.li>
 ;; Keywords: IRC, chat, client, Internet, logging
 
 ;; 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
@@ -21,9 +21,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:
 
 
 ;; Quick start:
 ;;
-;; (setq erc-enable-logging t)
+;; (require 'erc-log)
 ;; (setq erc-log-channels-directory "/path/to/logfiles") ; must be writable
+;; (erc-log-enable)
 ;;
-;; There are two ways to setup logging. The first will write to the log files
-;; on each incoming or outgoing line - this may not be optimal on a laptop
-;; HDD. To do this, M-x customize-variable erc-modules, and add "log".
+;; Or:
 ;;
-;; The second method will save buffers on /part, /quit, or killing the
-;; channel buffer. To do this, add the following to your .emacs:
+;; M-x customize-variable erc-modules, and add "log".
 ;;
-;; (require 'erc-log)
+;; There are two ways to setup logging.  The first (default) method
+;; will save buffers on /part, /quit, or killing the channel
+;; buffer.
+;;
+;; The second will write to the log files on each incoming or outgoing
+;; line - this may not be optimal on a laptop HDD.  To use this
+;; method, add the following to the above instructions.
+;;
+;; (setq erc-save-buffer-on-part nil
+;;       erc-save-queries-on-quit nil
+;;       erc-log-write-after-send t
+;;       erc-log-write-after-insert t)
 ;;
 ;; If you only want to save logs for some buffers, customise the
 ;; variable `erc-enable-logging'.
@@ -99,15 +106,19 @@ The function must take five arguments: BUFFER, TARGET, NICK, SERVER and PORT.
 BUFFER is the buffer to be saved,
 TARGET is the name of the channel, or the target of the query,
 NICK is the current nick,
-SERVER and PORT are the parameters used to connect BUFFERs
-`erc-server-process'."
+SERVER and PORT are the parameters that were used to connect to BUFFERs
+`erc-server-process'.
+
+If you want to write logs into different directories, make a
+custom function which returns the directory part and set
+`erc-log-channels-directory' to its name."
   :group 'erc-log
   :type '(choice (const :tag "Long style" erc-generate-log-file-name-long)
                 (const :tag "Long, but with network name rather than server"
                        erc-generate-log-file-name-network)
                 (const :tag "Short" erc-generate-log-file-name-short)
                 (const :tag "With date" erc-generate-log-file-name-with-date)
-                (symbol :tag "Other function")))
+                (function :tag "Other function")))
 
 (defcustom erc-truncate-buffer-on-save nil
   "Truncate any ERC (channel, query, server) buffer when it is saved."
@@ -134,10 +145,16 @@ Log files are stored in `erc-log-channels-directory'."
   "The directory to place log files for channels.
 Leave blank to disable logging.  If not nil, all the channel
 buffers are logged in separate files in that directory.  The
-directory should not end with a trailing slash."
+directory should not end with a trailing slash.
+
+If this is the name of a function, the function will be called
+with the buffer, target, nick, server, and port arguments.  See
+`erc-generate-log-file-name-function' for a description of these
+arguments."
   :group 'erc-log
   :type '(choice directory
-                (const nil)))
+                (function "Function")
+                (const :tag "Disable logging" nil)))
 
 (defcustom erc-log-insert-log-on-open nil
   "*Insert log file contents into the buffer if a log file exists."
@@ -186,6 +203,16 @@ This should ideally, be a \"catch-all\" coding system, like
 `emacs-mule', or `iso-2022-7bit'."
   :group 'erc-log)
 
+(defcustom erc-log-filter-function nil
+  "*If non-nil, pass text through the given function before writing it to
+a log file.
+
+The function should take one argument, which is the text to filter."
+  :group 'erc-log
+  :type '(choice (function "Function")
+                (const :tag "No filtering" nil)))
+
+
 ;;;###autoload (autoload 'erc-log-mode "erc-log" nil t)
 (define-erc-module log nil
   "Automatically logs things you receive on IRC into files.
@@ -195,8 +222,8 @@ format is defined through a formatting function on
 
 Since automatic logging is not always a Good Thing (especially if
 people say things in different coding systems), you can turn logging
-behaviour on and off with the variable `erc-enable-logging', which can
-also be a predicate function. To only log when you are not set away, use:
+behavior on and off with the variable `erc-enable-logging', which can
+also be a predicate function.  To only log when you are not set away, use:
 
 \(setq erc-enable-logging
       (lambda (buffer)
@@ -239,14 +266,7 @@ The current buffer is given by BUFFER."
     (with-current-buffer buffer
       (auto-save-mode -1)
       (setq buffer-file-name nil)
-      (cond ((boundp 'write-file-functions)
-            (set (make-local-variable 'write-file-functions)
-                 '(erc-save-buffer-in-logs)))
-           ((boundp 'local-write-file-hooks)
-            (setq local-write-file-hooks '(erc-save-buffer-in-logs)))
-           (t
-            (set (make-local-variable 'write-file-hooks)
-                 '(erc-save-buffer-in-logs))))
+      (erc-set-write-file-functions '(erc-save-buffer-in-logs))
       (when erc-log-insert-log-on-open
        (ignore-errors (insert-file-contents (erc-current-logfile))
                       (move-marker erc-last-saved-position
@@ -261,7 +281,7 @@ The current buffer is given by BUFFER."
 
 (defun erc-log-all-but-server-buffers (buffer)
   "Returns t if logging should be enabled in BUFFER.
-Returns nil iff `erc-server-buffer-p' returns t."
+Returns nil if `erc-server-buffer-p' returns t."
   (save-excursion
     (save-window-excursion
       (set-buffer buffer)
@@ -297,7 +317,8 @@ Logging is enabled if `erc-log-channels-directory' is non-nil, the directory
 is writeable (it will be created as necessary) and
 `erc-enable-logging' returns a non-nil value."
   (and erc-log-channels-directory
-       (erc-directory-writable-p erc-log-channels-directory)
+       (or (functionp erc-log-channels-directory)
+          (erc-directory-writable-p erc-log-channels-directory))
        (if (functionp erc-enable-logging)
           (funcall erc-enable-logging (or buffer (current-buffer)))
         erc-enable-logging)))
@@ -316,14 +337,19 @@ filename is downcased."
 If BUFFER is nil, the value of `current-buffer' is used.
 This is determined by `erc-generate-log-file-name-function'.
 The result is converted to lowercase, as IRC is case-insensitive"
-  (expand-file-name
-   (erc-log-standardize-name
-    (funcall erc-generate-log-file-name-function
-            (or buffer (current-buffer))
-            (or (buffer-name buffer) (erc-default-target))
-            (erc-current-nick)
-            erc-session-server erc-session-port))
-   erc-log-channels-directory))
+  (unless buffer (setq buffer (current-buffer)))
+  (let ((target (or (buffer-name buffer) (erc-default-target)))
+       (nick (erc-current-nick))
+       (server erc-session-server)
+       (port erc-session-port))
+    (expand-file-name
+     (erc-log-standardize-name
+      (funcall erc-generate-log-file-name-function
+              buffer target nick server port))
+     (if (functionp erc-log-channels-directory)
+        (funcall erc-log-channels-directory
+                 buffer target nick server port)
+       erc-log-channels-directory))))
 
 (defun erc-generate-log-file-name-with-date (buffer &rest ignore)
   "This function computes a short log file name.
@@ -380,17 +406,26 @@ You can save every individual message by putting this function on
   (or buffer (setq buffer (current-buffer)))
   (when (erc-logging-enabled buffer)
     (let ((file (erc-current-logfile buffer))
-         (coding-system-for-write erc-log-file-coding-system))
+         (coding-system erc-log-file-coding-system)
+         (inhibit-clash-detection t))  ; needed for XEmacs
       (save-excursion
        (with-current-buffer buffer
          (save-restriction
            (widen)
-           ;; early on in the initalisation, don't try and write the log out
+           ;; early on in the initialization, don't try and write the log out
            (when (and (markerp erc-last-saved-position)
                       (> erc-insert-marker (1+ erc-last-saved-position)))
-             (write-region (1+ (marker-position erc-last-saved-position))
-                           (marker-position erc-insert-marker)
-                           file t 'nomessage)
+             (let ((start (1+ (marker-position erc-last-saved-position)))
+                   (end (marker-position erc-insert-marker)))
+               (if (functionp erc-log-filter-function)
+                   (let ((text (buffer-substring start end)))
+                     (with-temp-buffer
+                       (insert (funcall erc-log-filter-function text))
+                       (let ((coding-system-for-write coding-system))
+                         (write-region (point-min) (point-max)
+                                       file t 'nomessage))))
+                 (let ((coding-system-for-write coding-system))
+                   (write-region start end file t 'nomessage))))
              (if (and erc-truncate-buffer-on-save (interactive-p))
                  (progn
                    (let ((inhibit-read-only t)) (erase-buffer))