From: Lars Ingebrigtsen Date: Mon, 23 Aug 2021 13:56:50 +0000 (+0200) Subject: Add new variable 'kill-buffer/delete-auto-save-files' X-Git-Tag: emacs-28.0.90~1342 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=591b8bd87a30bda3dad680752b7f63da8b5b74bd;p=emacs.git Add new variable 'kill-buffer/delete-auto-save-files' * doc/emacs/files.texi (Auto Save Files): Document it. * lisp/cus-start.el (standard): Add customize form. * lisp/files.el (delete-auto-save-files): Move definition to C (since it's used in the C layer). * src/buffer.c (Fkill_buffer): Use the new variable (and remove the old code that apparently didn't trigger for kill-buffer/delete-auto-save-files. (syms_of_buffer): Add new variable kill-buffer-delete-auto-save-files and move definition of delete-auto-save-files here (bug#21612). --- diff --git a/doc/emacs/files.texi b/doc/emacs/files.texi index 9aae0e9a0b3..9338e77859a 100644 --- a/doc/emacs/files.texi +++ b/doc/emacs/files.texi @@ -1191,6 +1191,13 @@ visited file. (You can inhibit this by setting the variable file name with @kbd{C-x C-w} or @code{set-visited-file-name} renames any auto-save file to go with the new visited name. +@vindex kill-buffer-delete-auto-save-files + Killing a buffer, by default, doesn't remove the buffer's auto-save +file. If @code{kill-buffer-delete-auto-save-files} is non-@code{nil}, +killing a buffer that has an auto-save file will make Emacs prompt the +user for whether the auto-save file should be deleted. (This is +inhibited is @code{delete-auto-save-files} is @code{nil}.) + @node Auto Save Control @subsection Controlling Auto-Saving diff --git a/etc/NEWS b/etc/NEWS index aefe582ad7c..b008c46291c 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -3824,12 +3824,22 @@ whenever the protected form terminates without error, with the specified variable bound to the the value of the protected form. +++ -** 'The 'uniquify' argument in 'auto-save-file-name-transforms' can be a symbol. +** The 'uniquify' argument in 'auto-save-file-name-transforms' can be a symbol. If this symbol is one of the members of 'secure-hash-algorithms', Emacs constructs the nondirectory part of the auto-save file name by applying that 'secure-hash' to the buffer file name. This avoids any risk of excessively long file names. ++++ +** New user option 'kill-buffer-delete-auto-save-files'. +If non-nil, killing a buffer that has an auto-save file will prompt +the user for whether that buffer should be deleted. (Note that +'delete-auto-save-files', if non-nil, was previously documented to +result in deletion of auto-save files when killing a buffer without +unsaved changes, but this has apparently not worked for several +decades, so the documented semantics of this variable has been changed +to match the behaviour.) + --- ** New user option 'etags-xref-prefer-current-file'. When non-nil, matches for identifiers in the file visited by the diff --git a/lisp/cus-start.el b/lisp/cus-start.el index 19975307894..1a3e5682bba 100644 --- a/lisp/cus-start.el +++ b/lisp/cus-start.el @@ -171,6 +171,8 @@ Leaving \"Default\" unchecked is equivalent with specifying a default of (const :tag "Right to Left" right-to-left) (const :tag "Dynamic, according to paragraph text" nil)) "24.1") + (delete-auto-save-files auto-save boolean) + (kill-buffer-delete-auto-save-files auto-save boolean "28.1") ;; callint.c (mark-even-if-inactive editing-basics boolean) ;; callproc.c diff --git a/lisp/files.el b/lisp/files.el index e519a8ea8b6..bd87b995756 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -42,15 +42,6 @@ "Finding files." :group 'files) - -(defcustom delete-auto-save-files t - "Non-nil means delete auto-save file when a buffer is saved or killed. - -Note that the auto-save file will not be deleted if the buffer is killed -when it has unsaved changes." - :type 'boolean - :group 'auto-save) - (defcustom directory-abbrev-alist nil "Alist of abbreviations for file directories. diff --git a/src/buffer.c b/src/buffer.c index 7e4c84911bb..7ba0c8bc2a6 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1768,6 +1768,7 @@ cleaning up all windows currently displaying the buffer to be killed. */) /* Run hooks with the buffer to be killed as the current buffer. */ { ptrdiff_t count = SPECPDL_INDEX (); + bool modified; record_unwind_protect_excursion (); set_buffer_internal (b); @@ -1782,9 +1783,12 @@ cleaning up all windows currently displaying the buffer to be killed. */) return unbind_to (count, Qnil); } + /* Is this a modified buffer that's visiting a file? */ + modified = !NILP (BVAR (b, filename)) + && BUF_MODIFF (b) > BUF_SAVE_MODIFF (b); + /* Query if the buffer is still modified. */ - if (INTERACTIVE && !NILP (BVAR (b, filename)) - && BUF_MODIFF (b) > BUF_SAVE_MODIFF (b)) + if (INTERACTIVE && modified) { AUTO_STRING (format, "Buffer %s modified; kill anyway? "); tem = do_yes_or_no_p (CALLN (Fformat, format, BVAR (b, name))); @@ -1792,6 +1796,17 @@ cleaning up all windows currently displaying the buffer to be killed. */) return unbind_to (count, Qnil); } + /* Delete the autosave file, if requested. */ + if (modified + && kill_buffer_delete_auto_save_files + && delete_auto_save_files + && !NILP (Frecent_auto_save_p ())) + { + tem = do_yes_or_no_p (build_string ("Delete auto-save file? ")); + if (!NILP (tem)) + call0 (intern ("delete-auto-save-file-if-necessary")); + } + /* If the hooks have killed the buffer, exit now. */ if (!BUFFER_LIVE_P (b)) return unbind_to (count, Qt); @@ -1888,24 +1903,6 @@ cleaning up all windows currently displaying the buffer to be killed. */) replace_buffer_in_windows_safely (buffer); Vinhibit_quit = tem; - /* Delete any auto-save file, if we saved it in this session. - But not if the buffer is modified. */ - if (STRINGP (BVAR (b, auto_save_file_name)) - && BUF_AUTOSAVE_MODIFF (b) != 0 - && BUF_SAVE_MODIFF (b) < BUF_AUTOSAVE_MODIFF (b) - && BUF_SAVE_MODIFF (b) < BUF_MODIFF (b) - && NILP (Fsymbol_value (intern ("auto-save-visited-file-name")))) - { - Lisp_Object delete; - delete = Fsymbol_value (intern ("delete-auto-save-files")); - if (! NILP (delete)) - internal_delete_file (BVAR (b, auto_save_file_name)); - } - - /* Deleting an auto-save file could have killed our buffer. */ - if (!BUFFER_LIVE_P (b)) - return Qt; - if (b->base_buffer) { INTERVAL i; @@ -6366,6 +6363,18 @@ nil NORECORD argument since it may lead to infinite recursion. */); Vbuffer_list_update_hook = Qnil; DEFSYM (Qbuffer_list_update_hook, "buffer-list-update-hook"); + DEFVAR_BOOL ("kill-buffer-delete-auto-save-files", + kill_buffer_delete_auto_save_files, + doc: /* If non-nil, offer to delete any autosave file when killing a buffer. + +If `delete-auto-save-files' is nil, any autosave deletion is inhibited. */); + kill_buffer_delete_auto_save_files = 0; + + DEFVAR_BOOL ("delete-auto-save-files", delete_auto_save_files, + doc: /* Non-nil means delete auto-save file when a buffer is saved. +This is the default. If nil, auto-save file deletion is inhibited. */); + delete_auto_save_files = 1; + defsubr (&Sbuffer_live_p); defsubr (&Sbuffer_list); defsubr (&Sget_buffer); diff --git a/test/src/buffer-tests.el b/test/src/buffer-tests.el index 118311c4d26..059926ff46b 100644 --- a/test/src/buffer-tests.el +++ b/test/src/buffer-tests.el @@ -1420,4 +1420,67 @@ with parameters from the *Messages* buffer modification." (remove-overlays) (should (= (length (overlays-in (point-min) (point-max))) 0)))) +(ert-deftest test-kill-buffer-auto-save-default () + (let ((file (make-temp-file "ert")) + auto-save) + (should (file-exists-p file)) + ;; Always answer yes. + (cl-letf (((symbol-function #'yes-or-no-p) (lambda (_) t))) + (unwind-protect + (progn + (find-file file) + (auto-save-mode t) + (insert "foo\n") + (should buffer-auto-save-file-name) + (setq auto-save buffer-auto-save-file-name) + (do-auto-save) + (should (file-exists-p auto-save)) + (kill-buffer (current-buffer)) + (should (file-exists-p auto-save))) + (ignore-errors (delete-file file)) + (when auto-save + (ignore-errors (delete-file auto-save))))))) + +(ert-deftest test-kill-buffer-auto-save-delete () + (let ((file (make-temp-file "ert")) + auto-save) + (should (file-exists-p file)) + (setq kill-buffer-delete-auto-save-files t) + ;; Always answer yes. + (cl-letf (((symbol-function #'yes-or-no-p) (lambda (_) t))) + (unwind-protect + (progn + (find-file file) + (auto-save-mode t) + (insert "foo\n") + (should buffer-auto-save-file-name) + (setq auto-save buffer-auto-save-file-name) + (do-auto-save) + (should (file-exists-p auto-save)) + ;; This should delete the auto-save file. + (kill-buffer (current-buffer)) + (should-not (file-exists-p auto-save))) + (ignore-errors (delete-file file)) + (when auto-save + (ignore-errors (delete-file auto-save))))) + ;; Answer no to deletion. + (cl-letf (((symbol-function #'yes-or-no-p) + (lambda (prompt) + (not (string-search "Delete auto-save file" prompt))))) + (unwind-protect + (progn + (find-file file) + (auto-save-mode t) + (insert "foo\n") + (should buffer-auto-save-file-name) + (setq auto-save buffer-auto-save-file-name) + (do-auto-save) + (should (file-exists-p auto-save)) + ;; This should not delete the auto-save file. + (kill-buffer (current-buffer)) + (should (file-exists-p auto-save))) + (ignore-errors (delete-file file)) + (when auto-save + (ignore-errors (delete-file auto-save))))))) + ;;; buffer-tests.el ends here