elisp: Filter Functions

 
 36.9.2 Process Filter Functions
 -------------------------------
 
 A process “filter function” is a function that receives the standard
 output from the associated process.  _All_ output from that process is
 passed to the filter.  The default filter simply outputs directly to the
 process buffer.
 
    By default, the error output from the process, if any, is also passed
 to the filter function, unless the destination for the standard error
 stream of the process was separated from the standard output when the
 process was created (SeeOutput from Processes).
 
    The filter function can only be called when Emacs is waiting for
 something, because process output arrives only at such times.  Emacs
 waits when reading terminal input (see the function
 ‘waiting-for-user-input-p’), in ‘sit-for’ and ‘sleep-for’ (See
 Waiting), and in ‘accept-process-output’ (SeeAccepting Output).
 
    A filter function must accept two arguments: the associated process
 and a string, which is output just received from it.  The function is
 then free to do whatever it chooses with the output.
 
    Quitting is normally inhibited within a filter function—otherwise,
 the effect of typing ‘C-g’ at command level or to quit a user command
 would be unpredictable.  If you want to permit quitting inside a filter
 function, bind ‘inhibit-quit’ to ‘nil’.  In most cases, the right way to
 do this is with the macro ‘with-local-quit’.  SeeQuitting.
 
    If an error happens during execution of a filter function, it is
 caught automatically, so that it doesn’t stop the execution of whatever
 program was running when the filter function was started.  However, if
 ‘debug-on-error’ is non-‘nil’, errors are not caught.  This makes it
 possible to use the Lisp debugger to debug filter functions.  See
 Debugger.
 
    Many filter functions sometimes (or always) insert the output in the
 process’s buffer, mimicking the actions of the default filter.  Such
 filter functions need to make sure that they save the current buffer,
 select the correct buffer (if different) before inserting output, and
 then restore the original buffer.  They should also check whether the
 buffer is still alive, update the process marker, and in some cases
 update the value of point.  Here is how to do these things:
 
      (defun ordinary-insertion-filter (proc string)
        (when (buffer-live-p (process-buffer proc))
          (with-current-buffer (process-buffer proc)
            (let ((moving (= (point) (process-mark proc))))
              (save-excursion
                ;; Insert the text, advancing the process marker.
                (goto-char (process-mark proc))
                (insert string)
                (set-marker (process-mark proc) (point)))
              (if moving (goto-char (process-mark proc)))))))
 
    To make the filter force the process buffer to be visible whenever
 new text arrives, you could insert a line like the following just before
 the ‘with-current-buffer’ construct:
 
      (display-buffer (process-buffer proc))
 
    To force point to the end of the new output, no matter where it was
 previously, eliminate the variable ‘moving’ from the example and call
 ‘goto-char’ unconditionally.
 
    Note that Emacs automatically saves and restores the match data while
 executing filter functions.  SeeMatch Data.
 
    The output to the filter may come in chunks of any size.  A program
 that produces the same output twice in a row may send it as one batch of
 200 characters one time, and five batches of 40 characters the next.  If
 the filter looks for certain text strings in the subprocess output, make
 sure to handle the case where one of these strings is split across two
 or more batches of output; one way to do this is to insert the received
 text into a temporary buffer, which can then be searched.
 
  -- Function: set-process-filter process filter
      This function gives PROCESS the filter function FILTER.  If FILTER
      is ‘nil’, it gives the process the default filter, which inserts
      the process output into the process buffer.
 
  -- Function: process-filter process
      This function returns the filter function of PROCESS.
 
    In case the process’s output needs to be passed to several filters,
 you can use ‘add-function’ to combine an existing filter with a new one.
 SeeAdvising Functions.
 
    Here is an example of the use of a filter function:
 
      (defun keep-output (process output)
         (setq kept (cons output kept)))
           ⇒ keep-output
      (setq kept nil)
           ⇒ nil
      (set-process-filter (get-process "shell") 'keep-output)
           ⇒ keep-output
      (process-send-string "shell" "ls ~/other\n")
           ⇒ nil
      kept
           ⇒ ("lewis@slug:$ "
      "FINAL-W87-SHORT.MSS    backup.otl              kolstad.mss~
      address.txt             backup.psf              kolstad.psf
      backup.bib~             david.mss               resume-Dec-86.mss~
      backup.err              david.psf               resume-Dec.psf
      backup.mss              dland                   syllabus.mss
      "
      "#backups.mss#          backup.mss~             kolstad.mss
      ")