summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Ingebrigtsen <larsi@gnus.org>2022-05-10 03:38:01 +0200
committerLars Ingebrigtsen <larsi@gnus.org>2022-05-10 03:46:43 +0200
commit0bee4cda881f7db4113cba541b684c334e828c4a (patch)
tree4873dc599fb34e07c5e967ea5d91cb867c151c1b
parent0b2f550e3229c7a1b001fb1a09e7a5b4e3ecfb3e (diff)
downloademacs-0bee4cda881f7db4113cba541b684c334e828c4a.tar.gz
Reimplement recent with-silent-modifications auto-save changes
* doc/lispref/buffers.texi (Buffer Modification): Document buffer-modified-p returning `autosaved'. * lisp/subr.el (with-silent-modifications): Use restore-buffer-modified-p instead of altering the buffer modiff (since this has other side effects like not updating after async `display' changes. * src/buffer.c (Fbuffer_modified_p): Allow returning whether the buffer has been autosaved after changes. (Frestore_buffer_modified_p): Allow adjusting whether the buffer has been autosaved after changes. * src/fileio.c (Fdo_auto_save): Refill the doc string.
-rw-r--r--doc/lispref/buffers.texi10
-rw-r--r--lisp/subr.el12
-rw-r--r--src/buffer.c47
-rw-r--r--src/fileio.c11
-rw-r--r--test/src/buffer-tests.el35
5 files changed, 86 insertions, 29 deletions
diff --git a/doc/lispref/buffers.texi b/doc/lispref/buffers.texi
index d8cf3d7919b..3e3b0bd9f01 100644
--- a/doc/lispref/buffers.texi
+++ b/doc/lispref/buffers.texi
@@ -541,10 +541,12 @@ file formerly visited.
@ref{Text}.
@defun buffer-modified-p &optional buffer
-This function returns @code{t} if the buffer @var{buffer} has been modified
-since it was last read in from a file or saved, or @code{nil}
-otherwise. If @var{buffer} is not supplied, the current buffer
-is tested.
+This function returns non-@code{nil} if the buffer @var{buffer} has
+been modified since it was last read in from a file or saved, or
+@code{nil} otherwise. If @var{buffer} has been autosaved after
+@var{buffer} was last modified, the symbol @code{autosaved} is
+returned. If @var{buffer} is not supplied, the current buffer is
+tested.
@end defun
@defun set-buffer-modified-p flag
diff --git a/lisp/subr.el b/lisp/subr.el
index 01549cc6f74..54c9f35264d 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -4594,21 +4594,17 @@ like `buffer-modified-p', checking whether the file is locked by
someone else, running buffer modification hooks, and other things
of that nature."
(declare (debug t) (indent 0))
- (let ((modified (make-symbol "modified"))
- (tick (make-symbol "tick")))
+ (let ((modified (make-symbol "modified")))
`(let* ((,modified (buffer-modified-p))
- (,tick (buffer-modified-tick))
(buffer-undo-list t)
(inhibit-read-only t)
(inhibit-modification-hooks t))
(unwind-protect
(progn
,@body)
- ;; We restore the buffer tick count, too, because otherwise
- ;; we'll trigger a new auto-save.
- (internal--set-buffer-modified-tick ,tick)
- (unless ,modified
- (restore-buffer-modified-p nil))))))
+ (when (or (not ,modified)
+ (eq ,modified 'autosaved))
+ (restore-buffer-modified-p ,modified))))))
(defmacro with-output-to-string (&rest body)
"Execute BODY, return the text it sent to `standard-output', as a string."
diff --git a/src/buffer.c b/src/buffer.c
index 6334e197f0e..f54714675e2 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -1376,12 +1376,23 @@ No argument or nil as argument means use current buffer as BUFFER. */)
DEFUN ("buffer-modified-p", Fbuffer_modified_p, Sbuffer_modified_p,
0, 1, 0,
- doc: /* Return t if BUFFER was modified since its file was last read or saved.
-No argument or nil as argument means use current buffer as BUFFER. */)
+ doc: /* Return non-nil if BUFFER was modified since its file was last read or saved.
+No argument or nil as argument means use current buffer as BUFFER.
+
+If BUFFER has been autosaved after BUFFER was last modified, the
+symbol `autosaved' is returned. */)
(Lisp_Object buffer)
{
struct buffer *buf = decode_buffer (buffer);
- return BUF_SAVE_MODIFF (buf) < BUF_MODIFF (buf) ? Qt : Qnil;
+ if (BUF_SAVE_MODIFF (buf) < BUF_MODIFF (buf))
+ {
+ if (BUF_AUTOSAVE_MODIFF (buf) == BUF_MODIFF (buf))
+ return Qautosaved;
+ else
+ return Qt;
+ }
+ else
+ return Qnil;
}
DEFUN ("force-mode-line-update", Fforce_mode_line_update,
@@ -1436,6 +1447,11 @@ and `buffer-file-truename' are non-nil. */)
DEFUN ("restore-buffer-modified-p", Frestore_buffer_modified_p,
Srestore_buffer_modified_p, 1, 1, 0,
doc: /* Like `set-buffer-modified-p', but doesn't redisplay buffer's mode line.
+A nil FLAG means to mark the buffer as unmodified. A non-nil FLAG
+means mark the buffer as modified, except the special value
+`autosaved', which will instead mark the buffer as having been
+autosaved.
+
This function also locks or unlocks the file visited by the buffer,
if both `buffer-file-truename' and `buffer-file-name' are non-nil.
@@ -1475,16 +1491,19 @@ state of the current buffer. Use with care. */)
recent-auto-save-p from t to nil.
Vice versa, if FLAG is non-nil and SAVE_MODIFF>=auto_save_modified
we risk changing recent-auto-save-p from nil to t. */
- SAVE_MODIFF = (NILP (flag)
- /* FIXME: This unavoidably sets recent-auto-save-p to nil. */
- ? MODIFF
- /* Let's try to preserve recent-auto-save-p. */
- : SAVE_MODIFF < MODIFF ? SAVE_MODIFF
- /* If SAVE_MODIFF == auto_save_modified == MODIFF,
- we can either decrease SAVE_MODIFF and auto_save_modified
- or increase MODIFF. */
- : modiff_incr (&MODIFF));
-
+ if (NILP (flag))
+ /* This unavoidably sets recent-auto-save-p to nil. */
+ SAVE_MODIFF = MODIFF;
+ else
+ {
+ if (EQ (flag, Qautosaved))
+ BUF_AUTOSAVE_MODIFF (b) = MODIFF;
+ /* If SAVE_MODIFF == auto_save_modified == MODIFF, we can either
+ decrease SAVE_MODIFF and auto_save_modified or increase
+ MODIFF. */
+ else if (SAVE_MODIFF >= MODIFF)
+ SAVE_MODIFF = modiff_incr (&MODIFF);
+ }
return flag;
}
@@ -6465,5 +6484,7 @@ will run for `clone-indirect-buffer' calls as well. */);
defsubr (&Soverlay_put);
defsubr (&Srestore_buffer_modified_p);
+ DEFSYM (Qautosaved, "autosaved");
+
Fput (intern_c_string ("erase-buffer"), Qdisabled, Qt);
}
diff --git a/src/fileio.c b/src/fileio.c
index 0610f7235a5..9da14c8f541 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -5972,14 +5972,17 @@ do_auto_save_eh (Lisp_Object ignore)
DEFUN ("do-auto-save", Fdo_auto_save, Sdo_auto_save, 0, 2, "",
doc: /* Auto-save all buffers that need it.
-This is all buffers that have auto-saving enabled
-and are changed since last auto-saved.
-Auto-saving writes the buffer into a file
-so that your editing is not lost if the system crashes.
+This is all buffers that have auto-saving enabled and are changed
+since last auto-saved.
+
+Auto-saving writes the buffer into a file so that your editing is not
+lost if the system crashes.
+
This file is not the file you visited; that changes only when you save.
Normally, run the normal hook `auto-save-hook' before saving.
A non-nil NO-MESSAGE argument means do not print any message if successful.
+
A non-nil CURRENT-ONLY argument means save only current buffer. */)
(Lisp_Object no_message, Lisp_Object current_only)
{
diff --git a/test/src/buffer-tests.el b/test/src/buffer-tests.el
index c1e5d0ebed3..10dac68f9fe 100644
--- a/test/src/buffer-tests.el
+++ b/test/src/buffer-tests.el
@@ -1482,4 +1482,39 @@ with parameters from the *Messages* buffer modification."
(when auto-save
(ignore-errors (delete-file auto-save))))))))
+(ert-deftest test-buffer-modifications ()
+ (ert-with-temp-file file
+ (with-current-buffer (find-file file)
+ (auto-save-mode 1)
+ (should-not (buffer-modified-p))
+ (insert "foo")
+ (should (buffer-modified-p))
+ (should-not (eq (buffer-modified-p) 'autosaved))
+ (do-auto-save nil t)
+ (should (eq (buffer-modified-p) 'autosaved))
+ (with-silent-modifications
+ (put-text-property 1 3 'face 'bold))
+ (should (eq (buffer-modified-p) 'autosaved))
+ (save-buffer)
+ (should-not (buffer-modified-p))
+ (with-silent-modifications
+ (put-text-property 1 3 'face 'italic))
+ (should-not (buffer-modified-p)))))
+
+(ert-deftest test-restore-buffer-modified-p ()
+ (ert-with-temp-file file
+ (with-current-buffer (find-file file)
+ (auto-save-mode 1)
+ (should-not (buffer-modified-p))
+ (insert "foo")
+ (should (buffer-modified-p))
+ (restore-buffer-modified-p nil)
+ (should-not (buffer-modified-p))
+ (insert "bar")
+ (do-auto-save nil t)
+ (should (eq (buffer-modified-p) 'autosaved))
+ (insert "zot")
+ (restore-buffer-modified-p 'autosaved)
+ (should (eq (buffer-modified-p) 'autosaved)))))
+
;;; buffer-tests.el ends here