*** empty log message ***
[bpt/emacs.git] / lisp / autorevert.el
index 361a11a..2cca9b0 100644 (file)
@@ -1,6 +1,7 @@
 ;;; autorevert.el --- revert buffers when files on disk change
 
-;; Copyright (C) 1997, 1998, 1999, 2001, 2004 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 1998, 1999, 2001, 2002, 2003, 2004,
+;;   2005, 2006, 2007, 2008 Free Software Foundation, Inc.
 
 ;; Author: Anders Lindgren <andersl@andersl.com>
 ;; Keywords: convenience
@@ -11,7 +12,7 @@
 
 ;; 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)
+;; the Free Software Foundation; either version 3, or (at your option)
 ;; any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
@@ -21,8 +22,8 @@
 
 ;; 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., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Commentary:
 
@@ -214,10 +215,10 @@ changes in subdirectories or in the contents, size, modes, etc.,
 of files.  You may still sometimes want to revert them manually.
 
 Use this option with care since it could lead to excessive auto-reverts.
-For more information, see Info node `(emacs-xtra)Autorevert'."
+For more information, see Info node `(emacs)Autorevert'."
   :group 'auto-revert
   :type 'boolean
-  :link '(info-link "(emacs-xtra)Autorevert"))
+  :link '(info-link "(emacs)Autorevert"))
 
 (defcustom global-auto-revert-ignore-modes ()
   "List of major modes Global Auto-Revert Mode should not check."
@@ -275,9 +276,9 @@ the list of old buffers.")
   "Position of last known end of file.")
 
 (add-hook 'find-file-hook
-         (lambda ()
-           (set (make-local-variable 'auto-revert-tail-pos)
-                (save-restriction (widen) (1- (point-max))))))
+         (lambda ()
+           (set (make-local-variable 'auto-revert-tail-pos)
+                (nth 7 (file-attributes buffer-file-name)))))
 
 ;; Functions:
 
@@ -290,7 +291,7 @@ This is a minor mode that affects only the current buffer.
 Use `global-auto-revert-mode' to automatically revert all buffers.
 Use `auto-revert-tail-mode' if you know that the file will only grow
 without being changed in the part that is already in the buffer."
-  nil auto-revert-mode-text nil
+  :group 'auto-revert :lighter auto-revert-mode-text
   (if auto-revert-mode
       (if (not (memq (current-buffer) auto-revert-buffer-list))
          (push (current-buffer) auto-revert-buffer-list))
@@ -314,7 +315,7 @@ This function is designed to be added to hooks, for example:
 ;;;###autoload
 (define-minor-mode auto-revert-tail-mode
   "Toggle reverting tail of buffer when file on disk grows.
-With arg, turn Tail mode on iff arg is positive.
+With arg, turn Tail mode on if arg is positive, otherwise turn it off.
 
 When Tail mode is enabled, the tail of the file is constantly
 followed, as with the shell command `tail -f'.  This means that
@@ -333,14 +334,30 @@ Use `auto-revert-mode' for changes other than appends!"
       (auto-revert-tail-mode 0)
       (error "This buffer is not visiting a file"))
     (if (and (buffer-modified-p)
-            (not auto-revert-tail-pos) ; library was loaded only after finding file
+            (zerop auto-revert-tail-pos) ; library was loaded only after finding file
             (not (y-or-n-p "Buffer is modified, so tail offset may be wrong.  Proceed? ")))
        (auto-revert-tail-mode 0)
+      ;; a-r-tail-pos stores the size of the file at the time of the
+      ;; last revert. After this package loads, it adds a
+      ;; find-file-hook to set this variable every time a file is
+      ;; loaded.  If the package is loaded only _after_ visiting the
+      ;; file to be reverted, then we have no idea what the value of
+      ;; a-r-tail-pos should have been when the file was visited.  If
+      ;; the file has changed on disk in the meantime, all we can do
+      ;; is offer to revert the whole thing. If you choose not to
+      ;; revert, then you might miss some output then happened
+      ;; between visiting the file and activating a-r-t-mode.
+      (and (zerop auto-revert-tail-pos)
+           (not (verify-visited-file-modtime (current-buffer)))
+           (y-or-n-p "File changed on disk, content may be missing.  \
+Perform a full revert? ")
+           ;; Use this (not just revert-buffer) for point-preservation.
+           (auto-revert-handler))
       ;; else we might reappend our own end when we save
       (add-hook 'before-save-hook (lambda () (auto-revert-tail-mode 0)) nil t)
       (or (local-variable-p 'auto-revert-tail-pos) ; don't lose prior position
-         (set (make-variable-buffer-local 'auto-revert-tail-pos)
-              (save-restriction (widen) (1- (point-max)))))
+         (set (make-local-variable 'auto-revert-tail-pos)
+              (nth 7 (file-attributes buffer-file-name))))
       ;; let auto-revert-mode set up the mechanism for us if it isn't already
       (or auto-revert-mode
          (let ((auto-revert-tail-mode t))
@@ -399,12 +416,16 @@ will use an up-to-date value of `auto-revert-interval'"
   "Revert current buffer, if appropriate.
 This is an internal function used by Auto-Revert Mode."
   (when (or auto-revert-tail-mode (not (buffer-modified-p)))
-    (let* ((buffer (current-buffer))
+    (let* ((buffer (current-buffer)) size
           (revert
            (or (and buffer-file-name
                     (not (file-remote-p buffer-file-name))
                     (file-readable-p buffer-file-name)
-                    (not (verify-visited-file-modtime buffer)))
+                    (if auto-revert-tail-mode
+                        (/= auto-revert-tail-pos
+                           (setq size
+                                 (nth 7 (file-attributes buffer-file-name))))
+                      (not (verify-visited-file-modtime buffer))))
                (and (or auto-revert-mode
                         global-auto-revert-non-file-buffers)
                     revert-buffer-function
@@ -428,7 +449,7 @@ This is an internal function used by Auto-Revert Mode."
                    (push window eoblist)))
           'no-mini t))
        (if auto-revert-tail-mode
-           (auto-revert-tail-handler)
+           (auto-revert-tail-handler size)
          ;; Bind buffer-read-only in case user has done C-x C-q,
          ;; so as not to forget that.  This gives undesirable results
          ;; when the file's mode changes, but that is less common.
@@ -443,22 +464,26 @@ This is an internal function used by Auto-Revert Mode."
       (when (or revert auto-revert-check-vc-info)
        (vc-find-file-hook)))))
 
-(defun auto-revert-tail-handler ()
-  (let ((size (nth 7 (file-attributes buffer-file-name)))
-       (modified (buffer-modified-p))
-       buffer-read-only                ; ignore
+(defun auto-revert-tail-handler (size)  
+  (let ((modified (buffer-modified-p))
+       (inhibit-read-only t)           ; Ignore.
        (file buffer-file-name)
-       buffer-file-name)               ; ignore that file has changed
-    (when (> size auto-revert-tail-pos)
+       (buffer-file-name nil))         ; Ignore that file has changed.
+    (when (/= auto-revert-tail-pos size)
+      (run-hooks 'before-revert-hook)
       (undo-boundary)
       (save-restriction
        (widen)
        (save-excursion
          (goto-char (point-max))
-         (insert-file-contents file nil auto-revert-tail-pos size)))
+         (insert-file-contents file nil
+                               (and (< auto-revert-tail-pos size)
+                                    auto-revert-tail-pos)
+                               size)))
+      (run-hooks 'after-revert-hook)
       (undo-boundary)
       (setq auto-revert-tail-pos size)
-      (set-buffer-modified-p modified)))
+      (restore-buffer-modified-p modified)))
   (set-visited-file-modtime))
 
 (defun auto-revert-buffers ()
@@ -484,46 +509,47 @@ are checked first the next time this function is called.
 This function is also responsible for removing buffers no longer in
 Auto-Revert mode from `auto-revert-buffer-list', and for canceling
 the timer when no buffers need to be checked."
-  (let ((bufs (if global-auto-revert-mode
-                 (buffer-list)
-               auto-revert-buffer-list))
-       (remaining ())
-       (new ()))
-    ;; Partition `bufs' into two halves depending on whether or not
-    ;; the buffers are in `auto-revert-remaining-buffers'.  The two
-    ;; halves are then re-joined with the "remaining" buffers at the
-    ;; head of the list.
-    (dolist (buf auto-revert-remaining-buffers)
-      (if (memq buf bufs)
-         (push buf remaining)))
-    (dolist (buf bufs)
-      (if (not (memq buf remaining))
-         (push buf new)))
-    (setq bufs (nreverse (nconc new remaining)))
-    (while (and bufs
-               (not (and auto-revert-stop-on-user-input
-                         (input-pending-p))))
-      (let ((buf (car bufs)))
-       (if (buffer-name buf)           ; Buffer still alive?
-           (with-current-buffer buf
-             ;; Test if someone has turned off Auto-Revert Mode in a
-             ;; non-standard way, for example by changing major mode.
-             (if (and (not auto-revert-mode)
-                      (not auto-revert-tail-mode)
-                      (memq buf auto-revert-buffer-list))
-                 (setq auto-revert-buffer-list
-                       (delq buf auto-revert-buffer-list)))
-             (when (auto-revert-active-p) (auto-revert-handler)))
-         ;; Remove dead buffer from `auto-revert-buffer-list'.
-         (setq auto-revert-buffer-list
-               (delq buf auto-revert-buffer-list))))
-      (setq bufs (cdr bufs)))
-    (setq auto-revert-remaining-buffers bufs)
-    ;; Check if we should cancel the timer.
-    (when (and (not global-auto-revert-mode)
-              (null auto-revert-buffer-list))
-      (cancel-timer auto-revert-timer)
-      (setq auto-revert-timer nil))))
+  (save-match-data
+    (let ((bufs (if global-auto-revert-mode
+                   (buffer-list)
+                 auto-revert-buffer-list))
+         (remaining ())
+         (new ()))
+      ;; Partition `bufs' into two halves depending on whether or not
+      ;; the buffers are in `auto-revert-remaining-buffers'.  The two
+      ;; halves are then re-joined with the "remaining" buffers at the
+      ;; head of the list.
+      (dolist (buf auto-revert-remaining-buffers)
+       (if (memq buf bufs)
+           (push buf remaining)))
+      (dolist (buf bufs)
+       (if (not (memq buf remaining))
+           (push buf new)))
+      (setq bufs (nreverse (nconc new remaining)))
+      (while (and bufs
+                 (not (and auto-revert-stop-on-user-input
+                           (input-pending-p))))
+       (let ((buf (car bufs)))
+         (if (buffer-name buf)         ; Buffer still alive?
+             (with-current-buffer buf
+               ;; Test if someone has turned off Auto-Revert Mode in a
+               ;; non-standard way, for example by changing major mode.
+               (if (and (not auto-revert-mode)
+                        (not auto-revert-tail-mode)
+                        (memq buf auto-revert-buffer-list))
+                   (setq auto-revert-buffer-list
+                         (delq buf auto-revert-buffer-list)))
+               (when (auto-revert-active-p) (auto-revert-handler)))
+           ;; Remove dead buffer from `auto-revert-buffer-list'.
+           (setq auto-revert-buffer-list
+                 (delq buf auto-revert-buffer-list))))
+       (setq bufs (cdr bufs)))
+      (setq auto-revert-remaining-buffers bufs)
+      ;; Check if we should cancel the timer.
+      (when (and (not global-auto-revert-mode)
+                (null auto-revert-buffer-list))
+       (cancel-timer auto-revert-timer)
+       (setq auto-revert-timer nil)))))
 
 
 ;; The end:
@@ -531,5 +557,5 @@ the timer when no buffers need to be checked."
 
 (run-hooks 'auto-revert-load-hook)
 
-;;; arch-tag: f6bcb07b-4841-477e-9e44-b18678e58876
+;; arch-tag: f6bcb07b-4841-477e-9e44-b18678e58876
 ;;; autorevert.el ends here