Use replace-buffer-contents?
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
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!
I imagine this would also eliminate the need for apheleia-max-alignment-size.
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.
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.
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.
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-contentson a sub-region if point happens to be within a modified part - skip the rcs patch entirely and use
replace-buffer-contentson 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