検索エンジンから来た人に注意このマニュアルは、Emacs ver. 19.x 向けのマニュアルを Mule 2.x の開発にあたり邦訳したものを、 電脳外道学会がミラーリングしているものであり、旧版製品パラノイアであるところの椅子人の趣味によるものです。しかしながら、現在の Emacs の主流は ver. 20 以降であり、ver 19.x と ver 20.x とでは、仕様の違いが少なからずあります。 したがって、一般的な Emacs ユーザーにとっては、
このマニュアルと実機の動作とが符合しない場合があります。
|
Emacsを実行すると、ほぼ直ちにエディタ・コマンド・ループ (editor command loop)に入ります。このループはキー・シーケンスを読み取り、 それらの定義を実行し、結果を表示します。本章では、これがどのように 行なわれるかと、Lispプログラムでそれを行なうことができるサブルーチンを 説明します。
コマンド・ループが最初にやらなければならないことは、
キー・シーケンスを読み込むことです。キー・シーケンスはイベントの
シーケンスであり、コマンドに翻訳されます。コマンド・ループは、
これを行なうのに関数read-key-sequence
を呼びます。
自作のLispコードでもこの関数を呼ぶことができます
(see section キー・シーケンス入力)。Lispプログラムではread-event
(see section イベントを一つ読み込む)による低水準な入力や、
discard-input
(see section そのほかのイベント入力機能)によって未処理の入力を
捨てることもできます。
キー・シーケンスは現在アクティブなキーマップを通してコマンドに
変換されます。これがどうなされるかを知るためには、See section キー検索。
結果は、キーボード・マクロあるいは対話的に呼出し可能な関数です。
キーがM-xならば、これは別のコマンドの名前を読み込み、
その後それを呼びます。これは、コマンドexecute-extended-command
(see section 対話的呼出し)が行ないます。
コマンドを実行するには、まずその引数を読み込む必要があります。
これにはcommand-execute
(see section 対話的呼出し)を呼び出します。
Lispで書かれたコマンドでは、interactive
指定にどのように引数を
読むのかが書かれています。これによって、
前置引数(see section 前置コマンド引数)を使ったり、
ミニバッファ(see section ミニバッファ)にプロンプトを出して
読み取ったりします。たとえば、コマンドfind-file
は
ミニバッファを使ってファイル名を読むよう書かれたinteractive
指定を
持っています。コマンドの関数本体はミニバッファを使いません。つまり、
このコマンドをLispコードから関数として呼び出した場合、ファイル名文字列を
普通のLisp関数引数として与えなければなりません。
コマンドが文字列あるいはベクタ(即ち、キーボード・マクロ)ならば、
execute-kbd-macro
を使ってそれを実行します。この関数を
自分自身で呼んでも構いません(see section キーボード・マクロ)。
実行中のコマンドを終らせるには、C-gをタイプします。 この文字によってとりやめる(quitting)(see section とりやめ)ことができます。
this-command
の内容はこれから実行しようとしているコマンドに
なっています。そして、last-command
は直前のコマンドを表しています。
See section フック。
this-command
はたった今実行したコマンドを表し、
last-command
はその前のものを表します。See section フック。
pre-command-hook
とpost-command-hook
との実行中、
とりやめは抑止されます。これらフック中でエラーが起こった場合には、
フックの実行だけを終らせ、それ以外は何もしません。
Lisp関数は、その本体のトップレベルに特殊形式interactive
の
呼出しを行なう形式があるならば、コマンドになります。この形式は、
実際の実行のときには何もしませんが、その存在は対話的呼出しが許されている
という意味のフラグとして働きます。その引数は、対話的呼出しの際に
引数をどのように読み込むかを制御します。
interactive
を使う
本節では、Lisp関数を対話的呼出し可能なコマンドにする
interactive
形式を、どのように書くのかを説明します。
コマンドはほかの関数同様Lispプログラムから呼び出されるかもしれませんが、 その場合は呼び手が引数を用意し、arg-descriptorは効果を持ちません。
interactive
形式が効果をもつのは、関数を呼び出す前に、
コマンド・ループ(実際にはそのサブルーチンcall-interactively
)が
その関数定義をスキャンしてinteractive
を探すからです。
一旦関数が呼び出されると、その本体のinteractive
形式を含む全ての形式が
実行されますが、この際はinteractive
は引数の評価さえ行なわずに
単にnil
を返します。
引数arg-descriptorには三つの可能性があります:
nil
。この場合、コマンドは引数なしで呼ばれます。
この結果、コマンドが一つ以上の引数を要求している場合は即座にエラーとなります。
(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)))
(interactive "bFrobnicate buffer: ")コード文字`b'で、補完を使って既存のバッファ名を読み込むことを 表します。バッファ名がコマンドに渡される唯一の引数で、文字列の残りは プロンプトです。 文字列中に改行文字があった場合、それがプロンプトの終りです。 文字列がそこで終ってなかった場合、文字列の残りは別の引数を指定する 別のコード文字とプロンプトを含んでなければなりません。 このようにして、任意個数の引数を指定できます。 プロンプト文字列に`%'を使って、直前の引数の値(第1引数以降)を プロンプト中に含めることができます。これは
format
(see section 文字列の書式変換)によって行なわれます。たとえば、
既存のバッファ名に続いて、そのバッファにつける新しい名前を読み込むには、
こうします:
(interactive "bBuffer to rename: \nsRename buffer %s to: ")文字列の最初の文字が`*'の場合、バッファが読みだし専用バッファならば エラーを通知します。 文字列の最初の文字が`@'の場合、そしてそのコマンドを起動するのに使われた キー・シーケンスがマウス・イベントを含むならば、その最初のイベントに 関連づけられたウィンドウがコマンド実行前に選択されます。 `*'と`@'とを一緒に使うこともできます。その順序は関係ありません。 実際の引数の読込みは、(`*'や`@'以外の文字から始まる) プロンプト文字列の残りの部分によって制御されます。
interactive
用のコード文字以下のコード文字の記述は、ここに定義するキー・ワードを含んでいます:
completing-read
(see section 補完)で読み込まれるためです。
?で可能な補完のリストを表示します。
interactive
に使用するコード文字記述子を挙げます:
fboundp
を満たすシンボル)。既存、補完、プロンプト。
commandp
を満たすシンボル)。既存、補完、プロンプト。
default-directory
(see section OS環境)。
既存、補完、デフォルト、プロンプト。
default-directory
。既存、補完、デフォルト、プロンプト。
describe-key
やglobal-set-key
のようなコマンドで
使います。
nil
ならば、nのときのように
数を読み込みます。数を要求します。See section 前置コマンド引数。プロンプト。
user-variable-p
を
満たす)。See section 高水準補完関数。既存、補完、プロンプト。
interactive
使用例
interactive
の例をいくつか挙げます:
(defun foo1 () ;foo1
は引数を取らない、 (interactive) ; 単に2語前に進むだけ。 (forward-word 2)) => foo1 (defun foo2 (n) ;foo2
は引数を一つ取り、 (interactive "p") ; それは数値前置引数。 (forward-word (* 2 n))) => foo2 (defun foo3 (n) ;foo3
は引数を一つ取り、 (interactive "nCount:") ; それはミニバッファから読み込まれる。 (forward-word (* 2 n))) => foo3 (defun three-b (b1 b2 b3) "Select three existing buffers. Put them into three windows, selecting the last one." (interactive "bBuffer1:\nbBuffer2:\nbBuffer3:") (delete-other-windows) (split-window (selected-window) 8) (switch-to-buffer b1) (other-window 1) (split-window (selected-window) 8) (switch-to-buffer b2) (other-window 1) (switch-to-buffer b3)) => three-b (three-b "*scratch*" "declarations.texi" "*mail*") => nil
コマンド・ループはキー・シーケンスを定義に変換した後、
その定義を関数command-execute
を使って起動します。
定義がコマンドとしての関数ならば、command-execute
は
call-interactively
を呼び出し、それが引数を読み込んでコマンドを
呼び出します。自分自身でこれら関数を呼んでも構いません。
t
を返します。
即ち、objectがコマンドであれば、そうします。さもなくば、
nil
を返します。
対話的に呼出し可能なオブジェクトには文字列とベクタ(キーボード・マクロとして
扱われます)、トップレベルのinteractive
呼出しを含むラムダ式、
そういったラムダ式から得られたバイトコード関数オブジェクト、
対話的と宣言された(autoload
への第4引数が非nil
)
自動ロード・オブジェクト、いくつかのプリミティブ関数を含みます。
シンボルはその関数定義がcommandp
ならば、commandp
です。
キーやキーマップはコマンドではありません。それどころか、コマンドを 検索するために使うものです(see section キーマップ)。
commandp
の実際の使用例については、
section 説明文字列へのアクセスのdocumentation
を参照してください。
record-flagが非nil
ならば、本コマンドとその引数は、
無条件にリストcommand-history
に追加されます。
さもなくば、コマンドはそれが引数読込みのためにミニバッファを使った場合に
かぎり、追加されます。See section コマンド履歴。
commandp
述語を満足する必要があります。即ち、対話的に呼出し可能な関数か
キーボード・マクロでなければなりません。
commandの文字列あるいはベクタはexecute-kbd-macro
が実行します。
関数はcall-interactively
にオプションrecord-flagとともに渡します。
シンボルはシンボルの場所内の関数定義を使うことで処理します。
autoload
定義によるシンボルは、それが対話的呼出し可能な関数として
宣言されていたならば、コマンドとして扱います。こういった定義の処理は、
指定のライブラリをロードしてから、そのシンボルの定義を再検査することで
行ないます。
completing-read
(see section 補完)を使って読み込みます。続いて指定のコマンドを
呼び出すために、command-execute
を使います。そのコマンドが何を
返そうとも、それがexecute-extended-command
の値になります。
コマンドが前置引数を求めると、prefix-argumentの値を受け取る
ことになります。execute-extended-command
が対話的に呼び出されたならば、
現在の前置引数がそのままprefix-argumentに使われます。
そのため、これが実行されるどのようなコマンドにも渡ります。
execute-extended-command
はM-xの普通の定義なので、
文字列`M-x'をプロンプトとして使用します
(execute-extended-command
の起動に使われたイベントから
プロンプトを取る方がよいのですが、これは実装するのが辛いのです)。
前置引数があれば、その値の記述も同じくプロンプトの一部となります。
(execute-extended-command 1) ---------- Buffer: Minibuffer ---------- 1 M-x forward-word RET ---------- Buffer: Minibuffer ---------- => t
interactive-p
を呼んだ関数)が
call-interactively
で対話的に呼び出されたのであるならば、
t
を返します(call-interactively
がLispから呼ばれようと、
エディタ・コマンド・ループから直接呼ばれようとも、何ら違いはありません)。
これを含む関数がLispの評価(あるいはapply
やfuncall
)で
呼ばれたならば、対話的に呼び出されたことになりません。
interactive-p
の最も普通の使い方は、案内メッセージを表示するかしないか
決めるために使うことです。特殊な例外として、interactive-p
は
キーボード・マクロ実行中はいつでもnil
を返すというのがあります。
これは、案内メッセージを抑制して、マクロの実行を速くするためです。
例:
(defun foo () (interactive) (and (interactive-p) (message "foo"))) => foo (defun bar () (interactive) (setq foobar (list (foo) (interactive-p)))) => bar ;; M-x fooとタイプする。 -| foo ;; M-x barとタイプする。 ;; こっちは何も表示しない。 foobar => (nil t)
エディタ・コマンド・ループは、いくつかのLisp変数を設定して 自身のためと実行されるコマンドのために、状態の記録を保持しています。
この値はthis-command
から、コマンドがコマンド・ループに帰るときに
コピーされます。そのコマンドが後続のコマンドのために前置引数を指定している
場合は、別です。
この変数は、常に現在の端末に対してローカルなのであって、バッファローカルには なりません。See section 複数のディスプレイ。
last-command
のように、普通は関数定義をともなう
シンボルです。
コマンド・ループはこの変数をコマンド実行の直前に設定し、
その値をコマンド実行終了時にlast-command
にコピーします
(コマンドが後続のコマンドのために前置引数を指定する場合を除きます)。
いくつかのコマンドではこの変数をコマンド実行中に設定して、
次に実行するコマンドへのフラグとします。特に、テキスト集合をkillする関数群は、
this-command
をkill-region
に設定して、直後に続く任意の
killコマンドがkillしたテキストを直前のkillに追加すべきであることが
わかるようにします。
エラー時に特定のコマンドを直前のコマンドとみなされたくない場合には、
そのコマンドをこれを防ぐように書かなければなりません。方法の一つは、
そのコマンドの冒頭でthis-command
をt
に設定し、
末尾でthis-command
を適切な値に戻すことです。このようにします:
(defun foo (args...) (interactive ...) (let ((old-this-command this-command)) (setq this-command t) ...do the work... (setq this-command old-this-command)))
(this-command-keys) ;; ここでC-u C-x C-eを使って、評価する。 => "^U^X^E"
この変数の使い方の一つは、メニューを次にポップ・アップするのにいい デフォルト位置を見つけることです。
self-insert-command
中にあります。そこでは、どの文字を挿入するかを
決定するために使っています。
last-command-event ;; ここでC-u C-x C-eを使って、評価する。 => 5
値は5となり、理由はそれがC-eのASCIIコードであるからです。
別名last-command-char
がEmacsバージョン18との互換のために存在します。
Emacsコマンド・ループはキーボードあるいはマウスの動きを表す 入力イベント(input event)のシーケンスを読み込みます。キーボードの 動きのためのイベントは、文字あるいはシンボルです。しかし、マウス・イベントは 常にリストです。本節では入力イベントの表現と意味を詳細に説明します。
nil
を返します。
キーボードから取ることができる入力には2種類あります。それらは、通常キーと ファンクション・キーです。通常キーは文字に対応します。これらが生成する イベントをLispは文字で表現します。Emacsバージョン18以前では、文字のみが イベントでした。文字イベントのイベント・タイプはその文字自身(整数)です。 イベント・タイプについては、section イベントの分類を参照してください。
入力文字イベントは0〜255までの基本コード(basic code)にいくつかあるいは 全ての修飾ビット(modifier bit)を加えたものから成ります:
自作プログラム内では、特定のビット番号は書かないのが一番です。
文字の修飾ビットを検査するには、関数event-modifiers
を
使ってください(see section イベントの分類)。キー・バインドを作る場合、
修飾ビットつき文字のリード構文(`\C-', `\M-', などなど)を
使うことができます。define-key
を使ってキー・バインドを作る場合は、
文字の指定に(control hyper ?x)
といったリストを使うこともできます
(see section キー・バインドの変更)。関数event-convert-list
は
そういったリストをイベント・タイプ(see section イベントの分類)に変換します。
ほとんどのキーボードはファンクション・キー(function key)(文字ではなく
名前や記号をもつキー)も備えています。ファンクション・キーはLispでは
シンボルとして表現されます。そしてシンボルの名前はファンクション・キーの
ラベルを小文字にしたものです。たとえば、F1と書かれたキーを押下すると、
シンボルf1
が入力ストリームに置かれます。
ファンクション・キー・イベントのイベント・タイプは、イベント・シンボル自身です。 See section イベントの分類。
以下に、ファンクション・キーについてのシンボル命名法の特例をいくつか挙げます:
backspace
, tab
, newline
, return
, delete
tab
として、Lispプログラムに伝えます。
ほとんどの場合、これら二つを区別することは有用ではありません。
そのため普通はfunction-key-map
が準備されていて、
tab
を9に対応させます。そのため文字コード9(文字C-i)の
キー・バインドがtab
にも適用されます。
このグループのほかのシンボルについても同様です。
関数read-char
も同様にこれらイベントを文字に変換します。
ASCIIでは、BSはC-hそのものです。しかしbackspace
は
文字コード127(DEL)に変換されます。8(BS)ではありません。
ほとんどのユーザがこちらの方を好みます。
left
, up
, right
, down
kp-add
, kp-decimal
, kp-divide
, ...
kp-0
, kp-1
, ...
kp-f1
, kp-f2
, kp-f3
, kp-f4
kp-home
, kp-left
, kp-up
, kp-right
, kp-down
home
, left
, ...に変換します。
kp-prior
, kp-next
, kp-end
, kp-begin
, kp-insert
, kp-delete
ファンクション・キーとともに、修飾キーALT, CTRL, HYPER, META, SHIFT, SUPERを使うことができます。 これらの表現方法は、シンボル名に前置をつけることです:
よって、METAを押下したF3キーのシンボルは、M-f3
です。
一つ以上の前置を使う場合、それらを英文字順に並べることを勧めます。
しかしその順序は、キー・バインドの検索と修正の関数への引数に使うときは
影響しません。
Emacsは4種類のマウス・イベントをサポートしています。それらは クリック・イベント、ドラッグ・イベント、ボタン押下イベント、移動イベントです。 全てのマウス・イベントはリストで表現されます。リストのCARは イベント・タイプです。これはどのマウス・ボタンが関係し、どの修飾キーがともに 使われたかを示します。イベント・タイプによって2連続、3連続のボタン押下も区別できます (see section 繰り返しイベント)。リストの残りの要素は、位置と時間の情報を与えます。
キー検索には、イベント・タイプのみが関わります。ここで二つのイベントが同じ
イベント・タイプならば同じコマンドを実行しなければなりません。コマンドは
これらイベントの完全な値に`e'対話コードを使ってアクセスできます。
See section interactive
用のコード文字。
マウス・イベントで始まるキー・シーケンスは、マウスが入っていたウィンドウ中の バッファのキーマップを使って読み込まれます。カレント・バッファではありません。 これは、ウィンドウ中のクリックがそのウィンドウ即ちそのバッファを選択するという 意味ではありません。キー・シーケンスのコマンドのバインド制御についてのみの 話です。
ユーザが同じ位置でマウス・ボタンを押して離したときに、クリック(click)・ イベントが発生します。マウス・クリック・イベントは次の形式を持ちます:
(event-type (window buffer-pos (x . y) timestamp) click-count)
これら要素が普通何を意味するかを説明します:
mouse-1
,mouse-2
, ...と番号づけられたシンボルのうちの
一つになります。
前置`A-', `C-', `H-', `M-', `S-', `s-'を
修飾子オルト、制御、ハイパー、メタ、シフト、スーパーに対して、
ファンクション・キーのときと同様に使うことができます。
このシンボルはイベントのイベント・タイプとしても働きます。キー・バインドは
そのイベントをイベント・タイプで記述します。それゆえ、mouse-1
に対する
キー・バインドがあれば、そのバインドはevent-typeがmouse-1
である
全てのイベントに対して適用されます。
(0 . 0)
からの
相対で表します。
buffer-pos, x, yの意味は、イベント位置がモード行や スクロール・バーのような画面の特別な部分内にあるときに若干異なってきます。
位置がスクロール・バー内にあるときは、buffer-posはシンボル
vertical-scroll-bar
かhorizontal-scroll-bar
になり、
(x . y)
の対はportion . whole
の対で
置き換えられます。ここでportionは、スクロール・バーの上端あるいは
左端からのクリックの距離であり、wholeはスクロール・バーの全長です。
位置がモード行あるいはwindowを右隣から分離する垂直線にあるときは、
buffer-posがシンボルmode-line
あるいはvertical-line
に
なります。モード行の場合は、yは意味のないデータです。垂直線の場合は、
xが意味のないデータとなります。
一つの特例として、buffer-posが単なるシンボルの代わりに、 シンボル(上に挙げたものの一つ)を含むリストになっている場合があります。 これは、イベントに対する架空の前置キーが入力ストリームに挿入された場合に 起こります。See section キー・シーケンス入力。
Emacsでは、着替えもせずにドラッグ・イベント(13)を行なえます。ドラッグ・イベント(drag event)は ユーザがマウス・ボタンを押して、それを離す前に異なる文字位置へ マウスを動かしたとき常に起こります。ほかの全てのマウス・イベント同様、 ドラッグ・イベントはLispのリストで表現されます。このリストはマウスの移動の 開始位置と最終位置との両方を記録しています。こんな感じです:
(event-type (window1 buffer-pos1 (x1 . y1) timestamp1) (window2 buffer-pos2 (x2 . y2) timestamp2) click-count)
ドラッグ・イベントは、シンボル名event-typeに前置`drag-'が ついています。イベントの2番目3番目の要素がドラッグの開始と終了の位置を 与えます。これを別にすれば、データはクリック・イベント(see section クリック・イベント)と 同じ意味合いを持ちます。マウス・イベントの2番目の要素は、皆同じ方法で アクセスできます。ドラッグ・イベントをほかと区別する必要はありません。
`drag-'前置は、`C-'や`M-'のような修飾キー前置の後に来ます。
read-key-sequence
がキー・バインドのないドラッグ・イベントを受け取り、
対応するクリック・イベントの方がバインドをもつならば、
read-key-sequence
はドラッグ・イベントを
ドラッグ開始位置でのクリック・イベントに変換します。
つまり、そうしたくないかぎり、クリックとドラッグの両イベントを区別する必要は
ない、ということです。
クリックとドラッグのイベントは、ユーザがマウス・ボタンを離したときに起きます。 これより早く起こせないのは、ボタンが離されるまでクリックをドラッグと 区別できないからです。
ボタンが押されると同時に動作を起こしたいならば、ボタン押下(button-down) イベント(14)を 操作する必要があります。これはボタンが押されるやいなやに発生します。 これはクリック・イベント(see section クリック・イベント)と全く見かけが同じ リストで表現されます。違うのは、event-typeシンボル名が 前置`down-'を含むことです。`down-'前置は`C-'や`M-'のような 修飾キー前置の後に来ます。
関数read-key-sequence
は、コマンドにバインドされていない
ボタン押下イベントは全て無視します。その結果Emacsコマンド・ループもそうする
ことになります。つまりボタン押下イベントで何かしようと思わないかぎり、
その定義を気にする必要がないという意味です。ボタン押下イベントを定義する
理由としてあり得そうなのは、そうすることでボタンが離されるまでのマウスの動きを
(移動イベントを読み込むことで)追跡できるというのがあります。
See section 移動イベント。
マウスを動かさずに素早く続けて同じマウス・ボタンを何度も押した場合、 Emacsでは特別な繰り返し(repeat)マウス・イベントを2回目以降の押下に対して 発生します。
もっともありふれた繰り返しイベントは、ダブルクリック(double-click)・ イベントです。Emacsではボタンを2度クリックしたときにダブルクリックを 発生します。このイベントはボタンを離したときに起きます(それがクリック・イベント 全てで普通)。
ダブルクリック・イベントのイベント・タイプには前置`double-'が
ついています。そのため、metaを押下した2番目のマウス・ボタンの
ダブルクリックは、M-double-mouse-2
としてLispプログラムに渡ります。
ダブルクリック・イベントにバインドがない場合は、対応する通常の
クリック・イベントのバインドが使われて、実行されます。そのため、
気にしたくなければダブルクリック機能に注意を払わなくて構いません。
ユーザがダブルクリックをすると、Emacsは最初に通常のクリック・イベントを 発生し、次にダブルクリック・イベントを発生します。それゆえ、 ダブルクリック・イベントのコマンド・バインドは、 シングルクリックのコマンドがすでに実行されていることを仮定して 設計しないとなりません。設計は、ダブルクリックが望みどおりの結果になるように、 シングルクリックの結果からやらないといけません。
ダブルクリックの意味がシングルクリックの意味の上にともかく 「増築されている」ならば、都合いいです -- これがダブルクリックに対する お薦めのユーザ・インタフェース設計の習慣です。
ボタンをクリックして、再びそれを押下し、ボタンを押下したままでマウスを 動かしはじめると、最後にボタンを離したときにダブルドラッグ(double-drag)・ イベントを得ることになります。そのイベント・タイプには、単なる`drag'の 代わりに`double-drag'がつきます。ダブルドラッグ・イベントがバインドを 持たない場合、Emacsはイベントが通常のドラッグだったかのように 代替バインドを探します。
ダブルクリックやダブルドラッグ・イベントよりも前に、ユーザが2度目にボタンを 押下したときに、Emacsはダブル押下(double-down)イベントを発生します。 そのイベント・タイプには、単なる`down'の代わりに`double-down'が つきます。ダブル押下イベントがバインドを持たない場合、Emacsはイベントが 通常のボタン押下イベントだったかのように代替バインドを探します。 それでもバインドが見つからない場合は、ダブル押下イベントは無視されます。
要約すると、ボタンをクリックして、直ちに再びそれを押下すると、 Emacsは押下イベントとクリック・イベントを最初のクリックに対して、 ダブル押下イベントを2回目の押下に対して、 最後にダブルクリックあるいはダブルドラッグ・イベントのいずれかを生成します。
ボタンを2度クリックして、さらにもう1度押下する、これらを素早く続けて行うと、 Emacsはトリプル押下(triple-down)イベントを、続けて トリプルクリック(triple-click)あるいは トリプルドラッグ(triple-drag)のいずれかを発生します。これらのイベントの イベント・タイプには`double'の代わりに`triple'がつきます。 どのトリプル・イベントでも、バインドを持たない場合、 Emacsは対応するダブル・イベントに使われるであろうバインドを使います。
ボタンを3回以上クリックし、再び押下した場合、3回目以降の押下に対するイベントは 全てトリプル・イベントとなります。Emacsは4重、5重、などなどのイベントを 区別するイベント・タイプを持ちません。それでも、イベント・リストを見て、 何回ボタンが押下されたかを正確に知ることができます。
double-click-time
の値よりも
小さくなければなりません。double-click-time
をnil
に設定すると、
マルチ・クリックの検出を完全に禁止します。t
に設定すると、
時間の制限を取り除きます。つまりEmacsはマルチ・クリックを場所のみで
検出するようになります。
Emacsは、マウス・ボタンの動きがなくてもマウス移動を表すために マウス移動(mouse motion)イベントを時折発生します。
(mouse-movement (window buffer-pos (x . y) timestamp))
リスト2番目の要素は、丁度クリック・イベント(see section クリック・イベント)のときの ように、マウスの現在の位置を表します。
特殊形式track-mouse
本体内では、移動イベントの発生が可能になっています。
track-mouse
形式外では、Emacsは単なるマウスの移動についてのイベントは
発生しません。よって、これらイベントは現れません。
read-event
を使って
移動イベントを読み込み、それにしたがって表示を修正します。
ユーザがボタンを離すと、クリック・イベントが発生します。 典型的には、bodyはクリック・イベントを認識した時点で帰り、 なおかつそのイベントは捨てるべきです。
ウィンドウ・システムはどのウィンドウがキーボード入力を受け取るかを ユーザが制御する一般的方法を備えています。このウィンドウの選択を フォーカス(focus)と呼びます。ユーザがEmacsのフレームを切替えるために 何かをすると、フォーカス・イベント(focus event)が発生します。 フォーカス・イベントの通常の定義はグローバル・キーマップにあり、ユーザが 期待するとおりにEmacs内で新たなフレームを選択するようになっています。 See section インプット・フォーカス。
フォーカス・イベントはLispではこんな感じのリストで表現されます:
(switch-frame new-frame)
ここでnew-frameは切替え先のフレームです。
ほとんどのXウィンドウ・マネージャは、単にマウスをウィンドウの中に移動するだけで フォーカスをそこに置けるようになっています。Emacsもこうなっているように 見えます。新たなフレーム内で、カーソルがはっきりするからです。 けれども、Lispプログラムにとってはほかの種類の入力が来ないかぎり、 フォーカスが変わったことを知る必要がありません。 そこで、Emacsは実際にユーザがキーボード・キーをタイプするか マウス・ボタンを押下するかを新たなフレームで行なった場合にかぎり、 フォーカス・イベントを発生します。つまりフレーム間でマウスを単に移動しても、 フォーカス・イベントは発生しません。
キー・シーケンスの途中でフォーカス・イベントが発生すると、 キー・シーケンスがグシャグシャになってしまうことでしょう。 そのためEmacsではキー・シーケンス途中でフォーカス・イベントが発生することは 絶対にありません。ユーザがキー・シーケンスの途中(つまり、前置キーの後)で フォーカスを変えたならば、Emacsはそのイベントを並べ替えて、 フォーカス・イベントが多重イベントのキー・シーケンスの前か後に来るように、 途中には来ないようにします。
ウィンドウ・システム内で発生したことを表す、そのほかのイベント・タイプ。
(delete-frame (frame))
delete-frame
イベントの標準定義は、frameの消去です。
(iconify-frame (frame))
ignore
です。
というのも、フレームはすでにアイコン化されていたので、
Emacsはすることがないのです。このイベント・タイプの目的は、
必要ならこういったイベントを追跡できるようにすることです。
(make-frame-visible (frame))
ignore
です。
というのも、フレームはすでにアイコン化解除されていたので、
Emacsはすることがないのです。
これらイベントのいずれかがキー・シーケンスの途中にきた場合 (つまり、前置キーの後)は、Emacsはこれらイベントを並べ替えて、 このイベントが多重イベントのキー・シーケンスの前か後に来るように、 途中には来ないようにします。
ユーザが同じ場所で左マウス・ボタンを押下して離したならば、 このようなイベント列が発生します:
(down-mouse-1 (#<window 18 on NEWS> 2613 (0 . 38) -864320)) (mouse-1 (#<window 18 on NEWS> 2613 (0 . 38) -864180))
制御キーを押下したまま、ユーザが2番目のマウス・ボタンを押下し、 マウスをある行から次の行へドラッグしたとします。これによって、 以下に示すような二つのイベントが発生します:
(C-down-mouse-2 (#<window 18 on NEWS> 3440 (0 . 27) -731219)) (C-drag-mouse-2 (#<window 18 on NEWS> 3440 (0 . 27) -731219) (#<window 18 on NEWS> 3510 (0 . 28) -729648))
メタとシフト・キーを押下したまま、ユーザが2番目のマウス・ボタンを ウィンドウのモード行で押下し、マウスを別のウィンドウへドラッグしたとします。 これによって、このようなイベントの組が発生します:
(M-S-down-mouse-2 (#<window 18 on NEWS> mode-line (33 . 31) -457844)) (M-S-drag-mouse-2 (#<window 18 on NEWS> mode-line (33 . 31) -457844) (#<window 20 on carlton-sanskrit.tex> 161 (33 . 3) -453816))
全てイベントはイベント・タイプ(event type)を持ち、キー・バインドでの 使用では、それによってイベントを分類しています。キーボード・イベントに ついては、イベント・タイプはイベント値に同じです。そのため文字の イベント・タイプは文字で、ファンクション・キー・シンボルのイベント・タイプは シンボル自身です。リストであるようなイベントについては、イベント・タイプは リストのCARにあるシンボルです。よって、イベント・タイプは常にシンボルか 文字となります。
同じ種の二つのイベントはキー・バインドに関するかぎり等価です。 そのため、どちらも常に同じコマンドを実行します。これは必ずしも これらが同一のことを行なうことを意味するわけではありません。 というのも、コマンドによってはイベント全体を見て何をするのか決めるからです。 たとえば、コマンドによってはマウス・イベントの位置を使って、 どのバッファに作用するかを決めます。
ときにはイベントをさらに詳しく分類することが便利です。たとえば、 イベントがMETAキーとともに使われたかどうかを確かめたい場合が あるかもしれません(ほかのキーやマウス・ボタンの使用は無視する)。
関数event-modifiers
とevent-basic-type
が、
こういった情報を都合よく得るために用意されています。
shift
, control
,
meta
, alt
, hyper
, super
を含みます。
加えて、マウス・イベント・シンボルの修飾子リストは、
常にclick
, drag
, down
のいずれかを含みます。
引数eventは完全なイベント・オブジェクトであるか、 単なるイベント・タイプかのいずれかです。
以下に例を挙げます:
(event-modifiers ?a) => nil (event-modifiers ?\C-a) => (control) (event-modifiers ?\C-%) => (control) (event-modifiers ?\C-\S-a) => (control shift) (event-modifiers 'f5) => nil (event-modifiers 's-f5) => (super) (event-modifiers 'M-S-f5) => (meta shift) (event-modifiers 'mouse-1) => (click) (event-modifiers 'down-mouse-1) => (down)
クリック・イベントについての修飾子のリストは、
明示的にclick
を含みますが、イベント・シンボル名自身は`clisk'を
含みません。
(event-basic-type ?a) => 97 (event-basic-type ?A) => 97 (event-basic-type ?\C-a) => 97 (event-basic-type ?\C-\S-a) => 97 (event-basic-type 'f5) => f5 (event-basic-type 's-f5) => f5 (event-basic-type 'M-S-f5) => f5 (event-basic-type 'down-mouse-1) => mouse-1
nil
を返します。
(event-convert-list '(control ?a)) => 1 (event-convert-list '(control meta ?a)) => -134217727 (event-convert-list '(control super f1)) => C-s-f1
本節ではマウス・ボタンや移動イベント中のデータをアクセスするのに 都合がいい関数を説明します。
これら二つの関数はマウス・ボタン・イベントの開始あるいは終了位置を 返します。位置はこの形式のリストです:
(window buffer-position (x . y) timestamp)
eventがクリックあるいはボタン押下イベントならば、 これがイベントの位置を返します。eventがドラッグ・イベントならば、 これがドラッグの開始位置を返します。
eventがドラッグ・イベントならば、これがユーザがボタンを離した位置を 返します。evnetがクリックあるいはボタン押下イベントならば、 その値は実際には開始位置で、こういったイベントが唯一もつ位置です。
これら四つの関数は上に挙げたような位置を取り、それのさまざまな部分を 返します。
(x . y)
というコンス・セルで返します。
(x . y)
という
コンス・セルで返します。これらはpositionから実際に取り出した
x, yの値より計算します。
(portion . whole)
というコンス・セルで、
その比が位置の割合となるような二つの整数を含みます。
(num . denom)
の組です。
典型的にはscroll-bar-event-ratio
が返した値です。
この関数は、スクロール・バー上の位置をバッファ位置に変換するのに便利です。 こうやります:
(+ (point-min) (scroll-bar-scale (posn-x-y (event-start event)) (- (point-max) (point-min))))
スクロール・バー・イベントが、x, y座標の組の代わりに、 二つの比をなす整数をもつことに注意してください。
文字列が使われるほとんどの部分において、私たちはその文字列をテキスト文字を 含むものとして概念化しています(同じ種類の文字がバッファあるいはファイルにも あるのです)。時折Lispプログラムは文字列をキーボード文字を含むものとして 扱います。たとえば、それらはキー・シーケンスやキーボード・マクロ定義であるかも しれません。そこで、キーボード文字を文字列中に置くための特別な規則が 存在します。というのも、それらはテキスト文字のように0から255の範囲に 限定されないからです。
METAを使ってタイプされたキーボード文字を
メタ文字(meta character)と呼びます。このようなイベントに対する
数値コードは
$2^{27}$
ビットを含みます。けれどもこれでは全然文字列に収まりません。
しかし初期のEmacsの版においては、これら文字に対して異なる表現を使っていました。
これらに128から255の範囲のコードを与えるのです。こうすれば文字列に収まり、
多くのLispプログラムが、特にdefine-key
や類似の関数の引数において、
`M-'によって表現されたメタ文字を文字列定数に含めていました。
キーボード文字イベントを文字列に入れる特別な規則を使っている これらプログラムを実行するために、後方互換性を提供しています。 こういう規則です:
read-key-sequence
のような関数は、これら規則にしたがった
キーボード入力文字の文字列を構築することができます。これら関数は、
イベントが文字列に収まらない場合には文字列の代わりにベクタを構築します。
リード構文`\M-'を文字列中で使用した場合、128から255の範囲内の コードが作られます(対応するキーボード・イベントを文字列に入れるために 修正したときに得られるコードと同じものです)。そのため、文字列中の メタ・イベントは、それらがどのように文字列に入ってくるかに関わらず、 一貫して機能します。
キーボード・イベントとしてのメタ文字の表現を変更した理由は、 127を超える基本文字コードのために空間を空けるためと、 そういった大きな文字コードのメタ類をサポートするためです。
新たなプログラムでは、これらの特別な互換性規則の使用を避けることが
できます。メタ文字を含む可能性があるキー・シーケンスに対しては、
文字列の代わりにベクタを使い、イベントの文字列をアクセスするには
listify-key-sequence
を使用すればいいのです。
unread-command-events
に
入れることができるイベントのリストに変換します。ベクタの変換は簡単ですが、
文字列の変換は文字列中のメタ文字に使用する特別な表現のために込み入ってます。
エディタ・コマンド・ループはキーボード入力を関数read-key-sequence
で
読み込み、その関数はread-event
を使っています。これらのおよびほかの
キーボード入力のための関数も同様に、Lispプログラムで使用できるように
なっています。section 一時表示のmomentary-string-display
や、
section 時間の経過あるいは入力を待つのsit-for
を参照してください。端末入力モードの制御と
端末入力のデバッグのための関数や変数については、See section 端末入力。
高水準入力機能については、section ミニバッファを参照してください。
コマンド・ループはキー・シーケンス入力を1回に一つ、
read-key-sequence
を呼び出すことで読み込みます。Lispプログラムで
同じようにこの関数を使えます。たとえば、describe-key
はこれを使って
説明するキーを読み込みます。
イベントが全て文字で、その全てが文字列に収まるならば、
read-key-sequence
は文字列を返します(see section 文字列にキーボード・イベントを入れる)。
それ以外ではベクタを返します。ベクタは全種類のイベント(文字、シンボル、リスト)
を収めることができるからです。文字列やベクタの要素はキー・シーケンス中の
イベントです。
関数read-key-sequence
は、とりやめを抑止します。つまりこの関数で
読込み中にタイプされたC-gは、ほかのなんらかの文字のように働き、
quit-flag
を設定しません。See section とりやめ。
引数promptは、プロンプトとしてエコー領域に表示されるべき文字列であるか、
プロンプトを表示しないことを意味するnil
であるか、のどちらかです。
以下の例では、プロンプト`?'がエコー領域に表示され、 ユーザはC-x C-fをタイプします。
(read-key-sequence "?") ---------- Echo Area ---------- ?C-x C-f ---------- Echo Area ---------- => "^X^F"
入力文字が大文字でキー・バインドはないが、その小文字のバインドならある場合、
read-key-sequence
はその文字を小文字に変換します。
lookup-key
は大文字小文字変換をこのように行なわないことに
注意してください。
関数read-key-sequence
はマウス・イベントも同じように変形します。
バインドされてないドラッグ・イベントをクリック・イベントに変換し、
バインドされてないボタン押下イベントを完全に捨てます。
同じようにフォーカス・イベントとそのほかのウィンドウ・イベントを並べ替えて、
キー・シーケンス中にほかの種類のイベントが絶対現れないようにします。
マウス・イベントがウィンドウの特別な部分、たとえばモード行やスクロール・バーで
発生した場合、イベント・タイプは何も特別なことを示しません。マウス・ボタンと
修飾キーの組合せが、いつもの表現と同じシンボルになっています。
ウィンドウ部分に関する情報は、イベントの違う場所、座標の中にあります。でも、
read-key-sequence
はこの情報を架空の前置キーに変換します。
これらは全てシンボルで、mode-line
, vertical-line
,
horizontal-scroll-bar
, vertical-scroll-bar
です。
これら架空の前置キーを使ったキー・シーケンスを定義することで、 特別なウィンドウ部分内でのマウス・クリックに対する意味を定義できます。
たとえば、read-key-sequence
を呼び、マウスをウィンドウのモード行で
クリックした場合、このような二つのイベントを得ます:
(read-key-sequence "Click on the mode line: ") => [mode-line (mouse-1 (#<window 6 on NEWS> mode-line (40 . 63) 5959987))]
コマンド入力の最低水準関数は、これら単一のイベントを読み込むものです。
関数read-event
は入力待ちであることを示すメッセージは何も表示しません。
もしそうしたいならば、message
をはじめに使ってください。メッセージを
表示しなかったならば、read-event
はエコーすることでプロンプトを出します。
つまり、現在のコマンドを導いた、または、現在のコマンドによって読み込まれた
イベントを表す表示をします。See section エコー領域。
cursor-in-echo-area
が非nil
ならば、read-event
は
カーソルを一時的にエコー領域に移動し、そこに表示される何らかのメッセージが
終るまでそうしています。それ以外では、read-event
はカーソル移動しません。
read-event
を呼んで右矢印ファンクション・キーを押下したとすると、
こうなります:
(read-event) => right
最初の例では、ユーザが文字1(ASCIIコード49)をタイプします。
2番目の例はキーボード・マクロ定義で、ミニバッファからeval-expression
を
使ってread-char
を呼んでいます。read-char
がキーボード・マクロの
直後の文字1を読み込んでいます。次にeval-expression
は
その戻り値をエコー領域に表示します。
(read-char) => 49 ;; これを評価するためにM-:を使うと仮定。 (symbol-function 'foo) => "^[:(read-char)^M1" (execute-kbd-macro 'foo) -| 49 => nil
関数read-quoted-char
を使って、ユーザに文字を指定するよういい、
ユーザが制御やメタ文字を簡便に指定できるようにすることができます。
文字どおりでも、8進文字コードでもどちらでもできます。
コマンドquoted-insert
はこの関数を使っています。
read-char
に似てますが、最初の文字が8進数字(0-7)だったときに
あと二つ8進数字を読み込んで(ただし、非8進数字が見つかれば止める)、
これら8進数字で表現される文字を返すというところが異なります。
とりやめは最初の文字の読込みでは抑止されているので、ユーザはC-gを 入力できます。See section とりやめ。
promptを与えると、それはユーザへのプロンプト文字列の指定となります。 プロンプト文字列は常にエコー領域に表示され、`-'がそれに続きます。
次の例では、ユーザが8進数177(10進で127)をタイプしています。
(read-quoted-char "What character") ---------- Echo Area ---------- What character-177 ---------- Echo Area ---------- => 127
本節ではイベントを取り出さずに「あらかじめ覗く」方法、 未処理の入力を検査する方法、保留中の入力を捨てる方法を説明します。
この変数が必要だったわけは、場合によっては関数がイベントを読み込んで、 それを使わないと決めることがあるからです。そのイベントをこの変数に格納すると、 コマンド・ループやコマンド入力を読み込む関数が、それを普通に処理します。
例として、数値前置引数を実現する任意桁数の数字を読み込む関数があります。 これが非数字イベントを見つけると、コマンド・ループが普通に読み込むように、 それを読み戻さなければなりません。同様に、段階的検索はこの機能を使って 検索時に特別な意味を持たないイベントを読み戻すようにします。というのも、 これらイベントは検索を抜けてから、普通に実行しなければならないためです。
unread-command-events
中に置けるようにするために、
キー・シーケンスからイベントを抜き出す信頼できる簡単な方法は、
listify-key-sequence
を使うことです(see section 文字列にキーボード・イベントを入れる)。
この変数は、今やほとんどobsoleteで、それはunread-command-events
を
代わりに使えるからです。これはEmacsバージョン18以前のために書かれたプログラムを
サポートするためだけに存在します。
t
の値で、そうでなければnil
の値で、
直ちに戻ります。ごくまれに読込み可能な入力がないのにt
で
戻ることもあります。
次の例では、Lispプログラムが文字1、ASCIIコード49を読み込みます。
これはlast-input-event
の値になります。一方、
C-e(C-x C-eコマンドを使ってこの式を評価したと仮定)の方は
last-command-event
の値として残ります。
(progn (print (read-char)) (print last-command-event) last-input-event) -| 49 -| 5 => 49
nil
を返します。
次の例では、この形式の評価が始まり次第、ユーザは沢山の文字をタイプすることも
できます。sleep-for
がスリープを終り次第、discard-input
が
スリープ中にタイプされた全ての文字を捨て去ります。
(progn (sleep-for 2) (discard-input)) => nil
待ち関数は、一定の時間が経つか入力があるまで待つために設計されました。
たとえば、計算の途中でポーズを置いて、ユーザが表示を眺めることができるように
したいことがあるかもしれません。sit-for
はポーズを置いて画面を
更新し、入力があれば直ちに戻ります。一方、sleep-for
は画面の更新は
しません。
t
となるのは、
sit-for
が入力が来ないでフルに待った場合です
(section そのほかのイベント入力機能のinput-pending-p
参照)。
それ以外のときは、値はnil
です。
引数secondsは整数でなくても構いません。浮動小数点数ならば、
sit-for
は小数で指定した秒を待ちます。いくつかのシステムでは
秒未満をサポートしていません。このようなシステムでは、secondsは
切り捨てられます。
オプション引数millisecはミリ秒単位の追加待ち時間を指定します。 これはsecondsで指定した時間に追加されます。 システムが小数秒をサポートしない場合の非0のmillisec指定は、 エラーとなります。
再表示は入力が来ると常にpreemptされるので、再表示が始まる前に入力が来ると、
再表示は全く行なわれなくなります。そのため、未処理の入力がある場合に
画面の更新を強制する方法はありません。けれども、未処理の入力がなければ
(sit-for 0)
を使って遅延なしに更新を強制できます。
nodispが非nil
ならば、sit-for
は再表示をしません。
しかし相変わらず、入力があり次第(または時間経過後すぐに)戻ります。
フレームのアイコン化あるいはアイコン化解除があるとsit-for
から戻ります。
というのも、これらはイベントを発生するからです。See section そのほかのウィンドウ・システム・イベント。
sit-for
の普通の目的は、表示したテキストを読む時間をユーザに
与えることです。
nil
を返します。
引数secondsは整数でなくても構いません。浮動小数点数ならば、
sleep-for
は小数で指定した秒を待ちます。いくつかのシステムでは
秒未満をサポートしていません。このようなシステムでは、secondsは
切り捨てられます。
オプション引数millisecはミリ秒単位の追加待ち時間を指定します。 これはsecondsで指定した時間に追加されます。 システムが小数秒をサポートしない場合には、非0のmillisec指定は エラーとなります。
確実に遅延を取りたい場合はsleep-for
を使ってください。
現在時刻を得るための関数については、See section 1日の時刻。
Lisp関数実行中のC-gのタイプは、Emacsがやっていることを 何であれとりやめ(quit)ます。これは制御が最も内側のアクティブな コマンド・ループに帰ることを意味します。
コマンド・ループがキーボード入力を待っているときにC-gをタイプしても
とりやめになりません。これは普通の入力文字同様に働きます。最も単純な例では、
違いを見分けることはできません。なぜなら、C-gは普通はコマンド
keyboard-quit
を実行し、その効果はとりやめだからです。
けれども、前置キーに続くC-gの場合、結果は未定義キーとなります。
この効果は、前置引数もろとも前置キーをキャンセルします。
ミニバッファ中では、C-gは異なる定義を持ちます。即ち、 ミニバッファを中断して外へ出るのです。つまり、事実上、ミニバッファを抜けて とりやめます(単にとりやめると、ミニバッファ中のコマンド・ループに戻る)。 コマンド・リーダが入力を読み込んでいるときに、直にC-gでとりやめないのは、 こうするとミニバッファ中でC-gの意味を再定義できるからです。 前置キーに続くC-gはミニバッファ中で再定義されていないので、 前置キーと前置引数とをキャンセルするという普通の効果を持ちます。 これも、C-gが常に直にとりやめるのだったら、できなかったことです。
C-gが直にとりやめるときは、変数quit-flag
をt
に
設定することでそうします。Emacsはこの変数を適切なときに検査して、値が
非nil
ならばとりやめます。そのためどんな方法でも、quit-flag
を
非nil
に設定すると、とりやめを引き起こします。
Cコードのレベルでは、とりやめはどこでも起こるというわけではありません。
quit-flag
を検査している特別な場所でのみ起こります。この理由は、
ほかの場所でとりやめるとEmacsの内部状態を一貫性のない状態にしてしまうかも
しれないからです。とりやめが安全な場所まで遅延されるので、とりやめでEmacsが
クラッシュすることはありません。
ある種のread-key-sequence
やread-quoted-char
のような関数は
入力待ち中だったとしてもとりやめを完全に防ぎます。とりやめの代わりに、
C-gは要求された入力として働きます。read-key-sequence
の場合なら、
コマンド・ループ中のC-gの特別な振舞をするように働きます。
read-quoted-char
の場合なら、C-qでC-gをquoteできるようにする
ために、こうなってます。
Lisp関数内のある部分でとりやめを防ぎたいならば、変数inhibit-quit
を
非nil
に束縛すればできます。こうすると、C-gがquit-flag
を
t
にいつもどおり設定しても、普通なら起こるはずのとりやめが起きません。
そのうち、inhibit-quit
が再びnil
になったとします。
たとえばlet
形式の終りでその束縛が解かれるなどです。
そのとき、quit-flag
がいまだ非nil
だったならば、
要求されていたとりやめが直ちに起こります。この振舞は、プログラムの
「クリティカル・セクション」内でとりやめが絶対起こらないようにしたい場合に
ふさわしいものです。
(read-quoted-char
のような)関数によっては、
C-gは特別な方法で扱われてとりやめを起こしません。
inhibit-quit
をt
に束縛して入力を読み込み、
inhibit-quit
をnil
にする前にquit-flag
を
nil
に再び設定すると、こうなります。read-quoted-char
の
定義からの引用が、これをどう行なうかを示しています。これは通常のとりやめが
最初の文字の入力後は許されていることも示しています。
(defun read-quoted-char (&optional prompt) "...documentation..." (let ((count 0) (code 0) char) (while (< count 3) (let ((inhibit-quit (zerop count)) (help-form nil)) (and prompt (message "%s-" prompt)) (setq char (read-char)) (if inhibit-quit (setq quit-flag nil))) ...) (logand 255 code)))
nil
ならば、inhibit-quit
が非nil
でないかぎり、
Emacsは直ちにとりやめます。C-gのタイプで、普通quit-flag
は
inhibit-quit
の値に関わらず、非nil
に設定されます。
quit-flag
がnil
以外の値に設定されているときに、
Emacsがとりやめるべきか否かを決定します。inhibit-quit
が
非nil
ならば、quit-flag
は特別な効果を持ちません。
quit
条件を(signal 'quit nil)
によって通知します。
これは、とりやめと同じことを行ないます(section エラーのsignal
を参照)。
C-g以外の文字をとりやめのために指定できます。
関数section 端末入力のset-input-mode
を参照してください。
ほとんどのEmacsコマンドは、コマンド自身に先立って指定される数値である
前置引数(prefix argument)を使えます(前置引数と前置キー(prefix key)を
混同しないように)。前置引数はいつでも一つの値で表現され、それは現在前置引数は
ないという意味のnil
かもしれません。Emacsコマンドは前置引数を使うかも
しれないし、無視するかもしれません。
前置引数には二つの表現があります。それらはそのまま(raw)と 数値(numeric)です。エディタ・コマンド・ループはそのままの表現を 内部的に使用し、その情報を格納するLisp変数もそのようにしますが、 コマンドはいずれの表現も要求できます。
以下がそのままの前置引数の取り得る値です:
nil
、前置引数がないことを意味します。この数値は1ですが、多くのコマンドが
nil
と整数1とを区別します。
-
。これは、数値なしでM--あるいはC-u -を
タイプしたことを示します。これと等価な数値は-1ですが、
コマンドによっては整数-1とシンボル-
とを区別します。
これら可能性は、次の関数をさまざまな前置で呼び出すことで例示できます。
(defun display-prefix (arg) "Display the value of the raw prefix arg." (interactive "P") (message "%s" arg))
以下がさまざまなそのままの前置引数でdisplay-prefix
を呼び出した結果です:
M-x display-prefix -| nil C-u M-x display-prefix -| (4) C-u C-u M-x display-prefix -| (16) C-u 3 M-x display-prefix -| 3 M-3 M-x display-prefix -| 3 ; (C-u 3
と同じ。) C-u - M-x display-prefix -| - M-- M-x display-prefix -| - ; (C-u -
と同じ。) C-u - 7 M-x display-prefix -| -7 M-- 7 M-x display-prefix -| -7 ; (C-u -7
と同じ。)
Emacsは前置引数を格納するために二つの変数を使用します。それらは
prefix-arg
とcurrent-prefix-arg
です。universal-argument
の
ようなほかのコマンドのために前置引数を準備するコマンドが、
値をprefix-arg
に格納します。対照的に、current-prefix-arg
は
現在のコマンドに前置引数を伝えます。これに値を設定してもこれ以降のコマンドの
前置引数には何の影響もありません。
普通コマンドは、前置引数に数値あるいはそのまま、どちらの表現を使うかを
interactive
宣言で指定します(See section interactive
を使う)。
その一方で、関数は前置引数の値を直に変数current-prefix-arg
で
見るかも知れません。しかしこれは若干汚いやり方です。
nil
ならば、値1が返ります。
-
ならば、-1が返ります。数ならば、その数が返ります。
リストならば、リストのCAR(数であるはず)が返ります。
(interactive "P")
で
アクセスします。
関数universal-argument
, digit-argument
,
negative-argument
は、ユーザに次のコマンドのための前置引数を
入力させようというのでないかぎり、呼び出さないでください。
Emacsのコマンド・ループには、Emacs起動時に自動的に入ります。 このトップレベルで起動したコマンド・ループを抜けることはありません。 Emacsが実行を続けるかぎり、これも実行を続けます。 Lispプログラムもやはりコマンド・ループを起動できます。 これはコマンド・ループを複数回アクティブにするので、 再帰編集(recursive edit)と呼びます。再帰編集レベルは、それを起動した いかなるコマンドをもサスペンドし、そのコマンドに戻るまではユーザに 任意の編集を許します。
再帰編集の間に利用可能なコマンドは、トップレベルの編集ループで 利用可能なものと同一であり、キーマップに定義されています。 いくつかの特殊なコマンドのみが再帰編集レベルを抜けます。 それ以外は終了時にその再帰編集レベルに戻ります (抜けるための特殊なコマンドは常に利用可能ですが、それらは再帰編集中以外は 何もしません)。
再帰的なものを含む、全てのコマンド・ループは汎用のエラー・ハンドラを 準備します。そうすることでコマンド・ループから実行したコマンド中で エラーが起きても、コマンド・ループを抜けることがなくなります。
ミニバッファ入力は特別な種類の再帰編集です。いくつかの特徴があり、 ミニバッファとミニバッファ・ウィンドウの表示を可能にしたりできますが、 思ったほど多くはありません。いくつかのキーはミニバッファ中では異なる振舞を します。しかし、それはミニバッファのローカル・マップのせいでしかありません。 したがってウィンドウを切替えれば、普通のEmacsコマンドが使えます。
再帰編集レベルを起動するには、関数recursive-edit
を呼び出します。
この関数は、コマンド・ループを含みます。タグexit
でのcatch
呼出しも含むので、exit
をthrowすることで再帰編集レベルを
抜けることが可能になります(see section 明示的な非局所脱出: catch
と throw
)。t
以外の値を
throwしたならば、recursive-edit
は普通にそれを呼び出した関数に戻ります。
コマンドC-M-c(exit-recursive-edit
)はexit
のthrowを
行ないます。t
値をthrowするとrecursive-edit
をとりやめ、
その結果制御は一つ上のコマンド・ループに戻ります。これを中断(abort)と
呼び、C-]で行ないます(abort-recursive-edit
)。
ほとんどのアプリケーションでは、ミニバッファの使用の一部を除いて 再帰編集を使うべきではありません。普通、カレント・バッファの主モードを 一時的に特別な主モードに変更すると、ユーザにとって使い易くなります。 この特別なモードは、直前のモードに戻るためのコマンドを持たなければなりません (Rmailのeコマンドはこのテクニックを使っています)。 あるいは特別なモードの新しいバッファを作成して、それを選択し、その中でユーザに 「再帰的に」編集する別のテキストを与えたいと思うことがあるかもしれません。 このモードでは、処理を完結させ、直前のバッファに戻るコマンドを定義して おきます(Rmailのmコマンドはこれを行ないます)。
再帰編集はデバッグに便利です。関数定義にブレークポイントの一種として
debug
呼出しを挿入しておき、関数がそこへきたら調べられるように
することができます。debug
は再帰編集の起動だけでなく、
デバッガのほかの機能も備えています。
再帰編集レベルは、query-replace
でC-rをタイプしたときや
C-x q (kbd-macro-query
)を使ったときにも使われます。
次の例では、関数simple-rec
がはじめにポイントを1語進め、
再帰編集に入り、エコー領域にメッセージを表示します。そこでユーザは望みの
編集を行なうことができます。それからC-M-cのタイプでそれを抜けて、
simple-rec
の実行を継続できます。
(defun simple-rec () (forward-word 1) (message "Recursive edit in progress") (recursive-edit) (forward-word 1)) => simple-rec (simple-rec) => nil
(throw 'exit nil)
です。
quit
の通知によって中断します。
この定義は事実上(throw 'exit t)
です。See section とりやめ。
コマンドの禁止(disabling a command)は、その実行の前にユーザの 確認を要求するようにコマンドに印をつけます。禁止は、初心者が混乱しやすい コマンドを、彼らが間違って使うのを防ぐために使います。
コマンドを禁止する低水準の機構は、そのコマンドのLispシンボルの
disabled
属性に非nil
を置くことです。これら属性は
普通ユーザの`.emacs'ファイルでこのようなLisp式によって設定されます。
(put 'upcase-region 'disabled t)
いくつかのコマンドは、これら属性がデフォルトで存在し、 `.emacs'ファイルでそれを取り除いているかも知れません。
disabled
属性の値が文字列なら、このコマンドが禁止されている旨を
告げるメッセージがその文字列を含んでいます。こんなふうに:
(put 'delete-region 'disabled "Text deleted this way cannot be yanked back!\n")
禁止されたコマンドを対話的に起動した場合に何が起こるかの詳細は、 See section `Disabling' in The GNU Emacs Manual。コマンドの禁止は Lispプログラムからそれを関数として呼び出す場合には何の効果も持ちません。
this-command-keys
を
使ってユーザがこのコマンドを実行するために何をタイプしたかを判別することが
できます。そのため、何のコマンドだったかを知ることができます。See section フック。
デフォルトでは、disabled-command-hook
はユーザに続行するか否かを
尋ねる関数を含んでいます。
コマンド・ループはそれまでに実行された複雑なコマンドの履歴を持っています。
こうすることで、これらコマンドの繰り返しの便宜を図ります。
複雑なコマンド(complex command)とは、対話引数の読込みにミニバッファを
使うものをいいます。これは、M-xコマンドの全て、M-:コマンドの全て、
そしてinteractive
指定でミニバッファから引数を読み込むコマンド全てを
含みます。コマンド自身の実行中にミニバッファを明示的に使用しても、
そのコマンドを複雑とは考えません。
command-history => ((switch-to-buffer "chistory.texi") (describe-key "^X^[") (visit-tags-table "~/emacs/src/") (find-tag "repeat-complex-command"))
この履歴リストは実際はミニバッファ履歴の特別な場合ですが (see section ミニバッファ履歴)、一つだけ捻りが加えられています。つまり、 要素は文字列ではなく式となってます。
沢山のコマンドが以前のコマンドの編集と呼出しのために用意されています。
コマンドrepeat-complex-command
, list-command-history
は
ユーザ・マニュアル(see section `Repetition' in The GNU Emacs Manual)に
説明してあります。ミニバッファ中では、使用された履歴コマンドは任意の
ミニバッファで利用可能なものと同じです。
キーボード・マクロ(keyboard macro)は、入力イベント・シーケンスの 缶詰で、コマンドとみなすこともできるし、キー定義をなすこともできます。 キーボード・マクロのLisp表現は、文字列あるいはイベントを含むベクタです。 Lispのマクロとキーボード・マクロとを混同しないようにしてください (see section マクロ)。
macroがシンボルならば、その関数定義をmacroの代わりに使います。 それがまた別のシンボルならば、この処理を繰り返します。 最終的には結果が文字列あるいはベクタになるはずです。結果がシンボル、文字列、 ベクタのいずれでもない場合は、エラーが通知されます。
引数countは繰り返し回数です。ここではmacroがその回数だけ
実行されます。countが省略されるか、nil
だった場合、
macroは1回だけ実行されます。0ならば、macroはエラーとなるか
検索に失敗するまで、延々と実行されます。
nil
です。コマンドを実行中のマクロから実行した場合、
コマンドはこの変数を検査して振舞を変えることができます。
自分自身でこの変数を設定するのは止めてください。
start-kbd-macro
とend-kbd-macro
とは、
この変数を設定します(自分自身でこの変数を設定するのは止めてください)。
この変数は、常に現在の端末に関してローカルであり、バッファローカルには できません。See section 複数のディスプレイ。
nil
です。
この変数は、常に現在の端末に対してローカルであり、バッファローカルには できません。See section 複数のディスプレイ。
Go to the first, previous, next, last section, table of contents.