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