diff options
author | Miles Bader <miles@gnu.org> | 2006-01-29 13:08:58 +0000 |
---|---|---|
committer | Miles Bader <miles@gnu.org> | 2006-01-29 13:08:58 +0000 |
commit | 597993cf4433604ea65e40d33ad6cfe83dab2fb7 (patch) | |
tree | 9e9cc6dbc0968bc83d7657c17ecade6b56691f89 /lisp/erc/erc-log.el | |
parent | 33c7860d38eb0f5416630b54a7a1b878810a5d3b (diff) | |
download | emacs-597993cf4433604ea65e40d33ad6cfe83dab2fb7.tar.gz |
Revision: emacs@sv.gnu.org/emacs--devo--0--patch-22
Creator: Michael Olson <mwolson@gnu.org>
Install ERC.
Diffstat (limited to 'lisp/erc/erc-log.el')
-rw-r--r-- | lisp/erc/erc-log.el | 358 |
1 files changed, 358 insertions, 0 deletions
diff --git a/lisp/erc/erc-log.el b/lisp/erc/erc-log.el new file mode 100644 index 00000000000..d4e6e5ad3fa --- /dev/null +++ b/lisp/erc/erc-log.el @@ -0,0 +1,358 @@ +;;; erc-log.el --- Logging facilities for ERC. + +;; Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + +;; Author: Lawrence Mitchell <wence@gmx.li> +;; Keywords: IRC, chat, client, Internet, logging + +;; Created 2003-04-26 +;; Logging code taken from erc.el and modified to use markers. + +;; This file is part of GNU Emacs. + +;; 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 implements log file writing support for ERC. + +;; Quick start: +;; +;; (setq erc-enable-logging t) +;; (setq erc-log-channels-directory "/path/to/logfiles") ; must be writable +;; +;; 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". +;; +;; The second method will save buffers on /part, /quit, or killing the +;; channel buffer. To do this, add the following to your .emacs: +;; +;; (require 'erc-log) +;; +;; You may optionally want the following code, to save all ERC buffers +;; without confirmation when exiting emacs: +;; +;; (defadvice save-buffers-kill-emacs (before save-logs (&rest args) activate) +;; (save-some-buffers t (lambda () +;; (when (and (eq major-mode 'erc-mode) +;; (not (null buffer-file-name))) t)))) +;; +;; If you only want to save logs for some buffers, customise the +;; variable `erc-enable-logging'. + +;; How it works: +;; +;; If logging is enabled, at some point, `erc-save-buffer-in-logs' +;; will be called. The "end" of the buffer is taken from +;; `erc-insert-marker', while `erc-last-saved-position' holds the +;; position the buffer was last saved at (as a marker, or if the +;; buffer hasn't been saved before, as the number 1 (point-min)). + +;; The region between `erc-last-saved-position' and +;; `erc-insert-marker' is saved to the current buffer's logfile, and +;; `erc-last-saved-position' is updated to reflect this. + +;;; History: +;; 2003-04-26: logging code pulled out of erc.el. Switched to using +;; markers. + +;;; TODO: +;; * Erc needs a generalised make-safe-file-name function, so that +;; generated file names don't contain any invalid file characters. +;; +;; * Really, we need to lock the logfiles somehow, so that if a user +;; is running multiple emacsen and/or on the same channel as more +;; than one user, only one process writes to the logfile. This is +;; especially needed for those logfiles with no nick in them, as +;; these would become corrupted. +;; For a single emacs process, the problem could be solved using a +;; variable which contained the names of buffers already being +;; logged. This would require that logging be buffer-local, +;; possibly not a bad thing anyway, since many people don't want to +;; log the server buffer. +;; For multiple emacsen the problem is trickier. On some systems, +;; on could use the function `lock-buffer' and `unlock-buffer'. +;; However, file locking isn't implemented on all platforms, for +;; example, there is none on w32 systems. +;; A third possibility might be to fake lockfiles. However, this +;; might lead to problems if an emacs crashes, as the lockfile +;; would be left lying around. + +;;; Code: + +(require 'erc) +(eval-when-compile (require 'cl)) + +(defgroup erc-log nil + "Logging facilities for ERC." + :group 'erc) + +(defcustom erc-generate-log-file-name-function 'erc-generate-log-file-name-long + "*A function to generate a log filename. +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'." + :group 'erc-log + :type '(choice (const erc-generate-log-file-name-long) + (const erc-generate-log-file-name-short) + (const erc-generate-log-file-name-with-date) + (symbol))) + +(defcustom erc-save-buffer-on-part nil + "*Save the channel buffer content using `erc-save-buffer-in-logs' on PART." + :group 'erc-log + :type 'boolean) + +(defcustom erc-truncate-buffer-on-save nil + "Truncate any ERC (channel, query, server) buffer when it is saved." + :group 'erc-log + :type 'boolean) + +(defcustom erc-enable-logging t + "If non-nil, ERC will log IRC conversations. +This can either be a boolean value of nil or t, or a function. +If the value is a function, it will be called with one argument, the +name of the current ERC buffer. One possible function, which saves +all but server buffers is `erc-log-all-but-server-buffers'. + +This variable is buffer local. Setting it via \\[customize] sets the +default value. + +Log files are stored in `erc-log-channels-directory'." + :group 'erc-log + :type '(choice boolean + function)) +(make-variable-buffer-local 'erc-enable-logging) + +(defcustom erc-log-channels-directory "~/log" + "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." + :group 'erc-log + :type '(choice directory + (const nil))) + +(defcustom erc-log-insert-log-on-open t + "*Insert log file contents into the buffer if a log file exists." + :group 'erc-log + :type 'boolean) + +(defcustom erc-save-queries-on-quit nil + "Save all query (also channel) buffers of the server on QUIT. +See the variable `erc-save-buffer-on-part' for details." + :group 'erc-log + :type 'boolean) + +(defcustom erc-log-file-coding-system (if (featurep 'xemacs) + 'binary + 'emacs-mule) + "*The coding system ERC should use for writing log files. + +This should ideally, be a \"catch-all\" coding system, like +`emacs-mule', or `iso-2022-7bit'." + :group 'erc-log) + +;;;###autoload (autoload 'erc-log-mode "erc-log" nil t) +(define-erc-module log nil + "Automatically logs things you receive on IRC into files. +Files are stored in `erc-log-channels-directory'; file name +format is defined through a formatting function on +`erc-generate-log-file-name-function'. + +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: + +\(setq erc-enable-logging + (lambda (buffer) + (with-current-buffer buffer + (not erc-away))))" + ;; enable + ((add-hook 'erc-insert-post-hook + 'erc-save-buffer-in-logs) + (add-hook 'erc-send-post-hook + 'erc-save-buffer-in-logs)) + ;; disable + ((remove-hook 'erc-insert-post-hook + 'erc-save-buffer-in-logs) + (remove-hook 'erc-send-post-hook + 'erc-save-buffer-in-logs))) + +(when erc-enable-logging + (add-hook 'erc-kill-buffer-hook + 'erc-save-buffer-in-logs) + (add-hook 'erc-kill-channel-hook + 'erc-save-buffer-in-logs) + (add-hook 'erc-quit-hook + 'erc-conditional-save-queries) + (add-hook 'erc-part-hook + 'erc-conditional-save-buffer)) + +(define-key erc-mode-map "\C-c\C-l" 'erc-save-buffer-in-logs) + +;;;functionality referenced from erc.el +(defun erc-log-setup-logging () + "Setup the buffer-local logging variables in the current buffer. +This function is destined to be run from `erc-connect-pre-hook'." + (when (erc-logging-enabled) + (auto-save-mode -1) + (setq buffer-offer-save t + buffer-file-name "") + (set (make-local-variable '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 + (1- (point-max))))))) + +;;; Append, so that 'erc-initialize-log-marker keeps running first. +(add-hook 'erc-connect-pre-hook 'erc-log-setup-logging 'append) + +(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." + (save-excursion + (save-window-excursion + (set-buffer buffer) + (not (erc-server-buffer-p))))) + +(defun erc-save-query-buffers (process) + "Save all buffers process." + (erc-with-all-buffers-of-server process + nil + (erc-save-buffer-in-logs))) + +(defun erc-conditional-save-buffer (buffer) + "Save Query BUFFER if `erc-save-queries-on-quit' is t." + (when erc-save-buffer-on-part + (erc-save-buffer-in-logs buffer))) + +(defun erc-conditional-save-queries (process) + "Save Query buffers of PROCESS if `erc-save-queries-on-quit' is t." + (when erc-save-queries-on-quit + (erc-save-query-buffers process))) + +;;;###autoload +(defun erc-logging-enabled (&optional buffer) + "Return non-nil if logging is enabled for BUFFER. +If BUFFER is nil, the value of `current-buffer' is used. +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) + (if (functionp erc-enable-logging) + (funcall erc-enable-logging (or buffer (current-buffer))) + erc-enable-logging))) + +(defun erc-current-logfile (&optional buffer) + "Return the logfile to use for BUFFER. +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 + (downcase (funcall erc-generate-log-file-name-function + (or buffer (current-buffer)) + (or (erc-default-target) (buffer-name buffer)) + (erc-current-nick) + erc-session-server erc-session-port)) + erc-log-channels-directory)) + +(defun erc-generate-log-file-name-with-date (buffer &rest ignore) + "This function computes a short log file name. +The name of the log file is composed of BUFFER and the current date. +This function is a possible value for `erc-generate-log-file-name-function'." + (concat (buffer-name buffer) "-" (format-time-string "%Y-%m-%d") ".txt")) + +(defun erc-generate-log-file-name-short (buffer &rest ignore) + "This function computes a short log file name. +In fact, it only uses the buffer name of the BUFFER argument, so +you can affect that using `rename-buffer' and the-like. This +function is a possible value for +`erc-generate-log-file-name-function'." + (concat (buffer-name buffer) ".txt")) + +(defun erc-generate-log-file-name-long (buffer target nick server port) + "Generates a log-file name in the way ERC always did it. +This results in a file name of the form #channel!nick@server:port.txt. +This function is a possible value for `erc-generate-log-file-name-function'." + (let ((file (concat + (if target (concat target "!")) + nick "@" server ":" (cond ((stringp port) port) + ((numberp port) + (number-to-string port))) ".txt"))) + ;; we need a make-safe-file-name function. + (convert-standard-filename file))) + +;;;###autoload +(defun erc-save-buffer-in-logs (&optional buffer) + "Append BUFFER contents to the log file, if logging is enabled. +If BUFFER is not provided, current buffer is used. +Logging is enabled if `erc-logging-enabled' returns non-nil. + +This is normally done on exit, to save the unsaved portion of the +buffer, since only the text that runs off the buffer limit is logged +automatically. + +You can save every individual message by putting this function on +`erc-insert-post-hook'." + (interactive) + (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)) + (save-excursion + (with-current-buffer buffer + (save-restriction + (widen) + ;; early on in the initalisation, 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) + (if (and erc-truncate-buffer-on-save (interactive-p)) + (progn + (let ((inhibit-read-only t)) (erase-buffer)) + (move-marker erc-last-saved-position (point-max)) + (erc-display-prompt)) + (move-marker erc-last-saved-position + ;; If we place erc-last-saved-position at + ;; erc-insert-marker, because text gets + ;; inserted /before/ erc-insert-marker, + ;; the log file will not be saved + ;; (erc-last-saved-position will always + ;; be equal to erc-insert-marker). + (1- (marker-position erc-insert-marker))))) + (set-buffer-modified-p nil)))))) + t) + +(provide 'erc-log) + +;;; erc-log.el ends here +;; +;; Local Variables: +;; indent-tabs-mode: t +;; tab-width: 8 +;; End: + +;; arch-tag: 54072f99-9f0a-4846-8908-2ccde92221de |