[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

18. コマンド・ループ

Emacsを実行すると、ほぼ直ちにエディタ・コマンド・ループ (editor command loop)に入ります。このループはキー・シーケンスを読み取り、 それらの定義を実行し、結果を表示します。本章では、これがどのように 行なわれるかと、Lispプログラムでそれを行なうことができるサブルーチンを 説明します。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

18.1 コマンド・ループ概観

コマンド・ループが最初にやらなければならないことは、 キー・シーケンスを読み込むことです。キー・シーケンスはイベントの シーケンスであり、コマンドに翻訳されます。コマンド・ループは、 これを行なうのに関数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 とりやめ)ことができます。

Variable: pre-command-hook

エディタ・コマンド・ループは、この正規フックを各コマンドの前に実行します。 この時点で、this-commandの内容はこれから実行しようとしているコマンドに なっています。そして、last-commandは直前のコマンドを表しています。 See section フック

Variable: post-command-hook

エディタ・コマンド・ループは、この正規フックを各コマンドの後 (とりやめあるいはエラーによって、途中で終ったコマンドも含む)に実行します。 それから、最初にコマンド・ループに入ったときにも実行します。 その時点では、this-commandはたった今実行したコマンドを表し、 last-commandはその前のものを表します。See section フック

pre-command-hookpost-command-hookとの実行中、 とりやめは抑止されます。これらフック中でエラーが起こった場合には、 フックの実行だけを終らせ、それ以外は何もしません。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

18.2 コマンドの定義

Lisp関数は、その本体のトップレベルに特殊形式interactiveの 呼出しを行なう形式があるならば、コマンドになります。この形式は、 実際の実行のときには何もしませんが、その存在は対話的呼出しが許されている という意味のフラグとして働きます。その引数は、対話的呼出しの際に 引数をどのように読み込むかを制御します。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

18.2.1 interactiveを使う

本節では、Lisp関数を対話的呼出し可能なコマンドにする interactive形式を、どのように書くのかを説明します。

Special Form: interactive arg-descriptor

この特殊形式が関数中にあると、それがコマンドであり、 それゆえ対話的に(M-xやこのコマンドにバインドされた キー・シーケンスの入力によって)呼び出され得ることを宣言します。 引数arg-descriptorは、コマンドが対話的に呼び出されたときに コマンドへの引数をどのように計算するかを宣言します。

コマンドはほかの関数同様Lispプログラムから呼び出されるかもしれませんが、 その場合は呼び手が引数を用意し、arg-descriptorは効果を持ちません。

interactive形式が効果をもつのは、関数を呼び出す前に、 コマンド・ループ(実際にはそのサブルーチンcall-interactively)が その関数定義をスキャンしてinteractiveを探すからです。 一旦関数が呼び出されると、その本体のinteractive形式を含む全ての形式が 実行されますが、この際はinteractiveは引数の評価さえ行なわずに 単にnilを返します。

引数arg-descriptorには三つの可能性があります:


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

18.2.2 interactive用のコード文字

以下のコード文字の記述は、ここに定義するキー・ワードを含んでいます:

補完

補完が使えます。TABSPCRETは名前の補完を行ないます。 引数が completing-read(see section 補完)で読み込まれるためです。 ?で可能な補完のリストを表示します。

既存

既存のオブジェクトの名前を要求します。無効な名前は受けつけません。つまり、 ミニバッファを抜けるコマンドでも、現在の入力が有効にならないかぎり抜けません。

デフォルト

ユーザが何のテキストもミニバッファに入力しないならば、ある種のデフォルト値が 使われます。デフォルトはコード文字次第です。

入出力なし

コード文字は何ら入力を読み込むことなしに、引数を計算します。 そのために、プロンプト文字列を使いませんし、プロンプト文字列を 与えても無視します。

コード文字がプロンプト文字列を使わなくとも、 それが文字列中の最後のコード文字でないかぎり、これに続く改行が必要です。

プロンプト

プロンプトがコード文字直後に続きます。プロンプトは文字列の終りか改行で 終ります。

特殊

このコード文字はinteractive文字列の先頭においてのみ意味を持ちます。 これにはプロンプトや改行は不要です。これは単独の孤立した文字です。

interactiveに使用するコード文字記述子を挙げます:

`*'

カレント・バッファが読みだし専用ならば、エラーを通知します。特殊。

`@'

このコマンドを起動したキー・シーケンス中の最初のマウス・イベントについての ウィンドウを選択します。特殊。

`a'

関数名(即ち、fboundpを満たすシンボル)。既存、補完、プロンプト。

`b'

既存のバッファ名。デフォルトには、カレント・バッファ(see section バッファ)の名前を 使います。既存、補完、デフォルト、プロンプト。

`B'

バッファ名。バッファが存在する必要はありません。デフォルトには、 カレント・バッファ以外の最近使われたバッファ名を使います。 補完、デフォルト、プロンプト。

`c'

文字。カーソルはエコー領域に移動しません。プロンプト。

`C'

コマンド名(即ち、commandpを満たすシンボル)。既存、補完、プロンプト。

`d'

整数でのポイント位置(see section ポイント)。入出力なし。

`D'

ディレクトリ名。デフォルトはカレント・バッファの現在の デフォルト・ディレクトリ、 default-directory(see section OS環境)。 既存、補完、デフォルト、プロンプト。

`e'

コマンドを起動したキー・シーケンス中の、最初あるいは次のマウス・イベント。 さらに詳しくいうと、`e'によりリストでイベントを取れるので、 リスト中のデータを見ることができます。See section 入力イベント。入出力なし。

`e'は一つのコマンドのinteractive指定で何度でも使えます。 コマンドを起動したキー・シーケンスにリストがnイベント分あった場合、 n番目の`e'n番目のそういったイベントを与えます。 リストではないイベント、ファンクション・キーやASCII文字などは、 `e'に関するかぎり勘定に入れません。

`f'

既存ファイル名(see section ファイル名)。デフォルト・ディレクトリは default-directory。既存、補完、デフォルト、プロンプト。

`F'

ファイル名。ファイルが存在する必要はありません。補完、デフォルト、プロンプト。

`k'

キー・シーケンス(see section キーマップの用語)。これによりイベントが 現在のキーマップ中にコマンド(あるいは未定義コマンド)として見つかるまで、 イベントを読み込み続けます。キー・シーケンス引数は文字列あるいはベクタで 表現されます。カーソルはエコー領域に移動しません。プロンプト。

この種の入力はdescribe-keyglobal-set-keyのようなコマンドで 使います。

`K'

定義を変更しようと考えているキー・シーケンス。これは`k'のように 働きますが、キー・シーケンスの最後の入力イベントについて、 普通(必要ならば)使用する未定義のキーを定義キーに変換するための変換を 抑止する点が異なります。

`m'

整数でのマーク位置。入出力なし。

`n'

ミニバッファから読み込む数。入力が数でなければ、ユーザは再度入力を 乞われます。前置引数がもしあっても、使いません。プロンプト。

`N'

そのままの前置引数。前置引数がnilならば、nのときのように 数を読み込みます。数を要求します。See section 前置コマンド引数。プロンプト。

`p'

数値前置引数(この`p'が小文字であることに注意)。入出力なし。

`P'

そのままの前置引数(この`p'が大文字であることに注意)。入出力なし。

`r'

ポイントとマークを二つの数値引数として、小さい方が先。これだけが 一つではなく、二つの連続した引数を指定するコード文字です。入出力なし。

`s'

任意テキスト、ミニバッファで読み込み、文字列として返します (see section ミニバッファからテキスト文字列を読みとる)。LFDRETのいずれでも入力を 打ち切ります(これらの文字を入力に含めるためにはC-qを使います)。 プロンプト。

`S'

ミニバッファでinternされたシンボルの名前を読み込みます。 いずれの空白文字でも入力を打ち切ります(空白文字を文字列に含めるには C-qを使います)。普通ならシンボルを打ち切るようなほかの文字 (たとえば括弧や角括弧)も、ここではそうなりません。プロンプト。

`v'

ユーザ・オプションとして宣言された変数(即ち、述語user-variable-pを 満たす)。See section 高水準補完関数。既存、補完、プロンプト。

`x'

リード構文を指定したLispオブジェクト。LFDあるいはRETで 打ち切ります。オブジェクトは評価されません。See section ミニバッファからLispオブジェクトを読み込みます。 プロンプト。

`X'

xのときのように読み込むLisp形式ですが、その後評価してその値がコマンドの 引数になるようにしたもの。プロンプト。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

18.2.3 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

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

18.3 対話的呼出し

コマンド・ループはキー・シーケンスを定義に変換した後、 その定義を関数command-executeを使って起動します。 定義がコマンドとしての関数ならば、command-executecall-interactivelyを呼び出し、それが引数を読み込んでコマンドを 呼び出します。自分自身でこれら関数を呼んでも構いません。

Function: commandp object

objectが対話的呼出しに適しているならば、tを返します。 即ち、objectがコマンドであれば、そうします。さもなくば、 nilを返します。

対話的に呼出し可能なオブジェクトには文字列とベクタ(キーボード・マクロとして 扱われます)、トップレベルのinteractive呼出しを含むラムダ式、 そういったラムダ式から得られたバイトコード関数オブジェクト、 対話的と宣言された(autoloadへの第4引数が非nil) 自動ロード・オブジェクト、いくつかのプリミティブ関数を含みます。

シンボルはその関数定義がcommandpならば、commandpです。

キーやキーマップはコマンドではありません。それどころか、コマンドを 検索するために使うものです(see section キーマップ)。

commandpの実際の使用例については、 説明文字列へのアクセスdocumentationを参照してください。

Function: call-interactively command &optional record-flag

この関数は、対話的呼出し可能な関数commandを、 そのinteractive呼出し指定に基づいて引数を読み込んで、呼び出します。 commandが関数や対話的に呼出し可能ではない場合(即ちコマンドではない)、 エラーを通知します。キーボード・マクロ(文字列とベクタ)は、たとえそれらが コマンドとみなされる場合でも、受けつけません。これらは関数ではないからです。

record-flagが非nilならば、本コマンドとその引数は、 無条件にリストcommand-historyに追加されます。 さもなくば、コマンドはそれが引数読込みのためにミニバッファを使った場合に かぎり、追加されます。See section コマンド履歴

Function: command-execute command &optional record-flag

この関数は、編集コマンドcommandを実行します。引数commandcommandp述語を満足する必要があります。即ち、対話的に呼出し可能な関数か キーボード・マクロでなければなりません。

commandの文字列あるいはベクタはexecute-kbd-macroが実行します。 関数はcall-interactivelyにオプションrecord-flagとともに渡します。

シンボルはシンボルの場所内の関数定義を使うことで処理します。 autoload定義によるシンボルは、それが対話的呼出し可能な関数として 宣言されていたならば、コマンドとして扱います。こういった定義の処理は、 指定のライブラリをロードしてから、そのシンボルの定義を再検査することで 行ないます。

Command: execute-extended-command prefix-argument

この関数は、コマンド名をミニバッファからcompleting-read (see section 補完)を使って読み込みます。続いて指定のコマンドを 呼び出すために、command-executeを使います。そのコマンドが何を 返そうとも、それがexecute-extended-commandの値になります。

コマンドが前置引数を求めると、prefix-argumentの値を受け取る ことになります。execute-extended-commandが対話的に呼び出されたならば、 現在の前置引数がそのままprefix-argumentに使われます。 そのため、これが実行されるどのようなコマンドにも渡ります。

execute-extended-commandM-xの普通の定義なので、 文字列`M-x'をプロンプトとして使用します (execute-extended-commandの起動に使われたイベントから プロンプトを取る方がよいのですが、これは実装するのが辛いのです)。 前置引数があれば、その値の記述も同じくプロンプトの一部となります。

 
(execute-extended-command 1)
---------- Buffer: Minibuffer ----------
1 M-x forward-word RET
---------- Buffer: Minibuffer ----------
     ⇒ t
Function: interactive-p

この関数は、これを含む関数(interactive-pを呼んだ関数)が call-interactivelyで対話的に呼び出されたのであるならば、 tを返します(call-interactivelyがLispから呼ばれようと、 エディタ・コマンド・ループから直接呼ばれようとも、何ら違いはありません)。 これを含む関数がLispの評価(あるいはapplyfuncall)で 呼ばれたならば、対話的に呼び出されたことになりません。

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)

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

18.4 コマンド・ループからの情報

エディタ・コマンド・ループは、いくつかのLisp変数を設定して 自身のためと実行されるコマンドのために、状態の記録を保持しています。

Variable: last-command

この変数は、コマンド・ループで実行された直前のコマンド(現在のコマンドの 一つ前)の名前を記録しています。普通、値は関数定義をともなうシンボルですが、 そうである保証はありません。

この値はthis-commandから、コマンドがコマンド・ループに帰るときに コピーされます。そのコマンドが後続のコマンドのために前置引数を指定している 場合は、別です。

この変数は、常に現在の端末に対してローカルなのであって、バッファローカルには なりません。See section 複数のディスプレイ

Variable: this-command

この変数は、エディタ・コマンド・ループで今実行しているコマンドの名前を 記録しています。last-commandのように、普通は関数定義をともなう シンボルです。

コマンド・ループはこの変数をコマンド実行の直前に設定し、 その値をコマンド実行終了時にlast-commandにコピーします (コマンドが後続のコマンドのために前置引数を指定する場合を除きます)。

いくつかのコマンドではこの変数をコマンド実行中に設定して、 次に実行するコマンドへのフラグとします。特に、テキスト集合をkillする関数群は、 this-commandkill-regionに設定して、直後に続く任意の killコマンドがkillしたテキストを直前のkillに追加すべきであることが わかるようにします。

エラー時に特定のコマンドを直前のコマンドとみなされたくない場合には、 そのコマンドをこれを防ぐように書かなければなりません。方法の一つは、 そのコマンドの冒頭でthis-commandtに設定し、 末尾で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)))
Function: this-command-keys

この関数は、現在のコマンドを起動したキー・シーケンスと、そのコマンドに対する 前置引数を生成した直前のコマンドを含む文字列あるいはベクタを返します。 これらイベントが全て文字ならば、値は文字列となります。See section 入力イベント

 
(this-command-keys)
;; ここでC-u C-x C-eを使って、評価する。
     ⇒ "^U^X^E"
Variable: last-nonmenu-event

この変数は、キー・シーケンスの一部として読み込んだ、最後に入力されたイベントを 保持します。このキー・シーケンスには、マウス・メニューからのイベントは 含みません。

この変数の使い方の一つは、メニューを次にポップ・アップするのにいい デフォルト位置を見つけることです。

Variable: last-command-event
Variable: last-command-char

この変数には、コマンドの一部としてコマンド・ループによって読み込まれた、 最後に入力されたイベントが設定されます。この変数の本質的使い方は、 self-insert-command中にあります。そこでは、どの文字を挿入するかを 決定するために使っています。

 
last-command-event
;; ここでC-u C-x C-eを使って、評価する。
     ⇒ 5

値は5となり、理由はそれがC-eASCIIコードであるからです。

別名last-command-charがEmacsバージョン18との互換のために存在します。

Variable: last-event-frame

この変数は、最後に入力したイベントがどのフレームに向けられたものかを 記録します。普通これはイベント発生時に選択されていたフレームですが、 そのフレームが入力フォーカスを別フレームにリダイレクトしていた場合、 この値はイベントのリダイレクト先のフレームになります。See section インプット・フォーカス


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

18.5 入力イベント

Emacsコマンド・ループはキーボードあるいはマウスの動きを表す 入力イベント(input event)のシーケンスを読み込みます。キーボードの 動きのためのイベントは、文字あるいはシンボルです。しかし、マウス・イベントは 常にリストです。本節では入力イベントの表現と意味を詳細に説明します。

Function: eventp object

この関数は、objectが入力イベントならば非nilを返します。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

18.5.1 キーボード・イベント

キーボードから取ることができる入力には2種類あります。それらは、通常キーと ファンクション・キーです。通常キーは文字に対応します。これらが生成する イベントをLispは文字で表現します。Emacsバージョン18以前では、文字のみが イベントでした。文字イベントのイベント・タイプはその文字自身(整数)です。 イベント・タイプについては、イベントの分類を参照してください。

入力文字イベントは0〜255までの基本コード(basic code)にいくつかあるいは 全ての修飾ビット(modifier bit)を加えたものから成ります:

メタ

文字コードの ビットは、メタ・キー押下状態でタイプされた文字であることを表します。

制御

文字コードの ビットは、非ASCII制御文字であることを表します。

C-aのようなASCII制御文字はそれ自身が特別な基本コードをもつので、 Emacsはそれらに特別なビットを与える必要がありません。 それゆえ、C-aのコードは単なる1です。

しかしASCIIにない制御の組合せをタイプした場合、 たとえば%を制御キーとともにタイプしたような場合、 得られる数値は%に を加えたものです(端末が非ASCII制御文字を サポートしていると仮定)。

シフト

文字コードの ビットは、 シフト・キー押下状態でタイプされたASCII制御文字であることを表します。

英文字については、小文字に対する大文字の基本コードを表します。 けれども数字と句読点については、シフト・キーは異なる基本コードの全く別な文字を 選択します。可能なときにはASCII文字集合の範囲内に収まるようにするために、 Emacsはこれらの文字については ビットを使わないようにします。

けれども、ASCIIC-AC-aと区別する手段を持たないので、 Emacsは ビットをC-Aに使用して、C-aには使いません。

ハイパー

文字コードの ビットは、 ハイパー・キー押下状態でタイプされた文字であることを表します。

スーパー

文字コードの ビットは、 スーパー・キー押下状態でタイプされた文字であることを表します。

オルト

文字コードの ビットは、 オルト・キー押下状態でタイプされた文字であることを表します (端末によっては、ALTと書かれたキーが実際のメタ・キーです)。

自作プログラム内では、特定のビット番号は書かないのが一番です。 文字の修飾ビットを検査するには、関数event-modifiersを 使ってください(see section イベントの分類)。キー・バインドを作る場合、 修飾ビットつき文字のリード構文(`\C-', `\M-', などなど)を 使うことができます。define-keyを使ってキー・バインドを作る場合は、 文字の指定に(control hyper ?x)といったリストを使うこともできます (see section キー・バインドの変更)。関数event-convert-listは そういったリストをイベント・タイプ(see section イベントの分類)に変換します。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

18.5.2 ファンクション・キー

ほとんどのキーボードはファンクション・キー(function key)(文字ではなく 名前や記号をもつキー)も備えています。ファンクション・キーはLispでは シンボルとして表現されます。そしてシンボルの名前はファンクション・キーの ラベルを小文字にしたものです。たとえば、F1と書かれたキーを押下すると、 シンボルf1が入力ストリームに置かれます。

ファンクション・キー・イベントのイベント・タイプは、イベント・シンボル自身です。 See section イベントの分類

以下に、ファンクション・キーについてのシンボル命名法の特例をいくつか挙げます:

backspace, tab, newline, return, delete

これらのキーは、ほとんどのキーボードに専用のキーをもつ共通の ASCII制御文字に対応します。

ASCIIでは、C-iTABは同じ文字です。 端末がこれらを区別できるならば、Emacsはその違いを前者を整数の9として、 後者をシンボルtabとして、Lispプログラムに伝えます。

ほとんどの場合、これら二つを区別することは有用ではありません。 そのため普通はfunction-key-mapが準備されていて、 tabを9に対応させます。そのため文字コード9(文字C-i)の キー・バインドがtabにも適用されます。 このグループのほかのシンボルについても同様です。 関数read-charも同様にこれらイベントを文字に変換します。

ASCIIでは、BSC-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

キーパッドのPFキー。

kp-home, kp-left, kp-up, kp-right, kp-down

キーパッドの矢印キー。Emacsは普通これらを非キーパッド・キー home, left, …に変換します。

kp-prior, kp-next, kp-end, kp-begin, kp-insert, kp-delete

付加的なキーパッド・キーで、普通はどこかほかの場所にも見つかるものと 重複します。Emacsは普通これらを似た名前の非キーパッド・キーに変換します。

ファンクション・キーとともに、修飾キーALT, CTRL, HYPER, META, SHIFT, SUPERを使うことができます。 これらの表現方法は、シンボル名に前置をつけることです:

`A-'

オルト修飾子。

`C-'

制御修飾子。

`H-'

ハイパー修飾子。

`M-'

メタ修飾子。

`S-'

シフト修飾子。

`s-'

スーパー修飾子。

よって、METAを押下したF3キーのシンボルは、M-f3です。 一つ以上の前置を使う場合、それらを英文字順に並べることを勧めます。 しかしその順序は、キー・バインドの検索と修正の関数への引数に使うときは 影響しません。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

18.5.3 マウス・イベント

Emacsは4種類のマウス・イベントをサポートしています。それらは クリック・イベント、ドラッグ・イベント、ボタン押下イベント、移動イベントです。 全てのマウス・イベントはリストで表現されます。リストのCARは イベント・タイプです。これはどのマウス・ボタンが関係し、どの修飾キーがともに 使われたかを示します。イベント・タイプによって2連続、3連続のボタン押下も区別できます (see section 繰り返しイベント)。リストの残りの要素は、位置と時間の情報を与えます。

キー検索には、イベント・タイプのみが関わります。ここで二つのイベントが同じ イベント・タイプならば同じコマンドを実行しなければなりません。コマンドは これらイベントの完全な値に`e'対話コードを使ってアクセスできます。 See section interactive用のコード文字

マウス・イベントで始まるキー・シーケンスは、マウスが入っていたウィンドウ中の バッファのキーマップを使って読み込まれます。カレント・バッファではありません。 これは、ウィンドウ中のクリックがそのウィンドウ即ちそのバッファを選択するという 意味ではありません。キー・シーケンスのコマンドのバインド制御についてのみの 話です。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

18.5.4 クリック・イベント

ユーザが同じ位置でマウス・ボタンを押して離したときに、クリック(click)・ イベントが発生します。マウス・クリック・イベントは次の形式を持ちます:

 
(event-type
 (window buffer-pos (x . y) timestamp)
 click-count)

これら要素が普通何を意味するかを説明します:

event-type

どのマウス・ボタンが使われたかを示すシンボルです。ボタンの左から右に向かって、 mouse-1,mouse-2, …と番号づけられたシンボルのうちの 一つになります。

前置`A-', `C-', `H-', `M-', `S-', `s-'を 修飾子オルト、制御、ハイパー、メタ、シフト、スーパーに対して、 ファンクション・キーのときと同様に使うことができます。

このシンボルはイベントのイベント・タイプとしても働きます。キー・バインドは そのイベントをイベント・タイプで記述します。それゆえ、mouse-1に対する キー・バインドがあれば、そのバインドはevent-typemouse-1である 全てのイベントに対して適用されます。

window

クリックを行なったときのウィンドウです。

x, y

これらはクリックのピクセル座標で、windowの左上隅(0 . 0)からの 相対で表します。

buffer-pos

クリックされた文字のバッファ位置です。

timestamp

イベント発生の時刻で、ミリ秒単位です(この値はEmacs Lisp整数の全範囲を、 約5時間で一周するので、時間的に近いイベントに関してのみ有効です)。

click-count

同じマウス・ボタンを素早く続けて押した回数です。See section 繰り返しイベント

buffer-pos, x, yの意味は、イベント位置がモード行や スクロール・バーのような画面の特別な部分内にあるときに若干異なってきます。

位置がスクロール・バー内にあるときは、buffer-posはシンボル vertical-scroll-barhorizontal-scroll-barになり、 (x . y)の対はportion . wholeの対で 置き換えられます。ここでportionは、スクロール・バーの上端あるいは 左端からのクリックの距離であり、wholeはスクロール・バーの全長です。

位置がモード行あるいはwindowを右隣から分離する垂直線にあるときは、 buffer-posがシンボルmode-lineあるいはvertical-lineに なります。モード行の場合は、yは意味のないデータです。垂直線の場合は、 xが意味のないデータとなります。

一つの特例として、buffer-posが単なるシンボルの代わりに、 シンボル(上に挙げたものの一つ)を含むリストになっている場合があります。 これは、イベントに対する架空の前置キーが入力ストリームに挿入された場合に 起こります。See section キー・シーケンス入力


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

18.5.5 ドラッグ・イベント

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はドラッグ・イベントを ドラッグ開始位置でのクリック・イベントに変換します。 つまり、そうしたくないかぎり、クリックとドラッグの両イベントを区別する必要は ない、ということです。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

18.5.6 ボタン押下イベント

クリックとドラッグのイベントは、ユーザがマウス・ボタンを離したときに起きます。 これより早く起こせないのは、ボタンが離されるまでクリックをドラッグと 区別できないからです。

ボタンが押されると同時に動作を起こしたいならば、ボタン押下(button-down) イベント(14)を 操作する必要があります。これはボタンが押されるやいなやに発生します。 これはクリック・イベント(see section クリック・イベント)と全く見かけが同じ リストで表現されます。違うのは、event-typeシンボル名が 前置`down-'を含むことです。`down-'前置は`C-'`M-'のような 修飾キー前置の後に来ます。

関数read-key-sequenceは、コマンドにバインドされていない ボタン押下イベントは全て無視します。その結果Emacsコマンド・ループもそうする ことになります。つまりボタン押下イベントで何かしようと思わないかぎり、 その定義を気にする必要がないという意味です。ボタン押下イベントを定義する 理由としてあり得そうなのは、そうすることでボタンが離されるまでのマウスの動きを (移動イベントを読み込むことで)追跡できるというのがあります。 See section 移動イベント


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

18.5.7 繰り返しイベント

マウスを動かさずに素早く続けて同じマウス・ボタンを何度も押した場合、 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重、などなどのイベントを 区別するイベント・タイプを持ちません。それでも、イベント・リストを見て、 何回ボタンが押下されたかを正確に知ることができます。

Function: event-click-count event

この関数は、eventを導くまでに到った、連続したボタン押下の回数を返します。 eventがダブル押下、ダブルクリック、ダブルドラッグならば、 値は2です。eventがトリプル・イベントならば、値は3以上です。 eventが(繰り返しイベントではない)通常のマウス・イベントならば、 値は1です。

Variable: double-click-time

繰り返しイベントを発生させるには、同じ画面位置で連続してマウス・ボタンを 押下し、連続するボタン押下の間隔がミリ秒でdouble-click-timeの値よりも 小さくなければなりません。double-click-timenilに設定すると、 マルチ・クリックの検出を完全に禁止します。tに設定すると、 時間の制限を取り除きます。つまりEmacsはマルチ・クリックを場所のみで 検出するようになります。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

18.5.8 移動イベント

Emacsは、マウス・ボタンの動きがなくてもマウス移動を表すために マウス移動(mouse motion)イベントを時折発生します。

 
(mouse-movement
 (window buffer-pos (x . y) timestamp))

リスト2番目の要素は、丁度クリック・イベント(see section クリック・イベント)のときの ように、マウスの現在の位置を表します。

特殊形式track-mouse本体内では、移動イベントの発生が可能になっています。 track-mouse形式外では、Emacsは単なるマウスの移動についてのイベントは 発生しません。よって、これらイベントは現れません。

Special Form: track-mouse body…

この特殊形式はbodyを実行し、そこではマウス移動イベントの発生が 可能になっています。典型的なbodyは、read-eventを使って 移動イベントを読み込み、それにしたがって表示を修正します。

ユーザがボタンを離すと、クリック・イベントが発生します。 典型的には、bodyはクリック・イベントを認識した時点で帰り、 なおかつそのイベントは捨てるべきです。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

18.5.9 フォーカス・イベント

ウィンドウ・システムはどのウィンドウがキーボード入力を受け取るかを ユーザが制御する一般的方法を備えています。このウィンドウの選択を フォーカス(focus)と呼びます。ユーザがEmacsのフレームを切替えるために 何かをすると、フォーカス・イベント(focus event)が発生します。 フォーカス・イベントの通常の定義はグローバル・キーマップにあり、ユーザが 期待するとおりにEmacs内で新たなフレームを選択するようになっています。 See section インプット・フォーカス

フォーカス・イベントはLispではこんな感じのリストで表現されます:

 
(switch-frame new-frame)

ここでnew-frameは切替え先のフレームです。

ほとんどのXウィンドウ・マネージャは、単にマウスをウィンドウの中に移動するだけで フォーカスをそこに置けるようになっています。Emacsもこうなっているように 見えます。新たなフレーム内で、カーソルがはっきりするからです。 けれども、Lispプログラムにとってはほかの種類の入力が来ないかぎり、 フォーカスが変わったことを知る必要がありません。 そこで、Emacsは実際にユーザがキーボード・キーをタイプするか マウス・ボタンを押下するかを新たなフレームで行なった場合にかぎり、 フォーカス・イベントを発生します。つまりフレーム間でマウスを単に移動しても、 フォーカス・イベントは発生しません。

キー・シーケンスの途中でフォーカス・イベントが発生すると、 キー・シーケンスがグシャグシャになってしまうことでしょう。 そのためEmacsではキー・シーケンス途中でフォーカス・イベントが発生することは 絶対にありません。ユーザがキー・シーケンスの途中(つまり、前置キーの後)で フォーカスを変えたならば、Emacsはそのイベントを並べ替えて、 フォーカス・イベントが多重イベントのキー・シーケンスの前か後に来るように、 途中には来ないようにします。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

18.5.10 そのほかのウィンドウ・システム・イベント

ウィンドウ・システム内で発生したことを表す、そのほかのイベント・タイプ。

(delete-frame (frame))

この種のイベントはユーザがウィンドウ・マネージャに特定のウィンドウを 消去するように命令したこと、それがEmacsのフレームだったことを示します。

delete-frameイベントの標準定義は、frameの消去です。

(iconify-frame (frame))

この種のイベントはユーザがウィンドウ・マネージャを使ってframeを アイコン化したことを示します。この標準定義はignoreです。 というのも、フレームはすでにアイコン化されていたので、 Emacsはすることがないのです。このイベント・タイプの目的は、 必要ならこういったイベントを追跡できるようにすることです。

(make-frame-visible (frame))

この種のイベントはユーザがウィンドウ・マネージャを使ってframeを アイコン化解除したことを示します。この標準定義はignoreです。 というのも、フレームはすでにアイコン化解除されていたので、 Emacsはすることがないのです。

これらイベントのいずれかがキー・シーケンスの途中にきた場合 (つまり、前置キーの後)は、Emacsはこれらイベントを並べ替えて、 このイベントが多重イベントのキー・シーケンスの前か後に来るように、 途中には来ないようにします。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

18.5.11 イベントの例

ユーザが同じ場所で左マウス・ボタンを押下して離したならば、 このようなイベント列が発生します:

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

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

18.5.12 イベントの分類

全てイベントはイベント・タイプ(event type)を持ち、キー・バインドでの 使用では、それによってイベントを分類しています。キーボード・イベントに ついては、イベント・タイプはイベント値に同じです。そのため文字の イベント・タイプは文字で、ファンクション・キー・シンボルのイベント・タイプは シンボル自身です。リストであるようなイベントについては、イベント・タイプは リストのCARにあるシンボルです。よって、イベント・タイプは常にシンボルか 文字となります。

同じ種の二つのイベントはキー・バインドに関するかぎり等価です。 そのため、どちらも常に同じコマンドを実行します。これは必ずしも これらが同一のことを行なうことを意味するわけではありません。 というのも、コマンドによってはイベント全体を見て何をするのか決めるからです。 たとえば、コマンドによってはマウス・イベントの位置を使って、 どのバッファに作用するかを決めます。

ときにはイベントをさらに詳しく分類することが便利です。たとえば、 イベントがMETAキーとともに使われたかどうかを確かめたい場合が あるかもしれません(ほかのキーやマウス・ボタンの使用は無視する)。

関数event-modifiersevent-basic-typeが、 こういった情報を都合よく得るために用意されています。

Function: event-modifiers event

この関数は、eventがもつ修飾子のリストを返します。 修飾子はシンボルです。これらは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'を 含みません。

Function: event-basic-type event

この関数は、eventが表す全ての修飾子を取り除いたキーあるいはマウス・ボタンを 返します。例を挙げます:

 
(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
Function: mouse-movement-p object

この関数は、objectがマウス移動イベントならば、非nilを返します。

Function: event-convert-list list

この関数は、修飾子名のリストと基本イベント・タイプをそれら全てを指定する イベント・タイプに変換します。例を挙げます:

 
(event-convert-list '(control ?a))
     ⇒ 1
(event-convert-list '(control meta ?a))
     ⇒ -134217727
(event-convert-list '(control super f1))
     ⇒ C-s-f1

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

18.5.13 イベントへのアクセス

本節ではマウス・ボタンや移動イベント中のデータをアクセスするのに 都合がいい関数を説明します。

これら二つの関数はマウス・ボタン・イベントの開始あるいは終了位置を 返します。位置はこの形式のリストです:

 
(window buffer-position (x . y) timestamp)
Function: event-start event

これはeventの開始位置を返します。

eventがクリックあるいはボタン押下イベントならば、 これがイベントの位置を返します。eventがドラッグ・イベントならば、 これがドラッグの開始位置を返します。

Function: event-end event

これはeventの終了位置を返します。

eventがドラッグ・イベントならば、これがユーザがボタンを離した位置を 返します。evnetがクリックあるいはボタン押下イベントならば、 その値は実際には開始位置で、こういったイベントが唯一もつ位置です。

これら四つの関数は上に挙げたような位置を取り、それのさまざまな部分を 返します。

Function: posn-window position

positionが入っているウィンドウを返します。

Function: posn-point position

positionのバッファ位置を返します。これは整数です。

Function: posn-x-y position

position内のピクセル・ベースのx, y座標を (x . y)というコンス・セルで返します。

Function: posn-col-row position

positionの(文字単位の)行と桁を(x . y)という コンス・セルで返します。これらはpositionから実際に取り出した x, yの値より計算します。

Function: posn-timestamp position

positionのタイムスタンプを返します。

Function: scroll-bar-event-ratio event

この関数は、スクロール・バー・イベントのスクロール・バー中の垂直位置を割合で 返します。値は(portion . whole)というコンス・セルで、 その比が位置の割合となるような二つの整数を含みます。

Function: scroll-bar-scale ratio total

この関数は、(事実上)ratiototalを乗じて、結果を整数に丸めます。 引数ratioは数ではなく、(num . denom)の組です。 典型的にはscroll-bar-event-ratioが返した値です。

この関数は、スクロール・バー上の位置をバッファ位置に変換するのに便利です。 こうやります:

 
(+ (point-min)
   (scroll-bar-scale
      (posn-x-y (event-start event))
      (- (point-max) (point-min))))

スクロール・バー・イベントが、x, y座標の組の代わりに、 二つの比をなす整数をもつことに注意してください。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

18.5.14 文字列にキーボード・イベントを入れる

文字列が使われるほとんどの部分において、私たちはその文字列をテキスト文字を 含むものとして概念化しています(同じ種類の文字がバッファあるいはファイルにも あるのです)。時折Lispプログラムは文字列をキーボード文字を含むものとして 扱います。たとえば、それらはキー・シーケンスやキーボード・マクロ定義であるかも しれません。そこで、キーボード文字を文字列中に置くための特別な規則が 存在します。というのも、それらはテキスト文字のように0から255の範囲に 限定されないからです。

METAを使ってタイプされたキーボード文字を メタ文字(meta character)と呼びます。このようなイベントに対する 数値コードは ビットを含みます。けれどもこれでは全然文字列に収まりません。 しかし初期のEmacsの版においては、これら文字に対して異なる表現を使っていました。 これらに128から255の範囲のコードを与えるのです。こうすれば文字列に収まり、 多くのLispプログラムが、特にdefine-keyや類似の関数の引数において、 `M-'によって表現されたメタ文字を文字列定数に含めていました。

キーボード文字イベントを文字列に入れる特別な規則を使っている これらプログラムを実行するために、後方互換性を提供しています。 こういう規則です:

read-key-sequenceのような関数は、これら規則にしたがった キーボード入力文字の文字列を構築することができます。これら関数は、 イベントが文字列に収まらない場合には文字列の代わりにベクタを構築します。

リード構文`\M-'を文字列中で使用した場合、128から255の範囲内の コードが作られます(対応するキーボード・イベントを文字列に入れるために 修正したときに得られるコードと同じものです)。そのため、文字列中の メタ・イベントは、それらがどのように文字列に入ってくるかに関わらず、 一貫して機能します。

キーボード・イベントとしてのメタ文字の表現を変更した理由は、 127を超える基本文字コードのために空間を空けるためと、 そういった大きな文字コードのメタ類をサポートするためです。

新たなプログラムでは、これらの特別な互換性規則の使用を避けることが できます。メタ文字を含む可能性があるキー・シーケンスに対しては、 文字列の代わりにベクタを使い、イベントの文字列をアクセスするには listify-key-sequenceを使用すればいいのです。

Function: listify-key-sequence key

この関数は、文字列あるいはベクタkeyを、unread-command-eventsに 入れることができるイベントのリストに変換します。ベクタの変換は簡単ですが、 文字列の変換は文字列中のメタ文字に使用する特別な表現のために込み入ってます。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

18.6 入力の読込み

エディタ・コマンド・ループはキーボード入力を関数read-key-sequenceで 読み込み、その関数はread-eventを使っています。これらのおよびほかの キーボード入力のための関数も同様に、Lispプログラムで使用できるように なっています。一時表示momentary-string-displayや、 時間の経過あるいは入力を待つsit-forを参照してください。端末入力モードの制御と 端末入力のデバッグのための関数や変数については、See section 端末入力

高水準入力機能については、ミニバッファを参照してください。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

18.6.1 キー・シーケンス入力

コマンド・ループはキー・シーケンス入力を1回に一つ、 read-key-sequenceを呼び出すことで読み込みます。Lispプログラムで 同じようにこの関数を使えます。たとえば、describe-keyはこれを使って 説明するキーを読み込みます。

Function: read-key-sequence prompt

この関数は、キー・シーケンスを一つ読み込んで、それを文字列あるいはベクタで 返します。イベントを読み込み続け、それが完全なキー・シーケンスになったとき 止めます。即ち、現在アクティブなキーマップで、何らかの非前置コマンドを 指定するに十分となるまでです。

イベントが全て文字で、その全てが文字列に収まるならば、 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"
Variable: num-input-keys

この変数の値は、現在のEmacsセッションにおいてこれまで処理された キー・シーケンスの個数です。これは端末から読み込んだキー・シーケンスと 実行されたキーボード・マクロ自身を読み込んだときのキー・シーケンスとを 含みます。

入力文字が大文字でキー・バインドはないが、その小文字のバインドならある場合、 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))]

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

18.6.2 イベントを一つ読み込む

コマンド入力の最低水準関数は、これら単一のイベントを読み込むものです。

Function: read-event

この関数は、コマンド入力の次のイベントを読み込んで返します。 必要ならばイベントが来るまで待ちます。イベントはユーザから直接あるいは キーボード・マクロから来ます。

関数read-eventは入力待ちであることを示すメッセージは何も表示しません。 もしそうしたいならば、messageをはじめに使ってください。メッセージを 表示しなかったならば、read-eventはエコーすることでプロンプトを出します。 つまり、現在のコマンドを導いた、または、現在のコマンドによって読み込まれた イベントを表す表示をします。See section エコー領域

cursor-in-echo-areaが非nilならば、read-eventは カーソルを一時的にエコー領域に移動し、そこに表示される何らかのメッセージが 終るまでそうしています。それ以外では、read-eventはカーソル移動しません。

read-eventを呼んで右矢印ファンクション・キーを押下したとすると、 こうなります:

 
(read-event)
     ⇒ right
Function: read-char

この関数は、コマンド入力の1文字を読み込んで返します。 文字を拾うまで、文字以外のいかなるイベントも捨てます。

最初の例では、ユーザが文字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

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

18.6.3 Quoteした文字入力

関数read-quoted-charを使って、ユーザに文字を指定するよういい、 ユーザが制御やメタ文字を簡便に指定できるようにすることができます。 文字どおりでも、8進文字コードでもどちらでもできます。 コマンドquoted-insertはこの関数を使っています。

Function: read-quoted-char &optional prompt

この関数は、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

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

18.6.4 そのほかのイベント入力機能

本節ではイベントを取り出さずに「あらかじめ覗く」方法、 未処理の入力を検査する方法、保留中の入力を捨てる方法を説明します。

Variable: unread-command-events

この変数は、コマンド入力として読み込まれるのを待っているイベントのリストを 保持しています。これらイベントはリストに現れた順に使われ、使われるにしたがって 一つづつ取り除かれます。

この変数が必要だったわけは、場合によっては関数がイベントを読み込んで、 それを使わないと決めることがあるからです。そのイベントをこの変数に格納すると、 コマンド・ループやコマンド入力を読み込む関数が、それを普通に処理します。

例として、数値前置引数を実現する任意桁数の数字を読み込む関数があります。 これが非数字イベントを見つけると、コマンド・ループが普通に読み込むように、 それを読み戻さなければなりません。同様に、段階的検索はこの機能を使って 検索時に特別な意味を持たないイベントを読み戻すようにします。というのも、 これらイベントは検索を抜けてから、普通に実行しなければならないためです。

unread-command-events中に置けるようにするために、 キー・シーケンスからイベントを抜き出す信頼できる簡単な方法は、 listify-key-sequenceを使うことです(see section 文字列にキーボード・イベントを入れる)。

Variable: unread-command-char

この変数は、コマンド入力として読み込まれるべき文字を保持します。 値 -1 の意味は、「空」です。

この変数は、今やほとんどobsoleteで、それはunread-command-eventsを 代わりに使えるからです。これはEmacsバージョン18以前のために書かれたプログラムを サポートするためだけに存在します。

Function: input-pending-p

この関数は、現在読込み可能なコマンド入力があるかないかを判別します。 読込み可能な入力があればtの値で、そうでなければnilの値で、 直ちに戻ります。ごくまれに読込み可能な入力がないのにtで 戻ることもあります。

Variable: last-input-event

この変数は、読み込んだ最新の端末入力イベントを記録します。 コマンドの一部でも、Lispプログラムによる明示的なものでも関係ありません。

次の例では、Lispプログラムが文字1ASCIIコード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

別名last-input-charが、Emacsバージョン18との互換のために存在します。

Function: discard-input

この関数は、端末入力バッファの中身を捨てて、定義の最中のキーボード・マクロが あったならばキャンセルします。nilを返します。

次の例では、この形式の評価が始まり次第、ユーザは沢山の文字をタイプすることも できます。sleep-forがスリープを終り次第、discard-inputが スリープ中にタイプされた全ての文字を捨て去ります。

 
(progn (sleep-for 2)
       (discard-input))
     ⇒ nil

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

18.7 時間の経過あるいは入力を待つ

待ち関数は、一定の時間が経つか入力があるまで待つために設計されました。 たとえば、計算の途中でポーズを置いて、ユーザが表示を眺めることができるように したいことがあるかもしれません。sit-forはポーズを置いて画面を 更新し、入力があれば直ちに戻ります。一方、sleep-forは画面の更新は しません。

Function: sit-for seconds &optional millisec nodisp

この関数は、(ユーザの未処理の入力がないならば)再表示を実行し、 seconds秒か入力があるまで待ちます。値がtとなるのは、 sit-forが入力が来ないでフルに待った場合です (そのほかのイベント入力機能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の普通の目的は、表示したテキストを読む時間をユーザに 与えることです。

Function: sleep-for seconds &optional millisec

この関数は、単純にseconds秒ポーズを置きます。表示は更新しません。 入力も全く気にしません。nilを返します。

引数secondsは整数でなくても構いません。浮動小数点数ならば、 sleep-forは小数で指定した秒を待ちます。いくつかのシステムでは 秒未満をサポートしていません。このようなシステムでは、secondsは 切り捨てられます。

オプション引数millisecはミリ秒単位の追加待ち時間を指定します。 これはsecondsで指定した時間に追加されます。 システムが小数秒をサポートしない場合には、非0のmillisec指定は エラーとなります。

確実に遅延を取りたい場合はsleep-forを使ってください。

現在時刻を得るための関数については、See section 1日の時刻


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

18.8 とりやめ

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-flagtに 設定することでそうします。Emacsはこの変数を適切なときに検査して、値が 非nilならばとりやめます。そのためどんな方法でも、quit-flagを 非nilに設定すると、とりやめを引き起こします。

Cコードのレベルでは、とりやめはどこでも起こるというわけではありません。 quit-flagを検査している特別な場所でのみ起こります。この理由は、 ほかの場所でとりやめるとEmacsの内部状態を一貫性のない状態にしてしまうかも しれないからです。とりやめが安全な場所まで遅延されるので、とりやめでEmacsが クラッシュすることはありません。

ある種のread-key-sequenceread-quoted-charのような関数は 入力待ち中だったとしてもとりやめを完全に防ぎます。とりやめの代わりに、 C-gは要求された入力として働きます。read-key-sequenceの場合なら、 コマンド・ループ中のC-gの特別な振舞をするように働きます。 read-quoted-charの場合なら、C-qC-gをquoteできるようにする ために、こうなってます。

Lisp関数内のある部分でとりやめを防ぎたいならば、変数inhibit-quitを 非nilに束縛すればできます。こうすると、C-gquit-flagtにいつもどおり設定しても、普通なら起こるはずのとりやめが起きません。 そのうち、inhibit-quitが再びnilになったとします。 たとえばlet形式の終りでその束縛が解かれるなどです。 そのとき、quit-flagがいまだ非nilだったならば、 要求されていたとりやめが直ちに起こります。この振舞は、プログラムの 「クリティカル・セクション」内でとりやめが絶対起こらないようにしたい場合に ふさわしいものです。

(read-quoted-charのような)関数によっては、 C-gは特別な方法で扱われてとりやめを起こしません。 inhibit-quittに束縛して入力を読み込み、 inhibit-quitnilにする前にquit-flagnilに再び設定すると、こうなります。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)))
Variable: quit-flag

この変数が非nilならば、inhibit-quitが非nilでないかぎり、 Emacsは直ちにとりやめます。C-gのタイプで、普通quit-flaginhibit-quitの値に関わらず、非nilに設定されます。

Variable: inhibit-quit

この変数は、quit-flagnil以外の値に設定されているときに、 Emacsがとりやめるべきか否かを決定します。inhibit-quitが 非nilならば、quit-flagは特別な効果を持ちません。

Command: keyboard-quit

この関数は、quit条件を(signal 'quit nil)によって通知します。 これは、とりやめと同じことを行ないます(エラーsignalを参照)。

C-g以外の文字をとりやめのために指定できます。 関数端末入力set-input-modeを参照してください。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

18.9 前置コマンド引数

ほとんどのEmacsコマンドは、コマンド自身に先立って指定される数値である 前置引数(prefix argument)を使えます(前置引数と前置キー(prefix key)を 混同しないように)。前置引数はいつでも一つの値で表現され、それは現在前置引数は ないという意味のnilかもしれません。Emacsコマンドは前置引数を使うかも しれないし、無視するかもしれません。

前置引数には二つの表現があります。それらはそのまま(raw)数値(numeric)です。エディタ・コマンド・ループはそのままの表現を 内部的に使用し、その情報を格納するLisp変数もそのようにしますが、 コマンドはいずれの表現も要求できます。

以下がそのままの前置引数の取り得る値です:

これら可能性は、次の関数をさまざまな前置で呼び出すことで例示できます。

 
(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-argcurrent-prefix-argです。universal-argumentの ようなほかのコマンドのために前置引数を準備するコマンドが、 値をprefix-argに格納します。対照的に、current-prefix-argは 現在のコマンドに前置引数を伝えます。これに値を設定してもこれ以降のコマンドの 前置引数には何の影響もありません。

普通コマンドは、前置引数に数値あるいはそのまま、どちらの表現を使うかを interactive宣言で指定します(See section interactiveを使う)。 その一方で、関数は前置引数の値を直に変数current-prefix-argで 見るかも知れません。しかしこれは若干汚いやり方です。

Function: prefix-numeric-value arg

この関数は、有効なそのままの前置引数argの数としての意味を返します。 引数はシンボル、数、リストです。nilならば、値1が返ります。 -ならば、-1が返ります。数ならば、その数が返ります。 リストならば、リストのCAR(数であるはず)が返ります。

Variable: current-prefix-arg

この変数は、現在のコマンドのそのままの前置引数を保持します。 コマンドは直接それを調べても構いませんが、普通は(interactive "P")で アクセスします。

Variable: prefix-arg

この変数の値は、次の編集コマンドのそのままの前置引数です。 次のコマンドのために前置引数を指定するコマンドは、 この変数を設定する働きがあります。

関数universal-argument, digit-argument, negative-argumentは、ユーザに次のコマンドのための前置引数を 入力させようというのでないかぎり、呼び出さないでください。

Command: universal-argument

本コマンドは入力を読み込み、次のコマンドのための前置引数を指定します。 本コマンドを自分で呼び出す場合は、自分が何をしているのかを理解の上で やってください。

Command: digit-argument arg

本コマンドは、次のコマンドのために前置引数を追加します。 引数argは、本コマンド前までのそのままの前置引数です。 これは、前置引数を更新するために使います。本コマンドを自分で呼び出す場合は、 自分が何をしているのかを理解の上でやってください。

Command: negative-argument arg

本コマンドは、次のコマンドのための数値引数を追加します。 引数argは本コマンド前までのそのままの前置引数です。 この値は新たな前置引数を作るために負数にされます。本コマンドを自分で 呼び出す場合は、自分が何をしているのかを理解の上でやってください。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

18.10 再帰編集

Emacsのコマンド・ループには、Emacs起動時に自動的に入ります。 このトップレベルで起動したコマンド・ループを抜けることはありません。 Emacsが実行を続けるかぎり、これも実行を続けます。 Lispプログラムもやはりコマンド・ループを起動できます。 これはコマンド・ループを複数回アクティブにするので、 再帰編集(recursive edit)と呼びます。再帰編集レベルは、それを起動した いかなるコマンドをもサスペンドし、そのコマンドに戻るまではユーザに 任意の編集を許します。

再帰編集の間に利用可能なコマンドは、トップレベルの編集ループで 利用可能なものと同一であり、キーマップに定義されています。 いくつかの特殊なコマンドのみが再帰編集レベルを抜けます。 それ以外は終了時にその再帰編集レベルに戻ります (抜けるための特殊なコマンドは常に利用可能ですが、それらは再帰編集中以外は 何もしません)。

再帰的なものを含む、全てのコマンド・ループは汎用のエラー・ハンドラを 準備します。そうすることでコマンド・ループから実行したコマンド中で エラーが起きても、コマンド・ループを抜けることがなくなります。

ミニバッファ入力は特別な種類の再帰編集です。いくつかの特徴があり、 ミニバッファとミニバッファ・ウィンドウの表示を可能にしたりできますが、 思ったほど多くはありません。いくつかのキーはミニバッファ中では異なる振舞を します。しかし、それはミニバッファのローカル・マップのせいでしかありません。 したがってウィンドウを切替えれば、普通のEmacsコマンドが使えます。

再帰編集レベルを起動するには、関数recursive-editを呼び出します。 この関数は、コマンド・ループを含みます。タグexitでのcatch 呼出しも含むので、exitをthrowすることで再帰編集レベルを 抜けることが可能になります(see section 明示的な非局所脱出: catchthrow)。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-replaceC-rをタイプしたときや C-x q (kbd-macro-query)を使ったときにも使われます。

Function: recursive-edit

この関数は、エディタ・コマンド・ループを起動します。Emacs初期化では自動的に 呼び出され、ユーザが編集を開始できるようにします。 Lispプログラムから呼び出した場合、再帰編集レベルに入ります。

次の例では、関数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
Command: exit-recursive-edit

この関数は、最も内側の(ミニバッファ入力を含む)再帰編集から抜けます。 この定義は事実上(throw 'exit nil)です。

Command: abort-recursive-edit

この関数は、最も内側の(ミニバッファ入力を含む)再帰編集を抜けた後、 その再帰編集を要求したコマンドをquitの通知によって中断します。 この定義は事実上(throw 'exit t)です。See section とりやめ

Command: top-level

この関数は、全ての再帰編集レベルを抜けます。その結果いかなる計算からも 完全に飛び出してメインのコマンド・ループに直接戻ってしまうので、 値を返しません。

Function: recursion-depth

この関数は、現在の再帰編集の深さを返します。再帰編集にない場合、 0を返します。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

18.11 コマンドの禁止

コマンドの禁止(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 (emacs)Disabling section `Disabling' in The GNU Emacs Manual。コマンドの禁止は Lispプログラムからそれを関数として呼び出す場合には何の効果も持ちません。

Command: enable-command command

これ以後、commandの実行に特別な確認が不要になります。 そして、(ユーザがいいといえば)ユーザの`.emacs'ファイルを書き換えて、 今後のセッションでもそうなるようにします。

Command: disable-command command

これ以後、commandの実行には特別な確認が必要になります。 そして、(ユーザがいいといえば)ユーザの`.emacs'ファイルを書き換えて、 今後のセッションでもそうなるようにします。

Variable: disabled-command-hook

本正規フックは、ユーザが禁止されたコマンドを対話的に起動したときに、 そのコマンドの代わりに実行されます。フック関数はthis-command-keysを 使ってユーザがこのコマンドを実行するために何をタイプしたかを判別することが できます。そのため、何のコマンドだったかを知ることができます。See section フック

デフォルトでは、disabled-command-hookはユーザに続行するか否かを 尋ねる関数を含んでいます。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

18.12 コマンド履歴

コマンド・ループはそれまでに実行された複雑なコマンドの履歴を持っています。 こうすることで、これらコマンドの繰り返しの便宜を図ります。 複雑なコマンド(complex command)とは、対話引数の読込みにミニバッファを 使うものをいいます。これは、M-xコマンドの全て、M-:コマンドの全て、 そしてinteractive指定でミニバッファから引数を読み込むコマンド全てを 含みます。コマンド自身の実行中にミニバッファを明示的に使用しても、 そのコマンドを複雑とは考えません。

Variable: command-history

この変数の値は、最近の複雑なコマンドのリストで、各要素が評価されるべき形式で 表現されています。編集セッションの間中、この変数に全ての複雑なコマンドが 記録し続けますが、ガベージ・コレクションが発生すると、 最初(最近)の30個以外の要素は削除されます(see section ガベージ・コレクション)。

 
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 (emacs)Repetition section `Repetition' in The GNU Emacs Manual)に 説明してあります。ミニバッファ中では、使用された履歴コマンドは任意の ミニバッファで利用可能なものと同じです。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

18.13 キーボード・マクロ

キーボード・マクロ(keyboard macro)は、入力イベント・シーケンスの 缶詰で、コマンドとみなすこともできるし、キー定義をなすこともできます。 キーボード・マクロのLisp表現は、文字列あるいはイベントを含むベクタです。 Lispのマクロとキーボード・マクロとを混同しないようにしてください (see section マクロ)。

Function: execute-kbd-macro macro &optional count

この関数は、macroをイベントのシーケンスとして実行します。 macroが文字列あるいはベクタなら、その中のイベントはユーザによって 入力されたのと全く同じように実行されます。シーケンスが単一の キー・シーケンスであると思ってはいけません。つまり、 普通キーボード・マクロ定義は複数のキー・シーケンスを連結したものです。

macroがシンボルならば、その関数定義をmacroの代わりに使います。 それがまた別のシンボルならば、この処理を繰り返します。 最終的には結果が文字列あるいはベクタになるはずです。結果がシンボル、文字列、 ベクタのいずれでもない場合は、エラーが通知されます。

引数countは繰り返し回数です。ここではmacroがその回数だけ 実行されます。countが省略されるか、nilだった場合、 macroは1回だけ実行されます。0ならば、macroはエラーとなるか 検索に失敗するまで、延々と実行されます。

Variable: executing-macro

この変数の内容は、現在実行中のキーボード・マクロを定義している文字列 あるいはベクタです。その時点で何のマクロも実行していないなら、値は nilです。コマンドを実行中のマクロから実行した場合、 コマンドはこの変数を検査して振舞を変えることができます。 自分自身でこの変数を設定するのは止めてください。

Variable: defining-kbd-macro

この変数は、キーボード・マクロの定義中であるか否かを示します。 コマンドはこの変数を検査して、マクロ定義中ならば振舞を変えることができます。 コマンドstart-kbd-macroend-kbd-macroとは、 この変数を設定します(自分自身でこの変数を設定するのは止めてください)。

この変数は、常に現在の端末に関してローカルであり、バッファローカルには できません。See section 複数のディスプレイ

Variable: last-kbd-macro

この変数は、最新のキーボード・マクロを定義したものです。 その値は文字列あるいはベクタ、あるいはnilです。

この変数は、常に現在の端末に対してローカルであり、バッファローカルには できません。See section 複数のディスプレイ


[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by Yasutaka SHINDOH on September, 29 2006 using texi2html 1.76.