Package: emacs;
Reported by: Stefan Monnier <monnier <at> iro.umontreal.ca>
Date: Fri, 2 May 2025 21:49:02 UTC
Severity: normal
Found in version 31.0.50
View this message in rfc822 format
From: Daniel Colascione <dancol <at> dancol.org> To: monnier <at> iro.umontreal.ca, 78221 <at> debbugs.gnu.org, acm <at> muc.de Cc: eliz <at> gnu.org, yantar92 <at> posteo.net, joaotavora <at> gmail.com Subject: bug#78221: `inhibit-recording-text-property-changes` Date: Mon, 12 May 2025 21:12:29 -0700
On May 12, 2025 8:48:16 PM PDT, "Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors" <bug-gnu-emacs <at> gnu.org> wrote: >>> - Don't notify changes to text-properties. >>> Currently, things like `put-text-property` run the *-change-functions >>> like any other buffer modification. In practice this is of dubious value: >>> - It's already the case that most calls to `put-text-property` and >>> friends don't cause any notification because they are wrapped within >>> a `with-silent-modifications` or otherwise take place from code >>> which always runs with `inhibit-modification-hooks` set >>> (e.g. because it's run from a *-change-function). >>> So *-change-functions can't reliably track changes to text-properties. >>> - Most *-change-functions are *not* interested in text-property >>> changes anyway. >>> The above two points suggest maybe we could just refrain from >>> running *-change-functions when changing the text-properties (just >>> like we do for changes to overlay properties). >>> Then again, this would be a backward-incompatible change, so there's >>> a chance some packages out there would be negatively affected. >>> Another option would be to allow packages to choose whether to receive >>> notifications like now or only for changes to the text. >>> E.g. just like we have `buffer-modified-tick` and >>> `buffer-chars-modified-tick`, we could have `*-change-functions` >>> and `*-chars-change-functions` (with some questions remaining about >>> `first-change-hook` and the `modification-hooks` property). >>> Or we could rely on a (symbol) property being set on the functions >>> added to `*-change-functions` to tell whether they want to know about >>> changes to text-properties or not. >>> Or maybe a more crude way would be a buffer-local variable controlling >>> whether `*-change-functions` are called for text-property changes. >> >> I think it was a mistake in the beginning to have text property >> modifications trigger before/after-c-f. > >+1 The idea, I think, was for users to directly manipulate text properties to attach semantic information. That's why In practice, text properties ended up being volatile implementation details. I think XEmacs got this more right by directly exposing intervals (which we have anyway) as extents. Water under the bridge now. > >> But seeing it's been that way for so long, I don't think it would be >> a good idea to change it now. > >The more I look at it, the more I see it as a serious mistake, indeed. >I still have not found a single *-change-function that needs to know >about text-property changes. > >On the contrary, I see that most code that changes text-properties >wraps those changes in `with-silent-modifications` to avoid the various >undesirable side-effects of treating text-properties as being part of >the text. Actually, the whole purpose of `with-silent-modifications` is >to work around that historical mistake. > >Of all the code that touches text-properties I see that the majority is >wrapped (directly or indirectly) in `with-silent-modifications`, and of >the remaining ones, the majority would actually benefit from being >wrapped as well (the authors just haven't bumped (yet) into the >downsides). > >The only case I have found so far where we do want to record >text-property changes (not to run *-change-functions, but to mark the >buffer as modified and to record the changes in the undo-list) is the >`enriched-mode`. Can we just delete enriched mode? Good idea, but the world ended up going in a different direction. >For that single use case the rest of ELisp code has had to pay the >complexity cost of `with-silent-modifications` (which is delicate to use >since its effect is nasty if you do modify the buffer's text) plus the >occasional performance cost of uselessly running the *-change-functions >and wasting memory by recording those changes on the undo-list (not to >mention the occasional breakage of promises of how *-change-functions >are run). > >AFAICT, in the long term, ELisp code would benefit from fixing that >historical mistake. > >I suggest we introduce a new boolean variable >`inhibit-recording-text-property-changes`: if nil we get the current >behavior, but if non-nil then all text-property modifications are >implicitly wrapped in a `with-silent-modifications`: they don't change >the modified-p flag, they don't change the undo list, they don't run any >modification hooks. > >I'd expect it to default to nil (for obvious backward compatibility >reasons), and major modes can set it buffer-locally to t. Eventually, >I'd hope even `enriched-mode` will set it to t, and will instead record >the text-property changes "by hand". Minor modes might need it too. I think it's fine to add a new hook variable, but I don't think it's safe or even especially convenient (relative to the new variable) to have something that changes the behavior of existing code at a distance. And speaking of hindsight: if we're going to add a new hook variable, how about making it a function compatible with add-function and such instead of a list of functions?
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.