diff --git a/doc/lispref/backups.texi b/doc/lispref/backups.texi index 50c7ace253c..f3f0902f364 100644 --- a/doc/lispref/backups.texi +++ b/doc/lispref/backups.texi @@ -852,6 +852,30 @@ It is important to assure that point does not continuously jump around as a consequence of auto-reverting. Of course, moving point might be inevitable if the buffer radically changes. +@defvar inhibit-auto-revert-buffers +When the current buffer is member of this variable (a list of buffers), +auto-reverting is suppressed for that buffer. This is useful if serious +changes are applied to that buffer which would be poisoned by an +unexpected auto-revert. After the change is finished, the buffer shall +be removed from @code{inhibit-auto-revert-buffers}. + +The check of membership in @code{inhibit-auto-revert-buffers} is applied +prior to the call of @code{buffer-stale-function}; any heavy check in +that function is avoided, therefore. + +If auto-reverting is triggered by file notification while +@code{inhibit-auto-revert-buffers} prevents this, auto-revert will +happen next time the buffer is polled for changes, unless +@code{auto-revert-avoid-polling} is non-@code{nil}. @pxref{(emacs) Auto +Revert}. +@end defvar + +@defmac inhibit-auto-revert &rest body +This macro adds the current buffer to +@code{inhibit-auto-revert-buffers}, runs @var{body}, and removes the +current buffer from @code{inhibit-auto-revert-buffers} afterwards. +@end defmac + You should make sure that the @code{revert-buffer-function} does not print messages that unnecessarily duplicate Auto Revert's own messages, displayed if @code{auto-revert-verbose} is @code{t}, and effectively diff --git a/etc/NEWS b/etc/NEWS index 8cf86d1375d..2464598c6d1 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -41,12 +41,12 @@ incorrectly in rare cases. ** In compatible terminals, 'xterm-mouse-mode' is turned on by default. For these terminals the mouse will work by default. A compatible -terminal is one that supports Emacs seting and getting the OS selection +terminal is one that supports Emacs setting and getting the OS selection data (a.k.a. the clipboard) and mouse button and motion events. With -xterm-mouse-mode enabled, you must use Emacs keybindings to copy to the +'xterm-mouse-mode' enabled, you must use Emacs keybindings to copy to the OS selection instead of terminal-specific keybindings. -You can keep the old behavior by putting `(xterm-mouse-mode -1)' in your +You can keep the old behavior by putting '(xterm-mouse-mode -1)' in your init file. @@ -75,7 +75,7 @@ In particular: To enable tooltips on TTY frames, call 'tty-tip-mode'. The presence of child frame support on TTY frames can be checked with -`(featurep 'tty-child-frames)'. +'(featurep 'tty-child-frames)'. Recent versions of Posframe and Corfu are known to use child frames on TTYs if they are supported. @@ -108,7 +108,7 @@ instead of its now-obsolete variable. ** Network Security Manager (NSM) is now more strict. *** NSM warns about TLS 1.1 by default. -It has been deprecated by RFC8996, published in 2021. +It has been deprecated by RFC 8996, published in 2021. *** NSM warns about DHE and RSA key exchange by default. Emacs now warns about ephemeral Diffie-Hellman key exchange, and static @@ -181,13 +181,9 @@ the "*Completions*" buffer is hidden. +++ *** New functions to modify window layout. Several functions to modify the window layout have been added: -'rotate-window-layout-clockwise' -'rotate-window-layout-anticlockwise' -'flip-window-layout-vertically' -'flip-window-layout-horizontally' -'transpose-window-layout' -'rotate-windows' -'rotate-windows-back' +'rotate-window-layout-clockwise', 'rotate-window-layout-anticlockwise', +'flip-window-layout-vertically', 'flip-window-layout-horizontally', +'transpose-window-layout', 'rotate-windows', and 'rotate-windows-back'. +++ *** New hook 'window-deletable-functions'. @@ -254,11 +250,11 @@ adjustment when a tab is restored, and avoids advice. *** New user option 'tab-bar-define-keys'. This controls which key bindings tab-bar creates. Values are t, the default, which defines all keys and is backwards compatible, 'numeric' -(tab number selection only), 'tab' (TAB and SHIFT-TAB keys only), nil +(tab number selection only), 'tab' ('TAB' and 'S-TAB' keys only), nil (which defines none). This is useful to avoid key binding conflicts, such as when folding in -outline mode using TAB keys, or when a user wants to define her own +outline mode using 'TAB' keys, or when a user wants to define her own tab-bar keys without first having to remove the defaults. --- @@ -386,13 +382,15 @@ modal editing packages. --- ** ASM mode + *** 'asm-mode-set-comment-hook' is obsolete. You can now set `asm-comment-char' from 'asm-mode-hook' instead. --- ** Ibuffer + *** New column 'recency' in Ibuffer display. -The variable 'ibuffer-formats' configures the Ibuffer formats. Add +The user option 'ibuffer-formats' configures the Ibuffer formats. Add 'recency' to the format to display the column. *** New value 'title' for the user option 'ibuffer-use-header-line'. @@ -404,11 +402,13 @@ When non-nil, buffer sizes are shown in human readable format. --- ** Buffer Menu + *** New user option 'Buffer-menu-human-readable-sizes'. When non-nil, buffer sizes are shown in human readable format. The default is nil, which retains the old format. ** Smerge + *** New command 'smerge-extend' extends a conflict over surrounding lines. ** Image Dired @@ -430,7 +430,7 @@ a web browser to load them. For example, it could be used like this: For better integration with the Qutebrowser, set 'browse-url(-secondary)-browser-function' to 'browse-url-qutebrowser'. -*** New GTK-native launch mode +*** New GTK-native launch mode. For better Wayland support, the pgtk toolkit exposes a new 'x-gtk-launch-uri' browse-url handler and uses it by default when URLs are browsed from a PGTK frame. For other frames, we fall back to the @@ -469,16 +469,15 @@ compatible. --- *** You can now regularly auto-save places. -Customize 'save-place-autosave-interval' to the number of seconds -between auto saving places. For example, to save places every 5 +Customize user option 'save-place-autosave-interval' to the number of +seconds between auto saving places. For example, to save places every 5 minutes: - M-x customize-option RET save-place-autosave-interval RET and set to - 300 seconds. + M-x customize-option RET save-place-autosave-interval RET 300 -Or in elisp: +Or in Elisp: - (setopt save-place-autosave-interval (* 60 5)) + (setopt save-place-autosave-interval (* 60 5)) If 'save-place-autosave-interval' is nil, auto saving is disabled; this is the default. As before, saved places are scheduled to be saved at @@ -680,7 +679,6 @@ build tags for the test commands. The 'go-ts-mode-test-flags' user option is available to set a list of additional flags to pass to the go test command line. - ** C-ts mode +++ @@ -901,13 +899,13 @@ the 'grep' results editable. The edits will be reflected in the buffer visiting the originating file. Typing 'C-c C-c' will leave the Grep Edit mode. -** time-stamp +** Time Stamp --- *** 'time-stamp' can up-case, capitalize and down-case date words. This control can be useful in languages in which days of the week and/or month names are capitalized only at the beginning of a sentence. For -details, see the built-in documentation for variable 'time-stamp-format'. +details, see the built-in documentation for user option 'time-stamp-format'. Because this feature is new in Emacs 31.1, do not use it in the local variables section of any file that might be edited by an older version @@ -915,12 +913,12 @@ of Emacs. --- *** Some historical 'time-stamp' conversions now warn. -'time-stamp-pattern' and 'time-stamp-format' had quietly -accepted several 'time-stamp' conversions (e.g., "%:y") that -have been deprecated since Emacs 27.1 (released in 2020). -These now generate a warning with a suggested migration. +'time-stamp-pattern' and 'time-stamp-format' had quietly accepted +several 'time-stamp' conversions (e.g., "%:y") that have been deprecated +since Emacs 27.1. These now generate a warning with a suggested +migration. -Merely having "(add-hook 'before-save-hook 'time-stamp)" +Merely having '(add-hook 'before-save-hook 'time-stamp)' in your Emacs init file does not expose you to this change. However, if you set 'time-stamp-format' or 'time-stamp-pattern' with a file-local variable, you may be asked to update the value. @@ -1076,6 +1074,19 @@ destination window is chosen using 'display-buffer-alist'. Example: display-buffer-use-some-window) (some-window . mru)))) +** Autorevert + ++++ +*** New variable 'inhibit-auto-revert-buffers'. +While a buffer is member of this variable, a list of buffers, +auto-reverting of this buffer is suppressed. + ++++ +*** New macro 'inhibit-auto-revert'. +This macro adds the current buffer to 'inhibit-auto-revert-buffers', +runs its body, and removes the current buffer from +'inhibit-auto-revert-buffers' afterwards. + * New Modes and Packages in Emacs 31.1 @@ -1085,7 +1096,7 @@ destination window is chosen using 'display-buffer-alist'. Example: ** Nested backquotes are not supported any more in Pcase patterns. --- -** The obsolete variable `redisplay-dont-pause' has been removed. +** The obsolete variable 'redisplay-dont-pause' has been removed. ** The 'rx' category name 'chinese-two-byte' must now be spelled correctly. An old alternative name (without the first 'e') has been removed. @@ -1161,7 +1172,7 @@ authorize the invoked D-Bus method (for example via polkit). ** The customization group 'wp' has been removed. It has been obsolete since Emacs 26.1. Use the group 'text' instead. -** Changes in tree-sitter modes. +** Changes in tree-sitter modes +++ *** Indirect buffers can have their own parser list. @@ -1186,7 +1197,7 @@ override flag by 'treesit-font-lock-setting-query', 'treesit-font-lock-setting-feature', 'treesit-font-lock-setting-enable', and 'treesit-font-lock-setting-override'. -*** New treesit thing 'list'. +*** New tree-sitter thing 'list'. Unlike the existing thing 'sexp' that defines both lists and atoms, 'list' defines only lists to be navigated by 'forward-sexp'. The new function 'treesit-forward-sexp-list' uses 'list' @@ -1209,9 +1220,9 @@ used to communicate the tree-sitter parsing results to *** Tree-sitter enabled modes now properly support 'hs-minor-mode'. All commands from hideshow.el can selectively display blocks -defined by the new treesit thing 'list'. +defined by the new tree-sitter thing 'list'. -*** New treesit thing 'comment'. +*** New tree-sitter thing 'comment'. The new variable 'forward-comment-function' is set to the new function 'treesit-forward-comment' if a major mode defines the thing 'comment'. @@ -1223,26 +1234,26 @@ variable 'treesit-language-display-name-alist' holds the translations of language symbols where that translation is not trivial. +++ -*** New command 'treesit-explore' +*** New command 'treesit-explore'. This command replaces 'treesit-explore-mode'. It turns on 'treesit-explore-mode' if it’s not on, and pops up the explorer buffer if it’s already on. +++ -*** 'treesit-explore-mode' now supports local parsers +*** 'treesit-explore-mode' now supports local parsers. Now 'treesit-explore-mode' (or 'treesit-explore') prompts for a parser rather than a language, and it’s now possible to select a local parser at point to explore. +++ -*** New variable 'treesit-aggregated-simple-imenu-settings' +*** New variable 'treesit-aggregated-simple-imenu-settings'. This variable allows major modes to setup Imenu for multiple languages. -*** New function 'treesit-add-simple-indent-rules' +*** New function 'treesit-add-simple-indent-rules'. This new function makes it easier to customize indent rules for tree-sitter modes. -*** New variable 'treesit-simple-indent-override-rules' +*** New variable 'treesit-simple-indent-override-rules'. Users can customize this variable to add simple custom indentation rules for tree-sitter major modes. diff --git a/lisp/autorevert.el b/lisp/autorevert.el index 1dcfe8e911f..b6dd9fb9015 100644 --- a/lisp/autorevert.el +++ b/lisp/autorevert.el @@ -772,11 +772,37 @@ If the buffer needs to be reverted, do it now." (when auto-revert-notify-modified-p (auto-revert-handler))))) +;;;###autoload +(progn + (defvar inhibit-auto-revert-buffers nil + "A list of buffers with suppressed auto-revert.") + + (defmacro inhibit-auto-revert (&rest body) + "Deactivate auto-reverting of current buffer temporarily. +Run BODY." + (declare (indent 0) (debug ((form body) body))) + `(progn + ;; Cleanup. + (dolist (buf inhibit-auto-revert-buffers) + (unless (buffer-live-p buf) + (setq inhibit-auto-revert-buffers + (delq buf inhibit-auto-revert-buffers)))) + (let ((buf (and (not (memq (current-buffer) inhibit-auto-revert-buffers)) + (current-buffer)))) + (unwind-protect + (progn + (when buf (add-to-list 'inhibit-auto-revert-buffers buf)) + ,@body) + (when buf + (setq inhibit-auto-revert-buffers + (delq buf inhibit-auto-revert-buffers)))))))) + (defun auto-revert-active-p () "Check if auto-revert is active in current buffer." - (or auto-revert-mode - auto-revert-tail-mode - auto-revert--global-mode)) + (and (or auto-revert-mode + auto-revert-tail-mode + auto-revert--global-mode) + (not (memq (current-buffer) inhibit-auto-revert-buffers)))) (defun auto-revert-handler () "Revert current buffer, if appropriate. @@ -798,14 +824,17 @@ This is an internal function used by Auto-Revert Mode." (setq size (file-attribute-size (file-attributes buffer-file-name))))) - (funcall (or buffer-stale-function - #'buffer-stale--default-function) - t))) + (and (not (memq (current-buffer) + inhibit-auto-revert-buffers)) + (funcall (or buffer-stale-function + #'buffer-stale--default-function) + t)))) (and (or auto-revert-mode global-auto-revert-non-file-buffers) - (funcall (or buffer-stale-function - #'buffer-stale--default-function) - t)))) + (and (not (memq (current-buffer) inhibit-auto-revert-buffers)) + (funcall (or buffer-stale-function + #'buffer-stale--default-function) + t))))) eob eoblist) (setq auto-revert-notify-modified-p nil auto-revert--last-time (current-time)) diff --git a/lisp/dired.el b/lisp/dired.el index 2eb6546107a..91163186443 100644 --- a/lisp/dired.el +++ b/lisp/dired.el @@ -944,9 +944,6 @@ Return value is the number of files marked, or nil if none were marked." "")))) (and (> count 0) count))) -(defvar-local dired--inhibit-auto-revert nil - "A non-nil value prevents `auto-revert-mode' from reverting the buffer.") - (defmacro dired-map-over-marks (body arg &optional show-progress distinguish-one-marked) "Eval BODY with point on each marked line. Return a list of BODY's results. @@ -983,48 +980,48 @@ marked file, return (t FILENAME) instead of (FILENAME)." ;;endless loop. ;;This warning should not apply any longer, sk 2-Sep-1991 14:10. `(prog1 - (let ((dired--inhibit-auto-revert t) - (inhibit-read-only t) - case-fold-search found results) - (if (and ,arg (not (eq ,arg 'marked))) - (if (integerp ,arg) - (progn ;; no save-excursion, want to move point. - (dired-repeat-over-lines - ,arg - (lambda () - (if ,show-progress (sit-for 0)) - (setq results (cons ,body results)))) - (when (< ,arg 0) - (setq results (nreverse results))) - results) - ;; non-nil, non-integer, non-marked ARG means use current file: - (list ,body)) - (let ((regexp (dired-marker-regexp)) next-position) - (save-excursion - (goto-char (point-min)) - ;; remember position of next marked file before BODY - ;; can insert lines before the just found file, - ;; confusing us by finding the same marked file again - ;; and again and... - (setq next-position (and (re-search-forward regexp nil t) - (point-marker)) - found (not (null next-position))) - (while next-position - (goto-char next-position) - (if ,show-progress (sit-for 0)) - (setq results (cons ,body results)) - ;; move after last match - (goto-char next-position) - (forward-line 1) - (set-marker next-position nil) - (setq next-position (and (re-search-forward regexp nil t) - (point-marker))))) - (if (and ,distinguish-one-marked (= (length results) 1)) - (setq results (cons t results))) - (if found - results - (unless (eq ,arg 'marked) - (list ,body)))))) + (inhibit-auto-revert + (let ((inhibit-read-only t) + case-fold-search found results) + (if (and ,arg (not (eq ,arg 'marked))) + (if (integerp ,arg) + (progn ;; no save-excursion, want to move point. + (dired-repeat-over-lines + ,arg + (lambda () + (if ,show-progress (sit-for 0)) + (setq results (cons ,body results)))) + (when (< ,arg 0) + (setq results (nreverse results))) + results) + ;; non-nil, non-integer, non-marked ARG means use current file: + (list ,body)) + (let ((regexp (dired-marker-regexp)) next-position) + (save-excursion + (goto-char (point-min)) + ;; remember position of next marked file before BODY + ;; can insert lines before the just found file, + ;; confusing us by finding the same marked file again + ;; and again and... + (setq next-position (and (re-search-forward regexp nil t) + (point-marker)) + found (not (null next-position))) + (while next-position + (goto-char next-position) + (if ,show-progress (sit-for 0)) + (setq results (cons ,body results)) + ;; move after last match + (goto-char next-position) + (forward-line 1) + (set-marker next-position nil) + (setq next-position (and (re-search-forward regexp nil t) + (point-marker))))) + (if (and ,distinguish-one-marked (= (length results) 1)) + (setq results (cons t results))) + (if found + results + (unless (eq ,arg 'marked) + (list ,body))))))) ;; save-excursion loses, again (dired-move-to-filename))) @@ -1294,12 +1291,6 @@ This feature is used by Auto Revert mode." ;; Do not auto-revert when the dired buffer can be currently ;; written by the user as in `wdired-mode'. buffer-read-only - ;; When a dired operation using dired-map-over-marks is in - ;; progress, dired--inhibit-auto-revert is bound to some - ;; non-nil value and we must not auto-revert because that could - ;; change the order of files leading to skipping or - ;; double-processing (see bug#75626). - (not dired--inhibit-auto-revert) (dired-directory-changed-p dirname)))) (defcustom dired-auto-revert-buffer nil @@ -4089,26 +4080,26 @@ non-empty directories is allowed." (while l (goto-char (marker-position (cdr (car l)))) (dired-move-to-filename) - (let ((inhibit-read-only t) - ;; Temporarily prevent auto-revert while deleting - ;; entry in the dired buffer (bug#71264). - (dired--inhibit-auto-revert t)) - (condition-case err - (let ((fn (car (car l)))) - (dired-delete-file fn dired-recursive-deletes trash) - ;; if we get here, removing worked - (setq succ (1+ succ)) - (progress-reporter-update progress-reporter succ) - (dired-fun-in-all-buffers - (file-name-directory fn) (file-name-nondirectory fn) - #'dired-delete-entry fn) - ;; For when FN's directory name is different - ;; from the current buffer's dired-directory. - (dired-delete-entry fn)) - (quit (throw '--delete-cancel (message "OK, canceled"))) - (error ;; catch errors from failed deletions - (dired-log "%s: %s\n" (car err) (error-message-string err)) - (setq failures (cons (car (car l)) failures))))) + ;; Temporarily prevent auto-revert while deleting entry in + ;; the dired buffer (bug#71264). + (inhibit-auto-revert + (let ((inhibit-read-only t)) + (condition-case err + (let ((fn (car (car l)))) + (dired-delete-file fn dired-recursive-deletes trash) + ;; if we get here, removing worked + (setq succ (1+ succ)) + (progress-reporter-update progress-reporter succ) + (dired-fun-in-all-buffers + (file-name-directory fn) (file-name-nondirectory fn) + #'dired-delete-entry fn) + ;; For when FN's directory name is different + ;; from the current buffer's dired-directory. + (dired-delete-entry fn)) + (quit (throw '--delete-cancel (message "OK, canceled"))) + (error ;; catch errors from failed deletions + (dired-log "%s: %s\n" (car err) (error-message-string err)) + (setq failures (cons (car (car l)) failures)))))) (setq l (cdr l))) (if (not failures) (progress-reporter-done progress-reporter) diff --git a/test/lisp/autorevert-tests.el b/test/lisp/autorevert-tests.el index 5e46216cc42..319f3285d2d 100644 --- a/test/lisp/autorevert-tests.el +++ b/test/lisp/autorevert-tests.el @@ -687,6 +687,41 @@ This expects `auto-revert--messages' to be bound by (auto-revert--deftest-remote auto-revert-test07-auto-revert-several-buffers "Check autorevert for several buffers visiting the same remote file.") +(ert-deftest auto-revert-test08-auto-revert-inhibit-auto-revert () + "Check the power of `inhibit-auto-revert'." + ;; `auto-revert-buffers' runs every 5". And we must wait, until the + ;; file has been reverted. + (with-auto-revert-test + (ert-with-temp-file tmpfile + (let ((times '(60 30 15)) + buf) + (unwind-protect + (progn + (auto-revert-tests--write-file "any text" tmpfile (pop times)) + (setq buf (find-file-noselect tmpfile)) + (with-current-buffer buf + (ert-with-message-capture auto-revert--messages + (inhibit-auto-revert + (auto-revert-mode 1) + (should auto-revert-mode) + + (auto-revert-tests--write-file "another text" tmpfile (pop times)) + ;; Check, that the buffer hasn't been reverted. + (auto-revert--wait-for-revert buf) + (should-not (string-match "another text" (buffer-string)))) + + ;; Check, that the buffer has been reverted. + (auto-revert--wait-for-revert buf) + (should (string-match "another text" (buffer-string)))))) + + ;; Exit. + (ignore-errors + (with-current-buffer buf (set-buffer-modified-p nil)) + (kill-buffer buf))))))) + +(auto-revert--deftest-remote auto-revert-test08-auto-revert-inhibit-auto-revert + "Check the power of `inhibit-auto-revert' on a remote file.") + ;; Mark all tests as unstable on Cygwin (bug#49665). (when (eq system-type 'cygwin) (dolist (test (apropos-internal "^auto-revert" #'ert-test-boundp))