diff options
Diffstat (limited to 'lisp/autorevert.el')
-rw-r--r-- | lisp/autorevert.el | 163 |
1 files changed, 124 insertions, 39 deletions
diff --git a/lisp/autorevert.el b/lisp/autorevert.el index 9ccb8b89641..58bb6d29705 100644 --- a/lisp/autorevert.el +++ b/lisp/autorevert.el @@ -44,6 +44,17 @@ ;; seconds. The check is aborted whenever the user actually uses ;; Emacs. You should never even notice that this package is active ;; (except that your buffers will be reverted, of course). +;; +;; After reverting a file buffer, Auto Revert Mode normally puts point +;; at the same position that a regular manual revert would. However, +;; there is one exception to this rule. If point is at the end of the +;; buffer before reverting, it stays at the end. Similarly if point +;; is displayed at the end of a file buffer in any window, it will stay +;; at the end of the buffer in that window, even if the window is not +;; selected. This way, you can use Auto Revert Mode to `tail' a file. +;; Just put point at the end of the buffer and it will stay there. +;; These rules apply to file buffers. For non-file buffers, the +;; behavior may be mode dependent. ;; Usage: ;; @@ -70,6 +81,7 @@ ;; Dependencies: (require 'timer) + (eval-when-compile (require 'cl)) @@ -96,10 +108,27 @@ Global Auto-Revert Mode applies to all buffers." Never set this variable directly, use the command `auto-revert-mode' instead.") (put 'auto-revert-mode 'permanent-local t) +(defvar auto-revert-timer nil + "Timer used by Auto-Revert Mode.") + (defcustom auto-revert-interval 5 - "Time, in seconds, between Auto-Revert Mode file checks." + "Time, in seconds, between Auto-Revert Mode file checks. +The value may be an integer or floating point number. + +If a timer is already active, there are two ways to make sure +that the new value will take effect immediately. You can set +this variable through Custom or you can call the command +`auto-revert-set-timer' after setting the variable. Otherwise, +the new value will take effect the first time Auto Revert Mode +calls `auto-revert-set-timer' for internal reasons or in your +next editing session." :group 'auto-revert - :type 'integer) + :type 'number + :set (lambda (variable value) + (set-default variable value) + (and (boundp 'auto-revert-timer) + auto-revert-timer + (auto-revert-set-timer)))) (defcustom auto-revert-stop-on-user-input t "When non-nil Auto-Revert Mode stops checking files on user input." @@ -108,9 +137,7 @@ Never set this variable directly, use the command `auto-revert-mode' instead.") (defcustom auto-revert-verbose t "When nil, Auto-Revert Mode will not generate any messages. - -Currently, messages are generated when the mode is activated or -deactivated, and whenever a file is reverted." +When non-nil, a message is generated whenever a file is reverted." :group 'auto-revert :type 'boolean) @@ -146,9 +173,15 @@ would only waste precious space." "When nil only file buffers are reverted by Global Auto-Revert Mode. When non-nil, both file buffers and buffers with a custom -`revert-buffer-function' are reverted by Global Auto-Revert Mode. - -Use this option with care since it could lead to excessive reverts." +`revert-buffer-function' and a `buffer-stale-function' are +reverted by Global Auto-Revert Mode. + +Use this option with care since it could lead to excessive reverts. +Note also that for some non-file buffers the check whether the +buffer needs updating may be imperfect, due to efficiency +considerations, and may not take all information listed in the +buffer into account. Hence, a non-nil value for this option does +not necessarily make manual updates useless for non-file buffers." :group 'auto-revert :type 'boolean) @@ -163,13 +196,33 @@ Use this option with care since it could lead to excessive reverts." :group 'auto-revert :type 'hook) +(defcustom auto-revert-check-vc-info nil + "If non-nil Auto Revert Mode reliably updates version control info. +Auto Revert Mode updates version control info whenever the buffer +needs reverting, regardless of the value of this variable. +However, the version control state can change without changes to +the work file. If the change is made from the current Emacs +session, all info is updated. But if, for instance, a new +version is checked in from outside the current Emacs session, the +version control number in the mode line, as well as other version +control related information, may not be properly updated. If you +are worried about this, set this variable to a non-nil value. + +This currently works by automatically updating the version +control info every `auto-revert-interval' seconds. Nevertheless, +it should not cause excessive CPU usage on a reasonably fast +machine, if it does not apply to too many version controlled +buffers. CPU usage depends on the version control system" + :group 'auto-revert + :type 'boolean + :version "21.4") + (defvar global-auto-revert-ignore-buffer nil "*When non-nil, Global Auto-Revert Mode will not revert this buffer. This variable becomes buffer local when set in any fashion.") (make-variable-buffer-local 'global-auto-revert-ignore-buffer) - ;; Internal variables: (defvar auto-revert-buffer-list '() @@ -181,9 +234,6 @@ buffers to this list. The timer function `auto-revert-buffers' is responsible for purging the list of old buffers.") -(defvar auto-revert-timer nil - "Timer used by Auto-Revert Mode.") - (defvar auto-revert-remaining-buffers '() "Buffers not checked when user input stopped execution.") @@ -219,7 +269,7 @@ This function is designed to be added to hooks, for example: ;;;###autoload (define-minor-mode global-auto-revert-mode - "Revert any buffer when file on disk change. + "Revert any buffer when file on disk changes. With arg, turn Auto Revert mode on globally if and only if arg is positive. This is a minor mode that affects all buffers. @@ -231,7 +281,12 @@ Use `auto-revert-mode' to revert a particular buffer." (defun auto-revert-set-timer () - "Restart or cancel the timer." + "Restart or cancel the timer used by Auto-Revert Mode. +If such a timer is active, cancel it. Start a new timer if +Global Auto-Revert Mode is active or if Auto-Revert Mode is active +in some buffer. Restarting the timer ensures that Auto-Revert Mode +will use an up-to-date value of `auto-revert-interval'" + (interactive) (if (timerp auto-revert-timer) (cancel-timer auto-revert-timer)) (setq auto-revert-timer @@ -241,6 +296,54 @@ Use `auto-revert-mode' to revert a particular buffer." 'auto-revert-buffers) nil))) +(defun auto-revert-active-p () + "Check if auto-revert is active (in current buffer or globally)." + (or auto-revert-mode + (and + global-auto-revert-mode + (not global-auto-revert-ignore-buffer) + (not (memq major-mode + global-auto-revert-ignore-modes))))) + +(defun auto-revert-handler () + "Revert current buffer, if appropriate. +This is an internal function used by Auto-Revert Mode." + (unless (buffer-modified-p) + (let ((buffer (current-buffer)) revert eob eoblist) + (or (and buffer-file-name + (file-readable-p buffer-file-name) + (not (verify-visited-file-modtime buffer)) + (setq revert t)) + (and (or auto-revert-mode global-auto-revert-non-file-buffers) + revert-buffer-function + (boundp 'buffer-stale-function) + (functionp buffer-stale-function) + (setq revert (funcall buffer-stale-function t)))) + (when revert + (when (and auto-revert-verbose + (not (eq revert 'fast))) + (message "Reverting buffer `%s'." (buffer-name))) + ;; If point (or a window point) is at the end of the buffer, + ;; we want to keep it at the end after reverting. This allows + ;; to tail a file. + (when buffer-file-name + (setq eob (eobp)) + (walk-windows + #'(lambda (window) + (and (eq (window-buffer window) buffer) + (= (window-point window) (point-max)) + (push window eoblist))) + 'no-mini t)) + (revert-buffer 'ignore-auto 'dont-ask 'preserve-modes) + (when buffer-file-name + (when eob (goto-char (point-max))) + (dolist (window eoblist) + (set-window-point window (point-max))))) + ;; `preserve-modes' avoids changing the (minor) modes. But we + ;; do want to reset the mode for VC, so we do it manually. + (when (or revert auto-revert-check-vc-info) + (vc-find-file-hook))))) + (defun auto-revert-buffers () "Revert buffers as specified by Auto-Revert and Global Auto-Revert Mode. @@ -249,10 +352,11 @@ Should `global-auto-revert-mode' be active all file buffers are checked. Should `auto-revert-mode' be active in some buffers, those buffers are checked. -Non-file buffers that have a custom `revert-buffer-function' are -reverted either when Auto-Revert Mode is active in that buffer, or -when the variable `global-auto-revert-non-file-buffers' is non-nil -and Global Auto-Revert Mode is active. +Non-file buffers that have a custom `revert-buffer-function' and +a `buffer-stale-function' are reverted either when Auto-Revert +Mode is active in that buffer, or when the variable +`global-auto-revert-non-file-buffers' is non-nil and Global +Auto-Revert Mode is active. This function stops whenever there is user input. The buffers not checked are stored in the variable `auto-revert-remaining-buffers'. @@ -291,27 +395,7 @@ the timer when no buffers need to be checked." (memq buf auto-revert-buffer-list)) (setq auto-revert-buffer-list (delq buf auto-revert-buffer-list))) - (when (and - (or auto-revert-mode - (and - global-auto-revert-mode - (not global-auto-revert-ignore-buffer) - (not (memq major-mode - global-auto-revert-ignore-modes)))) - (not (buffer-modified-p)) - (if (buffer-file-name) - (and (file-readable-p (buffer-file-name)) - (not (verify-visited-file-modtime buf))) - (and revert-buffer-function - (or (and global-auto-revert-mode - global-auto-revert-non-file-buffers) - auto-revert-mode)))) - (if auto-revert-verbose - (message "Reverting buffer `%s'." buf)) - (revert-buffer 'ignore-auto 'dont-ask 'preserve-modes) - ;; `preserve-modes' avoids changing the (minor) modes. But we - ;; do want to reset the mode for VC, so we do it explicitly. - (vc-find-file-hook))) + (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)))) @@ -329,4 +413,5 @@ the timer when no buffers need to be checked." (run-hooks 'auto-revert-load-hook) +;;; arch-tag: f6bcb07b-4841-477e-9e44-b18678e58876 ;;; autorevert.el ends here |