[ < ] | [ > ] | [ << ] | [上] | [ >> ] | [冒頭] | [目次] | [見出し] | [ ? ] |
読者がEmacsを起動すると, Emacsはほぼただちにエディタコマンドループ (editor command loop)に入ります. このループは, キー列を読み取り, それらの定義を実行し, 結果を表示します. 本章では, これがどのように行われるのか, および, Lispプログラムからこれを行うためのサブルーティンについて述べます.
20.1 コマンドループの概要 | How the command loop reads commands. | |
20.2 コマンドの定義 | Specifying how a function should read arguments. | |
20.3 対話的呼び出し | Calling a command, so that it will read arguments. | |
20.4 コマンドループからの情報 | Variables set by the command loop for you to examine. | |
20.5 入力イベント | What input looks like when you read it. | |
20.6 入力の読み取り | How to read input events from the keyboard or mouse. | |
20.7 特殊イベント | Events processed immediately and individually. | |
20.8 時間待ちと入力待ち | Waiting for user input or elapsed time. | |
20.9 中断 | How C-g works. How to catch or defer quitting. | |
20.10 前置コマンド引数 | How the commands to set prefix args work. | |
20.11 再帰編集 | Entering a recursive edit, and why you usually shouldn’t. | |
20.12 コマンドを禁止する | How the command loop handles disabled commands. | |
20.13 コマンド履歴 | How the command history is set up, and how accessed. | |
20.14 キーボードマクロ | How keyboard macros are implemented. |
[ < ] | [ > ] | [ << ] | [上] | [ >> ] | [冒頭] | [目次] | [見出し] | [ ? ] |
コマンドループがまず始めに行うことはキー列,
つまり, コマンドへ変換されるイベント列を読むことです.
これには関数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
の実行中は,
中断を禁止します.
これらのフックの1つを実行中にエラーが起きると,
エラーの無限ループを防ぐために,
フックの実行を終了しフック変数をnil
にします.
[ < ] | [ > ] | [ << ] | [上] | [ >> ] | [冒頭] | [目次] | [見出し] | [ ? ] |
Lisp関数の本体に, スペシャルフォームinteractive
を呼び出す
フォームがトップレベルにあると, Lisp関数はコマンドになります.
このフォームは実際に呼び出されてもなにもしませんが,
このフォームがあることで, 対話的に呼び出せることを表します.
その引数が, 対話的呼び出しにおける引数の読み方を制御します.
20.2.1 interactive の使い方 | General rules for interactive .
| |
20.2.2 interactive のコード文字 | The standard letter-codes for reading arguments in various ways. | |
20.2.3 interactive の使用例 | Examples of how to read interactive arguments. |
[ < ] | [ > ] | [ << ] | [上] | [ >> ] | [冒頭] | [目次] | [見出し] | [ ? ] |
interactive
の使い方本節では, Lisp関数を対話的に呼び出し可能なコマンドにするフォーム
interactive
の書き方について述べます.
このスペシャルフォームは, これを含む関数がコマンドであり, (M-xや当該関数にバインドしたキー列を入力することで) 対話的に呼び出せることを宣言する. 引数arg-descriptorは, コマンドを対話的に呼び出したときに コマンドに対する引数の計算方法を宣言する.
他の関数と同様に, コマンドはLispプログラムからも呼び出せるが, その場合, 呼び出し側が引数を渡し, arg-descriptorにはなんの効果もない.
フォームinteractive
が効果を発揮するのは,
コマンドループ(実際にはサブルーティンcall-interactively
)が
関数を呼び出すまえに関数定義を走査してこのフォームを探すからである.
関数が呼び出されると, フォームinteractive
を含めて
その本体のフォームが実行されるが, そのとき,
interactive
は引数を評価せずに単にnil
を返す.
引数arg-descriptorには3つの可能性があります.
nil
.
この場合, コマンドは引数なしで呼ばれる.
コマンドが1つ以上の引数を必要とする場合, これはただちにエラーになる.
この式が(ミニバッファを使うことを含めて)キーボード入力を読む場合には, 入力を読むまえのポイントの整数値やマークは, 入力を読んだあとでは正しくない可能性があることに留意すること. カレントバッファがサブプロセスの出力を受け取る可能性があるからである. コマンドが入力を待っているあいだにサブプロセスの出力が到着すると, ポイントやマークを再配置する可能性がある.
してはいけないことの例を示す.
(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
を使って引数を読むため,
<TAB>, <SPC>, <RET>は名前を補完する
(see section 補完).
?は補完候補のリストを表示する.
既存オブジェクトの名前を必要とする. 不正な名前は受け付けない. 現在の入力が正しくないとミニバッファから抜けるコマンドは動作しない.
ミニバッファにユーザーがなにもテキストを入力しないときに 使われるなんらかのデフォルト値. デフォルトはコード文字に依存する.
このコード文字は, 入力をまったく読まずに引数を計算する. したがって, プロンプト文字列を使わず, 読者が指定したプロンプト文字列は無視する.
コード文字はプロンプト文字列を使わないが, この文字が文字列の最後の文字でない場合には改行を続けること.
コード文字の直後にプロンプトが続く. プロンプトは文字列の終りか改行で終る.
このコード文字は, 対話指定文字列の先頭でのみ意味を持ち, プロンプトや改行を必要としない. これは1つの孤立した文字である.
以下に, interactive
に使うコード文字を説明します.
カレントバッファが読み出し専用であるとエラーを通知する. 「スペシャル」.
このコマンドを起動したキー列の最初のマウスイベントが表すウィンドウを選択する. 「スペシャル」.
関数名(つまり, fboundp
を満たすシンボル).
「既存」, 「補完」, 「プロンプト」.
既存バッファの名前. デフォルトでは, カレントバッファ(see section バッファ)の名前を使う. 「既存」, 「補完」, 「デフォルト」, 「プロンプト」.
バッファ名. バッファが既存である必要はない. デフォルトでは, カレントバッファ以外の最近使ったバッファの名前を使う. 「補完」, 「デフォルト」, 「プロンプト」.
文字. カーソルはエコー領域には移動しない. 「プロンプト」.
コマンド名(つまり, commandp
を満たすシンボル).
「既存」, 「補完」, 「プロンプト」.
整数としてのポイント位置(see section ポイント). 「入出力なし」.
ディレクトリ名.
デフォルトは, カレントバッファのカレントデフォルトディレクトリ
default-directory
(see section オペレーティングシステム環境).
「既存」, 「補完」, 「デフォルト」, 「プロンプト」.
コマンドを起動したキー列の最初やつぎのマウスイベント. より正確には, ‘e’はリストであるイベントを取得するので, 読者はリスト内のデータを調べられる. see section 入力イベント. 「入出力なし」.
1つのコマンドの対話指定で複数回‘e’を使える. コマンドを起動したキー列がn個のリストであるイベントである場合, n番目の‘e’は, n番目のそのようなイベントを与える. ‘e’では, ファンクションキーやASCII文字などのリストでないイベントは数えない.
既存ファイルの名前(see section ファイル名).
デフォルトディレクトリはdefault-directory
.
「既存」, 「補完」, 「デフォルト」, 「プロンプト」.
ファイル名. ファイルが既存である必要はない. 「補完」, 「デフォルト」, 「プロンプト」.
無関係な引数.
このコードは, 引数の値につねにnil
を与える.
「入出力なし」.
キー列(see section キーマップの用語). 現在のキーマップにおいてコマンドがみつかる(あるいは未定義コマンド)まで イベントを読み続ける. キー列引数は, 文字列かベクトルとして表現される. カーソルはエコー領域には移動しない. 「プロンプト」.
この種の入力は, describe-key
やglobal-set-key
などの
コマンドで使われる.
キー列であり, 読者がその定義を変更することを意図している. これは‘k’と同様に動作するが, キー列の最後の入力イベントに対しては, 未定義キーを定義済みのものに変換するために(必要なときに)普通使われる 変換処理を抑制する.
整数としてのマーク位置. 「入出力なし」.
カレントバッファの入力方式を用いてミニバッファで読んだ任意のテキスト. 文字列として返す (see (emacs-ja)Input Methods section ‘入力方式’ in GNU Emacs マニュアル). 「プロンプト」.
ミニバッファで読んだ数. 入力が数でないと, ユーザーに再入力を促す. もし前置引数があってもそれは使わない. 「プロンプト」.
数値前置引数. 前置引数がなければ, nで数を読む. 数を必要とする. see section 前置コマンド引数. 「プロンプト」.
数値前置引数. (この‘p’は小文字. ) 「入出力なし」.
生の前置引数. (この‘P’は大文字. ) 「入出力なし」.
2つの数値引数としてのポイントとマーク. 小さいほうが先にくる. これは, 1つではなく2つの連続した引数を指定する唯一のコード文字. 「入出力なし」.
ミニバッファで読んだ任意のテキスト. 文字列として返す(see section ミニバッファでのテキスト文字列の読み取り). C-jか<RET>で入力を終える. (これらの文字を入力に含めるにはC-qを使う. ) 「プロンプト」.
ミニバッファで読んだ名前をインターンしたシンボル. 白文字で入力を終える. (文字列に白文字を含めるにはC-qを使う. ) (丸括弧や角括弧などの)通常はシンボルを終える他の文字は, ここではシンボルを終端しない. 「プロンプト」.
ユーザーオプションと宣言された変数
(つまり, 述語user-variable-p
を満たす).
see section 高レベルの補完関数.
「既存」, 「補完」, 「プロンプト」.
入力構文で表されたLispオブジェクト. C-jか<RET>で終える. オブジェクトは評価しない. see section ミニバッファでのLispオブジェクトの読み取り. 「プロンプト」.
xのようにLispフォームを読むが, 評価しその値がコマンドの引数になる. 「プロンプト」.
コーディングシステム名(シンボル).
ユーザーの入力が空であると, 引数の値はnil
.
see section コーディングシステム.
「補完」, 「既存」, 「プロンプト」.
このコマンドに前置引数を指定した場合にのみ,
コーディングシステム名(シンボル).
前置引数がないと, ‘Z’は引数の値にnil
を与える.
「補完」, 「既存」, 「プロンプト」.
[ < ] | [ > ] | [ << ] | [上] | [ >> ] | [冒頭] | [目次] | [見出し] | [ ? ] |
interactive
の使用例ここではinteractive
の例を示します.
(defun foo1 () ; (defun foo2 (n) ; (defun foo3 (n) ; (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
を呼びます.
読者自身がこれらの関数を呼び出してもかまいません.
objectが対話的呼び出しに適していれば,
つまり, objectがコマンドであればt
を返す.
さもなければnil
を返す.
対話的呼び出しが可能なオブジェクトには,
(キーボードマクロとして扱われる)文字列やベクトル,
トップレベルでinteractive
を呼び出しているラムダ式,
そのようなラムダ式をコンパイルしたバイトコード関数オブジェクト,
対話的(autoload
の4番目の引数がnil
以外)
と宣言された自動ロードオブジェクト,
一部の基本関数が含まれる.
シンボルの関数定義がcommandp
を満たせば,
シンボルもcommandp
を満たす.
キーやキーマップはコマンドではない. それらはコマンドを探すために使われる(see section キーマップ).
commandp
の実用的な使用例については,
説明文字列の参照のdocumentation
を参照.
この関数は, 対話的呼び出し可能な関数commandを その対話指定に従って引数を読み取り呼び出す. commandが関数でなかったり, 対話的に呼び出せない(つまり, コマンドでない)場合には, エラーを通知する. キーボードマクロ(文字列やベクトル)はコマンドとみなすが, それらは関数でないため, この関数はキーボードマクロを受け付けない.
record-flagがnil
以外であると,
コマンドとその引数を無条件にリストcommand-history
に追加する.
さもなければ, 引数を読むために
コマンドがミニバッファを使った場合にのみ追加する.
see section コマンド履歴.
もし引数keysを指定すると, コマンドがそれを起動したイベントを 問い合わせたときに与えるイベント列を指定する.
この関数はcommandを実行する.
引数commandはcommandp
を満たすこと.
つまり, 対話的呼び出し可能な関数かキーボードマクロであること.
command
が文字列やベクトルであると,
execute-kbd-macro
で実行される.
関数であると, 省略可能なrecord-flagとともに関数を
call-interactively
に渡す.
シンボルは, その関数定義を使って処理する.
autoload
で定義されたシンボルは,
対話的呼び出し可能な関数と宣言されていればコマンドとみなす.
そのような定義では, 指定されたライブラリをロードしてから
シンボルの定義を再検査して処理する.
もし引数keysを指定すると, コマンドがそれを起動したイベントを 問い合わせたときに与えるイベント列を指定する.
この関数は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
を返す.
(Lispからcall-interactively
が呼び出されても,
エディタコマンドループが直接呼び出しても違いはない. )
これを含んだ関数がLispの評価(あるいはapply
やfuncall
)で
呼び出された場合は, 対話的呼び出しではない.
interactive-p
のもっとも一般的な用途は,
情報メッセージを表示するかどうか決めることです.
特別な例外として, キーボードマクロを実行中にはいつでも,
interactive-p
はnil
を返します.
これは情報メッセージを省いてマクロの実行を速くするためです.
つぎのように使います.
(defun foo () (interactive) (when (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) |
この種のことを行う別の方法は, コマンドを
対話的呼び出しではnil
以外の値になる引数print-message
を
取るようにし, その引数がnil
以外になるようなinteractive
指定を
使うことです.
つぎのようにします.
(defun foo (&optional print-message) (interactive "p") (when print-message (message "foo"))) |
‘p’で与えられる数値前置引数はけっしてnil
になりません.
[ < ] | [ > ] | [ << ] | [上] | [ >> ] | [冒頭] | [目次] | [見出し] | [ ? ] |
エディタコマンドループは, 自身や実行中のコマンドのために 状態記録を数個のLisp変数に設定します.
この変数は, コマンドループが(現在のコマンドの)まえに実行したコマンドの 名前を記録する. 通常, この値は関数定義を持つシンボルであるが, 保証はしない.
コマンドが後続のコマンドに対する前置引数を指定する場合を除いて,
コマンドからコマンドループへ戻るとthis-command
から値をコピーする.
この変数は現在の端末に対してつねにローカルであり, バッファに対してローカルにはならない. see section 複数ディスプレイ.
last-command
と同様にEmacsがこの変数に設定するが,
Lispプログラムではけっして変更しない.
この変数は, エディタコマンドループが
いま実行しているコマンドの名前を記録する.
last-command
と同様に, 通常は関数定義を持つシンボルである.
コマンドループは, コマンドを実行する直前にこの変数に設定し,
コマンドが終了すると(コマンドが後続のコマンドに対する
前置引数を指定する場合を除いて)
この値をlast-command
にコピーする.
後続のコマンドに対するフラグとして
実行中にこの変数に設定するコマンドもある.
特に, テキストをキルする関数群はthis-command
にkill-region
を
設定して, 直後に続くキルコマンドでは
キルしたテキストをまえのキルに追加するようにする.
特定のコマンドがエラーを起こした場合に
直前のコマンドとは認識されたくない場合には,
読者はそのコマンドがそれを防ぐように書く必要があります.
1つの方法は, 以下に示すように,
コマンドの始めで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)))
|
let
でthis-command
を束縛しません.
というのは, エラーがあるとlet
は古い値を復元するからです.
これこそがここでは避けたいlet
の機能です.
この関数は, 現在のコマンドに対して直前のコマンドが生成した前置引数を含めて, 現在のコマンドを起動したキー列を含んだ文字列かベクトルを返す. すべてのイベントが文字であれば, 値は文字列である. see section 入力イベント.
(this-command-keys)
;; C-u C-x C-eを使ってこの式を評価する
⇒ "^U^X^E"
|
this-command-keys
と同様だが, つねにベクトルでイベントを返すため,
文字列に入力イベントを保持する際の複雑さを扱う必要がない
(see section キーボードイベントを文字列で保持する).
この変数は, マウスメニューによるイベントを考慮せずに, キー列として読んだ最後の入力イベントを保持する.
この変数の1つの用途は,
メニューをポップアップする位置をx-popup-menu
に指示することである.
y-or-n-p
(see section Yes/Noの問い合わせ)も内部的に使っている.
この変数には, コマンドの一部としてコマンドループが
読んだ最後の入力イベントが設定される.
この変数の主な用途は, どの文字を挿入すべきかを決定するために
self-insert-command
が使うことである.
last-command-event
;; C-u C-x C-eを使ってこの式を評価する
⇒ 5
|
C-eのASCIIコードは5なので, 値は5である.
Emacs 18版との互換性のために別名last-command-char
がある.
この変数は, 最後の入力イベントを振り向けたフレームを記録する. 通常これは, イベントが生成されたときに選択されていたフレームであるが, そのフレームが入力フォーカスを別のフレームに振り向けていると, この値はイベントを振り向けた先のフレームである. see section 入力フォーカス.
[ < ] | [ > ] | [ << ] | [上] | [ >> ] | [冒頭] | [目次] | [見出し] | [ ? ] |
Emacsのコマンドループは, キーボードやマウスのユーザーの操作を表す 入力イベント(input event)列を読みます. キーボード操作に対するイベントは, 文字かシンボルです. マウスイベントはつねにリストです. 本節では, 入力イベントの表現方法やその意味を詳しく説明します.
この関数は, objectが入力イベントであるかイベント型であると
nil
以外を返す.
任意のシンボルがイベントやイベント型として使われることに注意.
eventp
は, Lispのプログラムコードがシンボルを
イベントとして使うかどうか区別できない.
そのかわりに, シンボルが, Emacsの現在のセッションにおいて入力として読まれた
イベントに使われたことがあるかどうかを区別する.
シンボルがそのように使われたことがなければ,
eventp
はnil
を返す.
20.5.1 キーボードイベント | Ordinary characters–keys with symbols on them. | |
20.5.2 ファンクションキー | Function keys–keys with names, not symbols. | |
20.5.3 マウスイベント | Overview of mouse events. | |
20.5.4 クリックイベント | Pushing and releasing a mouse button. | |
20.5.5 ドラッグイベント | Moving the mouse before releasing the button. | |
20.5.6 ボタン押し下げイベント | A button was pushed and not yet released. | |
20.5.7 繰り返しイベント | Double and triple click (or drag, or down). | |
20.5.8 モーションイベント | Just moving the mouse, not pushing a button. | |
20.5.9 フォーカスイベント | Moving the mouse between frames. | |
20.5.10 ウィンドウシステムのその他のイベント | Other events window systems can generate. | |
20.5.11 イベントの例 | Examples of the lists for mouse events. | |
20.5.12 イベントの分類 | Finding the modifier keys in an event symbol. Event types. | |
20.5.13 イベントの参照 | Functions to extract info from events. | |
20.5.14 キーボードイベントを文字列で保持する | Special considerations for putting keyboard character events in a string. |
[ < ] | [ > ] | [ << ] | [上] | [ >> ] | [冒頭] | [目次] | [見出し] | [ ? ] |
キーボードからは2種類の入力があります. 普通のキーとファンクションキーです. 普通のキーは文字に対応します. それらが生成するイベントは, Lispでは文字として表現されます. 文字イベントのイベント型は文字自身(整数)です. イベントの分類を参照してください.
入力文字イベントは, 0から524287までの基本コード(basic code)と 以下の修飾ビット(modifier bit)の任意の組み合わせです.
文字コードのビット は, メタキーを押し下げながら文字を打ったことを表す.
文字コードのビット は非ASCII文字のコントロール文字を表す.
C-aなどのASCIIコントロール文字には 独自の特別な基本コードがあるため, Emacsはそれを表すための特別なビットを必要としない. つまり, C-aのコードは単に1である.
しかし, コントロールキーを使った%などの ASCIIにないコントロールとの組み合わせを打った場合, 得られる数値は%のコードに を加えたものである (端末で非ASCIIのコントロール文字を扱えるとして).
文字コードのビット は, シフトキーを押し下げながら ASCIIコントロール文字を打ったことを表す.
英文字では, 基本コードそのものが大文字か小文字かを表す. 数字文字と区切り文字では, シフトキーは異なる基本コードのまったく異なる文字を選ぶ. 可能な限りASCII文字集合ですませるために, これらの文字に対しては, Emacsはビット を使わない.
しかし, ASCIIではC-AとC-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 イベントの分類).
[ < ] | [ > ] | [ << ] | [上] | [ >> ] | [冒頭] | [目次] | [見出し] | [ ? ] |
ほとんどのキーボードには, ファンクションキー(function key),
つまり, 文字ではない名前や記号のキーがあります.
Emacs Lispでは, ファンクションキーはシンボルで表現されます.
シンボルの(小文字の)名前がファンクションキーのラベルです.
たとえば, <F1>というラベルのキーを押すと,
入力ストリームにはシンボルf1
が置かれます.
ファンクションキーイベントのイベント型は, イベントシンボルそれ自身です. See section イベントの分類.
ファンクションキーに対するシンボル命名慣習の特例を以下に示します.
backspace
, tab
, newline
, return
, delete
これらのキーは, ほとんどのキーボードにある特別なキーを持つ 一般的なASCIIコントロール文字に対応する.
ASCIIでは, C-iと<TAB>は同じ文字である.
これらを区別できる端末では, 前者を整数9, 後者をシンボルtab
と
表現することで, EmacsはLispプログラムに区別を伝える.
ほとんどの場面では, これら2つを区別しても有用ではない.
そのため, 通常, function-key-map
(see section 入力イベントの変換)は,
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
キーパッドの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>の修飾キーを使えます. それらを表現するには, シンボル名に接頭辞を付けます.
アルト修飾.
コントロール修飾.
ハイパー修飾.
メタ修飾.
シフト修飾.
スーパー修飾.
したがって, <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
, …の1つである.
ファンクションキーの場合と同様に, アルト, コントロール, ハイパー, メタ, シフト, スーパーの 修飾キーを表す接頭辞‘A-’, ‘C-’, ‘H-’, ‘M-’, ‘S-’, ‘s-’も使える.
このシンボルはイベントのイベント型としての役割も果たす.
キーバインディングはイベント型でイベントを指定する.
したがって, mouse-1
に対するキーバインディングは,
イベント型event-typeがmouse-1
であるすべてのイベントに適用される.
クリックを行ったウィンドウ.
ウィンドウwindowの左上端を(0 . 0)
とした
クリック位置のピクセル単位の座標.
クリックした文字のバッファ内位置.
イベントが発生したときのミリ秒単位の時刻. (この値は, Emacs Lispの整数の範囲では約5時間で一周するので, 時間的に近傍のイベントを関連付ける場合にのみ有用である. )
同じマウスボタンを素早く押し下げた繰り返し回数. see section 繰り返しイベント.
モード行やスクロールバーなどのスクリーンの特別な部分で発生したイベントでは, 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は意味のあるデータではありません.
1つの特別な場面では, buffer-posは単一のシンボルではなく(上に述べた1つの)シンボルを 含んだリストになります. イベントに対する仮想的なプレフィックスキーを入力ストリームに挿入すると このようになります. See section キー列の入力.
[ < ] | [ > ] | [ << ] | [上] | [ >> ] | [冒頭] | [目次] | [見出し] | [ ? ] |
Emacsには, ドラッグイベントがあります. ユーザーがマウスボタンを押し下げてから, ボタンを離すまえに別の文字位置へマウスを動かすと ドラッグ(drag)イベントが発生します. マウスのすべてのイベントのように, Lispではドラッグイベントは リストとして表現されます. つぎのように, リストは開始マウス位置と終了位置を記録しています.
(event-type (window1 buffer-pos1 (x1 . y1) timestamp1) (window2 buffer-pos2 (x2 . y2) timestamp2) click-count) |
ドラッグイベントでは, シンボルevent-typeの名前には
接頭辞‘drag-’が付きます.
たとえば, ボタン2を押し下げてマウスをドラッグすると
イベントdrag-mouse-2
が生成されます.
イベントの2番目と3番目の要素は, ドラッグの開始位置と終了位置を与えます.
なお, データにはクリックイベントと同じ意味があります(see section クリックイベント).
ドラッグイベントかどうかを区別せずに,
マウスの任意のイベントの2番目の要素は同じ方法で参照できます.
接頭辞‘drag-’は, ‘C-’や‘M-’のような修飾キー接頭辞に続きます.
read-key-sequence
が,
キーバインディングを持たないドラッグイベントを受け取り, かつ,
それに対応するクリックイベントにはバインディングがある場合,
ドラッグイベントの開始位置をクリック位置とするクリックイベントに変換します.
つまり, 望まなければ, 読者はクリックイベントとドラッグイベントを区別する
必要がありません.
[ < ] | [ > ] | [ << ] | [上] | [ >> ] | [冒頭] | [目次] | [見出し] | [ ? ] |
クリックイベントとドラッグイベントは, ユーザーがマウスボタンを離したときに発生します. ボタンを離すまではクリックとドラッグを区別する方法がないため, ボタンを離すまで発生しえません.
ボタンを押し下げたらただちに動作を始めたい場合には, 読者はボタン押し下げ(button-down)イベントを処理する必要があります. (8) ボタンを押し下げるとただちに発生します. それらは, シンボルevent-typeの名前に 接頭辞‘down-’があることを除けば, クリックイベント(see section クリックイベント)とまったく同じリストで表現されます. 接頭辞‘down-’は, ‘C-’や‘M-’のような修飾キー接頭辞に続きます.
関数read-key-sequence
は,
コマンドバインディングを持たないボタン押し下げイベントを無視します.
したがって, Emacsのコマンドループもそれらを無視します.
つまり, 読者がボタン押し下げイベントでなにかをしたいのでなければ,
読者はボタン押し下げイベントを定義する必要はありません.
ボタン押し下げイベントを定義する理由は,
ボタンが離されるまで(モーションイベントを読んで)マウスの動きを
追跡するためです.
See section モーションイベント.
[ < ] | [ > ] | [ << ] | [上] | [ >> ] | [冒頭] | [目次] | [見出し] | [ ? ] |
マウスを動かさずに同一のマウスボタンを素早く連続して押し下げると, Emacsは2回目以降の押し下げに対して 特別な繰り返し(repeat)マウスイベントを生成します.
もっとも一般的な繰り返しイベントはダブルクリック(double-click) イベントです. ボタンを2回クリックすると, Emcasはダブルクリックイベントを生成します. (他のすべてのクリックイベントのように)読者がボタンを離したときに イベントが生成されます.
ダブルクリックイベントのイベント型には, 接頭辞‘double-’が含まれます.
したがって, <meta>を押し下げて2番目のボタンをダブルクリックすると,
LispプログラムにはM-double-mouse-2
が送られます.
ダブルクリックイベントにバインディングがなければ,
対応する普通のクリックイベントを用いて実行します.
したがって, 実際に利用したくない限りは,
読者はダブルクリック機能に注意する必要はありません.
ユーザーがダブルクリックすると, Emacsはまず普通のクリックイベントを生成し, つぎにダブルクリックイベントを生成します. したがって, ダブルクリックイベントのコマンドバインディングでは, すでに普通のクリックコマンドが動作済みであると仮定して設計する必要があります. 普通のクリックの結果をもとに望みのダブルクリックの結果を得るようにします.
普通のクリックの意味にダブルクリックの意味を 『追加』するようにすると便利です. ダブルクリックのユーザーインターフェイスはこのようにすることを勧めます.
ボタンをクリックして, ふたたびボタンを押し下げてそのままマウスを動かすと, 最終的にボタンを離した時点で, ダブルドラッグ(double-drag)イベントが 生成されます. そのイベント型には‘drag’のかわりに‘double-drag’が含まれます. ダブルドラッグイベントにバインディングがなければ, Emacsは普通のドラッグイベントとしてバインディングを探します.
ダブルクリックイベントやダブルドラッグイベントを生成するまえに, ユーザーがボタンを2回目に押し下げたとき, Emacsはダブルダウン(double-down)イベントを生成します. このイベント型には‘down’のかわりに‘double-down’が含まれます. ダブルダウンイベントにバインディングがなければ, Emacsは普通のボタン押し下げイベントとしてバインディングを探します. どちらでもバインディングがみつからなければ, ダブルダウンイベントは無視します.
まとめると, ボタンをクリックしてただちに再度ボタンを押し下げると, Emacsは, はじめのクリックに対してボタン押し下げイベントと クリックイベントを生成し, 再度ボタンを押し下げるとダブルダウンイベントを生成し, 最後にダブルクリックイベントかダブルドラッグイベントを生成します.
ボタンを2回クリックしてから再度押し下げる操作を素早く行うと, Emacsは, トリプルダウン(triple-down)イベントに続けて トリプルクリック(triple-click)イベントか トリプルドラッグ(triple-drag)イベントを生成します. これらのイベント型には‘double’のかわりに‘triple’が含まれます. トリプルのイベントにバインディングがなければ, Emacsは対応するダブルのイベントを使います.
ボタンを3回以上クリックしてから再度押し下げると, 3回目以降の押し下げに対するイベントはすべてトリプルのイベントです. Emacsは, クアドラプル(4回), クインタプル(5回), …などの イベントは生成しません. しかし, イベントリストを調べれば, ボタンを何回押したか正確にわかります.
この関数は, イベントeventにおいてボタンが連続して押された回数を返す. eventが, ダブルダウンイベント, ダブルクリックイベント, ダブルドラッグイベントであると, 値は2である. eventがトリプルのイベントであると, 値は3かそれ以上である. eventが(繰り返しイベントではない)普通のマウスイベントであると, 値は1である.
繰り返しイベントが生成されるためには,
同じスクリーン位置において連続してマウスボタンを押し下げ, しかも,
各押し下げの間隔は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はマウスの移動のみに対するイベントを生成しないので,
それらのイベントは現れません.
See section マウスの追跡.
[ < ] | [ > ] | [ << ] | [上] | [ >> ] | [冒頭] | [目次] | [見出し] | [ ? ] |
ウィンドウシステムは, どのウィンドウにキーボード入力を与えるかを ユーザーが制御するための一般的な方法を提供します. ウィンドウを選ぶことをフォーカス(focus)と呼びます. ユーザーがEmacsのフレームを切り替える操作を行うと, フォーカスイベント(focus event)が生成されます. グローバルキーマップにあるフォーカスイベントの普通の定義は, Emcasの新たなフレームを選択するようになっていて, これはユーザーが期待することです. See section 入力フォーカス.
Lispでは, フォーカスイベントはつぎのようなリストで表現されます.
(switch-frame new-frame) |
ここで, new-frameは切り替え先のフレームです.
Xのほとんどのウィンドウマネージャは, マウスをウィンドウへ入れるだけで当該ウィンドウにフォーカスが設定される ようになっています. フレームにマウスが入るとカーソルの形状を変更するので, Emacsでもそのようにします. しかし, Lispプログラムにとっては, なんらかの入力が到着するまではフォーカスの変更について知る必要がありません. そのため, ユーザーが実際にキーボードのキーを打つか 新たなフレームでマウスボタンを押し下げたときだけ, Emacsはフォーカスイベントを生成します. フレーム間でマウスを動かしただけでは, フォーカスイベントは生成されません.
キー列の途中にフォーカスイベントが現れると, キー列を乱します. そのため, Emacsはキー列の途中にはフォーカスイベントを生成しません. ユーザーがキー列の途中で, つまり, プレフィックスキーのあとでフォーカスを変更すると, 複数イベントのキー列のまえかうしろにフォーカスイベントを移動し, 途中には現れないようにEmacsはイベントの順序を並び替えます.
[ < ] | [ > ] | [ << ] | [上] | [ >> ] | [冒頭] | [目次] | [見出し] | [ ? ] |
ウィンドウシステム内で起きたことを表す他のイベントもあります.
(delete-frame (frame))
この種のイベントは, Emacsのフレームであるウィンドウを削除するコマンドを ユーザーがウィンドウマネージャに与えたことを表す.
イベントdelete-frame
の標準定義はフレームframeの削除である.
(iconify-frame (frame))
この種のイベントは,
ウィンドウマネージャを用いてユーザーがフレームframeを
アイコン化したことを表す.
これに対する標準定義はignore
である.
というのは, フレームはすでにアイコンになっているので,
Emacsが行うことはなにもないからである.
このイベント型の目的は,
必要ならばその種のイベントを読者が追跡できるようにしておくことである.
(make-frame-visible (frame))
この種のイベントは,
ウィンドウマネージャを用いてユーザーがアイコン化したフレームframeを
開いたことを表す.
これに対する標準定義はignore
である.
というのは, フレームはすでに見えるようになっているので,
Emacsが行うことはなにもないからである.
(mouse-wheel position delta)
この種のイベントは, (MSインテリマウスなどの)マウスのホイールを動かすと生成される. その典型的な効果はスクロールやズーミングである.
要素deltaはホイールの回転方向と回転量である. その絶対値はホイールを回すごとに増加する数である. 負のdeltaは, 逆転, つまり, ユーザーへ近付く方向への回転を表し, 正のdeltaは, 順転, つまり, ユーザーから遠ざかる方向への回転を表す.
要素positionはイベントの発生位置を表し, マウスクリックイベントで使われる形式と同じである.
この種のイベントは, ある種のシステムでのみ生成される.
(drag-n-drop position files)
この種のイベントは, Emacsの外側のアプリケーションで一群のファイルを選択し, それらをEmacsのフレームにドラッグ&ドロップしたときに生成される.
要素positionはイベントの発生位置を表し, マウスクリックイベントで使われる形式と同じであり, 要素filesはドラッグ&ドロップされたファイル名のリストである. このイベントを扱う通常の処理は, それらのファイルを訪問することである.
現状では, この種のイベントは, ある種のシステムでのみ生成される.
これらのイベントがキー列の途中, つまり, プレフィックスキーのうしろに現れると, 複数イベントのキー列のまえかうしろに当該イベントを移動し, 途中には現れないようにEmacsはイベントの順序を並び替えます.
[ < ] | [ > ] | [ << ] | [上] | [ >> ] | [冒頭] | [目次] | [見出し] | [ ? ] |
ユーザーが同じ場所でマウスの左ボタンを押し下げてから離すと, つぎのようなイベント列が生成されます.
(down-mouse-1 (#<window 18 on NEWS> 2613 (0 . 38) -864320)) (mouse-1 (#<window 18 on NEWS> 2613 (0 . 38) -864180)) |
コントロールキーを押し下げた状態で, ユーザーがマウスの2番目のボタンを押し下げ, マウスをつぎの行へドラッグすると, つぎのような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番目のボタンをウィンドウのモード行で押し下げ, マウスを別のウィンドウへドラッグすると, つぎのような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
は,
そのような情報を便利に与えるためのものです.
この関数は, eventにある修飾子のリストを返す.
修飾子はシンボルであり, shift
, control
,
meta
, alt
, hyper
, super
である.
さらに, マウスイベントシンボルの修飾子リストには,
必ず, click
, drag
, down
の1つが含まれる.
引数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
が明示的に含まれるが,
イベントシンボルの名前自体には‘click’は含まれない.
この関数は, 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 |
この関数は, objectがマウス移動のイベントならばnil
以外を返す.
この関数は, 修飾子名と基本イベント型のリストを それらが示すイベント型に変換する. たとえばつぎのとおり.
(event-convert-list '(control ?a)) ⇒ 1 (event-convert-list '(control meta ?a)) ⇒ -134217727 (event-convert-list '(control super f1)) ⇒ C-s-f1 |
[ < ] | [ > ] | [ << ] | [上] | [ >> ] | [冒頭] | [目次] | [見出し] | [ ? ] |
本節では, マウスボタンイベントやモーションイベント内のデータを 参照するための便利な関数について述べます.
つぎの2つの関数は, 以下の形式のリストであるマウスボタンイベントの 開始位置や終了位置を返します.
(window buffer-position (x . y) timestamp) |
イベントeventの開始位置を返す.
eventがクリックイベントやボタン押し下げイベントであると, イベントの位置を返す. eventがドラッグイベントであると, ドラッグの開始位置を返す.
イベントeventの終了位置を返す.
eventがドラッグイベントであると, ユーザーがマウスボタンを離したときの位置を返す. eventがクリックイベントかボタン押し下げイベントであると, 実際の値は開始位置であり, その種のイベントにある唯一の位置情報である.
つぎの5つの関数は, 上に述べた位置情報のリストを引数として, そのさまざまな部分を返す.
position内のウィンドウを返す.
positionのバッファ内位置を返す. これは整数である.
position内のピクセル単位のxy座標を
コンスセル(x . y)
として返す.
positionの(文字単位の)行(row)とコラム(col)の座標を
コンスセル(col . row)
として返す.
これらは実際にはposition内のxとyの値から計算される.
position内の時刻情報を返す.
つぎの関数はスクロールバーでのイベントを解読するのに便利です.
スクロールバー内でのイベントから, スクロールバーに対する縦方向の位置を返す.
その値は2つの整数を含むコンスセル(portion . whole)
であり,
その比は位置の割合を表す.
この関数は(実質的には)ratioにtotalを掛け,
結果を整数に丸める.
引数ratioは数ではなく(num . denom)
であり,
典型的にはscroll-bar-event-ratio
が返す値である.
この関数はスクロールバー内での位置を バッファ内での位置へ換算するのに便利である. つぎのように行う.
(+ (point-min) (scroll-bar-scale (posn-x-y (event-start event)) (- (point-max) (point-min)))) |
スクロールバー内でのイベントには, xy座標のかわりに比を表す2つの整数があることに注意.
[ < ] | [ > ] | [ << ] | [上] | [ >> ] | [冒頭] | [目次] | [見出し] | [ ? ] |
文字列が使われるほとんどの場面では, 文字列にはテキスト文字, つまり, バッファやファイルにある文字と同じ種類のものが入っていると考えています. 文字列にはキーボード文字が入っているとみなして使うLispプログラムもあります. たとえば, 文字列には, キー列やキーボードマクロの定義が入っているのです. しかし, キーボード文字を文字列に保持するのは複雑であり, それは歴史的な互換性を保つためにするのであり, また, つねに可能とは限りません.
新しいプログラムでは, キーボードイベントを文字列に保持しないで, このような複雑さを避けるように推奨します. つぎのようにします.
lookup-key
やdefine-key
に対する
引数以外にも使うつもりならば, 文字列のかわりにベクトルを使う.
たとえば, read-key-sequence
のかわりにread-key-sequence-vector
を
this-command-keys
のかわりにthis-command-keys-vector
を使う.
define-key
に直接渡す場合であっても, ベクトルで書く.
listify-key-sequence
(see section その他のイベント入力機能)を使って,
それをリストに変換しておく.
複雑さの原因は, キーボード入力に含まれる修飾ビットにあります. メタ修飾子以外の修飾ビットを文字列に入れることは不可能であり, メタ修飾子は特別な場合として唯一許されているのです.
初期のGNU Emacsでは, メタ文字を128から255の範囲のコードで表現していました.
その当時, 基本文字コードは0から127でしたから,
キーボード文字のすべてのコードは文字列に収まったのです.
多くのLispプログラムでメタ文字を表すために文字列定数内で‘\M-’を使い,
特に, define-key
や類似の関数に対する引数に使われ,
キー列やイベント列はつねに文字列で表現されていました.
127を超える大きな基本文字コードと追加の修飾ビットを扱えるようにしたとき, メタ文字の表現方法を変更せざるをえませんでした. 現在, メタ修飾子を表す文字内のビットは であり, そのような数を文字列に入れることはできません.
文字列定数で‘\M-’を使っているプログラムを扱えるように, 文字列にメタ文字を入れるための特別な規則があります. 以下は, 文字列を入力文字の列として解釈するための規則です.
キーボード入力文字の文字列を作るread-key-sequence
などの関数は
つぎの規則に従います.
つまり, 文字列に収まらないイベントであるときには,
文字列のかわりにベクトルを作ります.
読者が文字列で‘\M-’の入力構文を使うと, それらは128から255の範囲のコードになります. 対応するキーボードイベントを文字列に保存するように変更したときに得られる コードと同じです. したがって, 文字列内のメタイベントは, それらがどのように文字列に 収められたかに関わらず, 整合性のある動作をします.
しかし, 本節のはじめに述べた推奨方法に従ってこれらのことがらを避けるほうが, ほとんどのプログラムはよりよく動作するでしょう.
[ < ] | [ > ] | [ << ] | [上] | [ >> ] | [冒頭] | [目次] | [見出し] | [ ? ] |
エディタコマンドループは,
関数read-key-sequence
を使ってキー列を読み取ります.
なお, 関数read-key-sequence
は関数read-event
を使います.
これらやイベント入力を扱う他の関数は, Lispプログラムからも使えます.
一時的な表示のmomentary-string-display
,
および, 時間待ちと入力待ちのsit-for
を参照してください.
端末の入力モードの制御や端末入力のデバッグに関する関数や変数については,
See section 端末入力.
入力イベントを読むときにそれらを変換したり修正する機能については,
See section 入力イベントの変換.
上位レベルの入力機能については, ミニバッファを参照してください.
20.6.1 キー列の入力 | How to read one key sequence. | |
20.6.2 単一イベントの読み取り | How to read just one event. | |
20.6.3 クォートした文字の入力 | Asking the user to specify a character. | |
20.6.4 その他のイベント入力機能 | How to reread or throw away input events. |
[ < ] | [ > ] | [ << ] | [上] | [ >> ] | [冒頭] | [目次] | [見出し] | [ ? ] |
コマンドループは, read-key-sequence
を呼ぶことで
キー列の入力を読み取ります.
Lispプログラムからこの関数を呼び出してもよく,
たとえば, describe-key
は,
説明対象とするキーを読むためにこの関数を使います.
この関数は, キー列を読み取り文字列かベクトルとして返す. 完全なキー列を収集し終えるまで, つまり, 現在活性なキーマップにおいて, 非プレフィックスコマンドを 指定するのに十分になるまで, イベントを読み続ける.
イベントがすべて文字であり, かつ, それらが文字列に収まるならば,
read-key-sequence
は文字列(see section キーボードイベントを文字列で保持する)を返す.
さもなければ, ベクトルを返す.
ベクトルならば, 任意の種類のイベント, つまり,
文字, シンボル, リストを保持できるからである.
文字列やベクトルの要素は, キー列のイベントである.
引数promptは, プロンプトとしてエコー領域に表示する文字列であるか,
あるいは, プロンプトを表示しないことを意味するnil
である.
以下の例では, プロンプト‘?’がエコー領域に表示され, ユーザーはC-x C-fと打つ.
(read-key-sequence "?") ---------- Echo Area ---------- ?C-x C-f ---------- Echo Area ---------- ⇒ "^X^F" |
関数read-key-sequence
は中断を抑止する.
この関数が動作中にC-gを打っても, 他の文字と同様に扱い,
quit-flag
を設定しない.
see section 中断.
これはread-key-sequence
と同様であるが,
つねにベクトルとしてキー列を返し, 文字列としてはけっして返さない.
see section キーボードイベントを文字列で保持する.
入力文字が大文字であって, それらにキーバインディングがないとき,
対応する小文字にキーバインディングがあれば,
read-key-sequence
は文字を小文字に変換します.
lookup-key
はこのような変換を行わないことに注意してください.
関数read-key-sequence
は, ある種のマウスイベントも変換します.
バインディングのないドラッグイベントをクリックイベントに変換したり,
バインディングのないボタン押し下げイベントを完全に無視します.
さらに, フォーカスイベントとその他のウィンドウイベントを並び替えて,
それらが他のイベントのキー列の途中に現れないようにします.
マウスイベントが, モード行やスクロールバーなどのウィンドウの特別な部分で
生起しても, 特別なイベント型はなく, マウスボタンや修飾キーの
組み合わせを普通どおりに表したシンボルです.
ウィンドウのどの部分かに関する情報は,
イベント内の別の部分, つまり, 座標に入っています.
しかし, read-key-sequence
は, その情報を
シンボルmode-line
, vertical-line
, horizontal-scroll-bar
,
vertical-scroll-bar
を用いた仮想的な『プレフィックスキー』に変換します.
ウィンドウの特別な部分におけるマウスクリックの意味は,
これらの仮想的なプレフィックスキーを用いてキー列を定義することで
定義できます.
たとえば, read-key-sequence
を呼び出してから,
ウィンドウのモード行でクリックすると,
つぎのような2つのイベントを得ます.
(read-key-sequence "Click on the mode line: ") ⇒ [mode-line (mouse-1 (#<window 6 on NEWS> mode-line (40 . 63) 5959987))] |
この変数の値は, 現在のEmacsセッションにおいて, これまでに処理されたキー列の個数である. これには, 端末から読み取ったキー列, および, 実行したキーボードマクロから読み取ったキー列が含まれる.
この変数は, 端末からこれまでに受け取った入力イベントの総個数を保持する. キーボードマクロで生成されたものは含まない.
[ < ] | [ > ] | [ << ] | [上] | [ >> ] | [冒頭] | [目次] | [見出し] | [ ? ] |
コマンド入力用の最低レベルの関数は, 単一イベントを読み取る関数です.
この関数は, 必要ならばイベントの到着を待って, コマンド入力のつぎのイベントを読み取って返す. イベントは, ユーザーか(実行中の)キーボードマクロから直接得る.
promptがnil
以外であると,
これはプロンプトとしてエコー領域に表示される文字列であること.
さもなければ, read-event
は
入力待ちであることを示すメッセージを表示せずに,
そのかわりに, 現在のコマンドを実行するに至ったイベントや
現在のコマンドが読み取ったイベントをプロンプトとして表示する.
see section エコー領域.
suppress-input-methodがnil
以外であると,
このイベントの読み取りに関しては現在の入力方式を使わない.
入力方式の処理をせずにイベントを読みたいときには,
つねにこのようにすること.
input-method-function
を束縛してはならない(下記参照).
変数cursor-in-echo-area
がnil
以外であると,
read-event
は, エコー領域に表示されたメッセージの末尾に
カーソルを一時的に移動する.
さもなければ, read-event
はカーソルを移動しない.
read-event
がヘルプ文字と定義されたイベントを受け取ると,
それを返さずにread-event
がイベントを直接処理してしまう場合がある.
see section ヘルプ機能.
特殊イベント(special event)と呼ばれる他のイベントも
read-event
が直接処理する(see section 特殊イベント).
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-event
は, あれば現在の入力方式も起動します.
input-method-function
がnil
以外であれば,
それは関数であるはずです.
read-event
が修飾ビットのない(<SPC>を含む)印字文字を読み取ると,
引数としてイベントを渡してその関数を呼び出します.
これがnil
以外であると, その値は現在の入力方式関数を指定する.
注意:
この変数をlet
で束縛しないこと.
この変数はしばしばバッファローカルであり,
入力を読む周囲で束縛すると(読者がこれをもっとも束縛しそうなところ),
Emacsが入力を待っているときにバッファが非同期に切り替わると,
誤ったバッファに値を復元してしまうことがある.
入力方式関数は, 入力として使われるイベントのリストを返すべきです.
(リストがnil
であると入力がなかったことを意味し,
read-event
は別のイベントを待つ. )
これらのイベントは,
unread-command-events
内のイベントよりまえに処理されます.
入力方式関数が返したイベントは, それらが修飾ビットがない印字文字であっても,
入力方式関数に再度渡されることはありません.
入力方式関数がread-event
やread-key-sequence
を呼び出すときには,
input-method-function
をnil
に束縛して
再帰呼び出しを防ぐべきです.
キー列の2番目以降のイベントを読むときには, 入力方式関数を呼び出しません.
したがって, それらの文字は, 入力方式処理の対象ではありません.
入力方式の処理では,
overriding-local-map
とoverriding-terminal-local-map
の値を
検査するのがよいです.
これらの変数のいずれかがnil
以外であるときには,
入力方式ではその引数をリストに入れ,
それ以上処理せずにそのリストを返すべきです.
[ < ] | [ > ] | [ << ] | [上] | [ >> ] | [冒頭] | [目次] | [見出し] | [ ? ] |
ユーザーに文字入力を促して, コントロール文字やメタ文字を
文字そのものや文字の8進数コードで手軽に入力できるようにするには,
関数read-quoted-char
を使います.
コマンドquoted-insert
は, この関数を使っています.
この関数はread-char
に似ているが,
最初に読んだ文字が8進数字文字(0-7)であると,
任意個数の8進数字文字を読み取り(8進数字文字以外が現れると止める),
その数値の文字コードが表す文字を返す.
最初の文字を読むと中断を抑制するので, ユーザーはC-gを入力できる. see section 中断.
promptを与えると, それはユーザーへのプロンプトを表す文字列を指定する. プロンプト文字列はつねにエコー領域に表示され, あとに‘-’が続く.
つぎの例では, ユーザーは8進数177(10進数では127)を打つ.
(read-quoted-char "What character") ---------- Echo Area ---------- What character-177 ---------- Echo Area ---------- ⇒ 127 |
[ < ] | [ > ] | [ << ] | [上] | [ >> ] | [冒頭] | [目次] | [見出し] | [ ? ] |
本節では, イベントを処理せずに『まえもって覗き見』する方法,
処理待ちの入力の有無の検査方法, 処理待ちの入力の破棄方法について述べます.
関数read-passwd
も参照してください(see section パスワードの読み取り).
この変数は, コマンド入力として読まれることを 待っているイベントのリストを保持する. イベントはリストに現れる順に使われ, 使われると1つ1つ取り除かれる.
関数でイベントを読んだあとにそれを使わない場面があるため, この変数が必要になる. この変数にイベントを保存すると, コマンドループやコマンド入力を読む関数によって通常どおり処理される.
たとえば, 数値前置引数を実現する関数は, 任意個数の数字文字を読み取る. 数字文字でないイベントをみつけたら, そのイベントを読み戻して, コマンドループが通常どおりに読めるようにする必要がある. 同様に, インクリメンタルサーチでは, この機能を使って 探索においては意味を持たないイベントを読み戻す. なぜなら, そのようなイベントは探索を終了させ, 通常どおり実行される必要があるからである.
unread-command-events
に入れられるように
キー列からイベントを確実に簡単に取り出す方法は
listify-key-sequence
を使うことである(see section キーボードイベントを文字列で保持する).
もっとも最近に読み戻したイベントが最初に再度読まれるように, 普通はこのリストの先頭にイベントを追加する.
この関数は, 文字列やベクトルであるkeyを個々のイベントのリストに変換する.
この結果はunread-command-events
に入れられる.
この変数は, コマンド入力として読まれる文字を保持する. 値「-1」は, 『空』を意味する.
この変数はほとんど廃れており,
かわりにunread-command-events
を使うべきである.
Emacs 18版以前向けに書かれたプログラムを扱うためだけに存在する.
この関数は, 現在, コマンド入力があるかどうかを調べる.
ただちに返るが, 入力があれば値t
を,
さもなければnil
を返す.
入力がないのにt
を返すことが稀にある.
この変数は, コマンドの一部として, あるいは, Lispプログラムが明示的に 読み取った最後の端末入力イベントを記録する.
以下の例で, Lispプログラムは文字1(ASCIIコード49)を読む.
それがlast-input-event
の値になるが,
(この式を評価するコマンドはC-x C-eと仮定するので)
last-command-event
の値はC-eのままである.
(progn (print (read-char)) (print last-command-event) last-input-event) -| 49 -| 5 ⇒ 49 |
Emacs 18版との互換性のために, 別名last-input-char
が存在する.
この関数は端末入力バッファの内容を廃棄し,
定義中のキーボードマクロを取り消す.
これはnil
を返す.
以下の例で, フォームを評価しはじめてから, ユーザーは何文字か打つ.
sleep-for
が待機を終えると,
discard-input
は待機中に打たれた文字をすべて破棄する.
(progn (sleep-for 2) (discard-input)) ⇒ nil |
[ < ] | [ > ] | [ << ] | [上] | [ >> ] | [冒頭] | [目次] | [見出し] | [ ? ] |
特殊イベントは, 読まれるとただちに非常に低レベルで処理されます.
関数read-event
はこれらのイベントをそれ自身で処理してしまい,
それらを返すことはありません.
このように処理されるイベントは表示されることはなく,
キー列に組み込まれることもなく,
last-command-event
や(this-command-keys)
の値に
現れることもありません.
特殊イベントが数値引数を破棄することはなく,
unread-command-events
で読み戻すことはできません.
特殊イベントがキーボードマクロに現れることはなく,
読者がキーボードマクロを定義しているときに,
特殊イベントがキーボードマクロに記録されることはありません.
しかし, それらのイベントは,
読まれた直後にはlast-input-event
に現れますから,
これからイベントの定義で実際のイベントを見ることができます.
iconify-frame
, make-frame-visible
, delete-frame
の
イベント型は, 通常このように処理されます.
特殊イベントをどのように処理するか,
どのイベントが特殊イベントであるかを定義する
キーマップは変数special-event-map
にあります(see section 活性なキーマップ).
[ < ] | [ > ] | [ << ] | [上] | [ >> ] | [冒頭] | [目次] | [見出し] | [ ? ] |
待機関数は, 指定時間経過するか入力がくるまで待つように設計してあります.
たとえば, ユーザーに表示を眺める時間を与えるために
計算途中で休止したいでしょう.
sit-for
は, 休止してスクリーンを更新し,
入力がくるとただちに戻ります.
一方, sleep-for
はスクリーンを更新せずに休止します.
この関数は(処理待ちのユーザーからの入力がなければ)再表示を行い,
seconds秒休止するか, 入力がくるまで待つ.
入力がこずに(その他のイベント入力機能のinput-pending-p
を参照)
指定時間だけ休止した場合は, 戻り値はt
である.
さもなければ, 戻り値はnil
である.
引数secondsは整数である必要はない.
それが浮動小数点数であると, sit-for
は秒の小数も待つ.
秒単位しか扱えないシステムもあり,
そのようなシステムではsecondsを秒に切り下げる.
省略可能な引数millisecは, ミリ秒単位の追加待ち時間を指定する. これはsecondsで指定した時間に加えられる. 秒未満を扱えないシステムでは, millisecに0以外を指定するとエラーになる.
入力がくると再表示をつねに取り止め,
再表示開始まえに入力がくると, いっさい再表示しない.
したがって, 処理待ちの入力があると, 再表示を強制する方法はない.
しかし, 処理待ちの入力がなければ, (sit-for 0)
で再表示を強制できる.
nodispがnil
以外であると,
sit-for
は再表示はしないが,
入力がくるとただちに(あるいは指定時間だけ経過すると)戻る.
フレームをアイコンにしたりアイコンにしたフレームを開くと
イベントが生成されるため, sit-for
は戻る.
see section ウィンドウシステムのその他のイベント.
sit-for
の普通の目的は,
読者が表示したテキストを読む時間をユーザーに与えることである.
この関数は表示を更新せずに単にseconds秒だけ休止する.
入力にはいっさい注意を払わない.
nil
を返す.
引数secondsは整数である必要はない.
それが浮動小数点数であると, sleep-for
は秒の小数も待つ.
秒単位しか扱えないシステムもあり,
そのようなシステムではsecondsを秒に切り下げる.
省略可能な引数millisecは, ミリ秒単位の追加待ち時間を指定する. これはsecondsで指定した時間に加えられる. 秒未満を扱えないシステムでは, millisecに0以外を指定するとエラーになる.
遅延を保証したい場合にsleep-for
を使う.
現在時刻を取得する関数についてはSee section 時刻.
[ < ] | [ > ] | [ << ] | [上] | [ >> ] | [冒頭] | [目次] | [見出し] | [ ? ] |
Lisp関数が動作中にC-gを打つと, Emacsがなにを行っていても中断を引き起こします. つまり, もっとも内側の活性なコマンドループに制御が戻ります.
コマンドループがキーボード入力を待っているときにC-gを打っても,
中断を引き起こさずに, 普通の入力文字として動作します.
もっとも単純な場合, C-gはコマンドkeyboard-quit
を実行しますが,
その効果は中断を引き起こすことですから, 読者には区別できないはずです.
しかし, プレフィックスキーに続けてC-gを打つと,
それらは組み合わされて未定義キーになります.
その効果は, 前置引数を含めてプレフィックスキーを取り消します.
ミニバッファでは, C-gには別の定義があって, ミニバッファを強制終了させます. つまり, ミニバッファから抜け出て中断します. (単に中断したのでは, ミニバッファ内で コマンドループに戻るだけである. ) コマンドループで入力を読んでいるときにC-gで直接中断しない理由は, このようにミニバッファでその意味を再定義できるようにするためです. ミニバッファでは, プレフィックスキーに続くC-gは再定義してなく, プレフィックスキーと前置引数を取り消すという通常の効果を持ちます. C-gがつねに直接中断するのでは, このようにすることさえ不可能です.
C-gが直接に中断するときには,
変数quit-flag
にt
を設定します.
Emacsはこの変数を適切なときに検査しnil
でないと中断します.
したがって, quit-flag
にnil
以外を設定すると
中断を引き起こします.
Cのコードのレベルでは, どこでも中断できるわけではありません.
quit-flag
を検査している特別な箇所だけです.
このようにするのは, それ以外の箇所で中断すると
Emacsの内部状態に矛盾をきたす可能性があるからです.
中断は安全な場所まで延期されるので,
中断によってEmcasがクラッシュすることはありません.
read-key-sequence
やread-quoted-char
などのある種の関数は,
入力を待っている場合であっても中断を完全に抑制します.
中断するかわりに, C-gは入力として働きます.
read-key-sequence
の場合, コマンドループにおいて
C-gの特別なふるまいをもたらします.
read-quoted-char
の場合,
C-qでC-gをクォートできるようになります.
変数inhibit-quit
にnil
以外の値を束縛することで
Lisp関数のある部分において中断を抑制できます.
そうすると, C-gはそれでもいつもどおり
quit-flag
をt
にしますが,
その通常の結果である中断は抑制されます.
最終的にフォームlet
の終りで束縛が解除されるなどして
inhibit-quit
が再度nil
になります.
その時点でも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 ((message-log-max nil) done (first t) (code 0) char)
(while (not done)
(let ((inhibit-quit first)
…)
(and prompt (message "%s-" prompt))
(setq char (read-event))
(if inhibit-quit (setq quit-flag nil)))
…変数 |
inhibit-quit
がnil
であれば,
この変数がnil
以外であるとEmacsはただちに中断する.
C-gは, inhibit-quit
に関わらず,
通常, quit-flag
にnil
以外を設定する.
この変数は, quit-flag
がnil
以外の値に設定されたときに
Emacsが中断すべきかどうかを決定する.
inhibit-quit
がnil
以外であると,
quit-flag
に特別な意味はない.
この関数は(signal 'quit nil)
でquit
条件を通知する.
これは中断と同じことを行う.
(エラーのsignal
を参照. )
中断として使うC-g以外の特殊文字を使えます.
端末入力の関数set-input-mode
を参照してください.
[ < ] | [ > ] | [ << ] | [上] | [ >> ] | [冒頭] | [目次] | [見出し] | [ ? ] |
Emacsのほとんどのコマンドは, 前置引数(prefix argument),
つまりコマンド自身のまえに指定された数を利用できます.
(前置引数とプレフィックスキーを混同しないこと. )
前置引数はつねに値で表現され,
nil
であると現在は前置引数がないことを表します.
各コマンドは, 前置引数を使ってもよいし, 無視してもかまいません.
前置引数には2つの表現方法があります. 生(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 ; ( |
Emacsは, 前置引数を保持するために2つの変数,
prefix-arg
とcurrent-prefix-arg
を使います.
他のコマンド向けに前置引数を設定するuniversal-argument
などの
コマンドは, 前置引数をprefix-arg
に保持します.
対照的に, current-prefix-arg
には
現在のコマンドに対して前置引数を運ぶ役割があり,
この変数に設定しても以後のコマンドに対する前置引数には
なんの効果もありません.
通常, コマンドは, interactive
宣言により,
「生」か「数値」のいずれの表現の前置引数を使うか指定します.
(See section interactive
の使い方. )
あるいは, 変数current-prefix-arg
にある前置引数の値を
関数から直接見てもかまいませんが,
これは見通しのよい方法ではありません.
この関数は, 有効な生の前置引数の値argからそれに等価な数値を返す.
引数は, シンボル, 数, リストのいずれかである.
それがnil
であると, 戻り値は1である.
-
であると, 戻り値は-1である.
数であると, その数を返す.
リストであると, リストの(数であるはずの)CARを返す.
この変数は, 現在のコマンドに対する生の前置引数を保持する.
コマンドが直接この変数を調べてもよいが,
前置引数を参照する普通の方法は(interactive "P")
を使うことである.
この変数の値は, つぎの編集コマンド向けの生の前置引数である.
後続のコマンド向けの前置引数を指定するuniversal-argument
などの
コマンドは, この変数に設定することで動作する.
まえのコマンドで使われた生の前置引数の値.
つぎのコマンドは, 後続のコマンド向けの前置引数を設定するためのものです. それ以外の目的には呼ばないでください.
このコマンドは入力を読み取り, 後続のコマンド向けの前置引数を指定する. なにをしているか理解していない限り, 読者自身でこのコマンドを呼ばないこと.
このコマンドは, 後続のコマンド向けの前置引数に追加する. 引数argは, このコマンドが呼び出されるまえの生の前置引数であり, 前置引数を更新する計算に使われる. なにをしているか理解していない限り, 読者自身でこのコマンドを呼ばないこと.
このコマンドは, 後続のコマンド向けの数値前置引数に追加する. 引数argは, このコマンドが呼び出されるまえの生の前置引数であり, その値の符号を変えて新たな前置引数とする. なにをしているか理解していない限り, 読者自身でこのコマンドを呼ばないこと.
[ < ] | [ > ] | [ << ] | [上] | [ >> ] | [冒頭] | [目次] | [見出し] | [ ? ] |
Emacsが動作を始めると, Emacsのコマンドループに自動的に入ります. このトップレベルのコマンドループからはけっして抜けることはなく, Emacsが動いている限り動作し続けます. Lispプログラムからコマンドループを起動することもできます. そうすると, 活性なコマンドループが複数作られることになるので, それを再帰編集(recursive editing)と呼びます. 再帰編集レベルには, それを起動したコマンドを一時休止させ, 当該コマンドを再開するまでユーザーにどんな編集でも許す効果があります.
再帰編集中に利用可能なコマンドは, トップレベルのコマンドループと 同じものでありキーマップで定義されます. 再帰編集を抜けるための数個の特別なコマンドがあり, 完了すると再帰編集レベルから抜ける別のコマンドもあります. (再帰編集を抜けるコマンドはつねに利用可能であるが, 再帰編集中でないとなにも行わない. )
再帰編集を含むすべてのコマンドループでは, コマンドループから実行したコマンドのエラーによって コマンドループから抜け出さないように汎用目的のエラーハンドラを設定します.
ミニバッファでの入力は, 特別な種類の再帰編集です. これには, ミニバッファやミニバッファ用ウィンドウを表示するなどの特別な 処理がありますが, 読者が考えるよりは少ないのです. ミニバッファでは特別なふるまいをするキーもありますが, それらはミニバッファのローカルマップによるものです. ウィンドウを切り替えると, Emacsの普通のコマンドを使えます.
再帰編集レベルを起動するには, 関数recursive-edit
を呼び出します.
この関数にはコマンドループが含まれています.
さらに, exit
を伴ったcatch
の呼び出しもあり,
これにより, exit
へ投げることで
再帰編集レベルから抜け出せるようになっています
(see section 明示的な非ローカル脱出:
catch
とthrow
).
t
以外の値を投げると, recursive-edit
は,
呼び出し側の関数へ普通に戻ります.
コマンドC-M-c(exit-recursive-edit
)は, これを行います.
値t
を投げるとrecursive-edit
に中断を引き起こし,
1つ上のレベルのコマンドループへ制御を戻します.
これを強制終了(aborting)と呼び,
C-](abort-recursive-edit
)で行えます.
ミニバッファを使う場合を除いて, ほとんどのアプリケーションでは 再帰編集を使うべきではありません. カレントバッファのメジャーモードを 一時的な特別なメジャーモードに変更するほうが, 一般にはユーザーにとってより便利です. ただし, 当該メジャーモードには, まえのモードに戻るコマンドを用意しておきます. (rmailのコマンドeは, この方式を使っている. ) あるいは, 『再帰的に』編集する別のテキストをユーザーに与えたい場合には, 特別なモードの新たなバッファを作成してそれを選択します. 当該モードには, 処理を終えてまえのバッファに戻るコマンドを 定義しておきます. (rmailのコマンドmは, このようにする. )
再帰編集はデバッグに便利です.
ブレークポイントの一種として関数定義に
debug
の呼び出しを挿入しておくと,
その箇所に達したときにいろいろと調べられます.
debug
は再帰編集を起動しますが, デバッガとしての機能も提供します.
query-replace
でC-rを打ったり,
C-x q(kbd-macro-query
)を使ったときにも
再帰編集レベルが使われます.
この関数はエディタコマンドループを起動する. 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 |
この関数は, (ミニバッファでの入力を含む)もっとも内側の再帰編集から抜ける.
その関数定義は実質的には(throw 'exit nil)
である.
この関数は, 再帰編集から抜けたあとでquit
を通知することで,
(ミニバッファでの入力を含む)もっとも内側の再帰編集を
要請したコマンドを強制終了する.
その関数定義は実質的には(throw 'exit t)
である.
see section 中断.
この関数は, すべての再帰編集を抜ける. すべての計算を抜け出てメインのコマンドループへ直接戻るため, 値は返さない.
この関数は再帰編集の現在の深さを返す. 活性な再帰編集がなければ0を返す.
[ < ] | [ > ] | [ << ] | [上] | [ >> ] | [冒頭] | [目次] | [見出し] | [ ? ] |
コマンドを禁止するとは, コマンドを実行するまえにユーザーの確認を必要とするように コマンドに印を付けることです. コマンドを禁止するのは, 初心者に混乱をもたらす可能性のあるコマンドに対してや, コマンドの誤用を防ぐためです.
コマンドを禁止する低レベルの機構は,
コマンドのLispシンボルにnil
以外の属性disabled
を入れることです.
これらの属性は, 通常, ユーザーの‘.emacs’ファイルにて
つぎのようなLisp式で設定します.
(put 'upcase-region 'disabled t) |
数個のコマンドにはデフォルトでこれらの属性がありますから, ‘.emacs’ファイルで属性を取り除きます.
属性disabled
の値は文字列であり,
コマンドを禁止したことを表すメッセージです.
たとえばつぎのとおりです.
(put 'delete-region 'disabled "Text deleted this way cannot be yanked back!\n") |
禁止したコマンドを対話的に起動するとどうなるかについて 詳しくはSee (emacs-ja)Disabling section ‘使用禁止コマンド’ in GNU Emacs マニュアル. コマンドを禁止しても, Lispプログラムから関数として呼び出すことには なんの影響もありません.
これ以降, 特別な確認なしにcommandを実行可能にする. さらに(ユーザーが了承すれば)ユーザーの‘.emacs’ファイルを変更して, 将来のセッションでもそのようにする.
これ以降, commandの実行には特別な確認を必要とするようにする. さらに(ユーザーが了承すれば)ユーザーの‘.emacs’ファイルを変更して, 将来のセッションでもそのようにする.
禁止したコマンドをユーザーが対話的に起動したとき,
禁止したコマンドのかわりにこのノーマルフックを実行する.
フック関数では, this-command-keys
を使って
コマンドを実行するためにユーザーがなにを入力したかを調べ,
コマンドそのものを探し出せる.
see section フック.
デフォルトでは, disabled-command-hook
には,
ユーザーに処理を進めるかどうかを問い合わせる関数が入っている.
[ < ] | [ > ] | [ << ] | [上] | [ >> ] | [冒頭] | [目次] | [見出し] | [ ? ] |
コマンドループでは, 実行した複雑なコマンドの履歴を管理していて,
それらのコマンドを簡単に繰り返せるようにしています.
複雑なコマンドとは, ミニバッファを使って引数を読むコマンドです.
これには, 任意のM-xコマンド, 任意のM-:コマンド,
ミニバッファから引数を読み取るinteractive
指定を持つ任意のコマンドが
含まれます.
コマンド自身の実行中に明示的にミニバッファを使っても,
複雑なコマンドとはみなしません.
この変数の値は, 最近使った複雑なコマンドのリストであり,
各要素は評価すべきフォームを表す.
編集セッション中は, すべての複雑なコマンドを集積するが,
(変数history-length
で指定される)最大サイズに達すると
新しい要素を追加するたびに古い要素を削除する.
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-ja)Repetition section ‘ミニバッファコマンドの繰り返し’ in GNU Emacs マニュアル)に説明してあります。
ミニバッファ内では, 通常のミニバッファ履歴コマンドを使えます.
[ << ] | [ >> ] | [冒頭] | [目次] | [見出し] | [ ? ] |
この文書は新堂 安孝によって2009年9月22日にtexi2html 1.82を用いて生成されました。