Next: Interactive Codes, Up: Defining Commands [Contents][Index]
interactive
このセクションでは、Lisp関数をインタラクティブに呼び出し可能なコマンドにするinteractive
フォームの記述方法と、コマンドのinteractive
フォームの検証方法について説明します。
このスペシャルフォームは関数がコマンドであり、したがって(M-xを通じて、またはそのコマンドにバインドされたキーシーケンスのエンターすることにより)インタラクティブに呼び出されるかもしれないことを宣言する。引数arg-descriptorは、そのコマンドがインタラクティブに呼び出されたときに引数を計算する方法を宣言する。
コマンドは他の関数と同じようにLisp関数から呼び出されるかもしれないが、その場合呼び出し側は引数を提供し、arg-descriptorは効果をもたない。
interactive
フォームは関数ボディー内のトップレベルに置くか、関数シンボルのinteractive-form
プロパティ((Symbol Properties)を参照)になければならない。これはコマンドループが関数を呼び出す前にinteractiveフォームを調べることにより効果をもつ(Interactive Callを参照)。一度関数が呼び出されると関数ボディー内のすべてのフォームが実行される。このときボディー内にinteractive
フォームが出現しても、そのフォームは引数の評価さえされず、単にnil
をリターンする。
慣例により、interactive
フォームは関数ボディー内の最初のトップレベルフォームとするべきである。interactive
フォームがシンボルのinteractive-form
プロパティと関数ボディーの両方に存在する場合は、前者が優先される。interactive-form
フォームは既存の関数にinteractiveフォームを追加したり、その関数を再定義することなく引数をインタラクティブに処理する方法を変更するために使用できる。
引数arg-descriptorには3つの可能性があります:
nil
の場合、コマンドは引数なしで呼び出される。コマンドが1つ以上の引数を要求する場合は、すぐにエラーとなる。
(interactive "P\nbFrobnicate buffer: ")
コード文字‘P’はそのコマンドの1つ目の引数をrawコマンドプレフィクス(Prefix Command Argumentsを参照)にセットする。‘bFrobnicate buffer: ’は、ユーザーに‘Frobnicate buffer: ’のプロンプトを示して既存のバッファーの名前の入力を促し、これは2つ目かつ最後の引数になる。
プロンプト文字列には、プロンプト内の前の引数(1つ目の引数から始まる)の値を含めるために‘%’を使用できる。これはformat
(Formatting Stringsを参照)を使用して行われる。たとえば、以下は既存のバッファーの名前を読み取り、その後にそのバッファーに与える新たな名前を読み取る例である:
(interactive "bBuffer to rename: \nsRename buffer %s to: ")
文字列の先頭‘*’がある場合、そのバッファーが読み取り専用の場合にエラーがシグナルされる。
文字列の先頭が‘@’で、そのコマンドの呼び出しに使用されたキーシーケンスに何らかのマウスイベントが含まれる場合は、そのコマンドを実行する前に、それらのうち最初のイベントに結びつくウィンドウが選択される。
文字列の先頭が‘^’で、そのコマンドがシフト転換(shift-translation)を通じて呼び出された場合は、そのコマンドを実行する前に、マークをセットして一時的にリージョンをアクティブにするか、すでにアクティブなリージョンを拡張する。コマンドがシフト転換なしで呼び出されて、リージョンが一時的にアクティブな場合は、コマンドを実行する前に、そのリージョンを非アクティブにする。シフト転換はshift-select-mode
により、ユーザーレベルで制御される。Shift
Selection in The GNU Emacs Manualを参照のこと。
‘*’、‘@’、^
はともに使用でき、その場合は順序に意味はない。実際の引数の読み取りは残りのプロンプト文字列(‘*’、‘@’、^
以外の最初の文字以降)により制御される。
引数値としてポイントやマークを提供するのも一般的だが、何かを行いかつ(ミニバッファー使用の有無に関わらず)入力を読み取る場合は、読み取りの前にポイント値またはマーク値の整数を確実に取得しておくこと。カレントバッファーはサブプロセスの出力を受信するかもしれず、コマンドが入力を待つ間にサブプロセス出力が到着した場合、ポイントおよびマークの再配置が起こり得る。
以下は行ってはいけない例である:
(interactive (list (region-beginning) (region-end) (read-string "Foo: " nil 'my-history)))
これにたいし、以下はキーボード入力を読み取った後にポイントとマークを調べることにより、上記の問題を避ける例である:
(interactive (let ((string (read-string "Foo: " nil 'my-history))) (list (region-beginning) (region-end) string)))
警告:
引数値にはプリントや読み取りが不可能なデータ型を含めるべきではない。いくつかの機能は後続のセッションに読み込ませるためにcommand-history
をファイルに保存する。コマンドの引数に‘#<…>’構文を使用してプリントされるデータ型が含まれる場合、それらの機能は動作しないだろう。
しかしこれには少数の例外がある。(point)
、(mark)
、(region-beginning)
、(region-end)
などの一連の式に限定して使用するのに問題はない。なぜならEmacsはこれらを特別に認識して、コマンドヒストリー内に(値ではなく)その式を配すからである。記述した式がこれらの例外に含まれるかどうか確認するには、コマンドを実行した後に(car
command-history)
を調べればよい。
この関数はfunctionのinteractive
フォームをリターンする。functionがインタラクティブに呼び出し可能な関数(Interactive Callを参照)の場合、値はそのコマンドの引数を計算する方法を指定するinteractive
フォーム((interactive
spec)
)である。それ以外では値はnil
である。functionがシンボルの場合は、そのシンボルの関数定義が使用される。