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.
This commit is contained in:
parent
0b2f550e32
commit
0bee4cda88
5 changed files with 86 additions and 29 deletions
|
@ -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
|
||||
|
|
12
lisp/subr.el
12
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."
|
||||
|
|
47
src/buffer.c
47
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);
|
||||
}
|
||||
|
|
11
src/fileio.c
11
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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue