| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [表紙] | [目次] | [索引] | [検索] [上端 / 下端] |
オペレーティングシステムの用語では、 プロセス(process)とは、プログラムを実行する空間のことです。 Emacsはプロセスとして動いています。 Emacs Lispのプログラムでは、 独自のプロセスとして他のプログラムを起動できます。 それらは、Emacsプロセスのサブプロセス(subprocess)とか 子プロセス(child process)と呼ばれ、 Emacsプロセスはそれらの親プロセス(parent process)です。
Emacsのサブプロセスは、それを作成する方法に依存して、 同期(synchronous)であるか非同期(asynchronous)です。 同期サブプロセスを作成すると、 Lispプログラムは実行を継続するまえにそのサブプロセスの終了を待ちます。 非同期サブプロセスを作成すると、それはLispプログラムと並行して動作します。 この種のサブプロセスは、Emacs内部ではやはり『プロセス』と呼ばれる Lispオブジェクトで表現されます。 Lispプログラムはこのオブジェクトを用いて サブプロセスと通信したりそれを制御できます。 たとえば、シグナルを送ったり、状態情報を取得したり、 プロセスからの出力を受け取ったり、プロセスへ入力を送れます。
tを返し、 さもなければnilを返す。| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [表紙] | [目次] | [索引] | [検索] [上端 / 下端] |
プログラムを実行するために新たなサブプロセスを作る関数が3つあります。 その1つstart-processは、非同期プロセスを作成して プロセスオブジェクトを返します(see 節 36.4 非同期プロセスの作成)。 残りの2つ、call-processとcall-process-regionは 同期プロセスを作成しますが、プロセスオブジェクトは返しません (see 節 36.3 同期プロセスの作成)。
同期/非同期プロセスについては以下の節に述べます。 3つの関数の呼び出し方は類似しているので、 ここではそれらに共通な引数について述べます。
いずれの場合でも、関数の引数programは、 実行すべきプログラムを指定します。 そのファイルがみつからなかったり実行できないと、 エラーを通知します。 ファイル名が相対名であると、 変数exec-pathは探索すべきディレクトリのリストを保持しています。 Emacsは起動時に環境変数PATHの値に基づいてexec-pathを 初期化します。 `~'、`.'、`..'のファイル名の標準的な書き方は、 exec-pathでも普通どおりに解釈されますが、 (`$HOME'などの)環境変数の置換は認識しません。 それにはsubstitute-in-file-nameを使います (see 節 24.8.4 ファイル名を展開する関数)。
サブプロセスを作成する各関数には、 プログラムの標準出力の受け取り場所を指定する 引数buffer-or-nameがあります。 これはバッファかバッファ名である必要があります。 バッファ名であると、そのバッファが既存でなければ新たに作成します。 nilでもかまいませんが、その場合、 フィルタ関数で処理しない限り出力を破棄します。 (36.9.2 プロセスフィルタ関数とsee 節 18. Lispオブジェクトの読み取りと表示)。 通常、複数のプロセスの出力を同じバッファへは送らないようにします。 それらの出力がでたらめに混ざってしまうからです。
サブプロセスを作成する3つの関数すべてに、 &rest引数であるargsがあります。 argsはすべてが文字列である必要があり、 それぞれを区切ってコマンド行引数としてprogramに与えられます。 引数全体を指定されたプログラムへ直接渡すため、 これらの引数ではワイルドカード文字や他のシェル構文の特別な意味はありません。
注意: 引数programにはプログラムの名前だけを指定し、 コマンド行引数はいっさい指定しない。 コマンド行引数はargsで与えること。
サブプロセスのカレントディレクトリは default-directoryの値で決まります(see 節 24.8.4 ファイル名を展開する関数)。
サブプロセスはEmacsから環境変数を継承しますが、 優先するものをprocess-environmentで指定できます。 See 節 39.3 オペレーティングシステム環境。
movemailはそのようなプログラムの例であり、 inboxから新たなメイルを取り出すためにrmailが利用する。default-directoryの値) を意味するnilである。
引数programが絶対ファイル名でないと、 call-processとstart-processは exec-pathの値を使う。
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [表紙] | [目次] | [索引] | [検索] [上端 / 下端] |
Lispプログラムから、 ユーザーが指定したファイル名を含んだコマンドを指定して シェルを実行する必要がときどきあります。 これらのプログラムでは、任意の正しいファイル名を扱える必要があります。 しかし、シェルは、特定の文字がファイル名として現れると特別に扱うので、 そのような文字がシェルに混乱をもたらします。 そのような文字を扱うには、関数shell-quote-argumentを使います。
この関数が行うことの詳細は読者のオペレーティングシステムに依存する。 この関数は通常のシェル構文に合うように設計してある。 非標準のシェルを使う場合には、この関数を再定義する必要があろう。 MS-DOSでは、この関数はargumentを無変更で返す。 MS-DOSのシェルにはクォートの機能がないため、 これは本当は正しいことではないが最良のことである。
;; つぎの例はGNUとUNIXシステムのふるまいである
(shell-quote-argument "foo > bar")
=> "foo\\ \\>\\ bar"
|
シェルコマンドを作るshell-quote-argumentの使用例をつぎに示す。
(concat "diff -c "
(shell-quote-argument oldfile)
" "
(shell-quote-argument newfile))
|
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [表紙] | [目次] | [索引] | [検索] [上端 / 下端] |
同期プロセス(synchronous process)を作成すると、 Emacsは実行を続行するまえにそのプロセスが終了するのを待ちます。 diredはその例です。 lsを同期プロセスで実行し、その出力を少々修正します。 プロセスは同期なので、Emacsがなにかを行おうとするまえに ディレクトリ一覧全部がバッファに届きます。
Emacsは同期サブプロセスの終了を待ちますが、 ユーザーはC-gと打って中断できます。 C-gはまずシグナルSIGINTでサブプロセスをキルしようとしますが、 中断を完了するまえにサブプロセスが終了するのを待ちます。 その期間にユーザーがさらにC-gを打つと、 SIGKILLでサブプロセスを即座にキルし、ただちに中断を完了します。 See 節 20.9 中断。
同期サブプロセス作成関数は、 そのプロセスがどのように終了したかを表すものを返します。
同期サブプロセスからの出力は、ファイルから読むテキストと同様に、 コーディングシステムを用いて一般には復号化します。 call-process-regionがサブプロセスへ送る入力は、 ファイルへ書くテキストと同様に、 コーディングシステムを用いて符号化します。 See 節 32.10 コーディングシステム。
infileがnilでなければ プロセスへの標準入力はinfileであるが、 さもなければ`/dev/null'である。 引数destinationでプロセスの出力先をつぎのように指定する。
tnilこの場合、このプロセスはEmacsと並行して動作するので真のサブプロセスではない。 しかし、この関数から戻るとEmacsはサブプロセスの処理を本質的には終えたと いう意味で同期プロセスと考えることができる。
(real-destination error-destination)nilであるとエラー出力を破棄し、 tであると通常の出力に混ぜ、 文字列であるとその名前のファイルにエラー出力を振り向ける。
エラー出力を入れるバッファを直接に指定することはできない。 それを実装するのは難しすぎる。 しかし、エラー出力を一時ファイルへ送ってから そのファイルをバッファに挿入すれば、同じ効果を得られる。
displayがnil以外であると、call-processは、 出力が挿入されるとバッファを再表示する。 (しかし、コーディングシステムとして実際のデータから コーディングシステムを推定するundecidedを指定していると、 非ASCII文字に出会うと再表示を継続できない場合もある。 これを修正するのが困難である根本的な理由がある。) さもなければ、関数call-processは再表示しないので、 Emacsが通常の過程でそのバッファを再表示するまでは、 スクリーン上で結果は見えない。
残りの引数argsは、プログラムに対する コマンド行引数を指定する文字列である。
(待たないように指示しない限り)call-processが返す値は、 プロセスの終了理由を表す。 数でサブプロセスの終了状態を表し、 0は成功、それ以外の値は失敗を意味する。 プロセスがシグナルで終了すると、 call-processはシグナルを記述する文字列を返す。
つぎの例では、バッファ`foo'がカレントである。
(call-process "pwd" nil t)
=> nil
---------- Buffer: foo ----------
/usr/user/lewis/manual
---------- Buffer: foo ----------
(call-process "grep" nil "bar" nil "lewis" "/etc/passwd")
=> nil
---------- Buffer: bar ----------
lewis:5LTsHm66CSWKg:398:21:Bil Lewis:/user/lewis:/bin/csh
---------- Buffer: bar ----------
|
insert-directoryの定義にあるcall-processの よい使用例をつぎに示す。
(call-process insert-directory-program nil t nil switches
(if full-directory-p
(concat (file-name-as-directory file) ".")
file))
|
nil以外であると、送ったテキストを削除する。 これは、カレントバッファに送った入力のかわりに出力を挿入することを 意味するdestinationがtであるときに有用である。
引数destinationとdisplayは、 サブプロセスからの出力をどのように扱い、 出力か到着するたびに表示を更新するかどうかを制御する。 詳しくは、上記のcall-processの記述を参照。 destinationが整数0であると、 call-process-regionは、サブプロセスの終了を待たずに 出力を破棄してただちにnilを返す。
残りの引数argsは、プログラムに対する コマンド行引数を指定する文字列である。
call-process-regionの戻り値はcall-processと同様であり、 待たずに戻るように指示するとnilであり、 さもなければサブプロセスの終了状態を表す数か文字列である。
つぎの例では、 バッファ`foo'の始めの5文字(単語`input')を標準入力として ユーティリティcatを実行するためにcall-process-regionを使う。 catは、標準入力を標準出力へコピーする。 引数destinationがtであるので、 出力はカレントバッファに挿入される。
---------- Buffer: foo ----------
input-!-
---------- Buffer: foo ----------
(call-process-region 1 6 "cat" nil t)
=> nil
---------- Buffer: foo ----------
inputinput-!-
---------- Buffer: foo ----------
|
コマンドshell-command-on-regionは、 つぎのようにcall-process-regionを使う。
(call-process-region
start end
shell-file-name ; プログラムの名前
nil ; リージョンを削除しない
buffer ; 出力は
|
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [表紙] | [目次] | [索引] | [検索] [上端 / 下端] |
非同期プロセスを作成すると、Emacsとサブプロセスの両者は ただちに動作を継続します。 そしてプロセスはEmacsと並行に動作し、 両者は以下の節に述べる関数を用いて互いに通信できます。 しかし、通信は部分的に非同期です。 特定の関数を呼び出したときにだけEmacsはプロセスへデータを送り、 Emacsが入力待ちか時間待ちをしているときにだけ プロセスからの出力を受け取れます。
ここでは、非同期プロセスの作成方法について述べます。
残りの引数argsは、プログラムに対する コマンド行引数を指定する文字列である。
つぎの例では、最初のプロセスは動き始めると 100秒間(休止ではなく)動作する。 そのあいだに2番目のプロセスを動かし始めると、 一意であるためにそれには名前`my-process<1>'が与えられる。 2番目のプロセスは、最初のプロセスが終了するまえに バッファ`foo'にディレクトリ一覧を挿入する。 2番目のプロセスが終了するとそれを表すメッセージがバッファに挿入される。 しばらくして最初のプロセスが終了すると、 別のメッセージがバッファに挿入される。
(start-process "my-process" "foo" "sleep" "100")
=> #
|
start-processと同様であるが、 指定したコマンドを実行するためにシェルを用いる点が異なる。 引数commandはシェルコマンドの名前であり、 command-argsはそのシェルコマンドに対する引数である。 変数shell-file-nameは、使用するシェルを指定する。
start-processで直接にではなく シェルを介してプログラムを実行すると、 引数のワイルドカードなどのシェルの機能を利用できる。 つまり、ユーザー指定の任意のファイル名をコマンドに入れる場合には、 まえもってshell-quote-argumentでクォートし、 ファイル名内のシェルの特別な文字が そのような特別な意味を持たないようにする。 see 節 36.2 シェル引数。
nil以外であると疑似端末PTYを利用できる場合にはそれを用る。 さもなければパイプを用いる。
シェル(shell)モードなどのユーザーに見えるプロセス向けには、 パイプでは不可能なプロセスとその子プロセスとのあいだで ジョブ制御(C-c、C-zなど)を許すので 疑似端末PTYが望ましい。 プログラムの内部目的向けに使われるサブプロセスでは、 効率的なパイプを用いるほうがよい。 また、多くのシステムでは疑似端末PTYの総数には制約があり、 それらを浪費しないほうがよい。
process-connection-typeの値は start-processを呼び出したときに使われる。 したがって、start-processの呼び出しの周りでこの変数を束縛することで、 1つのサブプロセスに対する通信方法を指定できる。
(let ((process-connection-type nil)) ; パイプを使う (start-process ...)) |
サブプロセスが実際にはパイプか疑似端末PTYのどちらを 使っているかを調べるには、関数process-tty-nameを使う (see 節 36.6 プロセス情報)。
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [表紙] | [目次] | [索引] | [検索] [上端 / 下端] |
プロセスを削除するとは、サブプロセスからEmacsをただちに切り離し、 サブプロセスを活性なプロセスリストから取り除くことです。 サブプロセスへシグナルを送ってサブプロセスを終了させますが、 ただちに終了するとは保証されません。 プロセスオブジェクトを指すLispオブジェクトがある限り、 プロセスオブジェクトは存在し続けます。 プロセスマークは以前と同様に同じ場所 (プロセスからの出力をバッファに挿入した箇所)を指し続けます。
プロセスはいつでも明示的に削除できます。 プロセスは終了後に自動的に削除されますが、 終了後ただちにではありません。 終了したプロセスが自動的に削除されるまえに明示的に削除しても無害です。
exitを呼び出すかシグナルのために)終了した プロセスの自動削除を制御する。 nilであると、ユーザーがlist-processesを 実行するまで存在し続ける。 さもなければ、終了後にただちに削除する。SIGHUPでキルし削除する。 引数は、プロセス、プロセス名、バッファ、バッファ名のいずれかである。
(delete-process "*shell*")
=> nil
|
nilであると、プロセスを黙って削除する。 さもなければ、Emacsはプロセスのキルに関して問い合わせる。
問い合わせるようにしてあったプロセスであると戻り値はtであり、 さもなければ戻り値はnilである。 新たに作成されたプロセスは、つねに問い合わせ用になっている。
(process-kill-without-query (get-process "shell"))
=> t
|
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [表紙] | [目次] | [索引] | [検索] [上端 / 下端] |
プロセスに関する情報を返す関数がいくつかあります。 list-processesは対話的利用のためにあります。
nilを返す。
(process-list)
=> (#
|
nilを返す。 nameが文字列でないとエラーを通知する。
(get-process "shell")
=> #
|
(process-command (get-process "shell"))
=> ("/bin/csh" "-i")
|
tを返し、 ネットワーク接続に対しては(hostname service)を返す (see 節 36.12 ネットワーク接続)。実際のサブプロセスに対して可能な値はつぎのとおり。
runstopexitsignalopenclosednil
(process-status "shell")
=> run
(process-status (get-buffer "*shell*"))
=> run
x
=> #
|
ネットワーク接続では、process-statusは シンボルopenかclosedのいずれかを返す。 後者は、相手側が接続を閉じたか Emacsがdelete-processを行ったことを表す。
process-statusの結果を用いる。) processが終了していないと値は0である。nilを返す (36.4 非同期プロセスの作成のprocess-connection-typeを参照)。
(coding-system-for-decoding . coding-system-for-encoding) |
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [表紙] | [目次] | [索引] | [検索] [上端 / 下端] |
本節の関数を用いてEmacsが入力を送ると、 非同期プロセスは入力を受け取ります。 入力の送先であるプロセスと、送るべき入力データを指定する必要があります。 そのデータは、サブプロセスの『標準入力』に現れます。
疑似端末PTYのバッファ付き入力の容量に上限がある オペレーティングシステムもあります。 そのようなシステムでは、Emacsは他の文字に混ぜて定期的にEOFを送り、 文字が流れるように強制します。 ほとんどのプログラムでは、このようなEOFは無害なはずです。
ファイルに書き込むテキストと同様に、 サブプロセスの入力は、サブプロセスがそれを受け取るまえに コーディングシステムを用いて普通は符号化されます。 set-process-coding-systemで 使用するコーディングシステムを指定できます (see 節 36.6 プロセス情報)。 さもなければ、coding-system-for-writeが nil以外であればこれを使います。 それ以外ではデフォルトの機構で決まるものを使います (see 節 32.10.5 デフォルトのコーディングシステム)。
nilであると、カレントバッファのプロセスを用いる。
関数はnilを返す。
(process-send-string "shell<1>" "ls\n")
=> nil
---------- Buffer: *shell* ----------
...
introduction.texi syntax-tables.texi~
introduction.texi~ text.texi
introduction.txt text.texi~
...
---------- Buffer: *shell* ----------
|
nilであると、カレントバッファのプロセスを使う。)
startとendのどちらかが カレントバッファ内の位置を表す整数でもマーカでもないと、 エラーを通知する。 (どちらが大きな数であるかは重要ではない。)
process-nameを指定しなかったりnilであると、 この関数はカレントバッファのプロセスにEOFを送る。 カレントバッファにプロセスがないとエラーを通知する。
関数はprocess-nameを返す。
(process-send-eof "shell")
=> "shell"
|
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [表紙] | [目次] | [索引] | [検索] [上端 / 下端] |
サブプロセスにシグナルを送ることは、 サブプロセスの動作に割り込む一方法です。 それぞれ独自の意味を持つ異なるシグナルがいくつかあります。 一連のシグナルとそれらの名前は、オペレーティングシステムが定義します。 たとえば、シグナルSIGINTは、ユーザーがC-cを打った、 あるいは、それと同様なことが起こったことを意味します。
各シグナルには、サブプロセスに対する標準的な効果があります。 ほとんどのシグナルはサブプロセスをキルしますが、 その実行を一時停止したり再開するものもあります。 プログラムがシグナルを処理している場合には、 シグナルの効果を一般的に述べることはできません。
本節の関数を呼び出してシグナルを明示的に送ることができます。 また、Emacsは特定の場面で自動的にシグナルを送ります。 バッファを削除すると、そのバッファに対応付けられているすべての プロセスにシグナルSIGHUPを送ります。 Emacsを終了するときには、動作しているすべてのサブプロセスに シグナルSIGHUPを送ります。 (SIGHUPは、ユーザーが電話を切ったことを普通は表すシグナル。)
シグナルを送る各関数は、省略可能な2つの引数、 process-nameとcurrent-groupを受け付けます。
引数process-nameは、プロセス、プロセス名、nilのいずれかです。 これがnilであると、カレントバッファに対応付けられているプロセスが デフォルトになります。 process-nameがプロセスを指定しないとエラーを通知します。
引数current-groupは、Emacsのサブプロセスとして ジョブ制御可能なシェルを実行しているときに違いが現れるフラグです。 これがnil以外であると、 Emacsがサブプロセスとの通信に用いている端末の現在のプロセスグループに シグナルを送ります。 プロセスがジョブ制御可能なシェルであると、 これはシェルの現在のサブジョブ (10) であることを意味します。 nilであると、Emacsのサブプロセスの直接のプロセスグループに シグナルを送ります。 プロセスがジョブ制御可能なシェルであると、これはシェルそのものです。
オペレーティングシステムはパイプではプロセスグループを扱わないため、 サブプロセスとの通信にパイプを用いている場合には、 フラグcurrent-groupには効果はありません。 同じ理由で、パイプを用いている場合には ジョブ制御可能なシェル(のジョブ制御機能)は働きません。 36.4 非同期プロセスの作成の process-connection-typeを参照してください。
SIGINTを送って割り込む。 Emacsの外側では、『割り込み文字』(普通、C-cであるシステムもあり、 その他のシステムではDEL)を打つとこのシグナルを送る。 引数current-groupがnil以外であると、 この関数は、Emacsがサブプロセスと通信している端末上で 『C-cを打つ』と考えることができる。SIGKILLを送ってキルする。 このシグナルはサブプロセスを即座にキルし、 サブプロセスはこれを処理できない。SIGQUITを送る。 このシグナルは、『中断文字』 (Emacsの外側では普通はC-bやC-\)が 送るシグナルと同じものである。SIGTSTPを送って一時停止させる。 その実行を再開させるにはcontinue-processを使う。
Emacsの外側でジョブ制御可能なシステムでは、 『一時停止文字』(普通はC-z)が普通はこのシグナルを送る。 current-groupがnil以外であると、 この関数は、Emacsがサブプロセスと通信している端末上で 『C-zを打つ』と考えることができる。
SIGTCONTを送って実行を再開させる。 以前に一時停止させられたprocessを再開する。| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [表紙] | [目次] | [索引] | [検索] [上端 / 下端] |
サブプロセスが標準出力に書く出力を受け取る方法は2つあります。 プロセスに対応付けられたバッファに出力を挿入するか、 あるいは、フィルタ関数(filter function)と呼ばれる関数を 出力に対して作用させます。 プロセスにバッファもフィルタ関数もなければ、その出力は破棄します。
サブプロセスからの出力は、Emacsが待っている、つまり、 端末入力を読んでいるとき、 sit-forやsleep-forを実行中のとき(see 節 20.8 時間待ちと入力待ち)、 accept-process-output(see 節 36.9.3 プロセスからの出力を受け取る)を実行中のときに だけ到着します。 これにより、並行プログラムを普通は悩ますような タイミングエラーの問題を最小に抑えます。 たとえば、安全にプロセスを作成してから、 バッファかフィルタ関数を指定できます。 この処理の途中で待つような基本関数を呼び出さなければ、 出力は到着しません。
ファイルから読むテキストと同様に、 サブプロセスの出力は、バッファやフィルタ関数が受け取るまえに コーディングシステムを用いて普通は復号化します。 set-process-coding-systemで 使用するコーディングシステムを指定できます (see 節 36.6 プロセス情報)。 さもなければ、coding-system-for-readが nil以外であればこれを使います。 それ以外ではデフォルトの機構で決まるものを使います (see 節 32.10.5 デフォルトのコーディングシステム)。
警告: データからコーディングシステムを決定するundecidedのような コーディングシステムは、非同期サブプロセスの出力に対しては 完全に信頼性のある動作はできない。 これは、Emacsが非同期サブプロセスの出力が 到着するたびに一塊で処理するからである。 Emacsは1つの塊から正しい変換を検出しようと試みるが、 これがつねに動作するとは限らない。 したがって、可能な限り 文字コード変換と行末変換の両方を指定したコーディングシステムを使う。 つまり、undecidedやlatin-1などではなく、 latin-1-unixのようなものを使う。
36.9.1 プロセスバッファ If no filter, output is put in a buffer. 36.9.2 プロセスフィルタ関数 Filter functions accept output from the process. 36.9.3 プロセスからの出力を受け取る Explicitly permitting subprocess output. Waiting for subprocess output.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [表紙] | [目次] | [索引] | [検索] [上端 / 下端] |
プロセスには対応付けられたバッファが(普通は)あります。 そのバッファはEmacsの普通のバッファであり、2つの目的に使われます。 プロセスからの出力を保存することと、 プロセスがキルされたことを判定するためです。 バッファを用いてそれを操作しているプロセスを識別することもできます。 普通は1つのバッファに1つのプロセスを対応付けるからです。 プロセスの多くの応用では、プロセスへ送る入力を編集するために バッファを使いますが、これはEmacs Lispに組み込まれたことではありません。
プロセスにフィルタ関数(see 節 36.9.2 プロセスフィルタ関数)がなければ、 その出力は対応付けられたバッファに挿入されます。 出力の挿入位置はprocess-markで決定され、 process-markは挿入したばかりのテキストの末尾を 指すように更新されます。 process-markは普通はバッファの末尾にありますが、 つねにそうであるとは限りません。
(process-buffer (get-process "shell"))
=> #
|
processにバッファがなければ、 process-markはどこも指していないマーカである。
バッファにプロセス出力を挿入する際には、 挿入箇所を決定するためにこのマーカを使用し、 挿入したテキストの末尾を指すようにこのマーカを更新する。 これにより、出力の連続した塊を順に挿入できるのである。
バッファに出力を直接挿入する場合と同様に、 フィルタ関数はこのマーカを扱うべきである。 process-markを用いたフィルタ関数の好例は、以下の節にある。
プロセスへ送るためにユーザーがプロセスバッファに 入力することが予想されるときは、 プロセスマーカは新たな入力とそれ以前の出力を区切る。
nilであると、 プロセスに対応付けられたバッファはない。
(get-buffer-process "*shell*")
=> #
|
プロセスのバッファを削除すると、 サブプロセスにシグナルSIGHUPを送ってプロセスを削除する (see 節 36.8 プロセスにシグナルを送る)。
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [表紙] | [目次] | [索引] | [検索] [上端 / 下端] |
プロセスのフィルタ関数(filter function)は、 対応付けられたプロセスからの標準出力を受け取る関数です。 プロセスにフィルタがあると、そのプロセスからのすべての出力は フィルタに渡されます。 プロセスにフィルタがない場合に限って、 プロセスからの出力向けにプロセスバッファを直接使います。
フィルタ関数は、Emacsがなにかを待っているときにのみ呼ばれます。 そのような期間にのみプロセスの出力が到着するからです。 Emacsが待つのは、端末入力を読んでいるとき、 sit-forやsleep-forを実行中のとき(see 節 20.8 時間待ちと入力待ち)、 accept-process-output(see 節 36.9.3 プロセスからの出力を受け取る)を実行中のときです。
フィルタ関数は2つの引数、 対応付けられたプロセスとそのプロセスから受け取ったばかりの出力である文字列を 受け取ります。 関数は出力に対してなにを行ってもかまいません。
フィルタ関数の内側では中断は普通は禁止されています。 さもないと、コマンドレベルで打ったC-gの効果や、 ユーザーコマンドを中断するために打ったC-gの効果は予測できません。 フィルタ関数の内側で中断を行いたい場合には、 inhibit-quitにnilを束縛します。 See 節 20.9 中断。
フィルタ関数の実行中にエラーが発生するとそのエラーは自動的に捕捉され、 フィルタ関数を始動したときに動いていた プログラムの実行を停止しないようにします。 しかし、debug-on-errorがnil以外であると、 エラーを捕捉しません。 これにより、Lispデバッガでフィルタ関数をデバッグできます。 See 節 17.1 Lispデバッガ。
多くのフィルタ関数は、ときどきあるいはつねに、 プロセスのバッファにテキストを挿入します。 これはフィルタ関数がないときの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 節 33.6 マッチデータ。
プロセスのバッファに出力を書き込むフィルタ関数は、 そのバッファが有効であるかどうかを検査するべきです。 無効なバッファに挿入しようとするとエラーになります。 バッファが無効であれば、 式(buffer-name (process-buffer process)) を実行するとnilを返します。
関数に渡される出力は任意のサイズの塊できます。 同じ出力を2回生成するプログラムは、 あるときには一度に200文字の塊を1つ送る場合もあれば、 40文字の塊を5つ送る場合もあります。 サブプロセスの出力から特定のテキスト文字列を探すフィルタでは、 そのような文字列が2つかそれ以上の出力の塊に分割される場合も 扱えるようにします。
nilであると、プロセスにフィルタはない。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
")
|
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [表紙] | [目次] | [索引] | [検索] [上端 / 下端] |
非同期サブプロセスからの出力は、 Emacsが時間待ちや端末入力などの なんらかの外部事象を待っているときにのみ到着します。 Lispプログラムから特定の場面で出力の到着を明示的に許したり、 プロセスの出力が到着するのを待つことができると有用なことがあります。
nil以外であると、 この関数は、processからなんらかの出力を得るまで戻らない。
引数secondsとmillisecは、時間切れを指定する。 前者は秒単位の時間、後者はミリ秒単位の時間を指定する。 指定された2つの時間は合計され、 任意のサブプロセスの出力を受け取ったどうかに関わらず、 その時間だけ経過するとaccept-process-outputは戻ってくる。
引数secondsは整数である必要はない。 浮動小数点数であると、この関数は秒未満の時間も待つ。 秒未満を扱えないシステムもある。 そのようなシステムでは、secondsを切り下げる。
すべてのオペレーティングシステムで秒未満を扱えるわけではない。 扱えないシステムでmillisecにゼロ以外を指定すると エラーになる。
関数accept-process-outputは、 出力を得るとnil以外を返す。 あるいは、出力が到着するまえに時間切れするとnilを返す。
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [表紙] | [目次] | [索引] | [検索] [上端 / 下端] |
プロセスの番兵(process sentinel)は、 プロセスを終了/一時停止/継続させる (Emacsが送ったかプロセス自身の動作によって生起した)シグナルを含めて 対応付けられたプロセスの状態が任意の理由で変化したときに 呼び出される関数です。 プロセスの番兵は、プロセスが終了しても呼び出されます。 番兵は2つの引数、事象が発生したプロセスと 事象の種類を記述する文字列を受け取ります。
事象を記述する文字列はつぎのとおりです。
"finished\n".
"exited abnormally with code exitcode\n".
"name-of-signal\n".
"name-of-signal (core dumped)\n".番兵はEmacsが(たとえば、端末入力や時間経過、プロセスの出力を) 待っているときにのみ実行されます。 他のLispプログラムの実行途中で無秩序に番兵を実行した場合に起こる タイミングエラーを回避するためです。 sit-forやsleep-for(see 節 20.8 時間待ちと入力待ち)、あるいは、 accept-process-output(see 節 36.9.3 プロセスからの出力を受け取る)を 呼び出すとプログラムは待ちに入り、番兵が動けることになります。 Emacsは、コマンドループで入力を読むときにも番兵の実行を許します。
番兵の内側では中断は普通は禁止されています。 さもないと、コマンドレベルで打ったC-gの効果や、 ユーザーコマンドを中断するために打ったC-gの効果は予測できません。 番兵の内側で中断を行いたい場合には、 inhibit-quitにnilを束縛します。 See 節 20.9 中断。
プロセスのバッファに出力を書き込む番兵は、 そのバッファが有効であるかどうかを検査するべきです。 無効なバッファに挿入しようとするとエラーになります。 バッファが無効であれば、 式(buffer-name (process-buffer process)) を実行するとnilを返します。
番兵の実行中にエラーが発生するとそのエラーは自動的に捕捉され、 番兵を始動したときに動いていた プログラムの実行を停止しないようにします。 しかし、debug-on-errorがnil以外であると、 エラーを捕捉しません。 これにより、Lispデバッガで番兵をデバッグできます。 See 節 17.1 Lispデバッガ。
Emacsの初期の版では、正規表現を探索したり一致処理する番兵では、 マッチデータを明示的に保存/復元する必要がありました。 今のEmacsは、番兵に対してはこれを自動的に行いますから、 番兵で明示的に行う必要はありません。 See 節 33.6 マッチデータ。
nilであると、プロセスに番兵はない。 番兵がない場合のデフォルトのふるまいは、 プロセス状態が変化するとプロセスのバッファにメッセージを挿入する。
(defun msg-me (process event)
(princ
(format "Process: %s had the event `%s'" process event)))
(set-process-sentinel (get-process "shell") 'msg-me)
=> msg-me
(kill-process (get-process "shell"))
-| Process: #
|
nilを返す。nil以外を返し、 それ以外ではnilを返す。| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [表紙] | [目次] | [索引] | [検索] [上端 / 下端] |
トランザクションを用いたサブプロセスとの通信に トランザクションキュー(transaction queue)を使えます。 まずtq-createを用いて、 指定したプロセスとの通信用トランザクションキューを作成します。 そして、トランザクションを送るためにtq-enqueueを呼び出します。
引数questionは、トランザクションを始める送出メッセージである。 引数fnは、対応する応答が戻ってきたときに呼び出す関数である。 その関数は2つの引数、closureと受け取った応答で呼び出される。
引数regexpは、1つの応答だけに一致する正規表現である。 tq-enqueueが応答の末尾を判定するために使う。
tq-enqueueの戻り値そのものに意味はない。
トランザクションキューはフィルタ関数を用いて実装してあります。 See 節 36.9.2 プロセスフィルタ関数。
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [表紙] | [目次] | [索引] | [検索] [上端 / 下端] |
Emacs Lispプログラムは、同一マシンや別のマシン上の他のプロセスに対して TCPネットワーク接続を開くことができます。 ネットワーク接続は、サブプロセスと同様にLispが扱い、 プロセスオブジェクトとして表現されます。 しかし、通信相手のプロセスはEmacsプロセスの子プロセスではありませんから、 キルしたりシグナルを送ることはできません。 データの送受信のみが可能です。 delete-processは接続を閉じますが、 もう一方の端のプロセスをキルしません。 そのプロセスは、接続が閉じた場合の動作を判断する必要があります。
ネットワーク接続を表すプロセスオブジェクトと サブプロセスを表すプロセスオブジェクトとは、 関数process-statusを使って区別できます。 この関数は、ネットワーク接続に対しては openかclosedをつねに返し、 本当のサブプロセスに対してはこれらのいずれの値もけっして返しません。 See 節 36.6 プロセス情報。
引数nameは、プロセスオブジェクトに付ける名前を指定する。 必要に応じて一意にするために修正される。
引数buffer-or-nameは、接続に対応付けるバッファである。 出力を扱うフィルタ関数を指定しない限り、 接続からの出力はそのバッファに挿入される。 buffer-or-nameがnilであると、 接続にはバッファを対応付けないことを意味する。
引数hostとserviceは、接続先を指定する。 hostはホスト名(文字列)であり、 serviceは定義済みのネットワークサービス(文字列)か ポート番号(整数)である。
| [ << ] | [ >> ] | [表紙] | [目次] | [索引] | [検索] [上端 / 下端] |