* bug#18: Fine-grained revert-buffer
[not found] <jwvpruii0xr.fsf@iro.umontreal.ca>
@ 2013-12-17 3:16 ` Dmitry Gutov
2013-12-17 13:32 ` Stefan Monnier
2018-04-12 6:21 ` Toon Claes
2019-04-26 22:42 ` Mauro Aranda
2 siblings, 1 reply; 24+ messages in thread
From: Dmitry Gutov @ 2013-12-17 3:16 UTC (permalink / raw)
To: Stefan Monnier; +Cc: 18
The described functionality seems to be more or less available now.
Stefan Monnier <monnier@iro.umontreal.ca> writes:
> Write a revert-buffer that uses something like `diff' and then applies
> the patch to the buffer, so as to better preserve markers and undo
> info.
`revert-buffer' now preserves undo history.
> This would be used in places where a revert-buffer is needed but the
> changes are expected to be small, e.g. in VC.
`diff-hl' (in GNU ELPA) has command `diff-hl-revert-hunk' which reverts
only the diff hunk around point.
^ permalink raw reply [flat|nested] 24+ messages in thread
* bug#18: Fine-grained revert-buffer
2013-12-17 3:16 ` bug#18: Fine-grained revert-buffer Dmitry Gutov
@ 2013-12-17 13:32 ` Stefan Monnier
0 siblings, 0 replies; 24+ messages in thread
From: Stefan Monnier @ 2013-12-17 13:32 UTC (permalink / raw)
To: Dmitry Gutov; +Cc: 18
>> Write a revert-buffer that uses something like `diff' and then applies
>> the patch to the buffer, so as to better preserve markers and undo
>> info.
> `revert-buffer' now preserves undo history.
It's still significantly coarser than using diff: revert-buffer is
treated as a single delete+insert, so only the markers before the first
modification or after the last modification are preserved.
Stefan
^ permalink raw reply [flat|nested] 24+ messages in thread
* bug#18: Fine-grained revert-buffer
[not found] <jwvpruii0xr.fsf@iro.umontreal.ca>
2013-12-17 3:16 ` bug#18: Fine-grained revert-buffer Dmitry Gutov
@ 2018-04-12 6:21 ` Toon Claes
2018-04-12 12:18 ` Stefan Monnier
2019-04-26 22:42 ` Mauro Aranda
2 siblings, 1 reply; 24+ messages in thread
From: Toon Claes @ 2018-04-12 6:21 UTC (permalink / raw)
To: Stefan Monnier, Dmitry Gutov; +Cc: 18
[-- Attachment #1: Type: text/plain, Size: 395 bytes --]
I was digging through some old bugs, in ran into this one.
> It's still significantly coarser than using diff: revert-buffer is
> treated as a single delete+insert, so only the markers before the first
> modification or after the last modification are preserved.
What does M-x diff-buffer-with-file not do what you are trying to
achieve?
Also M-x ediff-current-file might be usable.
-- Toon
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
^ permalink raw reply [flat|nested] 24+ messages in thread
* bug#18: Fine-grained revert-buffer
2018-04-12 6:21 ` Toon Claes
@ 2018-04-12 12:18 ` Stefan Monnier
2018-04-14 7:00 ` Toon Claes
0 siblings, 1 reply; 24+ messages in thread
From: Stefan Monnier @ 2018-04-12 12:18 UTC (permalink / raw)
To: Toon Claes; +Cc: 18, Dmitry Gutov
Hi,
> I was digging through some old bugs, in ran into this one.
>> It's still significantly coarser than using diff: revert-buffer is
>> treated as a single delete+insert, so only the markers before the first
>> modification or after the last modification are preserved.
> What does M-x diff-buffer-with-file not do what you are trying to
> achieve?
> Also M-x ediff-current-file might be usable.
Not sure I understand the question: neither of those modifies the
current buffer, right?
Stefan
^ permalink raw reply [flat|nested] 24+ messages in thread
* bug#18: Fine-grained revert-buffer
2018-04-12 12:18 ` Stefan Monnier
@ 2018-04-14 7:00 ` Toon Claes
2018-04-14 14:14 ` Stefan Monnier
0 siblings, 1 reply; 24+ messages in thread
From: Toon Claes @ 2018-04-14 7:00 UTC (permalink / raw)
To: Stefan Monnier; +Cc: 18, Dmitry Gutov
[-- Attachment #1: Type: text/plain, Size: 386 bytes --]
Stefan Monnier <monnier@IRO.UMontreal.CA> writes:
>> What does M-x diff-buffer-with-file not do what you are trying to
>> achieve?
>> Also M-x ediff-current-file might be usable.
>
> Not sure I understand the question: neither of those modifies the
> current buffer, right?
With ediff you can apply chunks, but I'm not sure what kind of an
interface you would like to have?
-- Toon
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
^ permalink raw reply [flat|nested] 24+ messages in thread
* bug#18: Fine-grained revert-buffer
2018-04-14 7:00 ` Toon Claes
@ 2018-04-14 14:14 ` Stefan Monnier
0 siblings, 0 replies; 24+ messages in thread
From: Stefan Monnier @ 2018-04-14 14:14 UTC (permalink / raw)
To: Toon Claes; +Cc: 18, Dmitry Gutov
> With ediff you can apply chunks, but I'm not sure what kind of an
> interface you would like to have?
Something like
M-x revert-buffer-with-fine-grain RET
Stefan
^ permalink raw reply [flat|nested] 24+ messages in thread
* bug#18: Fine-grained revert-buffer
[not found] <jwvpruii0xr.fsf@iro.umontreal.ca>
2013-12-17 3:16 ` bug#18: Fine-grained revert-buffer Dmitry Gutov
2018-04-12 6:21 ` Toon Claes
@ 2019-04-26 22:42 ` Mauro Aranda
2019-04-27 7:34 ` Eli Zaretskii
` (2 more replies)
2 siblings, 3 replies; 24+ messages in thread
From: Mauro Aranda @ 2019-04-26 22:42 UTC (permalink / raw)
To: 18
[-- Attachment #1.1: Type: text/plain, Size: 3416 bytes --]
Short story of how I got to this bug report:
For a while now, I've been wanting to contribute to Emacs by doing
something more than reporting bugs and try to provide trivial fixes for
the bugs I found. So I looked into emacs-devel, to read about
recomendations for beginning to contribute. Based on some of the mails
I found [1], it looks like working on some wishlist items or minor bugs
would be good. So I said to myself: OK, let's see what is the oldest
one still open. And here I am.
Now I'll make a summary of what I've understood from the bug report:
The wish is to have a command that would act like 'revert-buffer'
(e.g., modifying the buffer rightaway), but that tries to do a better job
preserving markers. Also, it is desirable that undo info is preserved.
It is known that 'revert-buffer' preserves undo info nowadays, but what I
understand is that it would be good to keep undo info of parts of the
total reverted change, so the undo of the reverted action can be made by
steps, and not as a single undo operation.
I think that the alternatives proposed after the report [2] do not
fulfill the wish because they do not modify the buffer immediately. I'm
not sure how they act in regards to preserving markers and the undo
info, though.
AFAIK, the functionality wanted is still not present, so I'd guess it's
still relevant to work in this matter.
So for a week or so now, I've been working in a command that does what I
think it is wanted. The command is called 'revert-buffer-by-hunks'
(I've added 'rbbh' as a prefix for sending the file for you to
see/test), because it calls 'diff' and then with the output patches the
buffer.
At first, I wrote a command that used diff-mode under the hood, but I've
been having troubles with preserving markers. So I took a step back,
and wrote a new function that patches the buffer with the contents of
the file visited on disk. With that done, I think it is time for me to
show what I've written so far, in order to:
1) Know if the functionality is present (I don't think so, but I believe
this is the first thing to know in order to advance).
2) There's still interest in having this command.
3) Know if working on this subject would be appreciated, or should I
move on to other things.
4) Receieve feedback, suggestions, fixes on things I'm sure I'm missing.
5) Discuss some of the questions that have arisen while I've been
working on this.
I'll wait for answers regarding to 1-4. With regards to 5, I would like
to read opinions about:
a) What variables would you think should be customizable?
b) After reverting by hunks, I think it would be desirable to navigate
through the hunks reverted and toggle their state (i.e., go back and
forth to the contents before the revert operation and the contens on
disk). That is because I think it would be kinda annoying to want to
undo some of the reverted hunks, and to do that having to undo
sequentially from the Nth hunk reverted to the desired one.
I attach a first draft of my work. I'm hoping to hear suggestions and
corrections to improve it.
Best regards,
Mauro.
[1]
http://lists.gnu.org/archive/html/emacs-devel/2018-07/msg00451.html
http://lists.gnu.org/archive/html/emacs-devel/2017-08/msg00675.html
http://lists.gnu.org/archive/html/emacs-devel/2013-10/msg00805.html
[2]
Command diff-hl-revert-hunk, from diff-hl package
Command diff-buffer-with-file
Command ediff-current-file
[-- Attachment #1.2: Type: text/html, Size: 4123 bytes --]
[-- Attachment #2: rbbh-bug18.el --]
[-- Type: text/x-emacs-lisp, Size: 9294 bytes --]
;;; rbbh.el --- Revert Buffer By Hunks -*- lexical-binding: t -*-
(require 'diff)
;; At least for now, this are defconst.
(defconst rbbh-diff-command "diff"
"Name of the command to run diff")
(defconst rbbh-diff-switches "--normal"
"Switches to pass to diff.")
(defconst rbbh-diff-change-command-regexp
(let ((rng "\\([0-9]+\\)\\(\\|,\\([0-9]+\\)\\)"))
(concat "^" rng "\\([acd]\\)" rng "$"))
"Regular expression that matches the change commands for each hunk
Should be in synch with the switch used to call diff.")
(defconst rbbh-diff-buffer-name "*RBBH-Diff*"
"The name of the diff buffer internally created by `rbbh--run-diff'.")
(defvar rbbh-current-diff-buffer-name nil
"Name of the current diff buffer.")
(defvar rbbh-total-hunks 0
"Total hunks in the diff output.")
;; If `diff' and `diff-mode' are not to be required, this function should be
;; changed to do a lot of what `diff-no-select' does.
(defun rbbh--run-diff (buf)
"Compare contents of buffer BUF with those of the file it visits.
Runs `rbbh-diff-command' command to make the comparison, and puts its output
in a buffer, with basename `rbbh-diff-buffer-name'.
The command is run with the switches `rbbh-diff-switches'."
(let ((diff-command rbbh-diff-command)
(diff-use-labels nil)) ; Don't care about labels.
(setq rbbh-current-diff-buffer-name (generate-new-buffer
rbbh-diff-buffer-name))
(with-current-buffer buf
(diff-no-select buf buffer-file-name rbbh-diff-switches
t rbbh-current-diff-buffer-name))))
;; With this, reverted hunks can be undone one by one.
(defsubst rbbh--split-undo-hunk (buf)
"Force undo history to separate hunk replacements in buffer BUF."
(with-current-buffer buf
(undo-boundary)))
(defun rbbh-delete-line (&optional arg)
"Delete ARG lines (or the current line, if ARG is 0).
Does not put the killed text in the `kill-ring'. See `kill-whole-line' for
details on ARG."
(setq arg (or arg 1))
(if (and (> arg 0)
(eobp)
(save-excursion (forward-visible-line 0)
(eobp)))
(signal 'end-of-buffer nil))
(if (and (< arg 0)
(bobp)
(save-excursion (end-of-visible-line) (bobp)))
(signal 'beginning-of-buffer nil))
(cond ((zerop arg)
(delete-region (progn (forward-visible-line 0) (point))
(progn (end-of-visible-line) (point))))
((< arg 0)
(delete-region (progn (end-of-visible-line) (point))
(progn (forward-visible-line (1+ arg))
(unless (bobp)
(backward-char))
(point))))
(t
(delete-region (progn (forward-visible-line 0) (point))
(progn (forward-visible-line arg) (point))))))
(defsubst rbbh-count-total-hunks (diff-buf &optional change-command-re)
(with-current-buffer diff-buf
(save-excursion
(goto-char (point-min))
(let ((count 0)
(re (or change-command-re rbbh-diff-change-command-regexp)))
(while (re-search-forward re nil t)
(setq count (1+ count)))
count))))
(defsubst rbbh-get-hunk-contents (beg end)
"Get the hunk contents from positions BEG to END.
Expects that a diff buffer is the current buffer."
(let ((start (point)))
(forward-line (1+ (- beg end)))
(let ((text (buffer-substring start (point))))
;; Remember that we are using the --normal switch, hence the > and <
;; replacement.
(setq text (replace-regexp-in-string "^[><] " "" text))
text)))
(defun rbbh-patch-buffer (buf diff-buf)
"Patch the buffer BUF according to the contents of the diff buffer DIFF-BUF.
It works with a diff buffer that contains a --normal output from diff."
;; line-offset keeps memory of the lines added and deleted to the buffer BUF,
;; and it is necessary because the diff output will stay the same (line
;; references will stay relative to the unpatched buffer).
;; Added lines decrements offset, and deleted lines increment it.
(let ((line-offset 0)
(column (current-column))) ; To restore point just right.
(save-excursion
(with-current-buffer diff-buf
(goto-char (point-min))
(save-excursion
(while (re-search-forward rbbh-diff-change-command-regexp nil t)
(rbbh--split-undo-hunk buf) ; Make each change of hunk undoable.
(forward-line) ; skip the command.
;; Get ranges and the action, from the previous match.
(let* ((action-cmd (match-string 4))
(old-from (string-to-number (match-string 1)))
(old-to (if (match-beginning 3)
(string-to-number (match-string 3))
old-from))
(new-from (string-to-number (match-string 5)))
(new-to (if (match-beginning 7)
(string-to-number (match-string 7))
new-from)))
(cond ((equal action-cmd "a")
;; When adding, we take the text and remove > and <
;; (diff was called with --normal switch).
;; Then navigate to the line, accounting the offset,
;; and insert the text.
(let ((text (rbbh-get-hunk-contents new-to new-from)))
(with-current-buffer buf
(goto-char (point-min))
(forward-line (- old-from line-offset))
(setq line-offset (- line-offset (1+ (- new-to
new-from))))
(insert text))))
((equal action-cmd "d")
;; When deleting, navigate to the correct line and kill
;; as many lines as the range in the diff output says.
(with-current-buffer buf
(goto-char (point-min))
(forward-line (1- (- old-from line-offset)))
(setq line-offset (+ line-offset (1+
(- old-to old-from))))
(rbbh-delete-line (1+ (- old-to old-from)))))
((equal action-cmd "c")
;; When changing, is a combination of adding and deleting.
;; Get the text after "---", and act similar as we would
;; with adding.
;; But before, kill the lines, as we do when deleting.
(re-search-forward "^---")
(forward-line)
(let ((text (rbbh-get-hunk-contents new-to new-from)))
(with-current-buffer buf
(goto-char (point-min))
(forward-line (1- (- old-from line-offset)))
(rbbh-delete-line (1+ (- old-to old-from)))
(setq line-offset (+ line-offset (- old-to old-from)
new-from (- new-to)))
(insert text))))
(t
(error "Unknown command action in diff output"))))))))
(move-to-column column))) ; Restore column.
;; Not sure if the function would be a good candidate for
;; `revert-buffer-function'.
;; But just in case, make it take _ignore-auto as an argument.
;; Note that reverting with the contents of an auto save file is not supported.
;; It could be added, if suggested.
(defun rbbh-revert-buffer-by-hunks (&optional _ignore-auto noconfirm)
"Revert buffer by hunks, instead of doing a single deletion plus insertion.
This action is useful when you want to revert a buffer (like you would do with
`revert-buffer'), but then would like to undo some of the reverting.
When the buffer hasn't been modified, nothing is done.
This function is only useful for buffers visting files.
After reverting, it marks the buffer as not modified.
When NOCONFIRM is non-nil, don't ask for confirmation before reverting. The
other way of avoiding the query is provided by the variable
`revert-without-query'. Nevertheless, you will be always prompted, if the
file was changed externally.
The optional argument _IGNORE-AUTO is ignored and is provided only for
compatibility with `revert-buffer'. Thus, it is a candidate for the variable
`revert-buffer-function'."
(interactive)
(with-current-buffer (or (buffer-base-buffer (current-buffer))
(current-buffer))
(save-excursion
(let ((file-name buffer-file-name)
(buf (current-buffer))
;; Just in case we are not the revert-buffer-function.
(revert-buffer-in-progress-p t))
;; Repeat some of what revert-buffer--default does, because it is not
;; sure reverting by hunks is a candidate for revert-buffer-function.
(cond ((null file-name)
(error "Buffer does not seem to be associated with any file"))
((or (and (not (verify-visited-file-modtime buf))
(yes-or-no-p
(format "File %s was modified outside of Emacs. Really revert?"
file-name)))
noconfirm
;; Respect user choice.
(catch 'found
(dolist (regexp revert-without-query)
(when (string-match regexp file-name)
(throw 'found t))))
(yes-or-no-p (format "Revert buffer from file %s? "
file-name)))
(run-hooks 'before-revert-hook)
(rbbh--run-diff buf)
(rbbh-patch-buffer buf rbbh-current-diff-buffer-name)
;; Mark the buffer as not modified, like it would happen with
;; the default behavior of revert-buffer.
(set-buffer-modified-p nil)
;; Report to the user (this could be made optional).
(setq rbbh-total-hunks (rbbh-count-total-hunks
rbbh-current-diff-buffer-name))
(message "%d %s reverted" rbbh-total-hunks
(if (= rbbh-total-hunks 1)
"hunk"
"hunks"))
;; Kill the diff buffer we used.
(kill-buffer rbbh-current-diff-buffer-name)
(run-hooks 'after-revert-hook))
(t
(message "Revert aborted")))))))
(provide 'rbbh)
;;; rbbh.el ends here
^ permalink raw reply [flat|nested] 24+ messages in thread
* bug#18: Fine-grained revert-buffer
2019-04-26 22:42 ` Mauro Aranda
@ 2019-04-27 7:34 ` Eli Zaretskii
2019-04-27 15:10 ` Mauro Aranda
2019-04-27 8:31 ` martin rudalics
2019-04-28 2:47 ` Richard Stallman
2 siblings, 1 reply; 24+ messages in thread
From: Eli Zaretskii @ 2019-04-27 7:34 UTC (permalink / raw)
To: Mauro Aranda; +Cc: 18
> From: Mauro Aranda <maurooaranda@gmail.com>
> Date: Fri, 26 Apr 2019 19:42:02 -0300
>
> For a while now, I've been wanting to contribute to Emacs by doing
> something more than reporting bugs and try to provide trivial fixes for
> the bugs I found. So I looked into emacs-devel, to read about
> recomendations for beginning to contribute. Based on some of the mails
> I found [1], it looks like working on some wishlist items or minor bugs
> would be good. So I said to myself: OK, let's see what is the oldest
> one still open. And here I am.
Thanks!
> The wish is to have a command that would act like 'revert-buffer'
> (e.g., modifying the buffer rightaway), but that tries to do a better job
> preserving markers. Also, it is desirable that undo info is preserved.
> It is known that 'revert-buffer' preserves undo info nowadays, but what I
> understand is that it would be good to keep undo info of parts of the
> total reverted change, so the undo of the reverted action can be made by
> steps, and not as a single undo operation.
>
> I think that the alternatives proposed after the report [2] do not
> fulfill the wish because they do not modify the buffer immediately. I'm
> not sure how they act in regards to preserving markers and the undo
> info, though.
>
> AFAIK, the functionality wanted is still not present, so I'd guess it's
> still relevant to work in this matter.
Sounds correct to me.
> So for a week or so now, I've been working in a command that does what I
> think it is wanted. The command is called 'revert-buffer-by-hunks'
> (I've added 'rbbh' as a prefix for sending the file for you to
> see/test), because it calls 'diff' and then with the output patches the
> buffer.
>
> At first, I wrote a command that used diff-mode under the hood, but I've
> been having troubles with preserving markers. So I took a step back,
> and wrote a new function that patches the buffer with the contents of
> the file visited on disk. With that done, I think it is time for me to
> show what I've written so far, in order to:
>
> 1) Know if the functionality is present (I don't think so, but I believe
> this is the first thing to know in order to advance).
> 2) There's still interest in having this command.
> 3) Know if working on this subject would be appreciated, or should I
> move on to other things.
> 4) Receieve feedback, suggestions, fixes on things I'm sure I'm missing.
Please take a look at replace-buffer-contents, which is new with Emacs
26. It might allow you to implement this functionality in a much
simpler way, as it already contains an internal implementation of a
Diff-like comparison algorithm, and doesn't require the Diff program
to be installed.
One caveat: replace-buffer-contents can be very slow when the buffer
is large and reverting it requires a large number of small changes.
It will fall back to a simpler algorithm for large numbers of changes,
and could give up entirely if making the changes takes too much time,
see its doc string. Perhaps in those cases we should fall back to a
different code, like the one you wrote.
Did you time your code? How long does it take to revert buffers of
different sizes with different amounts of changes?
> a) What variables would you think should be customizable?
The name of the Diff command should be customizable. Or maybe just
use diff-command already provided by diff.el. Same with Diff
switches.
^ permalink raw reply [flat|nested] 24+ messages in thread
* bug#18: Fine-grained revert-buffer
2019-04-26 22:42 ` Mauro Aranda
2019-04-27 7:34 ` Eli Zaretskii
@ 2019-04-27 8:31 ` martin rudalics
2019-04-28 2:47 ` Richard Stallman
2 siblings, 0 replies; 24+ messages in thread
From: martin rudalics @ 2019-04-27 8:31 UTC (permalink / raw)
To: Mauro Aranda, 18
> 4) Receieve feedback, suggestions, fixes on things I'm sure I'm missing.
What's IMHO urgently needed are better heuristics for restoring
markers after reverting their buffer. Currently, most markers end up
at the beginning or end of a hunk that as been restored and thus
become useless.
What we probably need is an extra step to scan the buffer for markers
and save their textual context before reverting and a step to restore
them according to their textual context after reverting. But if your
method allows to easily determine which hunks remain unchanged, we
could avoid such textual search for markers in unchanged hunks and,
depending on the approach used for replacing text, simply restore
these markers from their offsets from the beginning of the hunk they
belong to.
Many thanks for working on this, martin
^ permalink raw reply [flat|nested] 24+ messages in thread
* bug#18: Fine-grained revert-buffer
2019-04-27 7:34 ` Eli Zaretskii
@ 2019-04-27 15:10 ` Mauro Aranda
2019-04-27 16:30 ` Eli Zaretskii
2019-04-29 12:49 ` martin rudalics
0 siblings, 2 replies; 24+ messages in thread
From: Mauro Aranda @ 2019-04-27 15:10 UTC (permalink / raw)
To: 18
[-- Attachment #1: Type: text/plain, Size: 4416 bytes --]
Eli and Martin, thanks for your answers.
Eli Zaretskii <eliz@gnu.org> writes:
> Please take a look at replace-buffer-contents, which is new with Emacs
> 26. It might allow you to implement this functionality in a much
> simpler way, as it already contains an internal implementation of a
> Diff-like comparison algorithm, and doesn't require the Diff program
> to be installed.
I didn't know of replace-buffer-contents, so I took a look at it. Nice
that its documentation even mentions the problem when a marker is
inside a hunk, because of the delete + insert thing (just like Martin
mentions). IMO, it does most of the things required, but here is one
problem I notice with respect to the expected functionality of
revert-buffer-by-hunks (as I've understood it):
It only calls Fundo_boundary before starting the whole set of
modifications, and thus after replacing the contents (in my tests, the
whole buffer), a single C-/ brings all the changes back, much like
revert-buffer. And since it binds inhibit-modification-hooks to t, I
think I can't bind locally after-change-functions to an expression that
calls undo-boundary, to do the trick.
Perhaps an optional call to Fundo_boundary in the while loop could be
enough, but I'm not sure how much it will impact on the speed of
replace-buffer-contents. Or more, if it is justified to add that call.
Please, point out to me if I'm not seeing this right.
Other than that, it looks like a perfect candidate to use (at least to me)
to get the functionality wanted.
> One caveat: replace-buffer-contents can be very slow when the buffer
> is large and reverting it requires a large number of small changes.
> It will fall back to a simpler algorithm for large numbers of changes,
> and could give up entirely if making the changes takes too much time,
> see its doc string. Perhaps in those cases we should fall back to a
> different code, like the one you wrote.
> Did you time your code? How long does it take to revert buffers of
> different sizes with different amounts of changes?
I haven't timed it yet. I didn't know if it would be considered good
enough, to time it. For a week, I've been testing it manually with some
of the changes in the Emacs sources, and the experience has been
satisfactory. Are there, by any chance, such tests for
replace-buffer-contents? I could use them, for comparison purposes.
I will try in the following days to define some parameters (such as
buffer size), and time revert-buffer-by-hunks, to provide some numbers.
Provided it is fast enough, I think something like replacing by hunks a
region would be a good fallback to replace-buffer-contents. I sure hope
so.
>> a) What variables would you think should be customizable?
>
> The name of the Diff command should be customizable. Or maybe just
> use diff-command already provided by diff.el. Same with Diff
> switches.
I agree. If using diff.el, it makes total sense to use those
variables. Of course, that means the patch-buffer function should
be modified to work on the different diff output formats (I think --context
and --unified should be enough). For the record, I don't propose to use
diff-apply-hunk and other diff-mode.el functions, because when I used
that, I ended up with markers at (point-min), I don't know why. But if
it is desired to reuse those functions instead of repeating code, I
think I will need time (and help, perhaps), to understand why that
happened.
martin rudalics <rudalics@gmx.at> writes:
> What we probably need is an extra step to scan the buffer for markers
> and save their textual context before reverting and a step to restore
> them according to their textual context after reverting. But if your
When I bumped into the problem of the marker being sent to the
beginning of the hunk, I started looking for something to get the
markers of the buffer, but didn't found anything at the Lisp level.
> method allows to easily determine which hunks remain unchanged, we
> could avoid such textual search for markers in unchanged hunks and,
> depending on the approach used for replacing text, simply restore
> these markers from their offsets from the beginning of the hunk they
> belong to.
Yes, I believe that by getting the diff output and with the line-offset
handling in the patch-buffer function, it would be easy to determine the
unchanged regions.
Thanks again to both of you.
Best regards,
Mauro.
[-- Attachment #2: Type: text/html, Size: 5232 bytes --]
^ permalink raw reply [flat|nested] 24+ messages in thread
* bug#18: Fine-grained revert-buffer
2019-04-27 15:10 ` Mauro Aranda
@ 2019-04-27 16:30 ` Eli Zaretskii
2019-04-27 17:46 ` Mauro Aranda
2019-04-29 12:49 ` martin rudalics
1 sibling, 1 reply; 24+ messages in thread
From: Eli Zaretskii @ 2019-04-27 16:30 UTC (permalink / raw)
To: Mauro Aranda; +Cc: 18
> From: Mauro Aranda <maurooaranda@gmail.com>
> Date: Sat, 27 Apr 2019 12:10:45 -0300
> Cc: Eli Zaretskii <eliz@gnu.org>, martin rudalics <rudalics@gmx.at>
>
> I didn't know of replace-buffer-contents, so I took a look at it. Nice
> that its documentation even mentions the problem when a marker is
> inside a hunk, because of the delete + insert thing (just like Martin
> mentions). IMO, it does most of the things required, but here is one
> problem I notice with respect to the expected functionality of
> revert-buffer-by-hunks (as I've understood it):
>
> It only calls Fundo_boundary before starting the whole set of
> modifications, and thus after replacing the contents (in my tests, the
> whole buffer), a single C-/ brings all the changes back, much like
> revert-buffer.
Is there a requirement to be able to undo the revert piecemeal? What
would be the use case for that?
> > Did you time your code? How long does it take to revert buffers of
> > different sizes with different amounts of changes?
>
> I haven't timed it yet. I didn't know if it would be considered good
> enough, to time it. For a week, I've been testing it manually with some
> of the changes in the Emacs sources, and the experience has been
> satisfactory. Are there, by any chance, such tests for
> replace-buffer-contents?
You can find one in bug#31888.
Also, this discussion:
http://lists.gnu.org/archive/html/help-gnu-emacs/2019-02/msg00000.html
indicates that using JSON pretty-printer might produce a good test
case.
^ permalink raw reply [flat|nested] 24+ messages in thread
* bug#18: Fine-grained revert-buffer
2019-04-27 16:30 ` Eli Zaretskii
@ 2019-04-27 17:46 ` Mauro Aranda
0 siblings, 0 replies; 24+ messages in thread
From: Mauro Aranda @ 2019-04-27 17:46 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: 18
[-- Attachment #1: Type: text/plain, Size: 1359 bytes --]
Eli Zaretskii <eliz@gnu.org> writes:
> Is there a requirement to be able to undo the revert piecemeal? What
> would be the use case for that?
Your questions made me open my eyes, so thanks. I originally thought
that it would be a good thing, for example if the user wants to revert some
of the changes but keep others. But that use case is already covered by
using diff-buffer-with-file, for example, and applying (or not) each hunk
separately. Even better, the undo process doesn't have to be from
the Nth hunk to the 1st, in order. So please, ignore what I said about
that problem, using replace-buffer-contents seems to be a great choice
to address this wishlist item.
>> I haven't timed it yet. I didn't know if it would be considered good
>> enough, to time it. For a week, I've been testing it manually with some
>> of the changes in the Emacs sources, and the experience has been
>> satisfactory. Are there, by any chance, such tests for
>> replace-buffer-contents?
>
> You can find one in bug#31888.
>
> Also, this discussion:
>
> http://lists.gnu.org/archive/html/help-gnu-emacs/2019-02/msg00000.html
>
> indicates that using JSON pretty-printer might produce a good test
> case.
Thanks.
I'll keep working on the potential fallback for replace-buffer-contents,
and report back when I feel I've made some progress.
Best regards,
Mauro.
[-- Attachment #2: Type: text/html, Size: 1754 bytes --]
^ permalink raw reply [flat|nested] 24+ messages in thread
* bug#18: Fine-grained revert-buffer
2019-04-26 22:42 ` Mauro Aranda
2019-04-27 7:34 ` Eli Zaretskii
2019-04-27 8:31 ` martin rudalics
@ 2019-04-28 2:47 ` Richard Stallman
2019-04-29 23:32 ` Mauro Aranda
2 siblings, 1 reply; 24+ messages in thread
From: Richard Stallman @ 2019-04-28 2:47 UTC (permalink / raw)
To: Mauro Aranda; +Cc: 18
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> So for a week or so now, I've been working in a command that does what I
> think it is wanted. The command is called 'revert-buffer-by-hunks'
> (I've added 'rbbh' as a prefix for sending the file for you to
> see/test), because it calls 'diff' and then with the output patches the
> buffer.
It sounds like an improvement in functionality,
but wouldn't it be a lot slower?
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
^ permalink raw reply [flat|nested] 24+ messages in thread
* bug#18: Fine-grained revert-buffer
2019-04-27 15:10 ` Mauro Aranda
2019-04-27 16:30 ` Eli Zaretskii
@ 2019-04-29 12:49 ` martin rudalics
2019-05-02 15:54 ` Basil L. Contovounesios
1 sibling, 1 reply; 24+ messages in thread
From: martin rudalics @ 2019-04-29 12:49 UTC (permalink / raw)
To: Mauro Aranda, 18
> When I bumped into the problem of the marker being sent to the
> beginning of the hunk, I started looking for something to get the
> markers of the buffer, but didn't found anything at the Lisp level.
We could introduce a function 'marker-list' based on BUF_MARKERS.
martin
^ permalink raw reply [flat|nested] 24+ messages in thread
* bug#18: Fine-grained revert-buffer
2019-04-28 2:47 ` Richard Stallman
@ 2019-04-29 23:32 ` Mauro Aranda
2019-04-30 0:17 ` Mauro Aranda
0 siblings, 1 reply; 24+ messages in thread
From: Mauro Aranda @ 2019-04-29 23:32 UTC (permalink / raw)
To: rms; +Cc: 18
[-- Attachment #1: Type: text/plain, Size: 460 bytes --]
Richard Stallman <rms@gnu.org> writes:
> It sounds like an improvement in functionality,
> but wouldn't it be a lot slower?
Hello Richard.
Compared to revert-buffer, yes, I would expect it to be slower (not sure
if a lot). But maybe the trade-off between time and preserving some
buffer information is worth it, let's see.
I'm finalizing some benchmarking, which I'll post in another email.
I'll wait for opinions about the results.
Best regards,
Mauro.
[-- Attachment #2: Type: text/html, Size: 639 bytes --]
^ permalink raw reply [flat|nested] 24+ messages in thread
* bug#18: Fine-grained revert-buffer
2019-04-29 23:32 ` Mauro Aranda
@ 2019-04-30 0:17 ` Mauro Aranda
2019-05-15 23:10 ` Mauro Aranda
0 siblings, 1 reply; 24+ messages in thread
From: Mauro Aranda @ 2019-04-30 0:17 UTC (permalink / raw)
To: 18; +Cc: rms
[-- Attachment #1.1: Type: text/plain, Size: 2294 bytes --]
I've now written a similar function to revert the buffer, but using
replace-buffer-contents as I was suggested. The new attached file
contains such function, which I called revert-buffer-with-fine-grain, to
honor a previous post.
I kept it as similar as I could to the revert-buffer-by-hunks
function, and went ahead to time both functions (I figure there will be
enough time to add functionality to them). I additionally timed
revert-buffer.
For the files in Bug#31888, the results were:
revert-buffer: 0.122238819
revert-buffer-with-fine-grain: 2.85150876
rbbh-revert-buffer-by-hunks: 2.044583634
all times in seconds, substracting GC time.
To gather more data, I compared emacs-25.3 and emacs-26.2 C source
files (from the src/ directory), checking them out from the git
repository. I did the test as if I was going back from emacs-26.2 to
emacs-25.3. I think these files provided a good range of changes in
size and number of hunks, obtained from `diff --normal'.
I attach the data as ascii file. Let me know if I should send it in
another format. The tests are with the latest master, optimized build,
run as `emacs -Q'.
For the majority of files, revert-buffer and
revert-buffer-with-fine-grain spent a similar amount of time when the
buffers or changes are not too big, so I believe that's promising for
implementing this functionality. On the contrary, reverting by hunks
(by calling diff), takes 1 to 4 times more than the other functions, in
these cases.
When there are many changes, replace-buffer-contents starts taking too
much time (as the docs warns). In those situations, reverting by hunks
does a much better job than using replace-buffer-contents, but I'm not
sure if it does a good enough job.
Some problematic files:
doprnt.c:
revert-buffer-with-fine-grain took 28.6 times more than revert-buffer
and rbbh-revert-buffer-by-hunks took 1.4 times more.
alloc.c:
revert-buffer-with-fine-grain took 18 times more than revert-buffer
and rbbh-revert-buffer-by-hunks took 6.5 times more.
lisp.h:
lisp.h took almost 9 minutes to revert, using
revert-buffer-with-fine-grain. It took 0.86 seconds to revert with
rbbh-revert-buffer-by-hunks.
I'll wait for opinions about the data I've collected. At least it was
super fun writing these tests.
Best regards,
Mauro.
[-- Attachment #1.2: Type: text/html, Size: 2554 bytes --]
[-- Attachment #2: bug18-benchmark-report.txt --]
[-- Type: text/plain, Size: 16641 bytes --]
FILE OLD-SIZE NEW-SIZE HUNKS REVERT-BUFFER REVERT-BUFFER-WITH-FINE-GRAIN RBBH-REVERT-BUFFER-BY-HUNKS FASTEST
alloc.c 204520 210496 283 0.161867116 2.917511896 1.0552727629999983 REVERT-BUFFER
atimer.c 14123 14136 4 0.046020625 0.008248911 0.035602406 REVERT-BUFFER-WITH-FINE-GRAIN
atimer.h 2171 2172 2 0.038901494 0.002417523 0.035891824 REVERT-BUFFER-WITH-FINE-GRAIN
bidi.c 124786 125185 13 0.090656241 0.060416566 0.082401697 REVERT-BUFFER-WITH-FINE-GRAIN
blockinput.h 2323 2324 2 0.039307267 0.002411168 0.064317919 REVERT-BUFFER-WITH-FINE-GRAIN
buffer.c 210665 209044 61 0.143055337 0.968004578 0.230475029 REVERT-BUFFER
buffer.h 46356 47253 15 0.064973197 0.043159018 0.06992736 REVERT-BUFFER-WITH-FINE-GRAIN
bytecode.c 44508 34618 239 0.066613893 3.489142178 0.580011116 REVERT-BUFFER
callint.c 30845 31243 7 0.050251428 0.021774817 0.047426037 REVERT-BUFFER-WITH-FINE-GRAIN
callproc.c 52414 52325 43 0.071063717 0.075534267 0.151233955 REVERT-BUFFER
casefiddle.c 13530 21561 52 0.044178998 6.891051039 0.3841988560000007 REVERT-BUFFER
casetab.c 8641 8642 2 0.039043268 0.003929146 0.030014963 REVERT-BUFFER-WITH-FINE-GRAIN
category.c 16498 16463 3 0.041939418 0.00622836 0.084981038 REVERT-BUFFER-WITH-FINE-GRAIN
category.h 4605 4606 1 0.040482543 0.00345493 0.044889223 REVERT-BUFFER-WITH-FINE-GRAIN
ccl.c 64892 64909 9 0.070900427 0.030533628 0.055278961 REVERT-BUFFER-WITH-FINE-GRAIN
ccl.h 3378 3379 1 0.04588569 0.002691297 0.073536779 REVERT-BUFFER-WITH-FINE-GRAIN
character.c 30011 31460 12 0.052486605 0.029383777 0.066101361 REVERT-BUFFER-WITH-FINE-GRAIN
character.h 22260 22807 10 0.053830548 0.020876249 0.062192254 REVERT-BUFFER-WITH-FINE-GRAIN
charset.c 71099 71353 27 0.074962076 0.049489547 0.105611403 REVERT-BUFFER-WITH-FINE-GRAIN
charset.h 19497 19498 2 0.047235499 0.010008397 0.033422475 REVERT-BUFFER-WITH-FINE-GRAIN
chartab.c 40500 40477 3 0.049410545 0.015412012 0.078390896 REVERT-BUFFER-WITH-FINE-GRAIN
cm.c 12450 12497 8 0.043428069 0.007110303 0.071706401 REVERT-BUFFER-WITH-FINE-GRAIN
cm.h 6663 6664 2 0.041632887 0.005074109 0.027991964 REVERT-BUFFER-WITH-FINE-GRAIN
cmds.c 16526 16599 7 0.043464735 0.009443738 0.086922391 REVERT-BUFFER-WITH-FINE-GRAIN
coding.c 338973 339614 50 0.218918413 0.20157885 0.297149338 REVERT-BUFFER-WITH-FINE-GRAIN
coding.h 25135 25089 9 0.055920525 0.040492158 0.049116102 REVERT-BUFFER-WITH-FINE-GRAIN
commands.h 1777 1778 2 0.038333406 0.002256192 0.071216051 REVERT-BUFFER-WITH-FINE-GRAIN
composite.c 62207 62662 22 0.067281703 0.039474305 0.106152595 REVERT-BUFFER-WITH-FINE-GRAIN
composite.h 12841 12842 2 0.04446548 0.007651007 0.029858029 REVERT-BUFFER-WITH-FINE-GRAIN
conf_post.h 12219 13619 32 0.056242699 0.325693328 0.140425235 REVERT-BUFFER
cygw32.c 4097 4103 4 0.038842823 0.00265903 0.034148954 REVERT-BUFFER-WITH-FINE-GRAIN
cygw32.h 1114 1115 2 0.039210464 0.00220437 0.029955317 REVERT-BUFFER-WITH-FINE-GRAIN
data.c 105970 111859 173 0.094676814 2.734272166 0.507381162 REVERT-BUFFER
dbusbind.c 56717 56114 33 0.070243362 0.038362096 0.140484387 REVERT-BUFFER-WITH-FINE-GRAIN
decompress.c 5818 5816 6 0.041662218 0.004534383 0.041537439 REVERT-BUFFER-WITH-FINE-GRAIN
dired.c 33933 35264 46 0.05955782 0.12735283 0.171601777 REVERT-BUFFER
dispextern.h 125049 125599 27 0.10867112 0.132929509 0.103543911 RBBH-REVERT-BUFFER-BY-HUNKS
dispnew.c 192820 195002 40 0.135618902 0.124463047 0.195216281 REVERT-BUFFER-WITH-FINE-GRAIN
disptab.h 3792 3793 2 0.041407997 0.004072388 0.032621194 REVERT-BUFFER-WITH-FINE-GRAIN
doc.c 30787 30364 60 0.055455104 130.980132808 0.228207555 REVERT-BUFFER
doprnt.c 17440 17341 11 0.049479473 1.413627296 0.068775543 REVERT-BUFFER
dosfns.c 24023 24024 2 0.044187791 0.0100866 0.032939456 REVERT-BUFFER-WITH-FINE-GRAIN
dosfns.h 1354 1355 2 0.036047381 0.001917393 0.061623187 REVERT-BUFFER-WITH-FINE-GRAIN
dynlib.c 8204 8144 13 0.04292256 0.008997861 0.092730799 REVERT-BUFFER-WITH-FINE-GRAIN
dynlib.h 1236 1470 4 0.037027106 0.00447962 0.078199247 REVERT-BUFFER-WITH-FINE-GRAIN
editfns.c 163739 176696 168 0.133892647 249.14845578 0.639357485 REVERT-BUFFER
emacs-icon.h 11227 9741 5 0.043397265 0.947593158 0.048989477 REVERT-BUFFER
emacs-module.c 36141 41083 123 0.057575392 5.448007516 0.323307959 REVERT-BUFFER
emacs-module.h 5926 11403 39 0.040898578 0.334262565 0.142350932 REVERT-BUFFER
emacs.c 76609 82259 104 0.097632113 0.811961117 0.340363608 REVERT-BUFFER
emacsgtkfixed.c 7610 7593 7 0.041874879 0.005103421 0.053669061 REVERT-BUFFER-WITH-FINE-GRAIN
emacsgtkfixed.h 1232 1233 2 0.03706817 0.002075296 0.032083909 REVERT-BUFFER-WITH-FINE-GRAIN
eval.c 114120 124710 188 0.089566989 4.163804995 0.543824388 REVERT-BUFFER
fileio.c 193895 198534 178 0.151393717 3.270869109 0.571415459 REVERT-BUFFER
filelock.c 25123 24916 18 0.054632309 0.026390242 0.071153462 REVERT-BUFFER-WITH-FINE-GRAIN
firstfile.c 1174 1181 4 0.038884864 0.002030319 0.054904955 REVERT-BUFFER-WITH-FINE-GRAIN
floatfns.c 14301 14942 42 0.046528565 0.068516559 0.134085384 REVERT-BUFFER
fns.c 144297 152390 261 0.112902402 4.763480833 0.8085245519999985 REVERT-BUFFER
font.c 156759 158090 46 0.120129576 0.102900966 0.202384744 REVERT-BUFFER-WITH-FINE-GRAIN
font.h 32767 35111 41 0.055870162 0.079008903 0.12258099 REVERT-BUFFER
fontset.c 63806 66015 43 0.067408803 0.065290436 0.144917553 REVERT-BUFFER-WITH-FINE-GRAIN
fontset.h 1870 1871 2 0.036939103 0.002259604 0.028910569 REVERT-BUFFER-WITH-FINE-GRAIN
frame.c 169459 197035 197 0.136880697 17.696388657 0.627852532 REVERT-BUFFER
frame.h 51724 55829 35 0.080263033 0.199977879 0.126515027 REVERT-BUFFER
fringe.c 47107 47410 6 0.062076056 0.024579915 0.051500861 REVERT-BUFFER-WITH-FINE-GRAIN
ftcrfont.c 8522 8999 13 0.039701297 0.01527066 0.083322726 REVERT-BUFFER-WITH-FINE-GRAIN
ftfont.c 76531 74736 29 0.082245455 0.090350911 0.126542403 REVERT-BUFFER
ftfont.h 1477 1478 1 0.038361266 0.002254715 0.02978958 REVERT-BUFFER-WITH-FINE-GRAIN
ftxfont.c 9252 9817 19 0.04149208 0.020666429 0.075906864 REVERT-BUFFER-WITH-FINE-GRAIN
getpagesize.h 1542 1543 2 0.037269099 0.003826465 0.03385904 REVERT-BUFFER-WITH-FINE-GRAIN
gfilenotify.c 10356 11005 10 0.043120063 0.012297779 0.048409167 REVERT-BUFFER-WITH-FINE-GRAIN
gmalloc.c 59535 58736 86 0.070805079 0.298190959 0.260342754 REVERT-BUFFER
gnutls.c 57350 88381 133 0.073447007 19.254059013 0.400401295 REVERT-BUFFER
gnutls.h 2782 3146 7 0.040269379 0.005348837 0.042948345 REVERT-BUFFER-WITH-FINE-GRAIN
gtkutil.c 162240 167021 65 0.132784821 1.139196604 0.219520555 REVERT-BUFFER
gtkutil.h 7148 7669 7 0.043334682 0.012003472 0.041287122 REVERT-BUFFER-WITH-FINE-GRAIN
image.c 270253 272136 197 0.222032555 0.370422944 0.8085088219999983 REVERT-BUFFER
indent.c 68725 72439 39 0.068987895 0.189844833 0.14166647 REVERT-BUFFER
indent.h 2171 2172 2 0.036882879 0.002405779 0.034486274 REVERT-BUFFER-WITH-FINE-GRAIN
inotify.c 11744 16423 29 0.041117104 1.236744776 0.097514496 REVERT-BUFFER
insdel.c 65329 69314 21 0.068142124 0.320765927 0.171091341 REVERT-BUFFER
intervals.c 69906 69176 9 0.067788171 0.045596863 0.052912751 REVERT-BUFFER-WITH-FINE-GRAIN
intervals.h 11702 11604 11 0.043759032 0.009736534 0.07818114 REVERT-BUFFER-WITH-FINE-GRAIN
keyboard.c 368698 375297 99 0.252331138 0.473319963 0.467540015 REVERT-BUFFER
keyboard.h 18424 18469 6 0.046965622 0.010921091 0.038617819 REVERT-BUFFER-WITH-FINE-GRAIN
keymap.c 112662 113335 17 0.084216628 0.0564676 0.096714192 REVERT-BUFFER-WITH-FINE-GRAIN
keymap.h 2301 2302 2 0.035580001 0.002403334 0.038579687 REVERT-BUFFER-WITH-FINE-GRAIN
kqueue.c 15899 16543 10 0.044132049 0.013038431 0.059911105 REVERT-BUFFER-WITH-FINE-GRAIN
lastfile.c 1892 2053 5 0.036227284 0.002568087 0.065688231 REVERT-BUFFER-WITH-FINE-GRAIN
lisp.h 151532 154743 265 0.143883944 539.879098116 0.8634533129999992 REVERT-BUFFER
lread.c 141434 153962 184 0.118116822 4.274483568 0.593424343 REVERT-BUFFER
macfont.h 2712 2848 3 0.039706181 0.003210469 0.03218999 REVERT-BUFFER-WITH-FINE-GRAIN
macros.c 12297 12307 3 0.042433666 0.005070165 0.032922824 REVERT-BUFFER-WITH-FINE-GRAIN
macros.h 1664 1665 2 0.035834709 0.002103647 0.03417143 REVERT-BUFFER-WITH-FINE-GRAIN
macuvs.h 478710 478842 9 0.18810203 0.262799859 0.148847166 RBBH-REVERT-BUFFER-BY-HUNKS
marker.c 21655 22190 6 0.047513658 0.013568349 0.041712445 REVERT-BUFFER-WITH-FINE-GRAIN
menu.c 45442 45310 8 0.060652415 0.022808651 0.089105706 REVERT-BUFFER-WITH-FINE-GRAIN
menu.h 2291 2276 3 0.039220719 0.002727945 0.038526396 REVERT-BUFFER-WITH-FINE-GRAIN
minibuf.c 71348 73754 41 0.068853934 0.092206008 0.144308866 REVERT-BUFFER
msdos.c 117032 117570 9 0.112412518 1.851569699 0.231427752 REVERT-BUFFER
msdos.h 4227 4348 5 0.040463461 0.004204848 0.038048758 REVERT-BUFFER-WITH-FINE-GRAIN
nsgui.h 4938 4939 2 0.042022512 0.007001236 0.058944579 REVERT-BUFFER-WITH-FINE-GRAIN
nsterm.h 38626 44083 44 0.070987911 0.506200995 0.144655482 REVERT-BUFFER
print.c 70038 73841 45 0.075677775 4.026341206 0.156848703 REVERT-BUFFER
process.c 227582 247290 295 0.182520433 33.337351562 0.9778028859999983 REVERT-BUFFER
process.h 8234 9836 16 0.04248304 0.036471351 0.064195176 REVERT-BUFFER-WITH-FINE-GRAIN
profiler.c 18482 18457 11 0.043813782 0.010350546 0.055780528 REVERT-BUFFER-WITH-FINE-GRAIN
puresize.h 3442 3443 3 0.041209498 0.003895388 0.051523827 REVERT-BUFFER-WITH-FINE-GRAIN
ralloc.c 33444 33083 7 0.047300992 0.016545621 0.073236082 REVERT-BUFFER-WITH-FINE-GRAIN
regex.c 194305 193326 97 0.180956001 2.264050441 0.400853427 REVERT-BUFFER
regex.h 23762 23784 18 0.058010483 0.034349127 0.076792213 REVERT-BUFFER-WITH-FINE-GRAIN
region-cache.c 26621 26622 2 0.044657595 0.009893444 0.033125219 REVERT-BUFFER-WITH-FINE-GRAIN
region-cache.h 5278 5279 2 0.036583676 0.003085804 0.03729832 REVERT-BUFFER-WITH-FINE-GRAIN
scroll.c 32513 32479 6 0.048482135 0.011519456 0.085286059 REVERT-BUFFER-WITH-FINE-GRAIN
search.c 103513 103321 61 0.085247674 0.077743493 0.182840625 REVERT-BUFFER-WITH-FINE-GRAIN
sheap.c 2942 2140 14 0.03976631 0.026304623 0.063643714 REVERT-BUFFER-WITH-FINE-GRAIN
sound.c 40357 40413 8 0.052568714 0.018852641 0.047058373 REVERT-BUFFER-WITH-FINE-GRAIN
syntax.c 109738 113161 158 0.089811894 1.489718905 0.426571084 REVERT-BUFFER
syntax.h 7761 7762 2 0.038928851 0.00411685 0.030386009 REVERT-BUFFER-WITH-FINE-GRAIN
sysdep.c 102007 111582 99 0.125249134 2.063423282 0.327923863 REVERT-BUFFER
sysselect.h 2283 2556 3 0.041331227 0.004221959 0.032962908 REVERT-BUFFER-WITH-FINE-GRAIN
syssignal.h 2232 2367 4 0.040001951 0.003490596 0.075596891 REVERT-BUFFER-WITH-FINE-GRAIN
sysstdio.h 1022 2125 3 0.038915162 0.009336122 0.039278783 REVERT-BUFFER-WITH-FINE-GRAIN
systime.h 3186 3187 2 0.038973828 0.003105359 0.066136036 REVERT-BUFFER-WITH-FINE-GRAIN
systty.h 2774 2754 3 0.040932298 0.003340021 0.034051161 REVERT-BUFFER-WITH-FINE-GRAIN
syswait.h 1909 1910 3 0.039859197 0.003133225 0.073393498 REVERT-BUFFER-WITH-FINE-GRAIN
term.c 130082 131097 57 0.10612057 0.083380755 0.184314108 REVERT-BUFFER-WITH-FINE-GRAIN
termcap.c 15849 15950 2 0.04222735 0.007319496 0.029681039 REVERT-BUFFER-WITH-FINE-GRAIN
termchar.h 9306 9142 3 0.041454424 0.005502333 0.026602545 REVERT-BUFFER-WITH-FINE-GRAIN
termhooks.h 28047 28799 10 0.055398372 0.022180439 0.050718634 REVERT-BUFFER-WITH-FINE-GRAIN
terminal.c 18532 18842 5 0.044959233 0.011095597 0.122524728 REVERT-BUFFER-WITH-FINE-GRAIN
terminfo.c 1604 1605 2 0.038392055 0.001939383 0.067747881 REVERT-BUFFER-WITH-FINE-GRAIN
termopts.h 1064 1065 2 0.037703218 0.001817652 0.053488153 REVERT-BUFFER-WITH-FINE-GRAIN
textprop.c 72068 72885 10 0.064344458 0.038806236 0.066604872 REVERT-BUFFER-WITH-FINE-GRAIN
tparam.c 7296 7399 9 0.042007352 0.00485408 0.069073729 REVERT-BUFFER-WITH-FINE-GRAIN
tparam.h 1285 1340 3 0.039350756 0.002158401 0.055662214 REVERT-BUFFER-WITH-FINE-GRAIN
undo.c 15682 15683 2 0.041746287 0.0054818 0.055823056 REVERT-BUFFER-WITH-FINE-GRAIN
unexaix.c 15514 15515 2 0.043068718 0.007149366 0.052384256 REVERT-BUFFER-WITH-FINE-GRAIN
unexcoff.c 15156 15157 2 0.043126896 0.007356162 0.071640362 REVERT-BUFFER-WITH-FINE-GRAIN
unexcw.c 9107 8916 12 0.040893674 0.006148143 0.075921995 REVERT-BUFFER-WITH-FINE-GRAIN
unexec.h 116 116 0 0.037351221 0.001481792 0.030958977 REVERT-BUFFER-WITH-FINE-GRAIN
unexelf.c 23765 21299 11 0.055085973 0.148562502 0.062808698 REVERT-BUFFER
unexhp9k800.c 9817 9817 0 0.04090394 0.004780748 0.055412393 REVERT-BUFFER-WITH-FINE-GRAIN
unexmacosx.c 43220 42350 6 0.052798485 0.026658083 0.071571429 REVERT-BUFFER-WITH-FINE-GRAIN
unexsol.c 604 604 0 0.035208442 0.001662678 0.066238698 REVERT-BUFFER-WITH-FINE-GRAIN
unexw32.c 26998 27189 25 0.053305457 0.027633396 0.107577629 REVERT-BUFFER-WITH-FINE-GRAIN
vm-limit.c 5745 5907 4 0.04196384 0.005421668 0.03522741 REVERT-BUFFER-WITH-FINE-GRAIN
w16select.c 22279 22280 2 0.045085852 0.008935241 0.06498178 REVERT-BUFFER-WITH-FINE-GRAIN
w32.c 266005 273748 66 0.181078688 0.631921554 0.263125389 REVERT-BUFFER
w32.h 8949 8953 4 0.043348847 0.00587437 0.034955102 REVERT-BUFFER-WITH-FINE-GRAIN
w32common.h 1665 1666 2 0.039060357 0.002266443 0.03460604 REVERT-BUFFER-WITH-FINE-GRAIN
w32console.c 23538 24696 22 0.047447161 0.020676648 0.076545807 REVERT-BUFFER-WITH-FINE-GRAIN
w32fns.c 324499 362552 212 0.212798448 27.595457489 0.770541459 REVERT-BUFFER
w32font.c 88643 90842 29 0.084941621 0.06859754 0.098763561 REVERT-BUFFER-WITH-FINE-GRAIN
w32font.h 2977 2942 3 0.037340952 0.003320466 0.033899604 REVERT-BUFFER-WITH-FINE-GRAIN
w32gui.h 4020 4021 2 0.041229534 0.004631639 0.046801214 REVERT-BUFFER-WITH-FINE-GRAIN
w32heap.c 23905 26233 16 0.047937511 0.043124013 0.093855669 REVERT-BUFFER-WITH-FINE-GRAIN
w32heap.h 2267 2245 4 0.035817589 0.002581281 0.076106299 REVERT-BUFFER-WITH-FINE-GRAIN
w32inevt.c 23375 24193 21 0.046940675 0.031258921 0.092333287 REVERT-BUFFER-WITH-FINE-GRAIN
w32inevt.h 1176 1177 2 0.038647248 0.001856762 0.070286152 REVERT-BUFFER-WITH-FINE-GRAIN
w32menu.c 45595 45600 13 0.058873353 0.024461548 0.107591311 REVERT-BUFFER-WITH-FINE-GRAIN
w32notify.c 24003 25122 43 0.048051419 0.300758335 0.144071725 REVERT-BUFFER
w32proc.c 114140 115841 30 0.096755499 0.087098186 0.131805171 REVERT-BUFFER-WITH-FINE-GRAIN
w32reg.c 4458 4473 4 0.040345631 0.003157181 0.03868723 REVERT-BUFFER-WITH-FINE-GRAIN
w32select.c 32498 35683 8 0.050830723 0.115461966 0.08138574 REVERT-BUFFER
w32select.h 953 954 2 0.037606903 0.001802497 0.073433088 REVERT-BUFFER-WITH-FINE-GRAIN
w32term.c 208214 216804 128 0.145846281 0.415995904 0.452017838 REVERT-BUFFER
w32term.h 30113 30169 16 0.061621368 0.043722401 0.068545239 REVERT-BUFFER-WITH-FINE-GRAIN
w32uniscribe.c 37252 37858 11 0.057969405 0.027828457 0.065789409 REVERT-BUFFER-WITH-FINE-GRAIN
w32xfns.c 7429 8449 4 0.041098022 0.014167224 0.062755404 REVERT-BUFFER-WITH-FINE-GRAIN
widget.c 15235 15408 20 0.045095625 0.015303378 0.091998888 REVERT-BUFFER-WITH-FINE-GRAIN
widget.h 2839 2847 4 0.043457376 0.00456613 0.033656627 REVERT-BUFFER-WITH-FINE-GRAIN
widgetprv.h 2192 2193 4 0.037846944 0.002410173 0.039192732 REVERT-BUFFER-WITH-FINE-GRAIN
window.c 247029 263196 113 0.162939125 1.823741433 0.43306532 REVERT-BUFFER
window.h 40676 42531 57 0.066477449 0.689007909 0.222435668 REVERT-BUFFER
xdisp.c 1014261 1063760 413 0.5658512699999992 12.162937169 2.625628421999999 REVERT-BUFFER
xfaces.c 198840 200689 44 0.147763674 0.128634805 0.199569644 REVERT-BUFFER-WITH-FINE-GRAIN
xfns.c 219992 249068 142 0.171112274 18.407242761 0.485589351 REVERT-BUFFER
xfont.c 31984 31266 17 0.052815587 0.044323719 0.075378341 REVERT-BUFFER-WITH-FINE-GRAIN
xftfont.c 23858 24658 23 0.05207835 0.093080592 0.079839883 REVERT-BUFFER
xgselect.c 5244 5440 11 0.039750655 0.005741394 0.085163324 REVERT-BUFFER-WITH-FINE-GRAIN
xgselect.h 1006 987 3 0.036149538 0.002049381 0.034493591 REVERT-BUFFER-WITH-FINE-GRAIN
xmenu.c 67074 68801 15 0.082159859 0.048041154 0.076409883 REVERT-BUFFER-WITH-FINE-GRAIN
xml.c 8054 8039 6 0.041931077 0.005001231 0.061182661 REVERT-BUFFER-WITH-FINE-GRAIN
xrdb.c 17375 17498 5 0.044372074 0.010911289 0.063701872 REVERT-BUFFER-WITH-FINE-GRAIN
xselect.c 86814 87776 16 0.075834191 0.049218864 0.126307181 REVERT-BUFFER-WITH-FINE-GRAIN
xsettings.c 30659 30639 4 0.056285683 0.015475462 0.043668936 REVERT-BUFFER-WITH-FINE-GRAIN
xsettings.h 1134 1135 2 0.037998495 0.001986804 0.08228136 REVERT-BUFFER-WITH-FINE-GRAIN
xsmfns.c 17559 17605 5 0.044120298 0.00907457 0.086251086 REVERT-BUFFER-WITH-FINE-GRAIN
xterm.c 383015 402521 208 0.277790626 2.71448703 0.8819136090000014 REVERT-BUFFER
xterm.h 41373 43427 13 0.06702646 0.065484843 0.055296514 RBBH-REVERT-BUFFER-BY-HUNKS
xwidget.c 37193 38456 52 0.058702233 2.440097854 0.184362455 REVERT-BUFFER
xwidget.h 3739 3622 5 0.03663353 0.004050851 0.037721191 REVERT-BUFFER-WITH-FINE-GRAIN
[-- Attachment #3: rbbh-bug18.el --]
[-- Type: text/x-emacs-lisp, Size: 11389 bytes --]
;;; rbbh.el --- Revert Buffer By Hunks -*- lexical-binding: t -*-
(require 'diff)
;; At least for now, this are defconst.
(defconst rbbh-diff-command "diff"
"Name of the command to run diff")
(defconst rbbh-diff-switches "--normal"
"Switches to pass to diff.")
(defconst rbbh-diff-change-command-regexp
(let ((rng "\\([0-9]+\\)\\(\\|,\\([0-9]+\\)\\)"))
(concat "^" rng "\\([acd]\\)" rng "$"))
"Regular expression that matches the change commands for each hunk
Should be in synch with the switch used to call diff.")
(defconst rbbh-diff-buffer-name "*RBBH-Diff*"
"The name of the diff buffer internally created by `rbbh--run-diff'.")
(defvar rbbh-current-diff-buffer-name nil
"Name of the current diff buffer.")
(defvar rbbh-total-hunks 0
"Total hunks in the diff output.")
;; If `diff' and `diff-mode' are not to be required, this function should be
;; changed to do a lot of what `diff-no-select' does.
(defun rbbh--run-diff (buf)
"Compare contents of buffer BUF with those of the file it visits.
Runs `rbbh-diff-command' command to make the comparison, and puts its output
in a buffer, with basename `rbbh-diff-buffer-name'.
The command is run with the switches `rbbh-diff-switches'."
(let ((diff-command rbbh-diff-command)
(diff-use-labels nil)) ; Don't care about labels.
(setq rbbh-current-diff-buffer-name (generate-new-buffer
rbbh-diff-buffer-name))
(with-current-buffer buf
(diff-no-select buf buffer-file-name rbbh-diff-switches
t rbbh-current-diff-buffer-name))))
;; With this, reverted hunks can be undone one by one.
(defsubst rbbh--split-undo-hunk (buf)
"Force undo history to separate hunk replacements in buffer BUF."
(with-current-buffer buf
(undo-boundary)))
(defun rbbh-delete-line (&optional arg)
"Delete ARG lines (or the current line, if ARG is 0).
Does not put the killed text in the `kill-ring'. See `kill-whole-line' for
details on ARG."
(setq arg (or arg 1))
(if (and (> arg 0)
(eobp)
(save-excursion (forward-visible-line 0)
(eobp)))
(signal 'end-of-buffer nil))
(if (and (< arg 0)
(bobp)
(save-excursion (end-of-visible-line) (bobp)))
(signal 'beginning-of-buffer nil))
(cond ((zerop arg)
(delete-region (progn (forward-visible-line 0) (point))
(progn (end-of-visible-line) (point))))
((< arg 0)
(delete-region (progn (end-of-visible-line) (point))
(progn (forward-visible-line (1+ arg))
(unless (bobp)
(backward-char))
(point))))
(t
(delete-region (progn (forward-visible-line 0) (point))
(progn (forward-visible-line arg) (point))))))
(defsubst rbbh-count-total-hunks (diff-buf &optional change-command-re)
(with-current-buffer diff-buf
(save-excursion
(goto-char (point-min))
(let ((count 0)
(re (or change-command-re rbbh-diff-change-command-regexp)))
(while (re-search-forward re nil t)
(setq count (1+ count)))
count))))
(defsubst rbbh-get-hunk-contents (beg end)
"Get the hunk contents from positions BEG to END.
Expects that a diff buffer is the current buffer."
(let ((start (point)))
(forward-line (1+ (- beg end)))
(let ((text (buffer-substring start (point))))
;; Remember that we are using the --normal switch, hence the > and <
;; replacement.
(setq text (replace-regexp-in-string "^[><] " "" text))
text)))
(defun rbbh-patch-buffer (buf diff-buf)
"Patch the buffer BUF according to the contents of the diff buffer DIFF-BUF.
It works with a diff buffer that contains a --normal output from diff."
;; line-offset keeps memory of the lines added and deleted to the buffer BUF,
;; and it is necessary because the diff output will stay the same (line
;; references will stay relative to the unpatched buffer).
;; Added lines decrements offset, and deleted lines increment it.
(let ((line-offset 0)
(column (current-column))) ; To restore point just right.
(save-excursion
(with-current-buffer diff-buf
(goto-char (point-min))
(save-excursion
(while (re-search-forward rbbh-diff-change-command-regexp nil t)
(rbbh--split-undo-hunk buf) ; Make each change of hunk undoable.
(forward-line) ; skip the command.
;; Get ranges and the action, from the previous match.
(let* ((action-cmd (match-string 4))
(old-from (string-to-number (match-string 1)))
(old-to (if (match-beginning 3)
(string-to-number (match-string 3))
old-from))
(new-from (string-to-number (match-string 5)))
(new-to (if (match-beginning 7)
(string-to-number (match-string 7))
new-from)))
(cond ((equal action-cmd "a")
;; When adding, we take the text and remove > and <
;; (diff was called with --normal switch).
;; Then navigate to the line, accounting the offset,
;; and insert the text.
(let ((text (rbbh-get-hunk-contents new-to new-from)))
(with-current-buffer buf
(goto-char (point-min))
(forward-line (- old-from line-offset))
(setq line-offset (- line-offset (1+ (- new-to
new-from))))
(insert text))))
((equal action-cmd "d")
;; When deleting, navigate to the correct line and kill
;; as many lines as the range in the diff output says.
(with-current-buffer buf
(goto-char (point-min))
(forward-line (1- (- old-from line-offset)))
(setq line-offset (+ line-offset (1+
(- old-to old-from))))
(rbbh-delete-line (1+ (- old-to old-from)))))
((equal action-cmd "c")
;; When changing, is a combination of adding and deleting.
;; Get the text after "---", and act similar as we would
;; with adding.
;; But before, kill the lines, as we do when deleting.
(re-search-forward "^---")
(forward-line)
(let ((text (rbbh-get-hunk-contents new-to new-from)))
(with-current-buffer buf
(goto-char (point-min))
(forward-line (1- (- old-from line-offset)))
(rbbh-delete-line (1+ (- old-to old-from)))
(setq line-offset (+ line-offset (- old-to old-from)
new-from (- new-to)))
(insert text))))
(t
(error "Unknown command action in diff output"))))))))
(move-to-column column))) ; Restore column.
;; Not sure if the function would be a good candidate for
;; `revert-buffer-function'.
;; But just in case, make it take _ignore-auto as an argument.
;; Note that reverting with the contents of an auto save file is not supported.
;; It could be added, if suggested.
(defun rbbh-revert-buffer-by-hunks (&optional _ignore-auto noconfirm)
"Revert buffer by hunks, instead of doing a single deletion plus insertion.
This action is useful when you want to revert a buffer (like you would do with
`revert-buffer'), but then would like to undo some of the reverting.
When the buffer hasn't been modified, nothing is done.
This function is only useful for buffers visting files.
After reverting, it marks the buffer as not modified.
When NOCONFIRM is non-nil, don't ask for confirmation before reverting. The
other way of avoiding the query is provided by the variable
`revert-without-query'. Nevertheless, you will be always prompted, if the
file was changed externally.
The optional argument _IGNORE-AUTO is ignored and is provided only for
compatibility with `revert-buffer'. Thus, it is a candidate for the variable
`revert-buffer-function'."
(interactive)
(with-current-buffer (or (buffer-base-buffer (current-buffer))
(current-buffer))
(save-excursion
(let ((file-name buffer-file-name)
(buf (current-buffer))
;; Just in case we are not the revert-buffer-function.
(revert-buffer-in-progress-p t))
;; Repeat some of what revert-buffer--default does, because it is not
;; sure reverting by hunks is a candidate for revert-buffer-function.
(cond ((null file-name)
(error "Buffer does not seem to be associated with any file"))
((or (and (not (verify-visited-file-modtime buf))
(yes-or-no-p
(format "File %s was modified outside of Emacs. Really revert? "
file-name)))
noconfirm
;; Respect user choice.
(catch 'found
(dolist (regexp revert-without-query)
(when (string-match regexp file-name)
(throw 'found t))))
(yes-or-no-p (format "Revert buffer from file %s? "
file-name)))
(run-hooks 'before-revert-hook)
(rbbh--run-diff buf)
(rbbh-patch-buffer buf rbbh-current-diff-buffer-name)
;; Mark the buffer as not modified, like it would happen with
;; the default behavior of revert-buffer.
(set-buffer-modified-p nil)
;; Report to the user (this could be made optional).
;; (setq rbbh-total-hunks (rbbh-count-total-hunks
;; rbbh-current-diff-buffer-name))
;; (message "%d %s reverted" rbbh-total-hunks
;; (if (= rbbh-total-hunks 1)
;; "hunk"
;; "hunks"))
;; Kill the diff buffer we used.
(kill-buffer rbbh-current-diff-buffer-name)
(run-hooks 'after-revert-hook))
(t
(message "Revert aborted")))))))
;; The next function uses replace-buffer-contents:
(defun revert-buffer-with-fine-grain (&optional _ignore-auto noconfirm)
"Replace current buffer text with the text of the visited file on disk.
Acts just like `revert-buffer', but tries to be as non-destructive as possible,
by preserving markers, properties and overlays.
In Lisp code, the first argument is IGNORE-AUTO: when nil, offers to revert
from the auto-save file. It defaults to nil.
When NOCONFIRM is non-nil, don't ask for confirmation before reverting. The
other way of avoiding the query is provided by the variable
`revert-without-query'. Nevertheless, the prompt can't be skipped if the file
was changed externally."
(interactive)
;; Repeat some of what revert-buffer--default does, because it is not sure
;; this revert function is a good candidate for revert-buffer-function.
(let ((buf (or (buffer-base-buffer (current-buffer))
(current-buffer)))
(file-name buffer-file-name)
(revert-buffer-in-progress-p t))
(cond ((null file-name)
(error "Buffer does not seem to be associated with any file"))
((or (and (not (verify-visited-file-modtime buf))
(yes-or-no-p
(format "File %s was modified outside of Emacs. Really revert? "
file-name)))
noconfirm
;; Respect user choice.
(catch 'found
(dolist (regexp revert-without-query)
(when (string-match regexp file-name)
(throw 'found t))))
(yes-or-no-p (format "Revert buffer from file %s? " file-name)))
(run-hooks 'before-revert-hook)
(save-excursion
;; This action reverts the whole buffer.
(save-restriction
(widen)
(with-temp-buffer
(insert-file-contents file-name)
(let ((temp-buf (current-buffer)))
(set-buffer buf)
(replace-buffer-contents temp-buf)))))
;; Mark the buffer as not modified, like it would happen with the
;; default behavior of revert-buffer.
(set-buffer-modified-p nil)
(run-hooks 'after-revert-hook))
(t
(message "Revert aborted")))))
(provide 'rbbh)
;;; rbbh.el ends here
^ permalink raw reply [flat|nested] 24+ messages in thread
* bug#18: Fine-grained revert-buffer
2019-04-29 12:49 ` martin rudalics
@ 2019-05-02 15:54 ` Basil L. Contovounesios
2019-05-02 16:20 ` Glenn Morris
2019-05-02 21:27 ` Richard Stallman
0 siblings, 2 replies; 24+ messages in thread
From: Basil L. Contovounesios @ 2019-05-02 15:54 UTC (permalink / raw)
To: martin rudalics; +Cc: 18, Mauro Aranda
martin rudalics <rudalics@gmx.at> writes:
>> When I bumped into the problem of the marker being sent to the
>> beginning of the hunk, I started looking for something to get the
>> markers of the buffer, but didn't found anything at the Lisp level.
>
> We could introduce a function 'marker-list' based on BUF_MARKERS.
I've opened a new ticket for this: https://debbugs.gnu.org/35536
[The acknowledgement email lists you as being CCed, but the copy of my
report does not. So, were you successfully CCed? If not, any ideas why?]
Thanks,
--
Basil
^ permalink raw reply [flat|nested] 24+ messages in thread
* bug#18: Fine-grained revert-buffer
2019-05-02 15:54 ` Basil L. Contovounesios
@ 2019-05-02 16:20 ` Glenn Morris
2019-05-02 16:23 ` Basil L. Contovounesios
2019-05-02 21:27 ` Richard Stallman
1 sibling, 1 reply; 24+ messages in thread
From: Glenn Morris @ 2019-05-02 16:20 UTC (permalink / raw)
To: Basil L. Contovounesios; +Cc: 18, Mauro Aranda
"Basil L. Contovounesios" wrote:
> I've opened a new ticket for this: https://debbugs.gnu.org/35536
>
> [The acknowledgement email lists you as being CCed, but the copy of my
> report does not. So, were you successfully CCed? If not, any ideas why?]
When you see this, it means the person is subscribed to bug-gnu-emacs
and has the Mailman option "no duplicates" enabled. Everything is
working fine.
^ permalink raw reply [flat|nested] 24+ messages in thread
* bug#18: Fine-grained revert-buffer
2019-05-02 16:20 ` Glenn Morris
@ 2019-05-02 16:23 ` Basil L. Contovounesios
0 siblings, 0 replies; 24+ messages in thread
From: Basil L. Contovounesios @ 2019-05-02 16:23 UTC (permalink / raw)
To: Glenn Morris; +Cc: 18, Mauro Aranda
Glenn Morris <rgm@gnu.org> writes:
> "Basil L. Contovounesios" wrote:
>
>> I've opened a new ticket for this: https://debbugs.gnu.org/35536
>>
>> [The acknowledgement email lists you as being CCed, but the copy of my
>> report does not. So, were you successfully CCed? If not, any ideas why?]
>
> When you see this, it means the person is subscribed to bug-gnu-emacs
> and has the Mailman option "no duplicates" enabled. Everything is
> working fine.
Good to hear, and sorry for the noise.
Thanks,
--
Basil
^ permalink raw reply [flat|nested] 24+ messages in thread
* bug#18: Fine-grained revert-buffer
2019-05-02 15:54 ` Basil L. Contovounesios
2019-05-02 16:20 ` Glenn Morris
@ 2019-05-02 21:27 ` Richard Stallman
2019-05-03 14:05 ` Basil L. Contovounesios
1 sibling, 1 reply; 24+ messages in thread
From: Richard Stallman @ 2019-05-02 21:27 UTC (permalink / raw)
To: Basil L. Contovounesios; +Cc: 18, maurooaranda
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> >> When I bumped into the problem of the marker being sent to the
> >> beginning of the hunk, I started looking for something to get the
> >> markers of the buffer, but didn't found anything at the Lisp level.
> >
> > We could introduce a function 'marker-list' based on BUF_MARKERS.
There is a reason why you can't get a copy of that list: if anything
else pointed to a copy of it, no marker in that buffer could be
garbage collected. We should look for some other way to solve your
problem.
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
^ permalink raw reply [flat|nested] 24+ messages in thread
* bug#18: Fine-grained revert-buffer
2019-05-02 21:27 ` Richard Stallman
@ 2019-05-03 14:05 ` Basil L. Contovounesios
2019-05-05 22:41 ` Richard Stallman
0 siblings, 1 reply; 24+ messages in thread
From: Basil L. Contovounesios @ 2019-05-03 14:05 UTC (permalink / raw)
To: Richard Stallman; +Cc: 18, maurooaranda
Richard Stallman <rms@gnu.org> writes:
> > >> When I bumped into the problem of the marker being sent to the
> > >> beginning of the hunk, I started looking for something to get the
> > >> markers of the buffer, but didn't found anything at the Lisp level.
> > >
> > > We could introduce a function 'marker-list' based on BUF_MARKERS.
>
> There is a reason why you can't get a copy of that list: if anything
> else pointed to a copy of it, no marker in that buffer could be
> garbage collected.
Isn't that true of all marker copying/manipulation at the Lisp level?
I think the manual already documents these pitfalls.
> We should look for some other way to solve your problem.
I think that would indeed be preferable.
--
Basil
^ permalink raw reply [flat|nested] 24+ messages in thread
* bug#18: Fine-grained revert-buffer
2019-05-03 14:05 ` Basil L. Contovounesios
@ 2019-05-05 22:41 ` Richard Stallman
0 siblings, 0 replies; 24+ messages in thread
From: Richard Stallman @ 2019-05-05 22:41 UTC (permalink / raw)
To: Basil L. Contovounesios; +Cc: 18, maurooaranda
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> > There is a reason why you can't get a copy of that list: if anything
> > else pointed to a copy of it, no marker in that buffer could be
> > garbage collected.
> Isn't that true of all marker copying/manipulation at the Lisp level?
There is always the possibility if blocking some markers from GC
by saving pointers to them and not clearing those out.
However, getting a list of ALL the markers would make it trivially
easy to block ALL the buffer's markers from GC.
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
^ permalink raw reply [flat|nested] 24+ messages in thread
* bug#18: Fine-grained revert-buffer
2019-04-30 0:17 ` Mauro Aranda
@ 2019-05-15 23:10 ` Mauro Aranda
2020-09-19 23:08 ` Lars Ingebrigtsen
0 siblings, 1 reply; 24+ messages in thread
From: Mauro Aranda @ 2019-05-15 23:10 UTC (permalink / raw)
To: 18
[-- Attachment #1.1: Type: text/plain, Size: 1953 bytes --]
I spent some time thinking on how to get this new revert command
integrated with the rest of revert-buffer functions, and I came up with
the attached patch.
Since the difference between revert-buffer and
revert-buffer-with-fine-grain lies at the insert-file-contents level, I
wrote an alternative to
revert-buffer-insert-file-contents--default-function, that uses
replace-buffer-contents, as Eli suggested. I named it
revert-buffer-insert-file-contents-delicately.
Then, revert-buffer-with-fine-grain only needs to bind
revert-buffer-insert-file-contents-function to
revert-buffer-insert-file-contents-delicately to get the job done.
There are some more things that revert-buffer-with-fine-grain needs to
do:
1) Manipulate the current-prefix-arg, just like revert-buffer does.
2) Since replace-buffer-contents can fail to replace conservatively,
return that information could be useful. But revert-buffer--default
always returns t after reverting, so I used a closure that then gets
called by revert-buffer-with-fine-grain.
To control how much time replace-buffer-contents spends trying to be
non-destructive, I introduced a new variable to pass as the MAX-SECS
argument. 2.0 secs looks like a good value, according to the previous
benchmark I posted, and the new one I post here. I think it should be
an acceptable delay.
As I said above, I timed the command, and to compare I timed
revert-buffer too. IMO, the results look good. Some files fail and
take a lot of time, yes, but I think it's unlikely that a user will revert
so many changes. And for those, at least the variable
revert-buffer-with-fine-grain-max-seconds helps to terminate the
execution earlier.
I also went ahead and wrote a test for revert-buffer-with-fine-grain,
because I figure it would be required, as well as the benchmarking.
As I was there, I wrote a similar test for revert-buffer.
Corrections and comments are welcome. Better names too.
Best regards,
Mauro.
[-- Attachment #1.2: Type: text/html, Size: 2238 bytes --]
[-- Attachment #2: bug18-benchmark.txt --]
[-- Type: text/plain, Size: 9521 bytes --]
FILE OLD SIZE NEW SIZE HUNKS REVERT-BUFFER REVERT-BUFFER-WITH-FINE-GRAIN
alloc.c 204520 209630 287 0.16885512700000097 2.52165405
atimer.c 14123 14136 4 0.045665537 0.010047017
atimer.h 2171 2172 2 0.037106671 0.00390519
bidi.c 124786 125185 13 0.092865676 0.062252294
blockinput.h 2323 2324 2 0.037787195 0.003917413
buffer.c 210665 209044 61 0.14611377900000155 0.937045737
buffer.h 46356 47253 15 0.068253374 0.045556969
bytecode.c 44508 34618 239 0.064439602 2.2386166
callint.c 30845 31243 7 0.049622551 0.022790706
callproc.c 52414 52325 43 0.070316457 0.080524749
casefiddle.c 13530 21561 52 0.04057578 4.619247387
casetab.c 8641 8642 2 0.038574295 0.005267704
category.c 16498 16463 3 0.037217646 0.007868557
category.h 4605 4606 1 0.040751777 0.005078507
ccl.c 64892 64909 9 0.074820042 0.034303878
ccl.h 3378 3379 1 0.040103519 0.004498693
character.c 30011 31460 12 0.046008242 0.03198511
character.h 22260 22807 10 0.051320439 0.023682425
charset.c 71099 71353 27 0.072188876 0.051697323
charset.h 19497 19498 2 0.045175674 0.01241516
chartab.c 40500 40477 3 0.046526946 0.016520792
cm.c 12450 12497 8 0.039806277 0.008985652
cm.h 6663 6664 2 0.040049252 0.007376253
cmds.c 16526 16599 7 0.042697529 0.010883493
coding.c 338973 339614 50 0.2216622490000007 0.201216524
coding.h 25135 25089 9 0.051864564 0.043502682
commands.h 1777 1778 2 0.037541285 0.003727237
composite.c 62207 62662 22 0.066043622 0.040960006
composite.h 12841 12842 2 0.043224544 0.01015017
conf_post.h 12219 13619 32 0.057944305 0.316720286
cygw32.c 4097 4103 4 0.034885675 0.00417603
cygw32.h 1114 1115 2 0.037897192 0.003836258
data.c 105970 111859 173 0.091105203 2.36943677
dbusbind.c 56717 56114 33 0.070967645 0.040514633
decompress.c 5818 5816 6 0.037711904 0.006254757
dired.c 33933 35264 46 0.054381819 0.129114725
dispextern.h 125049 125599 27 0.1125148320000024 0.137689716
dispnew.c 192820 195002 40 0.14034202000000218 0.126384317
disptab.h 3792 3793 2 0.038948776 0.005761964
doc.c 30787 30364 60 0.054206798 2.040920659
doprnt.c 17440 17341 11 0.045842997 1.418094702
dosfns.c 24023 24024 2 0.043931466 0.012107652
dosfns.h 1354 1355 2 0.036587962 0.00332782
dynlib.c 8204 8144 13 0.039442547 0.010899135
dynlib.h 1236 1470 4 0.034412925 0.006534886
editfns.c 163739 176696 168 0.133299667 21.842241128
emacs-icon.h 11227 9741 5 0.044211595 0.899394067
emacs-module.c 36141 41083 123 0.053157166 3.441990992
emacs-module.h 5926 11403 39 0.039310549 0.335723981
emacs.c 76609 82259 104 0.10241060499999777 0.782522409
emacsgtkfixed.c 7610 7593 7 0.038240874 0.006682527
emacsgtkfixed.h 1232 1233 2 0.036124012 0.00364657
eval.c 114120 124710 188 0.087589155 2.898722315
fileio.c 193895 198534 178 0.15175350999999848 2.107626342
filelock.c 25123 24916 18 0.0530457 0.0300633
firstfile.c 1174 1181 4 0.036274588 0.003423639
floatfns.c 14301 14942 42 0.043030942 0.070060678
fns.c 144297 152390 261 0.11314744 2.628062007
font.c 156759 158090 46 0.121857369 0.106117666
font.h 32767 35111 41 0.059272594 0.081385134
fontset.c 63806 66015 43 0.066742228 0.068749007
fontset.h 1870 1871 2 0.036201255 0.003774656
frame.c 169459 197035 197 0.14188052399999723 11.390826892
frame.h 51724 55829 35 0.084095598 0.1988903
fringe.c 47107 47410 6 0.058255718 0.025621315
ftcrfont.c 8522 8999 13 0.037593103 0.018471908
ftfont.c 76531 74736 29 0.084099509 0.099711345
ftfont.h 1477 1478 1 0.038385581 0.003884165
ftxfont.c 9252 9817 19 0.038092251 0.024402044
getpagesize.h 1542 1543 2 0.038198339 0.005960446
gfilenotify.c 10356 11005 10 0.039196636 0.014714363
gmalloc.c 59535 58736 86 0.074037819 0.298251602
gnutls.c 57350 88628 134 0.074161995 13.440509296
gnutls.h 2782 3146 7 0.039073927 0.007352292
gtkutil.c 162240 167021 65 0.137785641 1.102747434
gtkutil.h 7148 7669 7 0.042605124 0.014563785
image.c 270253 272136 197 0.24048663299999973 0.3771013260000001
indent.c 68725 72543 40 0.069655476 0.197957968
indent.h 2171 2172 2 0.037791099 0.003747767
inotify.c 11744 16423 29 0.040909679 1.174832033
insdel.c 65329 69314 21 0.066685515 0.325519413
intervals.c 69906 69176 9 0.067576748 0.050484365
intervals.h 11702 11604 11 0.045407397 0.011909646
keyboard.c 368698 375297 99 0.25862514299999695 0.465379164
keyboard.h 18424 18469 6 0.050166178 0.013732686
keymap.c 112662 113335 17 0.083695687 0.056851559
keymap.h 2301 2302 2 0.037595056 0.00372039
kqueue.c 15899 16543 10 0.044582652 0.015272174
lastfile.c 1892 2053 5 0.036237919 0.004087539
lisp.h 151532 154750 266 0.1509155469999975 35.897183584
lread.c 141434 153962 184 0.119046282 2.720143923
macfont.h 2712 2848 3 0.035859034 0.004644863
macros.c 12297 12307 3 0.041035809 0.006785675
macros.h 1664 1665 2 0.034252566 0.003497947
macuvs.h 478710 478842 9 0.208870107 0.281665641
marker.c 21655 22190 6 0.043885016 0.015349901
menu.c 45442 45310 8 0.060727013 0.025445792
menu.h 2291 2276 3 0.037475278 0.004453221
minibuf.c 71348 73754 41 0.070550615 0.094917805
msdos.c 117032 117570 9 0.11398439100000007 1.850454493
msdos.h 4227 4348 5 0.039840491 0.006227861
nsgui.h 4938 4939 2 0.041423981 0.010088069
nsterm.h 38626 44083 44 0.071184695 0.497490175
print.c 70038 73841 45 0.074963755 3.092901676
process.c 227582 247290 295 0.1890464100000002 22.090230694
process.h 8234 9836 16 0.041708021 0.039218551
profiler.c 18482 18457 11 0.045066153 0.012278255
puresize.h 3442 3443 3 0.04147238 0.005891998
ralloc.c 33444 33083 7 0.048564107 0.01934699
regex.c 194305 193326 97 0.18420549300000255 2.1140529800000034
regex.h 23762 23784 18 0.055106329 0.037439999
region-cache.c 26621 26622 2 0.040934119 0.011647109
region-cache.h 5278 5279 2 0.037751984 0.004508464
scroll.c 32513 32479 6 0.044252164 0.012821891
search.c 103513 103321 61 0.086465199 0.081540518
sheap.c 2942 2140 14 0.036889106 0.028218231
sound.c 40357 40413 8 0.05392959 0.021327448
syntax.c 109738 113161 158 0.087267454 1.434325523
syntax.h 7761 7762 2 0.037905493 0.005649024
sysdep.c 102007 111582 99 0.13289533099999673 1.989721573
sysselect.h 2283 2556 3 0.037274834 0.006309014
syssignal.h 2232 2367 4 0.038784503 0.00532734
sysstdio.h 1022 2125 3 0.03718488 0.013065842
systime.h 3186 3187 2 0.038469174 0.00488148
systty.h 2774 2754 3 0.039123787 0.005151832
syswait.h 1909 1910 3 0.039052899 0.004846281
term.c 130082 131097 57 0.109988258 0.086482128
termcap.c 15849 15950 2 0.04168113 0.009182658
termchar.h 9306 9142 3 0.03803749 0.007388463
termhooks.h 28047 28799 10 0.052728893 0.024784816
terminal.c 18532 18842 5 0.042489742 0.012637093
terminfo.c 1604 1605 2 0.037029904 0.003299949
termopts.h 1064 1065 2 0.037506564 0.00331266
textprop.c 72068 72885 10 0.062994933 0.039788584
tparam.c 7296 7399 9 0.039632713 0.006514832
tparam.h 1285 1340 3 0.036759551 0.003724787
undo.c 15682 15683 2 0.037444476 0.006994425
unexaix.c 15514 15515 2 0.041274868 0.009001772
unexcoff.c 15156 15157 2 0.042041924 0.009591851
unexcw.c 9107 8916 12 0.041075404 0.0078881
unexec.h 116 116 0 0.033408751 0.003039864
unexelf.c 23765 21299 11 0.053904654 0.148939647
unexhp9k800.c 9817 9817 0 0.036054582 0.006484522
unexmacosx.c 43220 42350 6 0.053606436 0.02987847
unexsol.c 604 604 0 0.035678632 0.00308533
unexw32.c 26998 27189 25 0.048881388 0.030160066
vm-limit.c 5745 5907 4 0.038113266 0.007256465
w16select.c 22279 22280 2 0.043059776 0.010776411
w32.c 266005 273748 66 0.18260096800000158 0.627642931
w32.h 8949 8953 4 0.042010636 0.007591838
w32common.h 1665 1666 2 0.036456443 0.003793719
w32console.c 23538 24696 22 0.048895075 0.023420836
w32fns.c 324499 362552 212 0.21937420400000068 18.248501324
w32font.c 88643 90842 29 0.081519657 0.072026383
w32font.h 2977 2942 3 0.039110585 0.004692282
w32gui.h 4020 4021 2 0.037496295 0.007041357
w32heap.c 23905 26233 16 0.049931017 0.050266279
w32heap.h 2267 2245 4 0.036854881 0.003951627
w32inevt.c 23375 24193 21 0.047331629 0.034662657
w32inevt.h 1176 1177 2 0.034336649 0.003406036
w32menu.c 45595 45600 13 0.060038168 0.027367082
w32notify.c 24003 25122 43 0.045228946 0.296313355
w32proc.c 114140 115841 30 0.098294186 0.089718993
w32reg.c 4458 4473 4 0.037260164 0.004628727
w32select.c 32498 35683 8 0.051822012 0.116391864
w32select.h 953 954 2 0.036962924 0.003246171
w32term.c 208214 216804 128 0.1463850479999982 0.415736768
w32term.h 30113 30169 16 0.060337364 0.048109823
w32uniscribe.c 37252 37858 11 0.054613041 0.030259303
w32xfns.c 7429 8449 4 0.037661536 0.016883024
widget.c 15235 15408 20 0.040981535 0.018154604
widget.h 2839 2847 4 0.039648354 0.00620097
widgetprv.h 2192 2193 4 0.034828463 0.003805451
window.c 247029 263196 113 0.1596132229999978 1.762098508
window.h 40676 42531 57 0.066522213 0.672974315
xdisp.c 1014261 1063910 413 0.5709538769999968 8.085211918999999
xfaces.c 198840 200689 44 0.15355596700000157 0.133174164
xfns.c 219992 249068 142 0.17801425699999682 11.777595139
xfont.c 31984 31266 17 0.04941573 0.045066529
xftfont.c 23858 24658 23 0.053319945 0.094962713
xgselect.c 5244 5440 11 0.038232549 0.007538058
xgselect.h 1006 987 3 0.034031095 0.003615276
xmenu.c 67074 68801 15 0.083512823 0.05330662
xml.c 8054 8039 6 0.038789874 0.007088776
xrdb.c 17375 17498 5 0.043487055 0.012977349
xselect.c 86814 87776 16 0.075765995 0.051242075
xsettings.c 30659 30639 4 0.056324614 0.018391707
xsettings.h 1134 1135 2 0.035387742 0.0035175
xsmfns.c 17559 17605 5 0.045125299 0.010618009
xterm.c 383015 402521 208 0.29099005199999517 2.1414645249999964
xterm.h 41373 43427 13 0.070231358 0.070234126
xwidget.c 37193 38456 52 0.05613786 2.158033152
xwidget.h 3739 3622 5 0.038403168 0.006243501
[-- Attachment #3: 0001-Add-a-new-functionality-for-reverting-visiting-file-.patch --]
[-- Type: text/x-patch, Size: 9941 bytes --]
From 50b1ce0185cd7b5f8be124eb4a612fd56e4e0657 Mon Sep 17 00:00:00 2001
From: Mauro Aranda <maurooaranda@gmail.com>
Date: Tue, 14 May 2019 22:23:17 -0300
Subject: [PATCH] Add a new functionality for reverting visiting-file buffers
* lisp/files.el (revert-buffer-with-fine-grain): New command. Revert
a buffer trying to be non-destructive, by using replace-buffer-contents.
(revert-buffer-insert-file-contents-delicately): New function, alternative
to revert-buffer-insert-file-contents-function--default-function.
(revert-buffer-with-fine-grain-max-seconds): New variable. Passed as
argument MAX-SECS of replace-buffer-contents.
* doc/emacs/files.texi (Reverting): Document the new command and the
new variable.
* etc/NEWS: Mention the new command and the new variable.
* test/lisp/files-tests.el (files-tests-lao files-tests-tzu): Helper
variables, taken from diffutils manual, to test reverting a buffer.
(files-tests-revert-buffer)
(files-tests-revert-buffer-with-fine-grain): New tests.
---
doc/emacs/files.texi | 14 ++++++++++
etc/NEWS | 10 +++++++
lisp/files.el | 71 ++++++++++++++++++++++++++++++++++++++++++++++++
test/lisp/files-tests.el | 54 ++++++++++++++++++++++++++++++++++++
4 files changed, 149 insertions(+)
diff --git a/doc/emacs/files.texi b/doc/emacs/files.texi
index 36ef1dc..3985124 100644
--- a/doc/emacs/files.texi
+++ b/doc/emacs/files.texi
@@ -916,6 +916,7 @@ Time Stamps
@node Reverting
@section Reverting a Buffer
@findex revert-buffer
+@findex revert-buffer-with-fine-grain
@cindex drastic changes
@cindex reread a file
@@ -936,6 +937,19 @@ Reverting
aliases to bring the reverted changes back, if you happen to change
your mind.
+@vindex revert-buffer-with-fine-grain-max-seconds
+ To revert a buffer more conservatively, you can use the command
+@code{revert-buffer-with-fine-grain}. This command acts like
+@code{revert-buffer}, but it tries to be as non-destructive as
+possible, making an effort to preserve all markers, properties and
+overlays in the buffer. Since reverting this way can be very slow
+when you have made a large number of changes, you can modify the
+variable @code{revert-buffer-with-fine-grain-max-seconds} to
+specify a maximum amount of seconds that replacing the buffer
+contents this way should take. Note that it is not ensured that the
+whole execution of @code{revert-buffer-with-fine-grain} won't take
+longer than this.
+
Some kinds of buffers that are not associated with files, such as
Dired buffers, can also be reverted. For them, reverting means
recalculating their contents. Buffers created explicitly with
diff --git a/etc/NEWS b/etc/NEWS
index 699a04b..90b45b0 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -439,6 +439,16 @@ If the region is active, the command joins all the lines in the
region. When there's no active region, the command works on the
current and the previous or the next line, as before.
++++
+** New command 'revert-buffer-with-fine-grain'.
+Revert a buffer trying to be as non-destructive as possible,
+preserving markers, properties and overlays.
+
++++
+** The new variable 'revert-buffer-with-fine-grain-max-seconds' specifies
+the maximum seconds that 'revert-buffer-with-fine-grain' should spend
+trying to be non-destructive.
+
\f
* Changes in Specialized Modes and Packages in Emacs 27.1
diff --git a/lisp/files.el b/lisp/files.el
index 8fa7f16..b672459 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -6076,6 +6076,77 @@ revert-buffer-insert-file-contents--default-function
(insert-file-contents file-name (not auto-save-p)
nil nil t))))))
+(defvar revert-buffer-with-fine-grain-max-seconds 2.0
+ "Maximum time that `revert-buffer-with-fine-grain' should spend trying to
+preserve markers, properties and overlays. If the operation takes more than
+this time, a single delete+insert is performed.
+Actually, this value is passed as the MAX-SECS argument to the function
+`replace-buffer-contents', so it is not ensured that the whole execution won't
+take longer. See `replace-buffer-contents' for more details.")
+
+(defun revert-buffer-insert-file-contents-delicately (file-name _auto-save-p)
+ "Optional function for `revert-buffer-insert-file-contents-function'.
+The function `revert-buffer-with-fine-grain' uses this function by binding
+`revert-buffer-insert-file-contents-function' to it.
+As with revert-buffer-insert-file-contents--default-function, FILE-NAME is
+the name of the file and AUTO-SAVE-P is non-nil if this is an auto-save file.
+Since calling `replace-buffer-contents' can take a long time, depending of
+the number of changes made to the buffer, it uses the value of the variable
+`revert-buffer-with-fine-grain-max-seconds' as a maximum time to try delicately
+reverting the buffer. If it fails, does a delete+insert. For more details,
+see `replace-buffer-contents'."
+ (cond ((not (file-exists-p file-name))
+ (error (if buffer-file-number
+ "File %s no longer exists"
+ "Cannot revert nonexistent file %s")
+ file-name))
+ ((not (file-readable-p file-name))
+ (error (if buffer-file-number
+ "File %s no longer readable"
+ "Cannot revert unreadable file %s")
+ file-name))
+ (t
+ (let* ((buf (current-buffer)) ; current-buffer is the buffer to revert.
+ (success
+ (save-excursion
+ (save-restriction
+ (widen)
+ (with-temp-buffer
+ (insert-file-contents file-name)
+ (let ((temp-buf (current-buffer)))
+ (set-buffer buf)
+ (replace-buffer-contents
+ temp-buf
+ revert-buffer-with-fine-grain-max-seconds)))))))
+ ;; See comments in revert-buffer-with-fine-grain for an explanation.
+ (defun revert-buffer-with-fine-grain-success-p ()
+ success))
+ (set-buffer-modified-p nil))))
+
+(defun revert-buffer-with-fine-grain (&optional ignore-auto noconfirm)
+ "Revert buffer preserving markers, overlays, etc.
+This command is an alternative to `revert-buffer' because it tries to be as
+non-destructive as possible, preserving markers, properties and overlays.
+Binds `revert-buffer-insert-file-contents-function' to the function
+`revert-buffer-insert-file-contents-delicately'.
+With a prefix argument, offer to revert from latest auto-save file. For more
+details on the arguments, see `revert-buffer'."
+ ;; See revert-buffer for an explanation of this.
+ (interactive (list (not current-prefix-arg)))
+ ;; Simply bind revert-buffer-insert-file-contents-function to the specialized
+ ;; function, and call revert-buffer.
+ (let ((revert-buffer-insert-file-contents-function
+ #'revert-buffer-insert-file-contents-delicately))
+ (revert-buffer ignore-auto noconfirm t)
+ ;; This closure is defined in revert-buffer-insert-file-contents-function.
+ ;; It is needed because revert-buffer--default always returns t after
+ ;; reverting, and it might be needed to report the success/failure of
+ ;; reverting delicately.
+ (when (fboundp 'revert-buffer-with-fine-grain-success-p)
+ (prog1
+ (revert-buffer-with-fine-grain-success-p)
+ (fmakunbound 'revert-buffer-with-fine-grain-success-p)))))
+
(defun recover-this-file ()
"Recover the visited file--get contents from its last auto-save file."
(interactive)
diff --git a/test/lisp/files-tests.el b/test/lisp/files-tests.el
index fe2e958..9a6f35d 100644
--- a/test/lisp/files-tests.el
+++ b/test/lisp/files-tests.el
@@ -1259,5 +1259,59 @@ files-tests-file-attributes-equal
(ignore-errors (advice-remove #'write-region advice))
(ignore-errors (delete-file temp-file-name)))))
+(defvar files-tests-lao "The Way that can be told of is not the eternal Way;
+The name that can be named is not the eternal name.
+The Nameless is the origin of Heaven and Earth;
+The Named is the mother of all things.
+Therefore let there always be non-being,
+ so we may see their subtlety,
+And let there always be being,
+ so we may see their outcome.
+The two are the same,
+But after they are produced,
+ they have different names.
+")
+
+(defvar files-tests-tzu "The Nameless is the origin of Heaven and Earth;
+The named is the mother of all things.
+
+Therefore let there always be non-being,
+ so we may see their subtlety,
+And let there always be being,
+ so we may see their outcome.
+The two are the same,
+But after they are produced,
+ they have different names.
+They both may be called deep and profound.
+Deeper and more profound,
+The door of all subtleties!
+")
+
+(ert-deftest files-tests-revert-buffer ()
+ "Test that revert-buffer is succesful."
+ (files-tests--with-temp-file temp-file-name
+ (with-temp-buffer
+ (insert files-tests-lao)
+ (write-file temp-file-name)
+ (erase-buffer)
+ (insert files-tests-tzu)
+ (revert-buffer t t t)
+ (should (compare-strings files-tests-lao nil nil
+ (buffer-substring (point-min) (point-max))
+ nil nil)))))
+
+(ert-deftest files-tests-revert-buffer-with-fine-grain ()
+ "Test that revert-buffer-with-fine-grain is successful."
+ (files-tests--with-temp-file temp-file-name
+ (with-temp-buffer
+ (insert files-tests-lao)
+ (write-file temp-file-name)
+ (erase-buffer)
+ (insert files-tests-tzu)
+ (should (revert-buffer-with-fine-grain t t))
+ (should (compare-strings files-tests-lao nil nil
+ (buffer-substring (point-min) (point-max))
+ nil nil)))))
+
(provide 'files-tests)
;;; files-tests.el ends here
--
2.7.4
^ permalink raw reply related [flat|nested] 24+ messages in thread
* bug#18: Fine-grained revert-buffer
2019-05-15 23:10 ` Mauro Aranda
@ 2020-09-19 23:08 ` Lars Ingebrigtsen
0 siblings, 0 replies; 24+ messages in thread
From: Lars Ingebrigtsen @ 2020-09-19 23:08 UTC (permalink / raw)
To: Mauro Aranda; +Cc: 18
Mauro Aranda <maurooaranda@gmail.com> writes:
> I spent some time thinking on how to get this new revert command
> integrated with the rest of revert-buffer functions, and I came up with
> the attached patch.
>
> Since the difference between revert-buffer and
> revert-buffer-with-fine-grain lies at the insert-file-contents level, I
> wrote an alternative to
> revert-buffer-insert-file-contents--default-function, that uses
> replace-buffer-contents, as Eli suggested. I named it
> revert-buffer-insert-file-contents-delicately.
[...]
> Corrections and comments are welcome. Better names too.
This was the final message in this thread (which is the oldest
still-open bug report in debbugs!).
I tried the patch out, and it almost worked flawlessly for me -- it did
the "really edit the buffer?" userlock thing, but that was easy enough
to disable, so I did that.
And I pushed the patch set to the trunk. I agree that perhaps the
command name isn't the most intuitive, so somebody with stronger ideas
about what the name of the command should be should go ahead and change
it.
--
(domestic pets only, the antidote for overdose, milk.)
bloggy blog: http://lars.ingebrigtsen.no
^ permalink raw reply [flat|nested] 24+ messages in thread
end of thread, other threads:[~2020-09-19 23:08 UTC | newest]
Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <jwvpruii0xr.fsf@iro.umontreal.ca>
2013-12-17 3:16 ` bug#18: Fine-grained revert-buffer Dmitry Gutov
2013-12-17 13:32 ` Stefan Monnier
2018-04-12 6:21 ` Toon Claes
2018-04-12 12:18 ` Stefan Monnier
2018-04-14 7:00 ` Toon Claes
2018-04-14 14:14 ` Stefan Monnier
2019-04-26 22:42 ` Mauro Aranda
2019-04-27 7:34 ` Eli Zaretskii
2019-04-27 15:10 ` Mauro Aranda
2019-04-27 16:30 ` Eli Zaretskii
2019-04-27 17:46 ` Mauro Aranda
2019-04-29 12:49 ` martin rudalics
2019-05-02 15:54 ` Basil L. Contovounesios
2019-05-02 16:20 ` Glenn Morris
2019-05-02 16:23 ` Basil L. Contovounesios
2019-05-02 21:27 ` Richard Stallman
2019-05-03 14:05 ` Basil L. Contovounesios
2019-05-05 22:41 ` Richard Stallman
2019-04-27 8:31 ` martin rudalics
2019-04-28 2:47 ` Richard Stallman
2019-04-29 23:32 ` Mauro Aranda
2019-04-30 0:17 ` Mauro Aranda
2019-05-15 23:10 ` Mauro Aranda
2020-09-19 23:08 ` Lars Ingebrigtsen
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).