Функция фильтрации процесса — это функция, которая принимает стандартный вывод связанного процесса. Весь вывод из этого процесса передается фильтру. По умолчанию фильтр просто выводит данные непосредственно в буфер процесса.
По умолчанию вывод ошибок процесса, если таковой имеется, также передается в функцию фильтрации, если только назначение для потока стандартных ошибок процесса не было отделено от стандартного вывода при создании процесса. Emacs вызывает функцию фильтрации только во время определенных вызовов функций. См. Получение вывода от процессов. Обратите внимание, что если какая-либо из этих функций вызывается фильтром, фильтр может быть вызван рекурсивно.
Функция фильтрации должна принимать два аргумента: связанный процесс и строку, которая только что была получена от него. Затем функция может делать с этим выводом что угодно.
Обычно внутри функции фильтрации запрещено завершение работы — иначе эффект нажатия C-g на уровне команд или завершение пользовательской команды был бы непредсказуемым. Если вы хотите разрешить завершение работы внутри функции фильтрации, привяжите inhibit-quit к nil. В большинстве случаев правильный способ сделать это — использовать макрос with-local-quit. См. Завершение работы.
Если во время выполнения функции фильтрации происходит ошибка, она перехватывается автоматически, поэтому она не останавливает выполнение любой программы, которая работала, когда была запущена функция фильтрации. Однако, если debug-on-error не равен nil, ошибки не перехватываются. Это позволяет использовать отладчик Lisp для отладки функций фильтрации. См. Отладчик Lisp. Если ошибка перехвачена, Emacs приостанавливается на process-error-pause-time секунд, чтобы пользователь увидел ошибку. См. Создание асинхронного процесса.
Многие функции фильтрации иногда (или всегда) вставляют вывод в буфер процесса, имитируя действия стандартного фильтра. Такие функции фильтрации должны убедиться, что они сохраняют текущий буфер, выбирают правильный буфер (если он отличается) перед вставкой вывода, а затем восстанавливают исходный буфер. Они также должны проверить, жив ли буфер, обновить маркер процесса и в некоторых случаях обновить значение точки. Вот как это сделать:
(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
;; Вставить текст, продвигая маркер процесса.
(goto-char (process-mark proc))
(insert string)
(set-marker (process-mark proc) (point)))
(if moving (goto-char (process-mark proc)))))))
Чтобы заставить фильтр отображать буфер процесса, когда поступает новый текст, вы можете вставить такую строку прямо перед конструкцией with-current-buffer:
(display-buffer (process-buffer proc))
Чтобы принудительно переместить точку в конец нового вывода, независимо от того, где она была ранее, удалите переменную moving из примера и вызовите goto-char безусловно. Обратите внимание, что это не обязательно перемещает точку окна. Стандартный фильтр на самом деле использует insert-before-markers, который перемещает все маркеры, включая точку окна. Это может переместить несвязанные маркеры, поэтому обычно лучше явно перемещать точку окна или устанавливать ее тип в t (см. Окна и Точка).
Обратите внимание, что Emacs автоматически сохраняет и восстанавливает данные совпадения при выполнении функций фильтрации. См. Данные совпадения.
Вывод в фильтр может поступать частями любого размера. Программа, которая выдает один и тот же вывод дважды подряд, может отправить его как одну партию в 200 символов один раз, а затем пять партий по 40 символов. Если фильтр ищет определенные текстовые строки в выводе подпроцесса, убедитесь, что вы обрабатываете случай, когда одна из этих строк разделена на две или более партии вывода; один из способов сделать это — вставить полученный текст во временный буфер, который затем можно будет просканировать.
Эта функция присваивает process функцию фильтрации filter. Если filter равен nil, она присваивает процессу стандартный фильтр, который вставляет вывод процесса в буфер процесса. Если filter равен t, Emacs перестает принимать вывод от процесса, если только это не сетевой серверный процесс, который ожидает входящих соединений.
Эта функция возвращает функцию фильтрации process.
Если вывод процесса необходимо передать нескольким фильтрам, вы можете использовать add-function, чтобы объединить существующий фильтр с новым. См. Настройка функций Emacs Lisp.
Вот пример использования функции фильтрации:
(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 ")