views:

107

answers:

3

Is there a way to trigger the execution of an emacs lisp function other than M-x myfun? I would like to have the function re-called every time the buffer is changed.

Background: I have a table of numbers with some mistakes. The table has column totals and other features which can be used to identify the mistakes. My elisp function highlights suspicious columns of numbers. What I would like is for the highlighting to disappear as soon as the numbers are corrected, without repeated calling of the highlight-errors function.

The analogous feature in Excel is called, I believe, "conditional formatting"

A: 

Add your function to the variable after-change-functions.

Dingo
A: 

Thanks. This sounds promising. Could you provide some more details, or point to an example?

josh
@josh: this shouldn't have been an answer, it should have been a comment under the answer or comment that you're replying to. Note that answers are not kept in chronological order, so there's no way to know who you're replying to.
Gilles
@josh: welcome to SO. It uses a Q only posts that answer a question should be posted as answers. You can comment on answers to your own questions and, once you have a rep of 50, on any question or answer. Also, should you ever need to add information to your own question, you can edit it.
outis
+7  A: 

The concept you're looking for in your first paragraphs is hooks. A hook variable is a list of functions that are executed when a certain event happens. Most hook variables have a name ending in -hook. The hook after-change-functions is executed each time you type something or otherwise change the buffer. Hooks are discussed in the Emacs Lisp manual under the heading "Hooks".

However, given what you're trying to do, it would be easier to use Emacs's highlighting mechanism. The solution may be as simple as adding a regexp in the right place.

Most files containing structured text (especially programming languages) are highlighted with the font locking mechanism. This is documented in both the Emacs and Emacs Lisp manuals under "Font Lock"; see in particular the function font-lock-add-keywords, for which the Emacs manual gives an example that is pretty much what you're after. There is also some information on the Emacs wiki.

ADDED:

Font lock can go beyond regexps; unfortunately the documentation is limited to the terse explanation in the docstring of font-lock-keywords. There are a few simple examples in cperl-mode.el (though they're somewhat buried in the mass). The wiki also references ctypes.el which uses this feature. Here is an example that highlights wrong integer additions.

(defun maybe-warn-about-addition ()
  (let ((x (string-to-int (match-string 1)))
        (y (string-to-int (match-string 2)))
        (z (string-to-int (match-string 3))))
    (if (/= (+ x y) z)
        font-lock-warning-face)))
(font-lock-add-keywords
 nil
 '(("\\s-\\([0-9]+\\)\\s-*\\+\\s-*\\([0-9]+\\)\\s-*=\\s-*\\([0-9]+\\)\\s-"
    (3 (maybe-warn-about-addition) t))))

Even the regexp can be replaced by arbitrary code that looks for the bounds of what you want to highlight (a function name as MATCHER, using the vocabulary from the docstring). There is an advanced example of font lock keywords in the standard C mode (cc-fonts.el).

Gilles
Thanks much. My sense was that Font Lock was customizable for regular expressions, but that there was not a facility for content-based conditions such as highlighting the line 1 1 3 (because 1 + 1 != 3) and then removing highlight when the line becomes 2 1 3 (because 2 + 1 does = 3).
josh
@josh: you can write arbitrary code to configure the highlighting with Font Lock, it's just a little more complicated. Your example is definitely possible. I'll look for some example code and add it to my answer.
Gilles