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

From: Ihor Radchenko <[email-masked]>
Date: Tue, 02 Apr 2024 14:22:29 +0000

Stefan Monnier <[email-masked]> writes:

>>> 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 am not sure if combining small changes into larger ones is at all a
good idea.  The changes are stored in strings, which get allocated and
re-allocated repeatedly.  Repeated string allocations, especially when
strings keep growing towards the buffer size, is likely going to
increase consing and make GCs more frequent.

> 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.

Aside...
How nice would it be if buffer state and buffer text were persistent.
Like in https://code.visualstudio.com/blogs/2018/03/23/text-buffer-reimplementation

> 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.

FYI, Org parser maintains such a list.
We previously discussed a similar API in
https://yhetil.org/emacs-bugs/87o7iq1emo.fsf@localhost/

> 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, ...).

This makes sense.

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>