(replace_buffer_in_all_windows):
[bpt/emacs.git] / lisp / autorevert.el
CommitLineData
4a35aff3
RS
1;; autorevert --- Revert buffers when file on disk change.
2
3;; Copyright (C) 1997 Free Software Foundation, Inc.
4
5;; Author: Anders Lindgren <andersl@csd.uu.se>
6;; Created: 1 Jun 1997
7;; Date: 3 Jul 1997
8
9;; This file is part of GNU Emacs.
10
11;; GNU Emacs is free software; you can redistribute it and/or modify
12;; it under the terms of the GNU General Public License as published by
13;; the Free Software Foundation; either version 2, or (at your option)
14;; any later version.
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
22;; along with GNU Emacs; see the file COPYING. If not, write to the
23;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24;; Boston, MA 02111-1307, USA.
25
26;;; Commentary:
27
28;; Introduction:
29;;
30;; Whenever a file that Emacs is editing has been changed by another
31;; program the user normally have to execute the command `revert-buffer'
32;; to load the new content of the file into Emacs.
33;;
34;; This package contains two minor modes: Global Auto-Revert Mode and
35;; Auto-Revert Mode. Both modes automatically reverts buffers
36;; whenever the corresponding files have been changed on disk.
37;;
38;; Auto-Revert Mode can be activated for individual buffers.
39;; Global Auto-Revert Mode applies to all file buffers.
40;;
41;; Both modes operates by checking the time stamp of all files at
42;; given intervals, the default is every five seconds. The check is
43;; aborted whenever the user actually use Emacs. Hopefully you will
44;; never even notice that this package is active (except that your
45;; buffers will be reverted, of course).
46
47;; Installation:
48;;
49;; To install this package, place it in somewhere on Emacs' load-path,
50;; byte-compile it (not necessary), and place the following lines in
51;; the appropriate init file:
52;;
53;; (autoload 'auto-revert-mode "autorevert" nil t)
54;; (autoload 'turn-on-auto-revert-mode "autorevert" nil nil)
55;; (autoload 'global-auto-revert-mode "autorevert" nil t)
56
57;; Usage:
58;;
59;; Go to the appropriate buffer and press:
60;; M-x auto-revert-mode RET
61;;
62;; To activate Global Auto-Revert Mode, press:
63;; M-x global-auto-revert-mode RET
64;;
65;; To activate Global Auto-Revert Mode every time Emacs is started the
66;; following line could be added to your ~/.emacs:
67;; (global-auto-revert-mode 1)
68;;
69;; The function `turn-on-auto-revert-mode' could be added to any major
70;; mode hook to activate Auto-Revert Mode for all buffers in that
71;; mode. For example, the following line will activate Auto-Revert
72;; Mode in all C mode buffers:
73;;
74;; (add-hook 'c-mode-hook 'turn-on-auto-revert-mode)
75
76;;; Code:
77
78;; Dependencies:
79
80(require 'timer)
81(eval-when-compile (require 'cl))
82
83
84;; Custom Group:
85;;
86;; The two modes will be placed next to Auto Save Mode under the
87;; Files group under Emacs.
88
89(defgroup auto-revert nil
90 "Revert individual buffer when file on disk change.
91
92Auto-Revert Mode can be activated for individual buffer.
93Global Auto-Revert Mode applies to all buffers."
94 :group 'files)
95
96
97;; Variables:
98
99(defvar auto-revert-mode nil
100 "*Non-nil when Auto-Revert Mode is active.
101
102Do never set this variable directly, use the command
103`auto-revert-mode' instead.")
104
105(defcustom global-auto-revert-mode nil
106 "When on, buffers are automatically reverted when files on disk change.
107
108Set this variable when using \\[customize] only. Otherwise, use the
109command `global-auto-revert-mode' instead."
110 :group 'auto-revert
111 :initialize 'custom-initialize-default
112 :set '(lambda (symbol value)
113 (global-auto-revert-mode (or value 0)))
114 :type 'boolean
115 :require 'autorevert)
116
117(defcustom auto-revert-interval 5
118 "Time, in seconds, between Auto-Revert Mode file checks."
119 :group 'auto-revert
120 :type 'integer)
121
122(defcustom auto-revert-stop-on-user-input t
123 "When non-nil Auto-Revert Mode stops checking files on user input."
124 :group 'auto-revert
125 :type 'boolean)
126
127(defcustom auto-revert-verbose t
128 "When nil, Auto-Revert Mode will not generate any messages.
129
130Currently, messages are generated when the mode is activated or
131deactivated, and whenever a file is reverted."
132 :group 'auto-revert
133 :type 'boolean)
134
135(defcustom auto-revert-mode-text " ARev"
136 "String to display in the mode line when Auto-Revert Mode is active.
137
138\(When the string is not empty, make sure that it has a leading space.)"
139 :tag "Auto Revert Mode Text" ; To separate it from `global-...'
140 :group 'auto-revert
141 :type 'string)
142
143(defcustom auto-revert-mode-hook nil
144 "Functions to run when Auto-Revert Mode is activated."
145 :tag "Auto Revert Mode Hook" ; To separate it from `global-...'
146 :group 'auto-revert
147 :type 'hook)
148
149(defcustom global-auto-revert-mode-text ""
150 "String to display when Global Auto-Revert Mode is active.
151
152The default is nothing since when this mode is active this text doesn't
153vary neither over time, nor between buffers. Hence a mode line text
154would only waste precious space."
155 :group 'auto-revert
156 :type 'string)
157
158(defcustom global-auto-revert-mode-hook nil
159 "Hook called when Global Auto-Revert Mode is activated."
160 :group 'auto-revert
161 :type 'hook)
162
163(defcustom global-auto-revert-non-file-buffers nil
164 "*When nil only file buffers are reverted by Global Auto-Revert Mode.
165
166When non-nil, both file buffers and buffers with a custom
167`revert-buffer-function' are reverted by Global Auto-Revert Mode."
168 :group 'auto-revert
169 :type 'boolean)
170
171(defcustom global-auto-revert-non-file-buffers nil
172 "When nil only file buffers are reverted by Global Auto-Revert Mode.
173
174When non-nil, both file buffers and buffers with a custom
175`revert-buffer-function' are reverted by Global Auto-Revert Mode.
176
177Use this option with care since it could lead to excessive reverts."
178 :group 'auto-revert
179 :type 'boolean)
180
181(defcustom global-auto-revert-ignore-modes '()
182 "List of major modes Global Auto-Revert Mode should not check."
183 :group 'auto-revert
184 :type '(repeat sexp))
185
186(defcustom auto-revert-load-hook nil
187 "Functions to run when Auto-Revert Mode is first loaded."
188 :tag "Load Hook"
189 :group 'auto-revert
190 :type 'hook)
191
192(defvar global-auto-revert-ignore-buffer nil
193 "*When non-nil, Gobal Auto-Revert Mode will not revert this buffer.
194
195This variable becomes buffer local when set in any faishon.")
196(make-variable-buffer-local 'global-auto-revert-ignore-buffer)
197
198
199;; Internal variables:
200
201(defvar auto-revert-buffer-list '()
202 "List of buffers in Auto-Revert Mode.
203
204Note that only Auto-Revert Mode, never Global Auto-Revert Mode, adds
205buffers to this list.
206
207The timer function `auto-revert-buffers' is responsible for purging
208the list of old buffers.")
209
210(defvar auto-revert-timer nil
211 "Timer used by Auto-Revert Mode.")
212
213(defvar auto-revert-remaining-buffers '()
214 "Buffers not checked when user input stopped execution.")
215
216
217;; Functions:
218
219;;;###autoload
220(defun auto-revert-mode (&optional arg)
221 "Revert buffer when file on disk change.
222
223This is a minor mode that affect only the current buffer.
224Use `global-auto-revert-mode' to automatically revert all buffers."
225 (interactive "P")
226 (make-local-variable 'auto-revert-mode)
227 (setq auto-revert-mode
228 (if (null arg)
229 (not auto-revert-mode)
230 (> (prefix-numeric-value arg) 0)))
231 (if (and auto-revert-verbose
232 (interactive-p))
233 (message "Auto-Revert Mode is now %s."
234 (if auto-revert-mode "on" "off")))
235 (if auto-revert-mode
236 (if (not (memq (current-buffer) auto-revert-buffer-list))
237 (push (current-buffer) auto-revert-buffer-list))
238 (setq auto-revert-buffer-list
239 (delq (current-buffer) auto-revert-buffer-list)))
240 (auto-revert-set-timer)
241 (when auto-revert-mode
242 (auto-revert-buffers)
243 (run-hooks 'auto-revert-mode-hook)))
244
245
246;;;###autoload
247(defun turn-on-auto-revert-mode ()
248 "Turn on Auto-Revert Mode.
249
250This function is designed to be added to hooks, for example:
251 (add-hook 'c-mode-hook 'turn-on-auto-revert-mode)"
252 (auto-revert-mode 1))
253
254
255;;;###autoload
256(defun global-auto-revert-mode (&optional arg)
257 "Revert any buffer when file on disk change.
258
259This is a minor mode that affect all buffers.
260Use `auto-revert-mode' to revert a particular buffer."
261 (interactive "P")
262 (setq global-auto-revert-mode
263 (if (null arg)
264 (not global-auto-revert-mode)
265 (> (prefix-numeric-value arg) 0)))
266 (if (and auto-revert-verbose
267 (interactive-p))
268 (message "Gobal Auto-Revert Mode is now %s."
269 (if global-auto-revert-mode "on" "off")))
270 (auto-revert-set-timer)
271 (when global-auto-revert-mode
272 (auto-revert-buffers)
273 (run-hooks 'global-auto-revert-mode-hook)))
274
275
276(defun auto-revert-set-timer ()
277 "Restart or cancel the timer."
278 (if (timerp auto-revert-timer)
279 (cancel-timer auto-revert-timer))
280 (if (or global-auto-revert-mode auto-revert-buffer-list)
281 (setq auto-revert-timer (run-with-timer auto-revert-interval
282 auto-revert-interval
283 'auto-revert-buffers))
284 (setq auto-revert-timer nil)))
285
286
287(defun auto-revert-buffers ()
288 "Revert buffers as specified by Auto-Revert and Global Auto-Revert Mode.
289
290Should `global-auto-revert-mode' be active all file buffers are checked.
291
292Should `auto-revert-mode' be active in some buffers, those buffers
293are checked.
294
295Non-file buffers that have a custom `revert-buffer-function' are
296reverted either when Auto-Revert Mode is active in that buffer, or
297when the variable `global-auto-revert-non-file-buffers' is non-nil
298and Global Auto-Revert Mode is active.
299
300This function stops whenever the user use Emacs. The buffers not
301checked are stored in the variable `auto-revert-remaining-buffers'.
302
303To avoid starvation, the buffers in `auto-revert-remaining-buffers'
304are checked first the next time this function is called.
305
306This function is also responslible for removing buffers no longer in
307Auto-Revert mode from `auto-revert-buffer-list', and for canceling
308the timer when no buffers need to be checked."
309 (let ((bufs (if global-auto-revert-mode
310 (buffer-list)
311 auto-revert-buffer-list))
312 (remaining '())
313 (new '()))
314 ;; Partition `bufs' into two halves depending on whether or not
315 ;; the buffers are in `auto-revert-remaining-buffers'. The two
316 ;; halves are then re-joined with the "remaining" buffers at the
317 ;; head of the list.
318 (dolist (buf auto-revert-remaining-buffers)
319 (if (memq buf bufs)
320 (push buf remaining)))
321 (dolist (buf bufs)
322 (if (not (memq buf remaining))
323 (push buf new)))
324 (setq bufs (nreverse (nconc new remaining)))
325 (while (and bufs
326 (not (and auto-revert-stop-on-user-input
327 (input-pending-p))))
328 (let ((buf (car bufs)))
329 (if (buffer-name buf) ; Buffer still alive?
330 (save-excursion
331 (set-buffer buf)
332 ;; Test if someone has turned off Auto-Revert Mode in a
333 ;; non-standard way, for example by changing major mode.
334 (if (and (not auto-revert-mode)
335 (memq buf auto-revert-buffer-list))
336 (setq auto-revert-buffer-list
337 (delq buf auto-revert-buffer-list)))
338 (when (and
339 (or auto-revert-mode
340 (and
341 global-auto-revert-mode
342 (not global-auto-revert-ignore-buffer)
343 (not (memq major-mode
344 global-auto-revert-ignore-modes))))
345 (not (buffer-modified-p))
346 (if (buffer-file-name)
347 (and (file-readable-p (buffer-file-name))
348 (not (verify-visited-file-modtime buf)))
349 (and revert-buffer-function
350 (or (and global-auto-revert-mode
351 global-auto-revert-non-file-buffers)
352 auto-revert-mode))))
353 (if auto-revert-verbose
354 (message "Reverting buffer `%s'." buf))
355 (revert-buffer t t)))
356 ;; Remove dead buffer from `auto-revert-buffer-list'.
357 (setq auto-revert-buffer-list
358 (delq buf auto-revert-buffer-list))))
359 (setq bufs (cdr bufs)))
360 (setq auto-revert-remaining-buffers bufs)
361 ;; Check if we should cancel the timer.
362 (when (and (not global-auto-revert-mode)
363 (null auto-revert-buffer-list))
364 (cancel-timer auto-revert-timer)
365 (setq auto-revert-timer nil))))
366
367
368;; The end:
369
370(unless (assq 'auto-revert-mode minor-mode-alist)
371 (push '(auto-revert-mode auto-revert-mode-text)
372 minor-mode-alist))
373(unless (assq 'global-auto-revert-mode minor-mode-alist)
374 (push '(global-auto-revert-mode global-auto-revert-mode-text)
375 minor-mode-alist))
376
377(provide 'autorevert)
378
379(run-hooks 'auto-revert-load-hook)
380
381;; This makes it possible to set Global Auto-Revert Mode from
382;; Customize.
383(if global-auto-revert-mode
384 (global-auto-revert-mode 1))
385
386;; autorevert.el ends here.