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 Emacs 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 Emacs to
wait, so that filter functions will run, by calling sit-for
or
sleep-for
(see section Waiting for Elapsed Time or Input), or accept-process-output
(see section Accepting Output from Processes). Emacs 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 section 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 section The Lisp Debugger.
Many filter functions sometimes or always insert the text in the
process's buffer, mimicking the actions of Emacs 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 (proc string) (let ((old-buffer (current-buffer))) (unwind-protect (let (moving) (set-buffer (process-buffer proc)) (setq moving (= (point) (process-mark proc))) (save-excursion ;; Insert the text, moving the process-marker. (goto-char (process-mark proc)) (insert string) (set-marker (process-mark proc) (point))) (if moving (goto-char (process-mark proc)))) (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 proc))
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. Now Emacs does this automatically; filter functions never need to do it explicitly. See section The 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.
nil
, it gives the process no filter.
nil
if it has none.
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 ")
Go to the first, previous, next, last section, table of contents.