GNU bug report logs -
#25111
How modification-hooks let-bind inhibit-modification-hooks?
Previous Next
Full log
View this message in rfc822 format
Hello, Eli and Noam (but mainly Noam).
It's about time we finally got this matter tidied up, so...
On Sun, Jun 09, 2019 at 15:00:16 +0300, Eli Zaretskii wrote:
> OK, after re-reading the discussions and the code, I don't think we
> should make the incompatible change suggested by Alan. We haven't
> bound inhibit-modification-hooks to t in the text-property hooks since
> the day the code was written, 24 years ago, so it makes no sense to me
> to do that now. Let's document the exception and move on.
> Noam's last patch LGTM, with the single minor gotcha:
> > +When Emacs calls these functions, @code{inhibit-modification-hooks} is
> > +set to @code{nil}, unlike for change hooks.
> This is from the part that changes the "Special Properties" node, and
> it's inaccurate: we don't bind inhibit-modification-hooks to nil, we
> just leave it at its previous binding. This distinction is important
> in recursive calls, when the caller caused inhibit-modification-hooks
> to be bound to non-nil.
I've corrected this bit by saying that "Unlike with other similar hooks,
when Emacs calls these functions, `inhibit-modification-hooks' does _not_
get bound to non-`nil'".
I've also added bits to the descriptions of
insert-{in-front,behind}-hooks, the text property version of them,
documenting that inhibit-modification-hooks gets bound to non-nil.
[ .... ]
I think the changes as now formulated are right. Perhaps one or both of
you might like to give the following patch a quick review. Thanks!
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index 7e8abb0440..68f40b55d8 100644
--- a/doc/lispref/display.texi
+++ b/doc/lispref/display.texi
@@ -1752,9 +1752,12 @@ Overlay Properties
length is the number of characters deleted, and the post-change
beginning and end are equal.)
-If these functions modify the buffer, they should bind
-@code{inhibit-modification-hooks} to @code{t} around doing so, to
-avoid confusing the internal mechanism that calls these hooks.
+When these functions are called, @code{inhibit-modification-hooks} is
+bound to non-@code{nil}. If the functions modify the buffer, you
+might want to bind @code{inhibit-modification-hooks} to nil, so as to
+cause the change hooks to run for these modifications. However, doing
+this may call your own change hook recursively, so be sure to prepare
+for that. @xref{Change Hooks}.
Text properties also support the @code{modification-hooks} property,
but the details are somewhat different (@pxref{Special Properties}).
diff --git a/doc/lispref/text.texi b/doc/lispref/text.texi
index 2e7c497f57..95ed758914 100644
--- a/doc/lispref/text.texi
+++ b/doc/lispref/text.texi
@@ -3621,9 +3621,12 @@ Special Properties
hook will only be run when removing some characters, replacing them
with others, or changing their text-properties.
-If these functions modify the buffer, they should bind
-@code{inhibit-modification-hooks} to @code{t} around doing so, to
-avoid confusing the internal mechanism that calls these hooks.
+Unlike with other similar hooks, when Emacs calls these functions,
+@code{inhibit-modification-hooks} does @emph{not} get bound to
+non-@code{nil}. If the functions modify the buffer, you should
+consider binding this variable to non-@code{nil} to prevent any buffer
+changes running the change hooks. Otherwise, you must be prepared for
+recursive calls. @xref{Change Hooks}.
Overlays also support the @code{modification-hooks} property, but the
details are somewhat different (@pxref{Overlay Properties}).
@@ -3639,6 +3642,13 @@ Special Properties
beginning and end of the inserted text. The functions are called
@emph{after} the actual insertion takes place.
+When these functions are called, @code{inhibit-modification-hooks} is
+bound to non-@code{nil}. If the functions modify the buffer, you
+might want to bind @code{inhibit-modification-hooks} to nil, so as to
+cause the change hooks to run for these modifications. However, doing
+this may call your own change hook recursively, so be sure to prepare
+for that.
+
See also @ref{Change Hooks}, for other hooks that are called
when you change text in a buffer.
@@ -5650,5 +5660,8 @@ Change Hooks
a modification hook does not cause other modification hooks to be run.
If you do want modification hooks to be run in a particular piece of
code that is itself run from a modification hook, then rebind locally
-@code{inhibit-modification-hooks} to @code{nil}.
+@code{inhibit-modification-hooks} to @code{nil}. However, doing this
+may cause recursive calls to the modification hooks, so be sure to
+prepare for that (for example, by binding some variable which tells
+your hook to do nothing).
@end defvar
--
Alan Mackenzie (Nuremberg, Germany).
This bug report was last modified 6 years and 30 days ago.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.