* 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).
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
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
(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
"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.
/* 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);
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)));
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);
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;
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);
(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