emacs-devel
[Top][All Lists]
Advanced

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

Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]


From: Daniel Colascione
Subject: Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
Date: Tue, 30 Aug 2016 10:27:45 -0700
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.2.0

On 08/30/2016 10:12 AM, Alan Mackenzie wrote:
Hello, Eli.

On Mon, Aug 29, 2016 at 05:50:11PM +0300, Eli Zaretskii wrote:
From: Daniel Colascione <address@hidden>
Date: Sun, 28 Aug 2016 20:18:32 -0700

    Please trust me that the documentation misleads.

You are welcome to suggest more accurate wording that describes the
current implementation.

I think it's only fair to point out that I did precisly this almost
three weeks ago (on 2016-08-10) and the welcome my efforts got was
somewhat less than wholeheartedly warm.

The current documentation misleads in asserting that b-c-f and a-c-f
cannot be used together in balanced pairs.  They most assuredly can,
with the exception of a tiny number of rarely occurring cases.  If this
were not true, CC Mode would not work at all.

Using b-c-f and a-c-f together is an essential technique - there are
things that cannot be done without it, or at least not in any reasonable
manner.  In this sense, maintaining a duplicate shadow buffer, or
scanning from BOB at every buffer change, or maintaining a separate
record of all text properties on a buffer, don't fall into the category
of reasonable, from my point of view.

Eliminating this technique from Emacs, whether by "polluting" the source
to stop it working altogether (as suggested by Stefan), or by forbidding
it in the documentation, has the effect of making Emacs a less powerful
programming system.  I don't think this is what any of us should want.

[ .... ]

How about this? I think this revised text captures the intent of the current implementation and preserves the ability to use b-c-f and a-c-f together. (The current revert-buffer behavior is just a bug and is contrary to my proposed documentation.)

diff --git a/doc/lispref/text.texi b/doc/lispref/text.texi
index 213eec9..6511da8 100644
--- a/doc/lispref/text.texi
+++ b/doc/lispref/text.texi
@@ -4798,6 +4798,13 @@ Change Hooks
 has been changed is always the current buffer when the function is
 called.

+The region given to each of these functions is a conservative
+approximation of the region about to changed.  After running the
+before-change-functions, Emacs will make zero or more fine-grained
+buffer changes and run after-change-functions for each.  Do not expect
+before-change-functions and after-change-functions to be called in
+balanced pairs.
+
 The length of the old text is the difference between the buffer
 positions before and after that text as it was before the change.  As
 for the changed text, its length is simply the difference between the
@@ -4809,14 +4816,14 @@ Change Hooks
 as changes in buffers created by Emacs internally for certain jobs,
 that should not be visible to Lisp programs.

-  Do @emph{not} expect the before-change hooks and the after-change
-hooks be called in balanced pairs around each buffer change.  Also
-don't expect the before-change hooks to be called for every chunk of
-text Emacs is about to delete.  These hooks are provided on the
-assumption that Lisp programs will use either before- or the
-after-change hooks, but not both, and the boundaries of the region
-where the changes happen might include more than just the actual
-changed text, or even lump together several changes done piecemeal.
+   Do @emph{not} expect the before-change hooks and the after-change
+hooks be called in balanced pairs around each buffer change.
+The before-change-functions region is a conservative bound on the zero
+or more fine-grained changes to follow.  Emacs informs user code about
+the actual changes to the buffer through calls to
+after-change-functions; these fine-grained changes will always fall
+inside the broad change region Emacs describes by calling
+before-change-functions.

 @defmac combine-after-change-calls address@hidden
 The macro executes @var{body} normally, but arranges to call the
diff --git a/src/buffer.c b/src/buffer.c
index 24c997f..60e448f 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -6027,6 +6027,13 @@ the beginning and end of the range of old text to be changed.
 \(For an insertion, the beginning and end are at the same place.)
 No information is given about the length of the text after the change.

+The region given to each of these functions is a conservative
+approximation of the region about to changed.  After running the
+before-change-functions, Emacs will make zero or more fine-grained
+buffer changes and run `after-change-functions' for each.  Do not
+expect `before-change-functions' and `after-change-functions' to be
+called in balanced pairs.
+
 Buffer changes made while executing the `before-change-functions'
 don't call any before-change or after-change functions.
 That's because `inhibit-modification-hooks' is temporarily set non-nil.



reply via email to

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