info-gnu-emacs
[Top][All Lists]
Advanced

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

New GNU ELPA package: track-changes - API to react to buffer modificatio


From: Sacha Chua
Subject: New GNU ELPA package: track-changes - API to react to buffer modifications
Date: Mon, 22 Apr 2024 08:40:10 -0400

    Summary: API to react to buffer modifications
   Requires: emacs-24
    Website: https://elpa.gnu.org/packages/track-changes.html
 Maintainer: Stefan Monnier <monnier@iro.umontreal.ca>
     Author: Stefan Monnier <monnier@iro.umontreal.ca>

This library is a layer of abstraction above `before-change-functions'
and `after-change-functions' which takes care of accumulating changes
until a time when its client finds it convenient to react to them.

It provides an API that is easier to use correctly than our
`*-change-functions' hooks.  Problems that it claims to solve:

- Before and after calls are not necessarily paired.
- The beg/end values don't always match.
- There's usually only one call to the hooks per command but
  there can be thousands of calls from within a single command,
  so naive users will tend to write code that performs poorly
  in those rare cases.
- The 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 new API is almost like `after-change-functions' except that:
- It provides the "before string" (i.e. the previous content of
  the changed area) rather than only its length.
- It can combine several changes into larger ones.
- Clients do not have to process changes right away, instead they
  can let changes accumulate (by combining them into a larger change)
  until it is convenient for them to process them.
- By default, changes are signaled at most once per command.

The API consists in the following functions:

    (track-changes-register SIGNAL &key NOBEFORE DISJOINT IMMEDIATE)
    (track-changes-fetch ID FUNC)
    (track-changes-unregister ID)

A typical use case might look like:

    (defvar my-foo--change-tracker nil)
    (define-minor-mode my-foo-mode
      "Fooing like there's no tomorrow."
      (if (null my-foo-mode)
          (when my-foo--change-tracker
            (track-changes-unregister my-foo--change-tracker)
            (setq my-foo--change-tracker nil))
        (unless my-foo--change-tracker
          (setq my-foo--change-tracker
                (track-changes-register
                 (lambda (id)
                   (track-changes-fetch
                    id (lambda (beg end before)
                         ..DO THE THING..))))))))



reply via email to

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