emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: An idea: combine-change-calls


From: Stefan Monnier
Subject: Re: An idea: combine-change-calls
Date: Sun, 25 Mar 2018 16:05:40 -0400
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/27.0.50 (gnu/linux)

> I've actually got a working implementation going.  It is this:
>
>     (defmacro combine-change-calls (beg end &rest form)
>       `(if (not inhibit-modification-hooks)
>            (let* ((-beg- ,beg) (-end- ,end)
>                   (end-marker (copy-marker -end-)))
>              (run-hook-with-args 'before-change-functions beg end)
>              (let ((inhibit-modification-hooks t))
>                ,@form)
>              (run-hook-with-args 'after-change-functions
>                                  beg (marker-position end-marker)
>                                  (- -end- -beg-)))
>          ,@form))

You need to evaluate `beg` and `end` even if inhibit-modification-hooks
is set, otherwise someone will get bitten.

I recommend you move the `form` to a lambda so you don't have to
duplicate it:

    `(let ((body (lambda () ,@form))
           (-beg- ,beg)
           (-end- ,end))
       ...)

Another benefit is that by moving `form` outside of the `let*`, you
won't need to use gensym/make-symbol nor obfuscated names.

I'd also recommend you check that `beg` hasn't changed position and that
the distance between end-marker and point-max remained the same.

>> Maybe combine-change-calls should also combine all those changes on the
>> undo-list into a big "delete+insert" (of course, it could also try and
>> keep the undo granularity but mark those undo entries so that they're
>> undone within their own combine-change-calls).
> :-)  Either of those would be quite a project, but possibly worth doing.

Replacing the entries with a pair of delete+insert should be
pretty easy.  Something like

    (let ((old-buffer-undo-list buffer-undo-list)
          (orig-text (buffer-substring beg end)))
      ...
      (setq buffer-undo-list
            `((,(marker-position end-marker) ,beg)
              (,orig-text . ,beg)
              . ,old-buffer-undo-list)))

modulo sanity checks (i.e. don't do it if undo is disabled and don't do
it if old-buffer-undo-list is not within buffer-undo-list any more).


        Stefan



reply via email to

[Prev in Thread] Current Thread [Next in Thread]