GNU bug report logs -
#70077
An easier way to track buffer changes
Previous Next
Full log
Message #14 received at 70077 <at> debbugs.gnu.org (full text, mbox):
On 2024-03-29 12:15, Stefan Monnier wrote:
> Tags: patch
>
> Our `*-change-functions` hook are fairly tricky to use right.
> Some of the issues are:
>
> - before and after calls are not necessarily paired.
> - the beg/end values don't always match.
> - there can be thousands of calls from within a single command.
> - these hooks are run at a fairly low-level so there are things they
> really shouldn't do, such as modify the buffer or wait.
> - the after call doesn't get enough info to rebuild the before-change
> state,
> so some callers need to use both before-c-f and after-c-f (and then
> deal with the first two points above).
>
> The worst part is that those problems occur rarely, so many coders
> don't
> see it at first and have to learn them the hard way, sometimes forcing
> them to rethink their original design.
>
> So I think we should provide something simpler.
> I attached a proof-of-concept API which aims to do that, with the
> following entry points:
>
> (defun track-changes-register ( signal)
> "Register a new tracker and return a new tracker ID.
> SIGNAL is a function that will be called with no argument when
> the current buffer is modified, so that we can react to the change.
> Once called, SIGNAL is not called again until `track-changes-fetch'
> is called with the corresponding tracker ID."
>
> (defun track-changes-unregister (id)
> "Remove the tracker denoted by ID.
> Trackers can consume resources (especially if `track-changes-fetch'
> is
> not called), so it is good practice to unregister them when you
> don't
> need them any more."
>
> (defun track-changes-fetch (id func)
> "Fetch the pending changes.
> ID is the tracker ID returned by a previous
> `track-changes-register'.
> FUNC is a function. It is called with 3 arguments (BEGIN END
> BEFORE)
> where BEGIN..END delimit the region that was changed since the last
> time `track-changes-fetch' was called and BEFORE is a string
> containing
> the previous content of that region.
>
> If no changes occurred since the last time, FUNC is not called and
> we return nil, otherwise we return the value returned by FUNC,
> and re-enable the TRACKER corresponding to ID."
>
> It's not meant as a replacement of the existing hooks since it doesn't
> try to accommodate some uses such as those that use before-c-f to
> implement a finer-grained form of read-only text.
>
> The driving design was:
>
> - Try to provide enough info such that it is possible and easy to
> maintain a copy of the buffer simply by applying the reported
> changes.
> E.g. for uses such as `eglot.el` or `crdt.el`.
> - Make the API less synchronous: take care of combining small changes
> into larger ones, and let the clients decide when they react to
> changes.
>
> If you're in the Cc, it's because I believe you have valuable
> experience
> with those hooks, so I'd be happy to hear your thought about whether
> you think this would indeed (have) be(en) better than what we have.
Your description of the problem is entirely consistent with my
experience. The last time I
checked it was `subst-char-in-region' which was causing most of the
difficulties, normally as a result of `fill-paragraph'.
If I remember correctly, I think this wouldn't be enough for my use. You
keep two buffers
in sync, you have to use before-change-function -- it is only before any
change that the
two buffers are guaranteed to be in sync and it is this that allows you
to work out what the
`start' and `end' positions mean in the copied buffer. Afterward, you
cannot work out what the end position because you don't know if the
change is a change, insertion, deletion or both.
Last time I checked, I did find relatively few primitives that were
guilty of being inconsistent -- in the case of `subst-char-in-region',
it returned the maximal area of effect before the and the minimal area
of effect after. Would it not be easier to fix these?
Phil
This bug report was last modified 1 year and 99 days ago.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.