Subject: Re: bug#70077: An easier way to track buffer changes

From: Stefan Monnier <[email-masked]>
Date: Mon, 01 Apr 2024 13:49:48 -0400

>>>  ... That's why `track-changes.el` bundles those into a single (BEG END
>>> BEFORE) change, which makes sure BEG/END are currently-valid buffer
>>> positions and thus easy to use.
>>> The previous buffer state is not directly available but can be
>>> easily reconstructed from (BEG END BEFORE).
>> Do I understand correctly that such bundling may result in a situation
>> when BEFORE is very long? In particular, I am thinking of a situation
>> when there are changes near the beginning and the end of buffer in quick
>> succession.
> Yes!

I'm not sure how to combine the benefits of combining small changes into
larger ones with the benefits of keeping distant changes separate.

I don't want to expose in the API a "sequence of changes", because
that's difficult to use in general: the only thing a client can conveniently
do with it is to keep their own copy of the buffer (e.g. in the LSP
server) and apply the changes in the order given.  But if for some
reason you need to do something else (e.g. convert the position from
charpos to line+col) you're in a world of hurt because (except for the
last element in the sequence) you don't have easy access to the state
the buffer was in when the change was made.

We could expose a list of simultaneous (and thus disjoint) changes,
which avoids the last problem.  But it's a fair bit more work for us, it
makes the API more complex for the clients, and it's rarely what the
clients really want anyway.

But it did occur to me that we could solve the "disjoint changes"
problem in the following way: signal the client (from
`before-change-functions`) when a change is about to be made "far" from
the currently pending changes.

The API would still expose only (BEG END BEFORE) rather than
lists/sequences of changes, but the clients could then decide to record
disjoint changes as they occur and thus create&manage their own
list/sequence of changes.  More specifically, someone could come
a create a new API on top which exposes a list/sequence of changes.

The main downside is that this signal of "upcoming disjoint change"
would have to be called from `before-change-functions`, so the client
would need to be careful as usual (e.g. don't modify the buffer, don't
do any blocking operation, ...).

        Stefan