Next: , Previous: Process Buffers, Up: Output from Processes


57.8.2 Process Filter Functions

A process filter function is a function that receives the standard output from the associated process. If a process has a filter, then all output from that process is passed to the filter. The process buffer is used directly for output from the process only when there is no filter.

A filter function must accept two arguments: the associated process and a string, which is the output. The function is then free to do whatever it chooses with the output.

A filter function runs only while SXEmacs is waiting (e.g., for terminal input, or for time to elapse, or for process output). This avoids the timing errors that could result from running filters at random places in the middle of other Lisp programs. You may explicitly cause SXEmacs to wait, so that filter functions will run, by calling sit-for or sleep-for (see Waiting), or accept-process-output (see Accepting Output). SXEmacs is also waiting when the command loop is reading input.

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. See Quitting.

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, the error-catching is turned off. This makes it possible to use the Lisp debugger to debug the filter function. See Debugger.

Many filter functions sometimes or always insert the text in the process's buffer, mimicking the actions of SXEmacs when there is no filter. Such filter functions need to use set-buffer in order to be sure to insert in that buffer. To avoid setting the current buffer semipermanently, these filter functions must use unwind-protect to make sure to restore the previous current buffer. They should also update the process marker, and in some cases update the value of point. Here is how to do these things:

     (defun ordinary-insertion-filter (process string)
       (let ((old-buffer (current-buffer)))
         (unwind-protect
             (let (moving)
               (set-buffer (process-buffer process))
               (setq moving (= (point) (process-mark process)))
               (save-excursion
                 ;; Insert the text, moving the process-marker.
                 (goto-char (process-mark process))
                 (insert string)
                 (set-marker (process-mark process) (point)))
               (if moving (goto-char (process-mark process))))
           (set-buffer old-buffer))))

The reason to use an explicit unwind-protect rather than letting save-excursion restore the current buffer is so as to preserve the change in point made by goto-char.

To make the filter force the process buffer to be visible whenever new text arrives, insert the following line just before the unwind-protect:

     (display-buffer (process-buffer process))

To force point to move to the end of the new output no matter where it was previously, eliminate the variable moving and call goto-char unconditionally.

In earlier Emacs versions, every filter function that did regexp searching or matching had to explicitly save and restore the match data. SXEmacs does this automatically; filter functions never need to do it explicitly. See Match Data.

A filter function that writes the output into the buffer of the process should check whether the buffer is still alive. If it tries to insert into a dead buffer, it will get an error. If the buffer is dead, (buffer-name (process-buffer process)) returns nil.

The output to the function 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.

— Function: set-process-filter process filter

This function gives process the filter function filter. If filter is nil, then the process will have no filter. If filter is t, then no output from the process will be accepted until the filter is changed. (Output received during this time is not discarded, but is queued, and will be processed as soon as the filter is changed.)

— Function: process-filter process

This function returns the filter function of process, or nil if it has none. t means that output processing has been stopped.

Here is an example of 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[8] % "
     "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
     ")