プロセスのフィルタ関数とは、関連付けられたプロセスからの標準出力を受け取る関数のことです。そのプロセスからのすべての出力がフィルタに渡されます。デフォルトのフィルタは、単にプロセスバッファへ直接出力します。
デフォルトでは、プロセスの標準エラーストリームの出力先がプロセス作成時に標準出力から分離されていない限り、プロセスからのエラー出力(もしあれば)もフィルタ関数に渡されます。Emacsがフィルタ関数を呼び出すのは、特定の関数呼び出し時のみです。プロセスからの出力の受け取りを参照してください。なお、これらの関数のいずれかがフィルタによって呼び出された場合、フィルタが再帰的に呼び出される可能性があることに注意してください。
フィルタ関数は、関連付けられたプロセスと、そこから受信したばかりの文字列という2つの引数を受け取る必要があります。その後、関数は出力に対して自由に処理を行うことができます。
通常、フィルタ関数内での終了は抑制されています。そうしないと、コマンドレベルで C-g
と入力したり、ユーザーコマンドを終了させたりした際の挙動が予測不能になるためです。フィルタ関数内での終了を許可したい場合は、inhibit-quit を nil
にバインドしてください。多くの場合、これを実現する適切な方法はマクロ with-local-quit
を使用することです。終了 を参照してください。
フィルタ関数の実行中にエラーが発生した場合、それは自動的に捕捉されるため、フィルタ関数が開始された時点で実行されていたプログラムの処理が停止することはありません。ただし、debug-on-error が nil
以外の場合、エラーは捕捉されません。これにより、Lispデバッガを使用してフィルタ関数をデバッグすることが可能になります。Lispデバッガを参照してください。エラーが捕捉されると、ユーザーがエラーを確認できるよう、Emacsは
process-error-pause-time 秒間一時停止します。非同期プロセスの作成を参照してください。
多くのフィルタ関数は、デフォルトフィルタの動作を模して、出力をプロセスのバッファに挿入することがあります(あるいは常にそうします)。こうしたフィルタ関数は、現在のバッファを保存し、出力を挿入する前に(異なる場合は)正しいバッファを選択し、その後元のバッファを復元する必要があります。また、バッファがまだ有効であるかを確認し、プロセスマーカーを更新し、場合によってはpointの値を更新する必要があります。これらの処理を行う方法は以下の通りです。
(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)))))))
新しいテキストが届くたびにフィルターがプロセスバッファを強制的に表示させるには、with-current-buffer 構文の直前に次のような行を挿入できます。
(display-buffer (process-buffer proc))
以前の位置に関わらず、ポイントを新しい出力の末尾に強制的に移動させるには、例から変数 moving
を削除し、goto-char
を無条件に呼び出してください。なお、これによりウィンドウポイントが必ずしも移動するとは限りません。デフォルトのフィルタでは実際には insert-before-markers
が使用されており、これによりウィンドウポイントを含むすべてのマーカーが移動します。無関係なマーカーまで移動してしまう可能性があるため、一般的にはウィンドウポイントを明示的に移動させるか、その挿入タイプを
t に設定する方が適切です(ウィンドウとポイント を参照)。
なお、Emacsはフィルタ関数の実行中に、マッチデータを自動的に保存・復元します。マッチデータを参照してください。
フィルタへの出力は、任意のサイズのチャンク単位で届く場合があります。同じ出力を2回連続で生成するプログラムは、1回目は200文字の1バッチとして、次は40文字の5バッチとして送信することがあります。フィルタがサブプロセスの出力の中から特定のテキスト文字列を検索する場合、これらの文字列のいずれかが2つ以上の出力バッチにまたがって分割されるケースへの対応を必ず行ってください。その方法の一つとして、受信したテキストを一時バッファに挿入し、そこで検索を行うという方法があります。
この関数は、process にフィルタ関数 filter
を設定します。filter が nil
の場合、プロセスにデフォルトのフィルタが設定され、プロセスの出力がプロセスバッファに挿入されます。filter が t の場合、Emacs
はプロセスからの出力の受け付けを停止します。ただし、受信接続を待ち受けるネットワークサーバープロセスの場合はこの限りではありません。
この関数は、process のフィルタ関数を返します。
処理の出力を複数のフィルタに渡す必要がある場合は、add-function
を使用して既存のフィルタと新しいフィルタを組み合わせることができます。Advising Emacs Lisp Functions を参照してください。
フィルター関数の使用例を以下に示します。
(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 ")