elisp: Change Hooks

 
 31.28 Change Hooks
 ==================
 
 These hook variables let you arrange to take notice of changes in
 buffers (or in a particular buffer, if you make them buffer-local).  See
 also SeeSpecial Properties, for how to detect changes to specific
 parts of the text.
 
    The functions you use in these hooks should save and restore the
 match data if they do anything that uses regular expressions; otherwise,
 they will interfere in bizarre ways with the editing operations that
 call them.
 
  -- Variable: before-change-functions
      This variable holds a list of functions to call when Emacs is about
      to modify a buffer.  Each function gets two arguments, the
      beginning and end of the region that is about to change,
      represented as integers.  The buffer that is about to change is
      always the current buffer when the function is called.
 
  -- Variable: after-change-functions
      This variable holds a list of functions to call after Emacs
      modifies a buffer.  Each function receives three arguments: the
      beginning and end of the region just changed, and the length of the
      text that existed before the change.  All three arguments are
      integers.  The buffer that has been changed is always the current
      buffer when the function is called.
 
      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 first two arguments.
 
    Output of messages into the ‘*Messages*’ buffer does not call these
 functions, and neither do certain internal buffer changes, such as
 changes in buffers created by Emacs internally for certain jobs, that
 should not be visible to Lisp programs.
 
    Do _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.
 
  -- Macro: combine-after-change-calls body...
      The macro executes BODY normally, but arranges to call the
      after-change functions just once for a series of several changes—if
      that seems safe.
 
      If a program makes several text changes in the same area of the
      buffer, using the macro ‘combine-after-change-calls’ around that
      part of the program can make it run considerably faster when
      after-change hooks are in use.  When the after-change hooks are
      ultimately called, the arguments specify a portion of the buffer
      including all of the changes made within the
      ‘combine-after-change-calls’ body.
 
      *Warning:* You must not alter the values of
      ‘after-change-functions’ within the body of a
      ‘combine-after-change-calls’ form.
 
      *Warning:* if the changes you combine occur in widely scattered
      parts of the buffer, this will still work, but it is not advisable,
      because it may lead to inefficient behavior for some change hook
      functions.
 
  -- Variable: first-change-hook
      This variable is a normal hook that is run whenever a buffer is
      changed that was previously in the unmodified state.
 
  -- Variable: inhibit-modification-hooks
      If this variable is non-‘nil’, all of the change hooks are
      disabled; none of them run.  This affects all the hook variables
      described above in this section, as well as the hooks attached to
      certain special text properties (SeeSpecial Properties) and
      overlay properties (SeeOverlay Properties).
 
      Also, this variable is bound to non-‘nil’ while running those same
      hook variables, so that by default modifying the buffer from 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 ‘inhibit-modification-hooks’ to ‘nil’.