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


36.9.2 プロセスフィルタ関数

プロセスのフィルタ関数(filter function)は、 対応付けられたプロセスからの標準出力を受け取る関数です。 プロセスにフィルタがあると、そのプロセスからのすべての出力は フィルタに渡されます。 プロセスにフィルタがない場合に限って、 プロセスからの出力向けにプロセスバッファを直接使います。

フィルタ関数は、Emacsがなにかを待っているときにのみ呼ばれます。 そのような期間にのみプロセスの出力が到着するからです。 Emacsが待つのは、端末入力を読んでいるとき、 sit-forsleep-forを実行中のとき(see Waiting)、 accept-process-output(see Accepting Output)を実行中のときです。

フィルタ関数は2つの引数、 対応付けられたプロセスとそのプロセスから受け取ったばかりの出力である文字列を 受け取ります。 関数は出力に対してなにを行ってもかまいません。

フィルタ関数の内側では中断は普通は禁止されています。 さもないと、コマンドレベルで打ったC-gの効果や、 ユーザーコマンドを中断するために打ったC-gの効果は予測できません。 フィルタ関数の内側で中断を行いたい場合には、 inhibit-quitnilを束縛します。 See Quitting

フィルタ関数の実行中にエラーが発生するとそのエラーは自動的に捕捉され、 フィルタ関数を始動したときに動いていた プログラムの実行を停止しないようにします。 しかし、debug-on-errornil以外であると、 エラーを捕捉しません。 これにより、Lispデバッガでフィルタ関数をデバッグできます。 See Debugger

多くのフィルタ関数は、ときどきあるいはつねに、 プロセスのバッファにテキストを挿入します。 これはフィルタ関数がないときのEmacsの動作を模倣するものです。 そのようなフィルタ関数では、対象のバッファに挿入するために set-bufferを使う必要があります。 カレントバッファをなかば恒久的に切り替えないように、 これらのフィルタ関数はカレントバッファを記録/復元する必要があります。 プロセスマーカを更新し、必要に応じてポイントの値も更新します。 これらはつぎのように行います。

     (defun ordinary-insertion-filter (proc string)
       (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))))))

カレントバッファを記録/復元するためにsave-excursionではなく with-current-bufferを使うのは、 2番目のgoto-charの呼び出しで行うポイントの移動効果を 有効にするためです。

新たにテキストが到着するたびにプロセスバッファが見えるように フィルタ関数で強制するには、 つぎのような行をwith-current-bufferの直前に入れます。

     (display-buffer (process-buffer proc))

ポイント位置に関わらずに新たな出力の末尾にポイントを移動するには、 変数movingを削除して、 無条件にgoto-charを呼び出します。

Emacsの初期の版では、正規表現を探索したり一致処理するフィルタ関数では、 マッチデータを明示的に保存/復元する必要がありました。 今のEmacsは、フィルタ関数に対してはこれを自動的に行いますから、 フィルタ関数で明示的に行う必要はありません。 See Match Data

プロセスのバッファに出力を書き込むフィルタ関数は、 そのバッファが有効であるかどうかを検査するべきです。 無効なバッファに挿入しようとするとエラーになります。 バッファが無効であれば、 式(buffer-name (process-buffer process)) を実行するとnilを返します。

関数に渡される出力は任意のサイズの塊できます。 同じ出力を2回生成するプログラムは、 あるときには一度に200文字の塊を1つ送る場合もあれば、 40文字の塊を5つ送る場合もあります。 サブプロセスの出力から特定のテキスト文字列を探すフィルタでは、 そのような文字列が2つかそれ以上の出力の塊に分割される場合も 扱えるようにします。

— Function: set-process-filter process filter

この関数は、プロセスprocessにフィルタ関数filterを指定する。 filternilであると、プロセスにフィルタはない。

— Function: process-filter process

この関数は、プロセスprocessのフィルタ関数を返す。 あるいは、フィルタ関数がなければnilを返す。

フィルタ関数の使用例をつぎに示します。

     (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
     ")