]> code.delx.au - gnu-emacs/blobdiff - lisp/erc/erc-stamp.el
Face cleanups. Remove some uses of old-style face spec and :bold/:italic.
[gnu-emacs] / lisp / erc / erc-stamp.el
index afd070e4e068931b0b1ebf711a382d68912c28fd..5831233affedca012b2f32013d1d5c87fb3e49f6 100644 (file)
@@ -1,6 +1,6 @@
-;;; erc-stamp.el --- Timestamping for Emacs IRC CLient
+;;; erc-stamp.el --- Timestamping for ERC messages
 
-;; Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2004, 2006-2012  Free Software Foundation, Inc.
 
 ;; Author: Mario Lang <mlang@delysid.org>
 ;; Keywords: comm, processes, timestamp
@@ -8,10 +8,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 2, 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
@@ -19,9 +19,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:
 
@@ -49,7 +47,7 @@ in your .emacs file or interactively using `load-library'."
   :group 'erc)
 
 (defcustom erc-timestamp-format "[%H:%M]"
-  "*If set to a string, messages will be timestamped.
+  "If set to a string, messages will be timestamped.
 This string is processed using `format-time-string'.
 Good examples are \"%T\" and \"%H:%M\".
 
@@ -58,21 +56,53 @@ If nil, timestamping is turned off."
   :type '(choice (const nil)
                 (string)))
 
-(defcustom erc-insert-timestamp-function 'erc-insert-timestamp-right
-  "*Function to use to insert timestamps.
+(defcustom erc-timestamp-format-left "\n[%a %b %e %Y]\n"
+  "If set to a string, messages will be timestamped.
+This string is processed using `format-time-string'.
+Good examples are \"%T\" and \"%H:%M\".
+
+This timestamp is used for timestamps on the left side of the
+screen when `erc-insert-timestamp-function' is set to
+`erc-insert-timestamp-left-and-right'.
+
+If nil, timestamping is turned off."
+  :group 'erc-stamp
+  :type '(choice (const nil)
+                (string)))
+
+(defcustom erc-timestamp-format-right " [%H:%M]"
+  "If set to a string, messages will be timestamped.
+This string is processed using `format-time-string'.
+Good examples are \"%T\" and \"%H:%M\".
+
+This timestamp is used for timestamps on the right side of the
+screen when `erc-insert-timestamp-function' is set to
+`erc-insert-timestamp-left-and-right'.
+
+If nil, timestamping is turned off."
+  :group 'erc-stamp
+  :type '(choice (const nil)
+                (string)))
+
+(defcustom erc-insert-timestamp-function 'erc-insert-timestamp-left-and-right
+  "Function to use to insert timestamps.
 
 It takes a single argument STRING which is the final string
 which all text-properties already appended.  This function only cares about
 inserting this string at the right position.  Narrowing is in effect
 while it is called, so (point-min) and (point-max) determine the region to
-operate on."
+operate on.
+
+You will probably want to set
+`erc-insert-away-timestamp-function' to the same value."
   :group 'erc-stamp
-  :type '(choice (const :tag "Right" erc-insert-timestamp-right)
+  :type '(choice (const :tag "Both sides" erc-insert-timestamp-left-and-right)
+                (const :tag "Right" erc-insert-timestamp-right)
                 (const :tag "Left" erc-insert-timestamp-left)
                 function))
 
 (defcustom erc-away-timestamp-format "<%H:%M>"
-  "*Timestamp format used when marked as being away.
+  "Timestamp format used when marked as being away.
 
 If nil, timestamping is turned off when away unless `erc-timestamp-format'
 is set.
@@ -82,17 +112,19 @@ If `erc-timestamp-format' is set, this will not be used."
   :type '(choice (const nil)
                 (string)))
 
-(defcustom erc-insert-away-timestamp-function 'erc-insert-timestamp-right
-  "*Function to use to insert the away timestamp.
+(defcustom erc-insert-away-timestamp-function
+  'erc-insert-timestamp-left-and-right
+  "Function to use to insert the away timestamp.
 
 See `erc-insert-timestamp-function' for details."
   :group 'erc-stamp
-  :type '(choice (const :tag "Right" erc-insert-timestamp-right)
+  :type '(choice (const :tag "Both sides" erc-insert-timestamp-left-and-right)
+                (const :tag "Right" erc-insert-timestamp-right)
                 (const :tag "Left" erc-insert-timestamp-left)
                 function))
 
 (defcustom erc-hide-timestamps nil
-  "*If non-nil, timestamps will be invisible.
+  "If non-nil, timestamps will be invisible.
 
 This is useful for logging, because, although timestamps will be
 hidden, they will still be present in the logs."
@@ -100,7 +132,7 @@ hidden, they will still be present in the logs."
   :type 'boolean)
 
 (defcustom erc-echo-timestamps nil
-  "*If non-nil, print timestamp in the minibuffer when point is moved.
+  "If non-nil, print timestamp in the minibuffer when point is moved.
 Using this variable, you can turn off normal timestamping,
 and simply move point to an irc message to see its timestamp
 printed in the minibuffer."
@@ -108,19 +140,19 @@ printed in the minibuffer."
   :type 'boolean)
 
 (defcustom erc-echo-timestamp-format "Timestamped %A, %H:%M:%S"
-  "*Format string to be used when `erc-echo-timestamps' is non-nil.
+  "Format string to be used when `erc-echo-timestamps' is non-nil.
 This string specifies the format of the timestamp being echoed in
 the minibuffer."
   :group 'erc-stamp
   :type 'string)
 
 (defcustom erc-timestamp-intangible t
-  "*Whether the timestamps should be intangible, i.e. prevent the point
+  "Whether the timestamps should be intangible, i.e. prevent the point
 from entering them and instead jump over them."
   :group 'erc-stamp
   :type 'boolean)
 
-(defface erc-timestamp-face '((t (:bold t :foreground "green")))
+(defface erc-timestamp-face '((t :weight bold :foreground "green"))
   "ERC timestamp face."
   :group 'erc-faces)
 
@@ -147,7 +179,7 @@ or `erc-send-modify-hook'."
        (error "Timestamp function unbound"))
       (when (and (fboundp erc-insert-away-timestamp-function)
                 erc-away-timestamp-format
-                (with-current-buffer (erc-server-buffer) erc-away)
+                (erc-away-time)
                 (not erc-timestamp-format))
        (funcall erc-insert-away-timestamp-function
                 (erc-format-timestamp ct erc-away-timestamp-format)))
@@ -160,8 +192,20 @@ or `erc-send-modify-hook'."
   "Last timestamp inserted into the buffer.")
 (make-variable-buffer-local 'erc-timestamp-last-inserted)
 
+(defvar erc-timestamp-last-inserted-left nil
+  "Last timestamp inserted into the left side of the buffer.
+This is used when `erc-insert-timestamp-function' is set to
+`erc-timestamp-left-and-right'")
+(make-variable-buffer-local 'erc-timestamp-last-inserted-left)
+
+(defvar erc-timestamp-last-inserted-right nil
+  "Last timestamp inserted into the right side of the buffer.
+This is used when `erc-insert-timestamp-function' is set to
+`erc-timestamp-left-and-right'")
+(make-variable-buffer-local 'erc-timestamp-last-inserted-right)
+
 (defcustom erc-timestamp-only-if-changed-flag t
-  "*Insert timestamp only if its value changed since last insertion.
+  "Insert timestamp only if its value changed since last insertion.
 If `erc-insert-timestamp-function' is `erc-insert-timestamp-left', a
 string of spaces which is the same size as the timestamp is added to
 the beginning of the line in its place. If you use
@@ -171,7 +215,7 @@ timestamp."
   :type 'boolean)
 
 (defcustom erc-timestamp-right-column nil
-  "*If non-nil, the column at which the timestamp is inserted,
+  "If non-nil, the column at which the timestamp is inserted,
 if the timestamp is to be printed to the right.  If nil,
 `erc-insert-timestamp-right' will use other means to determine
 the correct column."
@@ -180,11 +224,17 @@ the correct column."
          (integer :tag "Column number")
          (const :tag "Unspecified" nil)))
 
-(defcustom erc-timestamp-right-align-by-pixel nil
-  "*If non-nil, insert the right timestamp based on a pixel value.
-This is needed when variable-width text precedes a timestamp.
+(defcustom erc-timestamp-use-align-to (and (not (featurep 'xemacs))
+                                          (>= emacs-major-version 22)
+                                          (eq window-system 'x))
+  "If non-nil, use the :align-to display property to align the stamp.
+This gives better results when variable-width characters (like
+Asian language characters and math symbols) precede a timestamp.
 Unfortunately, it only works in Emacs 22 and when using the X
-Window System."
+Window System.
+
+A side effect of enabling this is that there will only be one
+space before a right timestamp in any saved logs."
   :group 'erc-stamp
   :type 'boolean)
 
@@ -197,22 +247,23 @@ Window System."
         (s (if ignore-p (make-string len ? ) string)))
     (unless ignore-p (setq erc-timestamp-last-inserted string))
     (erc-put-text-property 0 len 'field 'erc-timestamp s)
+    (erc-put-text-property 0 len 'invisible 'timestamp s)
     (insert s)))
 
-(defun erc-insert-aligned (string pos &optional fallback)
-  "Insert STRING based on a fraction of the width of the buffer.
-Fraction is roughly (/ POS (window-width)).
+(defun erc-insert-aligned (string pos)
+  "Insert STRING at the POSth column.
 
-If `erc-timestamp-right-align-by-pixel' is nil, use
-\(- POS FALLBACK) to determine how many spaces to insert."
-  (if (not erc-timestamp-right-align-by-pixel)
-      (insert (make-string (- pos fallback) ? ) string)
+If `erc-timestamp-use-align-to' is t, use the :align-to display
+property to get to the POSth column."
+  (if (not erc-timestamp-use-align-to)
+      (indent-to pos)
     (insert " ")
-    (let ((offset (floor (* (/ (1- pos) (window-width) 1.0)
-                           (nth 2 (window-inside-pixel-edges))))))
-      (put-text-property (1- (point)) (point) 'display
-                        `(space :align-to (,offset))))
-    (insert string)))
+    (put-text-property (1- (point)) (point) 'display
+                      (list 'space ':align-to pos)))
+  (insert string))
+
+;; Silence byte-compiler
+(defvar erc-fill-column)
 
 (defun erc-insert-timestamp-right (string)
   "Insert timestamp on the right side of the screen.
@@ -237,40 +288,57 @@ be printed just before the window-width."
     (goto-char (point-max))
     (forward-char -1);; before the last newline
     (let* ((current-window (get-buffer-window (current-buffer)))
+          (str-width (string-width string))
           (pos (cond
-                (erc-timestamp-right-column
-                 (+ erc-timestamp-right-column (length string)))
+                (erc-timestamp-right-column erc-timestamp-right-column)
                 ((and (boundp 'erc-fill-mode)
                       erc-fill-mode
-                      (boundp 'erc-fill-column))
-                 (1+ erc-fill-column))
-                (current-window
-                 (- (window-width current-window)
-                    1))
+                      (boundp 'erc-fill-column)
+                      erc-fill-column)
+                 (1+ (- erc-fill-column str-width)))
                 (fill-column
-                 (1+ fill-column))
+                 (1+ (- fill-column str-width)))
                 (t
-                 (- (window-width)
-                    1))))
+                 (- (window-width) str-width 1))))
           (from (point))
           (col (current-column))
           indent)
-      ;; deal with variable-width characters
-      (setq pos (- pos (string-width string))
-           ;; the following is a kludge that works with most
-           ;; international input
-           col (+ col (ceiling (/ (- col (- (point) (point-at-bol))) 1.6))))
+      ;; The following is a kludge used to calculate whether to move
+      ;; to the next line before inserting a stamp.  It allows for
+      ;; some margin of error if what is displayed on the line differs
+      ;; from the number of characters on the line.
+      (setq col (+ col (ceiling (/ (- col (- (point) (point-at-bol))) 1.6))))
       (if (< col pos)
-         (erc-insert-aligned string pos col)
+         (erc-insert-aligned string pos)
        (newline)
-       (setq from (point))
        (indent-to pos)
+       (setq from (point))
        (insert string))
-      (erc-put-text-property from (1+ (point)) 'field 'erc-timestamp)
-      (erc-put-text-property from (1+ (point)) 'rear-nonsticky t)
+      (erc-put-text-property from (point) 'field 'erc-timestamp)
+      (erc-put-text-property from (point) 'rear-nonsticky t)
       (when erc-timestamp-intangible
        (erc-put-text-property from (1+ (point)) 'intangible t)))))
 
+(defun erc-insert-timestamp-left-and-right (string)
+  "This is another function that can be assigned to
+`erc-insert-timestamp-function'.  If the date is changed, it will
+print a blank line, the date, and another blank line.  If the time is
+changed, it will then print it off to the right."
+  (let* ((ct (current-time))
+        (ts-left (erc-format-timestamp ct erc-timestamp-format-left))
+        (ts-right (erc-format-timestamp ct erc-timestamp-format-right)))
+    ;; insert left timestamp
+    (unless (string-equal ts-left erc-timestamp-last-inserted-left)
+      (goto-char (point-min))
+      (erc-put-text-property 0 (length ts-left) 'field 'erc-timestamp ts-left)
+      (insert ts-left)
+      (setq erc-timestamp-last-inserted-left ts-left))
+    ;; insert right timestamp
+    (let ((erc-timestamp-only-if-changed-flag t)
+         (erc-timestamp-last-inserted erc-timestamp-last-inserted-right))
+      (erc-insert-timestamp-right ts-right)
+      (setq erc-timestamp-last-inserted-right ts-right))))
+
 ;; for testing: (setq erc-timestamp-only-if-changed-flag nil)
 
 (defun erc-format-timestamp (time format)
@@ -319,6 +387,21 @@ set, and timestamping is already active."
   (setq erc-hide-timestamps nil)
   (erc-munge-invisibility-spec))
 
+(defun erc-toggle-timestamps ()
+  "Hide or show timestamps in ERC buffers.
+
+Note that timestamps can only be shown for a message using this
+function if `erc-timestamp-format' was set and timestamping was
+enabled when the message was inserted."
+  (interactive)
+  (if erc-hide-timestamps
+      (setq erc-hide-timestamps nil)
+    (setq erc-hide-timestamps t))
+  (mapc (lambda (buffer)
+         (with-current-buffer buffer
+           (erc-munge-invisibility-spec)))
+       (erc-buffer-list)))
+
 (defun erc-echo-timestamp (before now)
   "Print timestamp text-property of an IRC message.
 Argument BEFORE is where point was before it got moved and
@@ -326,8 +409,8 @@ NOW is position of point currently."
   (when erc-echo-timestamps
     (let ((stamp (get-text-property now 'timestamp)))
       (when stamp
-       (message (format-time-string erc-echo-timestamp-format
-                                    stamp))))))
+       (message "%s" (format-time-string erc-echo-timestamp-format
+                                         stamp))))))
 
 (provide 'erc-stamp)
 
@@ -338,4 +421,3 @@ NOW is position of point currently."
 ;; tab-width: 8
 ;; End:
 
-;; arch-tag: 9f6d31bf-61ba-45c5-bdbf-56331486ea27