*** empty log message ***
[bpt/emacs.git] / lisp / autorevert.el
CommitLineData
e8af40ee 1;;; autorevert.el --- revert buffers when files on disk change
4a35aff3 2
38f442c6 3;; Copyright (C) 1997, 1998, 1999, 2001, 2004 Free Software Foundation, Inc.
4a35aff3 4
a468671a 5;; Author: Anders Lindgren <andersl@andersl.com>
f5f727f8 6;; Keywords: convenience
a468671a
GM
7;; Created: 1997-06-01
8;; Date: 1999-11-30
4a35aff3
RS
9
10;; This file is part of GNU Emacs.
11
12;; GNU Emacs is free software; you can redistribute it and/or modify
13;; it under the terms of the GNU General Public License as published by
14;; the Free Software Foundation; either version 2, or (at your option)
15;; any later version.
16
17;; GNU Emacs is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
23;; along with GNU Emacs; see the file COPYING. If not, write to the
24;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25;; Boston, MA 02111-1307, USA.
26
27;;; Commentary:
28
29;; Introduction:
30;;
31;; Whenever a file that Emacs is editing has been changed by another
48764ae2 32;; program the user normally has to execute the command `revert-buffer'
4a35aff3
RS
33;; to load the new content of the file into Emacs.
34;;
35;; This package contains two minor modes: Global Auto-Revert Mode and
48764ae2 36;; Auto-Revert Mode. Both modes automatically revert buffers
2d677766
LT
37;; whenever the corresponding files have been changed on disk and the
38;; buffer contains no unsaved changes.
4a35aff3 39;;
ae229809
LT
40;; Auto-Revert Mode can be activated for individual buffers. Global
41;; Auto-Revert Mode applies to all file buffers. (If the user option
42;; `global-auto-revert-non-file-buffers' is non-nil, it also applies
43;; to some non-file buffers. This option is disabled by default.)
44;; Since checking a remote file is too slow, these modes do not check
45;; or revert remote files.
4a35aff3 46;;
48764ae2
DL
47;; Both modes operate by checking the time stamp of all files at
48;; intervals of `auto-revert-interval'. The default is every five
49;; seconds. The check is aborted whenever the user actually uses
50;; Emacs. You should never even notice that this package is active
51;; (except that your buffers will be reverted, of course).
1f41bcba
LT
52;;
53;; After reverting a file buffer, Auto Revert Mode normally puts point
54;; at the same position that a regular manual revert would. However,
55;; there is one exception to this rule. If point is at the end of the
56;; buffer before reverting, it stays at the end. Similarly if point
57;; is displayed at the end of a file buffer in any window, it will stay
58;; at the end of the buffer in that window, even if the window is not
59;; selected. This way, you can use Auto Revert Mode to `tail' a file.
60;; Just put point at the end of the buffer and it will stay there.
61;; These rules apply to file buffers. For non-file buffers, the
62;; behavior may be mode dependent.
2d677766
LT
63;;
64;; While you can use Auto Revert Mode to tail a file, this package
65;; contains a third minor mode, Auto Revert Tail Mode, which does so
66;; more efficiently, as long as you are sure that the file will only
67;; change by growing at the end. It only appends the new output,
68;; instead of reverting the entire buffer. It does so even if the
69;; buffer contains unsaved changes. (Because they will not be lost.)
4a35aff3
RS
70
71;; Usage:
72;;
dddc748b 73;; Go to the appropriate buffer and press either of:
4a35aff3 74;; M-x auto-revert-mode RET
dddc748b 75;; M-x auto-revert-tail-mode RET
4a35aff3
RS
76;;
77;; To activate Global Auto-Revert Mode, press:
78;; M-x global-auto-revert-mode RET
79;;
48764ae2
DL
80;; To activate Global Auto-Revert Mode every time Emacs is started
81;; customise the option `global-auto-revert-mode' or the following
82;; line could be added to your ~/.emacs:
4a35aff3
RS
83;; (global-auto-revert-mode 1)
84;;
85;; The function `turn-on-auto-revert-mode' could be added to any major
86;; mode hook to activate Auto-Revert Mode for all buffers in that
87;; mode. For example, the following line will activate Auto-Revert
88;; Mode in all C mode buffers:
89;;
90;; (add-hook 'c-mode-hook 'turn-on-auto-revert-mode)
91
92;;; Code:
93
94;; Dependencies:
95
96(require 'timer)
0f98bc23 97
71c8db4c 98(eval-when-compile (require 'cl))
4a35aff3
RS
99
100
101;; Custom Group:
102;;
103;; The two modes will be placed next to Auto Save Mode under the
104;; Files group under Emacs.
105
106(defgroup auto-revert nil
48764ae2 107 "Revert individual buffers when files on disk change.
4a35aff3
RS
108
109Auto-Revert Mode can be activated for individual buffer.
110Global Auto-Revert Mode applies to all buffers."
f5f727f8
DN
111 :group 'files
112 :group 'convenience)
4a35aff3
RS
113
114
115;; Variables:
116
dddc748b
DP
117;;; What's this?: ;; Autoload for the benefit of `make-mode-line-mouse-sensitive'.
118;;; What's this?: ;;;###autoload
4a35aff3
RS
119(defvar auto-revert-mode nil
120 "*Non-nil when Auto-Revert Mode is active.
0e4f9468
SM
121Never set this variable directly, use the command `auto-revert-mode' instead.")
122(put 'auto-revert-mode 'permanent-local t)
4a35aff3 123
dddc748b
DP
124(defvar auto-revert-tail-mode nil
125 "*Non-nil when Auto-Revert Tail Mode is active.
9e559f9b
LT
126Never set this variable directly, use the command
127`auto-revert-tail-mode' instead.")
dddc748b
DP
128(put 'auto-revert-tail-mode 'permanent-local t)
129
a2ac68f1
LT
130(defvar auto-revert-timer nil
131 "Timer used by Auto-Revert Mode.")
132
4a35aff3 133(defcustom auto-revert-interval 5
ad660075 134 "Time, in seconds, between Auto-Revert Mode file checks.
a2ac68f1
LT
135The value may be an integer or floating point number.
136
137If a timer is already active, there are two ways to make sure
138that the new value will take effect immediately. You can set
139this variable through Custom or you can call the command
140`auto-revert-set-timer' after setting the variable. Otherwise,
141the new value will take effect the first time Auto Revert Mode
142calls `auto-revert-set-timer' for internal reasons or in your
143next editing session."
4a35aff3 144 :group 'auto-revert
a2ac68f1
LT
145 :type 'number
146 :set (lambda (variable value)
147 (set-default variable value)
148 (and (boundp 'auto-revert-timer)
149 auto-revert-timer
150 (auto-revert-set-timer))))
4a35aff3
RS
151
152(defcustom auto-revert-stop-on-user-input t
6547d313
LT
153 "When non-nil, user input temporarily interrupts Auto-Revert Mode.
154When nil, Auto-Revert Mode checks files and reverts buffers, with
155quitting disabled, without paying attention to user input. Thus,
156it might take a while before Emacs responds to your input."
4a35aff3
RS
157 :group 'auto-revert
158 :type 'boolean)
159
160(defcustom auto-revert-verbose t
6547d313 161 "When nil, Auto-Revert Mode does not generate any messages.
0e5dcfd7 162When non-nil, a message is generated whenever a file is reverted."
4a35aff3
RS
163 :group 'auto-revert
164 :type 'boolean)
165
166(defcustom auto-revert-mode-text " ARev"
167 "String to display in the mode line when Auto-Revert Mode is active.
168
169\(When the string is not empty, make sure that it has a leading space.)"
170 :tag "Auto Revert Mode Text" ; To separate it from `global-...'
171 :group 'auto-revert
172 :type 'string)
173
dddc748b
DP
174(defcustom auto-revert-tail-mode-text " Tail"
175 "String to display in the mode line when Auto-Revert Tail Mode is active.
176
177\(When the string is not empty, make sure that it has a leading space.)"
178 :group 'auto-revert
0a306700 179 :type 'string
bf247b6e 180 :version "22.1")
dddc748b 181
4a35aff3
RS
182(defcustom auto-revert-mode-hook nil
183 "Functions to run when Auto-Revert Mode is activated."
184 :tag "Auto Revert Mode Hook" ; To separate it from `global-...'
185 :group 'auto-revert
186 :type 'hook)
187
188(defcustom global-auto-revert-mode-text ""
189 "String to display when Global Auto-Revert Mode is active.
190
191The default is nothing since when this mode is active this text doesn't
48764ae2 192vary over time, or between buffers. Hence mode line text
4a35aff3
RS
193would only waste precious space."
194 :group 'auto-revert
195 :type 'string)
196
197(defcustom global-auto-revert-mode-hook nil
198 "Hook called when Global Auto-Revert Mode is activated."
199 :group 'auto-revert
200 :type 'hook)
201
202(defcustom global-auto-revert-non-file-buffers nil
d9e4328d 203 "When nil, Global Auto-Revert mode operates only on file-visiting buffers.
4a35aff3
RS
204
205When non-nil, both file buffers and buffers with a custom
0e5dcfd7 206`revert-buffer-function' and a `buffer-stale-function' are
9ae0d84f
LT
207reverted by Global Auto-Revert mode. These include the Buffer
208List buffer, and Dired buffers showing complete local
209directories. Dired buffers do not auto-revert as a result of
210changes in subdirectories or in the contents, size, modes, etc.,
211of files. You may still sometimes want to revert them manually.
0e4f9468 212
d9e4328d 213Use this option with care since it could lead to excessive auto-reverts.
9ae0d84f 214For more information, see Info node `(emacs-xtra)Autorevert'."
4a35aff3 215 :group 'auto-revert
843c51ae
LT
216 :type 'boolean
217 :link '(info-link "(emacs-xtra)Autorevert"))
4a35aff3 218
dddc748b 219(defcustom global-auto-revert-ignore-modes ()
4a35aff3
RS
220 "List of major modes Global Auto-Revert Mode should not check."
221 :group 'auto-revert
222 :type '(repeat sexp))
223
224(defcustom auto-revert-load-hook nil
225 "Functions to run when Auto-Revert Mode is first loaded."
226 :tag "Load Hook"
227 :group 'auto-revert
228 :type 'hook)
229
71c8db4c
LT
230(defcustom auto-revert-check-vc-info nil
231 "If non-nil Auto Revert Mode reliably updates version control info.
232Auto Revert Mode updates version control info whenever the buffer
233needs reverting, regardless of the value of this variable.
234However, the version control state can change without changes to
235the work file. If the change is made from the current Emacs
236session, all info is updated. But if, for instance, a new
237version is checked in from outside the current Emacs session, the
238version control number in the mode line, as well as other version
239control related information, may not be properly updated. If you
240are worried about this, set this variable to a non-nil value.
241
242This currently works by automatically updating the version
243control info every `auto-revert-interval' seconds. Nevertheless,
244it should not cause excessive CPU usage on a reasonably fast
245machine, if it does not apply to too many version controlled
246buffers. CPU usage depends on the version control system"
247 :group 'auto-revert
248 :type 'boolean
bf247b6e 249 :version "22.1")
71c8db4c 250
4a35aff3 251(defvar global-auto-revert-ignore-buffer nil
f1e3ff80 252 "*When non-nil, Global Auto-Revert Mode will not revert this buffer.
4a35aff3 253
48764ae2 254This variable becomes buffer local when set in any fashion.")
4a35aff3
RS
255(make-variable-buffer-local 'global-auto-revert-ignore-buffer)
256
4a35aff3
RS
257;; Internal variables:
258
dddc748b 259(defvar auto-revert-buffer-list ()
4a35aff3
RS
260 "List of buffers in Auto-Revert Mode.
261
262Note that only Auto-Revert Mode, never Global Auto-Revert Mode, adds
263buffers to this list.
264
265The timer function `auto-revert-buffers' is responsible for purging
266the list of old buffers.")
267
dddc748b 268(defvar auto-revert-remaining-buffers ()
4a35aff3
RS
269 "Buffers not checked when user input stopped execution.")
270
dddc748b
DP
271(defvar auto-revert-tail-pos 0
272 "Position of last known end of file.")
273
274(add-hook 'find-file-hook
275 (lambda ()
276 (set (make-local-variable 'auto-revert-tail-pos)
277 (save-restriction (widen) (1- (point-max))))))
4a35aff3
RS
278
279;; Functions:
280
281;;;###autoload
0e4f9468 282(define-minor-mode auto-revert-mode
48764ae2 283 "Toggle reverting buffer when file on disk changes.
4a35aff3 284
48764ae2
DL
285With arg, turn Auto Revert mode on if and only if arg is positive.
286This is a minor mode that affects only the current buffer.
dddc748b
DP
287Use `global-auto-revert-mode' to automatically revert all buffers.
288Use `auto-revert-tail-mode' if you know that the file will only grow
289without being changed in the part that is already in the buffer."
0e4f9468 290 nil auto-revert-mode-text nil
4a35aff3
RS
291 (if auto-revert-mode
292 (if (not (memq (current-buffer) auto-revert-buffer-list))
293 (push (current-buffer) auto-revert-buffer-list))
294 (setq auto-revert-buffer-list
295 (delq (current-buffer) auto-revert-buffer-list)))
296 (auto-revert-set-timer)
297 (when auto-revert-mode
dddc748b
DP
298 (auto-revert-buffers)
299 (setq auto-revert-tail-mode nil)))
4a35aff3
RS
300
301
302;;;###autoload
303(defun turn-on-auto-revert-mode ()
304 "Turn on Auto-Revert Mode.
305
306This function is designed to be added to hooks, for example:
307 (add-hook 'c-mode-hook 'turn-on-auto-revert-mode)"
308 (auto-revert-mode 1))
309
310
dddc748b
DP
311;;;###autoload
312(define-minor-mode auto-revert-tail-mode
313 "Toggle reverting tail of buffer when file on disk grows.
314With arg, turn Tail mode on iff arg is positive.
315
316When Tail mode is enabled, the tail of the file is constantly
317followed, as with the shell command `tail -f'. This means that
318whenever the file grows on disk (presumably because some
319background process is appending to it from time to time), this is
320reflected in the current buffer.
321
322You can edit the buffer and turn this mode off and on again as
323you please. But make sure the background process has stopped
324writing before you save the file!
325
326Use `auto-revert-mode' for changes other than appends!"
327 :group 'find-file :lighter auto-revert-tail-mode-text
328 (when auto-revert-tail-mode
329 (unless buffer-file-name
330 (auto-revert-tail-mode 0)
331 (error "This buffer is not visiting a file"))
332 (if (and (buffer-modified-p)
333 (not auto-revert-tail-pos) ; library was loaded only after finding file
334 (not (y-or-n-p "Buffer is modified, so tail offset may be wrong. Proceed? ")))
335 (auto-revert-tail-mode 0)
336 ;; else we might reappend our own end when we save
337 (add-hook 'before-save-hook (lambda () (auto-revert-tail-mode 0)) nil t)
338 (or (local-variable-p 'auto-revert-tail-pos) ; don't lose prior position
339 (set (make-variable-buffer-local 'auto-revert-tail-pos)
340 (save-restriction (widen) (1- (point-max)))))
341 ;; let auto-revert-mode set up the mechanism for us if it isn't already
342 (or auto-revert-mode
343 (let ((auto-revert-tail-mode t))
344 (auto-revert-mode 1)))
345 (setq auto-revert-mode nil))))
346
347
348;;;###autoload
349(defun turn-on-auto-revert-tail-mode ()
350 "Turn on Auto-Revert Tail Mode.
351
352This function is designed to be added to hooks, for example:
353 (add-hook 'my-logfile-mode-hook 'turn-on-auto-revert-tail-mode)"
354 (auto-revert-tail-mode 1))
355
356
4a35aff3 357;;;###autoload
0e4f9468 358(define-minor-mode global-auto-revert-mode
0e5dcfd7 359 "Revert any buffer when file on disk changes.
4a35aff3 360
48764ae2
DL
361With arg, turn Auto Revert mode on globally if and only if arg is positive.
362This is a minor mode that affects all buffers.
4a35aff3 363Use `auto-revert-mode' to revert a particular buffer."
0e4f9468 364 :global t :group 'auto-revert :lighter global-auto-revert-mode-text
4a35aff3
RS
365 (auto-revert-set-timer)
366 (when global-auto-revert-mode
0e4f9468 367 (auto-revert-buffers)))
4a35aff3
RS
368
369
370(defun auto-revert-set-timer ()
0e5dcfd7 371 "Restart or cancel the timer used by Auto-Revert Mode.
d97c8375 372If such a timer is active, cancel it. Start a new timer if
0e5dcfd7
LT
373Global Auto-Revert Mode is active or if Auto-Revert Mode is active
374in some buffer. Restarting the timer ensures that Auto-Revert Mode
375will use an up-to-date value of `auto-revert-interval'"
a2ac68f1 376 (interactive)
4a35aff3
RS
377 (if (timerp auto-revert-timer)
378 (cancel-timer auto-revert-timer))
0e4f9468
SM
379 (setq auto-revert-timer
380 (if (or global-auto-revert-mode auto-revert-buffer-list)
381 (run-with-timer auto-revert-interval
382 auto-revert-interval
dddc748b 383 'auto-revert-buffers))))
4a35aff3 384
ed35db71
EZ
385(defun auto-revert-active-p ()
386 "Check if auto-revert is active (in current buffer or globally)."
387 (or auto-revert-mode
dddc748b 388 auto-revert-tail-mode
ed35db71
EZ
389 (and
390 global-auto-revert-mode
391 (not global-auto-revert-ignore-buffer)
392 (not (memq major-mode
393 global-auto-revert-ignore-modes)))))
394
ed35db71 395(defun auto-revert-handler ()
0e5dcfd7
LT
396 "Revert current buffer, if appropriate.
397This is an internal function used by Auto-Revert Mode."
dddc748b
DP
398 (when (or auto-revert-tail-mode (not (buffer-modified-p)))
399 (let* ((buffer (current-buffer))
400 (revert
401 (or (and buffer-file-name
402 (not (file-remote-p buffer-file-name))
403 (file-readable-p buffer-file-name)
404 (not (verify-visited-file-modtime buffer)))
2d677766 405 (and (or auto-revert-mode
dddc748b
DP
406 global-auto-revert-non-file-buffers)
407 revert-buffer-function
408 (boundp 'buffer-stale-function)
409 (functionp buffer-stale-function)
410 (funcall buffer-stale-function t))))
411 eob eoblist)
d4411cef 412 (when revert
71c8db4c
LT
413 (when (and auto-revert-verbose
414 (not (eq revert 'fast)))
633e0363 415 (message "Reverting buffer `%s'." (buffer-name)))
1f41bcba
LT
416 ;; If point (or a window point) is at the end of the buffer,
417 ;; we want to keep it at the end after reverting. This allows
418 ;; to tail a file.
419 (when buffer-file-name
420 (setq eob (eobp))
421 (walk-windows
422 #'(lambda (window)
423 (and (eq (window-buffer window) buffer)
424 (= (window-point window) (point-max))
425 (push window eoblist)))
426 'no-mini t))
dddc748b
DP
427 (if auto-revert-tail-mode
428 (auto-revert-tail-handler)
7ebc19f9
RS
429 ;; Bind buffer-read-only in case user has done C-x C-q,
430 ;; so as not to forget that. This gives undesirable results
431 ;; when the file's mode changes, but that is less common.
90e118ab
LT
432 (let ((buffer-read-only buffer-read-only))
433 (revert-buffer 'ignore-auto 'dont-ask 'preserve-modes)))
1f41bcba
LT
434 (when buffer-file-name
435 (when eob (goto-char (point-max)))
436 (dolist (window eoblist)
437 (set-window-point window (point-max)))))
71c8db4c
LT
438 ;; `preserve-modes' avoids changing the (minor) modes. But we
439 ;; do want to reset the mode for VC, so we do it manually.
440 (when (or revert auto-revert-check-vc-info)
441 (vc-find-file-hook)))))
ed35db71 442
dddc748b
DP
443(defun auto-revert-tail-handler ()
444 (let ((size (nth 7 (file-attributes buffer-file-name)))
445 (modified (buffer-modified-p))
446 buffer-read-only ; ignore
447 (file buffer-file-name)
448 buffer-file-name) ; ignore that file has changed
449 (when (> size auto-revert-tail-pos)
d918508e 450 (undo-boundary)
dddc748b
DP
451 (save-restriction
452 (widen)
453 (save-excursion
454 (goto-char (point-max))
455 (insert-file-contents file nil auto-revert-tail-pos size)))
d918508e 456 (undo-boundary)
dddc748b
DP
457 (setq auto-revert-tail-pos size)
458 (set-buffer-modified-p modified)))
459 (set-visited-file-modtime))
460
4a35aff3
RS
461(defun auto-revert-buffers ()
462 "Revert buffers as specified by Auto-Revert and Global Auto-Revert Mode.
463
464Should `global-auto-revert-mode' be active all file buffers are checked.
465
466Should `auto-revert-mode' be active in some buffers, those buffers
467are checked.
468
0e5dcfd7
LT
469Non-file buffers that have a custom `revert-buffer-function' and
470a `buffer-stale-function' are reverted either when Auto-Revert
471Mode is active in that buffer, or when the variable
472`global-auto-revert-non-file-buffers' is non-nil and Global
473Auto-Revert Mode is active.
4a35aff3 474
48764ae2 475This function stops whenever there is user input. The buffers not
4a35aff3
RS
476checked are stored in the variable `auto-revert-remaining-buffers'.
477
478To avoid starvation, the buffers in `auto-revert-remaining-buffers'
479are checked first the next time this function is called.
480
48764ae2 481This function is also responsible for removing buffers no longer in
4a35aff3
RS
482Auto-Revert mode from `auto-revert-buffer-list', and for canceling
483the timer when no buffers need to be checked."
484 (let ((bufs (if global-auto-revert-mode
485 (buffer-list)
486 auto-revert-buffer-list))
dddc748b
DP
487 (remaining ())
488 (new ()))
4a35aff3
RS
489 ;; Partition `bufs' into two halves depending on whether or not
490 ;; the buffers are in `auto-revert-remaining-buffers'. The two
491 ;; halves are then re-joined with the "remaining" buffers at the
492 ;; head of the list.
493 (dolist (buf auto-revert-remaining-buffers)
494 (if (memq buf bufs)
495 (push buf remaining)))
496 (dolist (buf bufs)
497 (if (not (memq buf remaining))
498 (push buf new)))
499 (setq bufs (nreverse (nconc new remaining)))
500 (while (and bufs
501 (not (and auto-revert-stop-on-user-input
502 (input-pending-p))))
503 (let ((buf (car bufs)))
504 (if (buffer-name buf) ; Buffer still alive?
0e4f9468 505 (with-current-buffer buf
4a35aff3
RS
506 ;; Test if someone has turned off Auto-Revert Mode in a
507 ;; non-standard way, for example by changing major mode.
508 (if (and (not auto-revert-mode)
dddc748b 509 (not auto-revert-tail-mode)
4a35aff3
RS
510 (memq buf auto-revert-buffer-list))
511 (setq auto-revert-buffer-list
512 (delq buf auto-revert-buffer-list)))
c86afc19 513 (when (auto-revert-active-p) (auto-revert-handler)))
4a35aff3
RS
514 ;; Remove dead buffer from `auto-revert-buffer-list'.
515 (setq auto-revert-buffer-list
516 (delq buf auto-revert-buffer-list))))
517 (setq bufs (cdr bufs)))
518 (setq auto-revert-remaining-buffers bufs)
519 ;; Check if we should cancel the timer.
520 (when (and (not global-auto-revert-mode)
521 (null auto-revert-buffer-list))
522 (cancel-timer auto-revert-timer)
523 (setq auto-revert-timer nil))))
524
525
526;; The end:
4a35aff3
RS
527(provide 'autorevert)
528
529(run-hooks 'auto-revert-load-hook)
530
ab5796a9 531;;; arch-tag: f6bcb07b-4841-477e-9e44-b18678e58876
e8af40ee 532;;; autorevert.el ends here