apheleia icon indicating copy to clipboard operation
apheleia copied to clipboard

Use replace-buffer-contents?

Open milanst opened this issue 5 years ago • 6 comments

Sorry, this is just a question, I'm not reporting a bug or anything.

Emacs 26 and later come with the function replace-buffer-contents which can be used to efficiently replace the contents of the current buffer by the contests of a different buffer, trying to make minimal edits and preserving marks and the point as much as possible. Underneath it uses code from https://github.com/coreutils/gnulib/blob/master/lib/diffseq.h which is based on well knows algorithms.

Is there a reason why this function is not used, instead of writing a new diff implementation or working with RCS patches? It seems much simpler to use replace-buffer-contents.

I use it daily for automatically formatting OCaml code with ocamlformat. I don't remember it ever moved my point where I didn't expect it (for example, I never saw something like issue #2 ) and I never noticed any slowness.

You can see example use here https://github.com/ocaml-ppx/ocamlformat/blob/02ea48f0d09a48fb2a25fdba75a8bf20872dadb5/emacs/ocamlformat.el#L211

milanst avatar Mar 10 '21 21:03 milanst

I can't think of any reason not to use this function, other than I was not aware of it when I authored this package. (That, and we will have to increase the minimum allowed Emacs version to 26.1 from 25.2.) Thanks for pointing out the area for improvement!

raxod502 avatar Mar 21 '21 19:03 raxod502

I imagine this would also eliminate the need for apheleia-max-alignment-size.

raxod502 avatar Mar 21 '21 19:03 raxod502

If you don't want to increase the minimum supported Emacs version (I guess that depends on the users of this package, I don't know if it is easy to figure out how many are on Emacs 25 or earlier), you could keep the current code as a fallback. They do something like that in ocamlformat.el that I linked earlier (plus they also handle some initial bug in replace-buffer-contents). But I think long term probably the right approach is to rely on replace-buffer-contents.

milanst avatar Mar 23 '21 16:03 milanst

I think it is OK to bump the required Emacs version. Generally I try to support at least the most recent Emacs version that is shipped in an Ubuntu LTS release. As Emacs 26 has been available in Ubuntu 20.04 for almost a year now, I think it is fine to move on, especially since it will greatly improve the maintainability and performance in Apheleia.

raxod502 avatar Mar 28 '21 22:03 raxod502

Note that, if I'm reading https://github.com/purcell/emacs-reformatter/pull/24 right, the RCS patch method may be faster than replace-buffer-contents.

dsedivec avatar Jul 03 '21 16:07 dsedivec

I'm spending some time looking into this. Here's a webpage that documents the basic algorithm used by replace-buffer-contents: https://www.nathaniel.ai/myers-diff/

I think the tradeoffs between the various methods are unclear, so I will implement all of them and allow the user to select the one that is most appropriate, or potentially dynamically pick one depending on the file size, etc. I imagine that we will want to offer the following 3 options:

  • generate and apply rcs patch, then use replace-buffer-contents on a sub-region if point happens to be within a modified part
  • skip the rcs patch entirely and use replace-buffer-contents on the whole buffer no matter what
  • generate and apply rcs patch, then use current dynamic programming algorithm if point happens to be within a modified part

raxod502 avatar Jan 22 '22 03:01 raxod502