]> git.eshelyaron.com Git - emacs.git/commitdiff
Reimplement recent with-silent-modifications auto-save changes
authorLars Ingebrigtsen <larsi@gnus.org>
Tue, 10 May 2022 01:38:01 +0000 (03:38 +0200)
committerLars Ingebrigtsen <larsi@gnus.org>
Tue, 10 May 2022 01:46:43 +0000 (03:46 +0200)
* 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.

doc/lispref/buffers.texi
lisp/subr.el
src/buffer.c
src/fileio.c
test/src/buffer-tests.el

index d8cf3d7919bb30172231f643f4f0a3fed6db9ae8..3e3b0bd9f01ac525ed62dce4d9cf2e801be50fa6 100644 (file)
@@ -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
index 01549cc6f749c6428686de91ca76439f310afd08..54c9f35264de7bd9075c98641696fd5980610ea2 100644 (file)
@@ -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."
index 6334e197f0e2963d5993d4e3a5c452bed4e511b3..f54714675e2a1474f6a427fbcaafac06b2757d8e 100644 (file)
@@ -1376,12 +1376,23 @@ No argument or nil as argument means use current buffer as BUFFER.  */)
 \f
 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);
 }
index 0610f7235a58e0d507e7007d437b168d7fb2f05f..9da14c8f54131b08b88bfc78a1bc672c8d652b5d 100644 (file)
@@ -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)
 {
index c1e5d0ebed3932e4b00d91c0b960cf2c5e4c949c..10dac68f9feddf95e9aa6be6cfc801ba2ff4d227 100644 (file)
@@ -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