I am in the process of writing some Elisp code which needs to provide feedback to the user about a certain aspect of the state of the buffer. (This is a bit vague, I know, but the whole thing is not yet blog-ready – sorry for that. And since it is a fair amount of code, I won’t be blogging about it in detail when it’s done, so I decided to share one or two things if they are potentially interesting.) The point is that every change to the buffer’s content may change that aspect, and computing it may be a bit expensive. The problem is, how to do that efficiently?
My first thought, computing the state in post-command-hook, is obviously a bad idea – it wouldn’t make any sense to recompute the state after point motion commands. I decided to use after-change-functions, which seemed best suited to the task, with one caveat: I might prefer to “batch” several keypresses made in quick succession and recompute the state only after all of them. How to do that, without hacking into Emacs C core? Is that possible at all?
Well of course it is, it is Emacs, after all! Here is the idea I learned from Emanuel Berg on the Emacs mailing list. Every Emacs buffer has two very specific counters, the “modification count” and the “character-change modification count”. Their actual numbers they hold are apparently not necessarily meaningful – what is important is when they are incremented. The modification count is incremented whenever the buffer is modified (including the changes in text properties). The character-change modification count is only modified when the text contained in the buffer is changed. This means that a function (it may be run using an idle timer, for instance) may e.g. store the value of one of them (with the help of one of the buffer-modified-tick
or buffer-chars-modified-tick
functions) in one invocation and compare it to the value during the next invocation, and if they differ, the function knows that the buffer was changed.
As usual, Emacs proves to be extremely flexible and able to support a lot of workflows, even without modifying its C code and recompiling. And – although today’s post was a bit advanced and very specific – if you want to learn how to modify Emacs so that it suits your needs better, it is probably best to start with Robert J. Chassell’s An Introduction to Programming in Emacs Lisp. It may be a bit boring for programmers, since it assumes that the reader has no coding experience, but I bet any programmer has mastered the art of skipping less interesting parts of lengthy documents (not that I necessarily approve of it!), so that shouldn’t be a problem. And if you read Chassell’s excelent Introduction, you might find a certain other book worthy of your attention, too. (Although to be fair, the subject of today’s post is most probably just a bit too advanced to make it to the book.)