| [ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
入力イベントとコマンドとのバインディング(対応)は、 キーマップ(keymap)と呼ばれるデータ構造に記録されています。 キーマップの各バインディング(あるいはバインド(bind))は、 個々のイベント型を別のキーマップかコマンドに対応付けます。 イベント型のバインディングがキーマップであると、 後続の入力イベントを探すためにそのキーマップを使います。 コマンドがみつかるまで、これを繰り返します。 この処理全体をキー探索(key lookup)と呼びます。
| 21.1 キーマップの用語 | Definitions of terms pertaining to keymaps. | |
| 21.2 キーマップの形式 | What a keymap looks like as a Lisp object. | |
| 21.3 キーマップの作成 | Functions to create and copy keymaps. | |
| 21.4 継承とキーマップ | How one keymap can inherit the bindings of another keymap. | |
| 21.5 プレフィックスキー | Defining a key with a keymap as its definition. | |
| 21.6 活性なキーマップ | Each buffer has a local keymap to override the standard (global) bindings. A minor mode can also override them. | |
| 21.7 キー探索 | How extracting elements from keymaps works. | |
| 21.8 キー探索関数 | How to request key lookup. | |
| 21.9 キーバインディングの変更 | Redefining a key in a keymap. | |
| 21.10 キーをバインドするためのコマンド | Interactive interfaces for redefining keys. | |
| 21.11 キーマップの走査 | Looking through all keymaps, for printing help. | |
| 21.12 メニューキーマップ | Defining a menu as a keymap. |
キーマップ(keymap)は、イベント型を定義に対応させる表です。 (この定義は任意のLispオブジェクトであるが、 コマンドループによる実行においては、特定の型のみが意味を持つ)。 与えられたイベント(あるいはイベント型)とキーマップから、 Emacsはイベントの定義を得ることができます。 イベントは、文字、ファンクションキー、マウス操作です (see section 20.5 入力イベント)。
ある単位を構成する入力イベントの列をキー列(key sequence)、 あるいは、略してキー(key)と呼びます。 単一イベントから成る列はつねにキー列であり、複数イベント列もキー列です。
キーマップは、任意のキー列に対するバインディング、 つまり、定義を決定します。 キー列が単一イベントから成るとき、 そのバインディングはキーマップ内の当該イベントの定義です。 複数のイベントから成るキー列のバインディングは、 繰り返し処理で探します。 つまり、最初のイベントのバインディングを探すと、 それはキーマップであるはずです。 続いて、そのキーマップから2番目のイベントのバインディングを探します。 これをキー列のすべてのイベントを使い尽くすまで行います
キー列のバインディングがキーマップであると、
そのキー列をプレフィックスキー(prefix key)と呼びます。
さもなければ、(追加できるイベントがないので)
完全なキー(complete key)と呼びます。
バインディングがnilであると、キーは未定義であるといいます。
プレフィックスキーの例は、C-c、C-x、C-x 4です。
定義されている完全なキーの例は、X、RET、C-x 4 C-fです。
未定義な完全なキーの例は、C-x C-gとC-c 3です。
詳しくは、See section 21.5 プレフィックスキー。
キー列のバインディングを探す際の規則では、 (最後のイベントのまえまでにみつかる)途中のバインディングは すべてキーマップであると仮定します。 これが満たされないと、イベントの列があるまとまりを構成せず、 1つのキー列になりません。 いいかえれば、有効なキー列の末尾からいくつかのイベントを取りさると、 つねにプレフィックスキーになる必要があります。 たとえば、C-f C-nはキー列ではありません。 C-fはプレフィックスキーではないので、 C-fで始まる列はキー列ではありません。
複数イベントから成るキー列の候補は、 プレフィックスキーのバインディングに依存します。 したがって、キーマップが異なればそれらは異なり、 バインディングを変更するとそれらは変わります。 しかし、単一イベントから成る列は、プレフィックスに依存しないので、 つねにキー列です。
ある時点には、複数個の主キーマップが活性です。 つまり、キーバインディングの探索に使われます。 それらは、 すべてのバッファが共有するグローバルマップ(global map)、 特定のメジャーモードに関連付けられたローカルマップ(local keymap)、 現在オンにしてあるマイナモードに属する マイナモードキーマップ(minor mode keymaps)です。 (すべてのマイナモードにキーマップがあるわけではない。) ローカルキーマップのバインディングは、 対応するグローバルなバインディングを隠します(つまり優先する)。 マイナモードキーマップは、ローカルとグローバルの両方のキーマップを隠します。 詳しくはSee section 21.6 活性なキーマップ。
キーマップは、そのCARがシンボルkeymapであるリストです。
リストの残りの要素がキーマップのキーバインディングを定義します。
オブジェクトがキーマップであるかどうか検査するには、
関数keymapp(下記参照)を使います。
キーマップでは、シンボルkeymapのうしろに、
さまざまな種類の要素が現れます。
(type . binding)
(t . binding)
vector
キーマップにベクトルがあると、ベクトルの要素がnilであっても
ベクトルが各ASCII文字のバインディングをつねに定義する。
そのようなnilのバインディングは、
ASCII文字に対しては
キーマップのデフォルトのキーバインディングを無効にする。
しかし、ASCII文字以外のイベントに対しては、
デフォルトのバインディングが意味を持つ。
nilのバインディングが
低優先順位のキーマップを隠すことはない。
つまり、ローカルマップがnilのバインディングを与えると、
Emacsはグローバルマップのバインディングを使う。
string
キーマップは、メタ文字に対するバインディングを直接には記録していません。
そのかわりに、キー探索においては、メタ文字は2文字から成る列とみなし、
先頭文字はESC(あるいは、meta-prefix-charの現在値)です。
つまり、キーM-aは実際にはESC aと表現され、
そのグローバルなバインディングは
esc-mapのaでみつかります(see section 21.5 プレフィックスキー)。
Lispモードに対するローカルキーマップの例を示します。 これは疎なキーマップです。 DEL、TAB、C-c C-l、M-C-q、M-C-xに対する バインディングを定義しています。
lisp-mode-map
=>
(keymap
;; TAB
(9 . lisp-indent-line)
;; DEL
(127 . backward-delete-char-untabify)
(3 keymap
;; C-c C-l
(12 . run-lisp))
(27 keymap
;; M-C-qはESC C-qとみなされる
(17 . indent-sexp)
;; M-C-xはESC C-xとみなされる
(24 . lisp-send-defun)))
|
tを返し、
さもなければnilを返す。
より正確には、この関数は、
そのCARがkeymapであるリストかどうかを検査する。
(keymapp '(keymap))
=> t
(keymapp (current-global-map))
=> t
|
ここでは、キーマップを作成するための関数について述べます。
nilであり、それ以外の種類のイベントに対するバインディングはない。
(make-keymap)
=> (keymap [nil nil nil ... nil nil])
|
promptを指定すると、 それはキーマップに対する全面プロンプト文字列になる。 全面プロンプト文字列はメニューキーマップ (see section 21.12 メニューキーマップ)に有用である。
make-keymapの場合同様、
プロンプト文字列を指定する。
(make-sparse-keymap)
=> (keymap)
|
(setq map (copy-keymap (current-local-map)))
=> (keymap
;; (これはメタ文字を意味する)
(27 keymap
(83 . center-paragraph)
(115 . center-line))
(9 . tab-to-tab-stop))
(eq map (current-local-map))
=> nil
(equal map (current-local-map))
=> t
|
キーマップでは、親キーマップ(parent keymap)と呼ぶ別のキーマップの バインディングを継承できます。 そのようなキーマップはつぎのようになります。
(keymap bindings... . parent-keymap) |
このキーマップは、キーを探索する時点において parent-keymapが有するすべてのバインディングを継承しますが、 それらにはbindingsが追加されたり優先します。
define-keyや他のキーバインディング関数でparent-keymapの
バインディングを変更すると、それらの変更は、
bindingsで隠されない限り継承側のキーマップからも見えます。
その逆は真ではありません。
define-keyで継承側のキーマップを修正すると、
それはbindingsに影響するだけでparent-keymapには影響しません。
親キーマップを用いたキーマップを作成する正しい方法は、
set-keymap-parentを使うことです。
親キーマップを用いたキーマップを直接作成するようなコードがある場合には、
set-keymap-parentを用いるようにプログラムを変更してください。
keymap-parentはnilを返す。
nilであると、
この関数はkeymapに親キーマップをいっさい与えない。
keymapに(プレフィックスキー用のバインディングである) サブマップがあれば、それらもparentが指定するプレフィックスキーを 反映する新たな親マップを受け取る。
text-mode-mapからキーマップを継承する方法を示します。
(let ((map (make-sparse-keymap))) (set-keymap-parent map text-mode-map) map) |
プレフィックス(prefix key)とは、
そのバインディングがキーマップであるキー列のことです。
そのキーマップが、プレフィックスキー以降のキーでなにをするかを定義します。
たとえば、C-xはプレフィックスキーであり、
変数ctl-x-mapに保持されたキーマップを使います。
このキーマップは、C-xで始まるキー列に対するバインディングを定義します。
Emacsの標準プレフィックスキーのなかには、 Lisp変数にも保持されたキーマップを使うものがあります。
esc-mapは、プレフィックスキーESC用のグローバルマップである。
したがって、すべてのメタ文字のグローバルな定義はここにある。
このキーマップはESC-prefixの関数定義でもある。
help-mapは、プレフィックスキーC-hに対する
グローバルキーマップである。
mode-specific-mapは、プレフィックスキーC-cに対する
グローバルキーマップである。
このキーマップは実際にはグローバルでありモード固有ではないが、
その名前は、C-h b(display-bindings)の出力において
C-cに関する有用な情報を与える。
というのは、このプレフィックスキーの主な用途は、
モード固有のバインディングのためだからである。
ctl-x-mapは、プレフィックスキーC-xに対して使われる
グローバルキーマップである。
このキーマップは、シンボルControl-X-prefixの関数セルに現れる。
mule-keymapは、プレフィックスキーC-x RETに対して使われる
グローバルキーマップである。
ctl-x-4-mapは、プレフィックスキーC-x 4に対して使われる
グローバルキーマップである。
ctl-x-5-mapは、プレフィックスキーC-x 5に対して使われる
グローバルキーマップである。
2C-mode-mapは、プレフィックスキーC-x 6に対して使われる
グローバルキーマップである。
vc-prefix-mapは、プレフィックスキーC-x vに対して使われる
グローバルキーマップである。
facemenu-keymapは、プレフィックスキーM-gに対して使われる
グローバルキーマップである。
プレフィックスキーのキーマップバインディングは、
当該プレフィックスキーに続くイベントを探すために使われます。
(その関数定義がキーマップであるシンボルでもよい。
効果は同じであるが、シンボルはプレフィックスキーに対する名前として働く。)
したがって、C-xのバインディングは
シンボルControl-X-prefixであり、
その関数セルがコマンドC-x用のキーマップを保持している。
(ctl-x-mapの値も同じキーマップである。)
プレフィックスキーの定義は、任意の活性なキーマップにあってかまいません。 プレフィックスキーとしてのC-c、C-x、C-h、ESCの 定義はグローバルマップにあるので、これらのプレフィックスキーは つねに利用できます。 メジャーモードやマイナモードでは、 プレフィックスキーの定義をローカルキーマップや マイナモードキーマップに入れることで、 キーをプレフィックスとして再定義できます。 See section 21.6 活性なキーマップ。
複数の活性なキーマップにおいて、キーがプレフィックスと定義されていると、 さまざまな定義は実質的には併合されます。 マイナモードキーマップで定義されたコマンドが最優先で、 つぎにローカルマップのプレフィックス定義、 そしてグローバルマップのプレフィックス定義が続きます。
以下の例では、ローカルキーマップにおいて、
C-pをC-xに等価なプレフィックスキーにします。
続いてC-p C-fのバインディングを
C-x C-fのように関数find-fileにします。
キー列C-p 6はどの活性なキーマップでもみつかりません。
(use-local-map (make-sparse-keymap))
=> nil
(local-set-key "\C-p" ctl-x-map)
=> nil
(key-binding "\C-p\C-f")
=> find-file
(key-binding "\C-p6")
=> nil
|
この関数は、変数としてのsymbolにも値としてキーマップを設定する。 symbolを返す。
Emacsには、通常、たくさんのキーマップがあります。 ある時点では、それらの数個が活性になっていて、 ユーザー入力の解釈に関与します。 それらは、グローバルキーマップ、カレントバッファのローカルキーマップ、 オンになっているマイナモードのキーマップです。
グローバルキーマップ(global keymap)は、
C-fのようなカレントバッファに依存せずに
定義されたキーのバインディングを保持します。
変数global-mapはこのキーマップを保持していて、
このキーマップはつねに活性です。
各バッファには別のキーマップ、つまり、
バッファのローカルキーマップ(local keymap)があり、
キーに対する新しい定義や無効にする定義を保持しています。
カレントバッファのローカルキーマップは、
overriding-local-mapで無効にしない限り、つねに活性です。
テキスト属性により、バッファの特定部分に対する
代替ローカルマップを指定できます。
31.19.4 特別な意味を持つ属性を参照してください。
各マイナモードもキーマップを持てます。 その場合、マイナモードがオンであると当該キーマップは活性です。
変数overriding-local-mapがnil以外であると、
バッファのローカルキーマップとそのすべてのマイナモードキーマップに
取ってかわるローカルキーマップを指定します。
キーが入力されるとどのコマンドを実行するかを決定するために、 すべての活性なキーマップを一緒に使います。 Emacsは、キーマップの1つでバインディングがみつかるまで、 優先順位が高いほうからこれらのキーマップを1つ1つ探索します。 1つのキーマップで探索する処理のことを キー探索(key lookup)といいます。 21.7 キー探索を参照してください。
通常、Emacsはまずminor-mode-map-alistで指定される順に
マイナモードキーマップでキーを探します。
キーに対するバインディングがなければ、
Emacsはローカルキーマップで探します。
そこにもバインディングがなければ、
Emacsはグローバルキーマップで探します。
しかし、overriding-local-mapがnil以外であれば、
Emacsはまずそのキーマップで探してから、
グローバルキーマップで探します。
同じメジャーモードを使う各バッファは、通常、同じローカルキーマップを
使うので、キーマップはモードにローカルであると考えることができます。
(たとえばlocal-set-keyを使って)バッファのローカルキーマップを
修正すると、当該キーマップを共有している別のバッファでも
その修正が見えます。
Lispモードや他の数個のメジャーモードで使われるローカルキーマップは、
それらのモードがまだ使われていなくても存在します。
そのようなローカルキーマップは、lisp-mode-mapなどの変数の値です。
使用頻度の低いほとんどのメジャーモードでは、
セッションで始めてそのモードを使ったときに
ローカルキーマップを作成します。
ミニバッファにもローカルキーマップがあります。 それにはさまざまな補完コマンドや脱出コマンドが含まれます。 See section 19.1 ミニバッファの紹介。
Emacsには、別の用途のキーマップもあります。
read-key-sequenceでイベントを変換するためのものです。
See section 37.8.2 入力イベントの変換。
標準的なキーマップの一覧についてはSee section E. 標準のキーマップ。
self-insert-commandをバインドする
完全なキーマップである。
グローバルマップのバインディングを修正することは実用的ですが、 この変数には、動作開始時のキーマップ以外の値は設定しないこと。
global-mapを変更していなければ、
これはglobal-mapの値と同じである。
(current-global-map)
=> (keymap [set-mark-command beginning-of-line ...
delete-backward-char])
|
nilを返す。
つぎの例では、(lisp対話モードを使っている)バッファ`*scratch*'の
キーマップは疎なキーマップであり、
ASCIIコード27のESCに対する指定も別の疎なキーマップである。
(current-local-map)
=> (keymap
(10 . eval-print-last-sexp)
(9 . lisp-indent-line)
(127 . backward-delete-char-untabify)
(27 keymap
(24 . eval-defun)
(17 . indent-sexp)))
|
nilを返す。
グローバルキーマップを変更することは、とうてい普通のことではない。
nilであると、
バッファにはローカルキーマップがなくなる。
use-local-mapはnilを返す。
ほとんどのメジャーモードコマンドは、この関数を使う。
(variable . keymap) |
変数variableの値がnil以外であれば、
キーマップkeymapは活性である。
典型的には、variableはマイナモードをオン/オフする変数である。
see section 22.2.2 キーマップとマイナモード。
minor-mode-map-alistの要素とminor-mode-alistの要素とは、
異なる構造であることに注意してほしい。
キーマップは要素のCDRである必要があり、
要素のCADRがキーマップであるようなリストではだめである。
CADRは、(リストの)キーマップであるか、
関数定義がキーマップであるシンボルである。
複数のマイナモードキーマップが活性な場合、
それらの優先順位は、minor-mode-map-alistでの順番である。
読者は、互いに干渉しないようにマイナモードを設計する必要がある。
正しくできていれば、順序は関係ないはずである。
マイナモードについて詳しくは22.2.2 キーマップとマイナモードを参照。
minor-mode-key-binding(see section 21.8 キー探索関数)も参照のこと。
minor-mode-map-alistの要素と同じ形で、
(variable . keymap)である。
minor-mode-overriding-map-alistの要素として変数が現れると、
当該要素が指定するキーマップで、
minor-mode-map-alist内の同じ変数で指定したキーマップを
完全に置き換える。
minor-mode-overriding-map-alistは、すべてのバッファにおいて、
自動的にバッファにローカルになる。
nil以外の値であると、この変数は、
バッファのローカルキーマップ、ならびに、すべてのマイナモードキーマップの
かわりに用いるキーマップを保持する。
このキーマップは、現在のグローバルキーマップを除く、
他のすべての活性なキーマップを無効にする。
nil以外であると、この変数は、
overriding-local-map、および、バッファのローカルキーマップと
すべてのマイナモードキーマップのかわりに用いるキーマップを保持する。
この変数はつねに現在の端末に対してローカルであり、 バッファに対してローカルにはならない。 see section 28.2 複数ディスプレイ。 これはインクリメンタルサーチモードの実装に使われている。
nil以外であれば、
overriding-local-mapやoverriding-terminal-local-mapの値は、
メニューバーの表示に影響する。
デフォルト値はnilであり、
そのため、それらのマップはメニューバーには影響しない。
これら2つのキーマップ変数は、メニューバーの表示に影響しないときであっても、 メニューバーを用いて入力したキー列の実行には影響することに注意してほしい。 そのため、メニューバーのキー列が到着したら、 そのキー列を探索し実行するまえに、これらの変数をクリアすべきである。 これらの変数を使うモードでは、典型的にはつぎのようにする。 つまり、モードで処理できないイベントは『読み戻し』てモードから抜ける。
read-eventが当該イベントのバインディングを直接実行する。
see section 20.7 特殊イベント。
キー探索(key lookup)とは、 与えられたキーマップからキー列のバインディングを捜し出す処理です。 バインディングを実際に実行することは、キー探索ではありません。
キー探索では、キー列の各イベントのイベント型のみを使い、
イベントの他の部分は無視します。
実際、キー探索に使われるキー列では、
マウスイベント全体(リスト)ではなく
そのイベント型(シンボル)のみを指定します。
See section 20.5 入力イベント。
そのような『キー列』は、command-executeの動作には不十分ですが、
キーの探索や再バインディングには十分です。
キー列が複数のイベントから構成される場合、 キー探索ではイベントを順番に処理します。 先頭のイベントのバインディングを探しますが、 それはキーマップであるはずです。 続いて、そのキーマップから2番目のイベントのバインディングを探します。 これをキー列のすべてのイベントを使い尽くすまで行います。 (このように探した最後のイベントに対するバインディングは、 キーマップであたっりそうでないかもしれない。) つまり、キー探索処理は、 キーマップから単一イベントを探索するという単純な処理として定義できます。 これがどのように行われるかは、 キーマップ内のイベントに対応付けられたオブジェクトの型に依存します。
キーマップでイベント型を探してみつかった値のことを
キーマップ項目(keymap entry)という単語で表します。
(これには、メニューキーバインディングにある
項目文字列や他の追加要素を含まない。
というのは、lookup-keyや他のキー探索関数は、
それらを戻り値として返さないからである。)
キーマップ項目として任意のLispオブジェクトをキーマップに保存できますが、
キー探索においてそのすべてが意味を持つとは限りません。
意味のある種類のキー項目をつぎに示します。
nil
nilは、探索に使ったここまでのイベントが
未定義キーを構成することを意味する。
キーマップにイベント型が記載されてなく、かつ、
デフォルトのバインディングもない場合には、
そのイベント型に対しては、バインディングがnilであるのと等価。
keymapであれば、
そのリストはキーマップであり、キーマップとして扱われる(上記参照)。
lambdaであれば、
そのリストはラムダ式である。
これはコマンドとみなされ、そのように扱われる(上記参照)。
(othermap . othertype) |
キー探索中に間接項目に出会うと、 othertypeのバインディングをothermapで探しそれを用いる。
この機能により、あるキーを別のキーに対する別名として定義できる。
たとえば、CARがesc-mapと呼ばれるキーマップであり
CDRが32(SPCの文字コード)である項目は、
『Meta-SPCのグローバルバインディングを
それがなんであれ使う』という意味になる。
キーマップやキーボードマクロ(文字列やベクトル)は正しい関数ではないので、
関数定義としてキーマップ、文字列、ベクトルを持つシンボルは、
正しい関数ではない。
しかし、キーバインディングとしては正しい。
定義がキーボードマクロである場合には、そのシンボルは
command-executeの引数としても正しい
(see section 20.3 対話的呼び出し)。
シンボルundefinedについて特記しておく。
これは、キーを未定義として扱うことを意味する。
正確には、キーは定義されており、
そのバインディングはコマンドundefinedである。
しかし、そのコマンドは、未定義キーに対して自動的に行われることと
同じことを行う。
つまり、(dingを呼び出して)ベルを鳴らすが、
エラーは通知しない。
undefinedは、グローバルキーバインディングを無効にして
キーをローカルに『未定義』にするためにローカルキーマップで使われる。
nilのローカルバインディングでは、
グローバルバインディングを無効にしないため、こうはならない。
まとめると、キー項目は、キーマップ、コマンド、キーボードマクロ、
これら3つのいずれかになるシンボル、間接項目、nilです。
2つの文字をコマンドに、1つを別のキーマップに対応付ける
疎なキーマップの例を示します。
このキーマップは、emacs-lisp-mode-mapの通常の値です。
ここで、それぞれ、9はTAB、
127はDEL、27はESC、17はC-q、
24はC-xの文字コードであることに注意してください。
(keymap (9 . lisp-indent-line)
(127 . backward-delete-char-untabify)
(27 keymap (17 . indent-sexp) (24 . eval-defun)))
|
ここでは、キー探索に関わる関数や変数について述べます。
lookup-keyを用いてキーを探す。
例を示す。
(lookup-key (current-global-map) "\C-x\C-f")
=> find-file
(lookup-key (current-global-map) "\C-x\C-f12345")
=> 2
|
文字列やベクトルであるkeyが、 keymapで指定されたプレフィックスキーに対して正しいキー列でなければ、 keyは『長すぎる』のであって、 1つのキー列に収まらない余分なイベントが末尾にある。 その場合、戻り値は数であり、 完全なキーを構成するkeyの先頭からのイベント数を表す。
accept-defaultsがnil以外であると、
lookup-keyは、keyの特定のイベントに
対するバインディングだけでなく、
デフォルトのバインディングも考慮する。
さもなければ、lookup-keyは、
keyの特定のイベントに対するバインディングだけを報告し、
特に指定しない限りデフォルトのバインディングは無視する。
(それには、keyの要素としてtを与える。
21.2 キーマップの形式を参照。)
keyにメタ文字が含まれる場合、
当該文字は暗黙のうちに2文字の列、
つまり、meta-prefix-charの値と対応する非メタ文字
に置き換えられる。
したがって、つぎの最初の例は、2番目の例に変換して処理される。
(lookup-key (current-global-map) "\M-f")
=> forward-word
(lookup-key (current-global-map) "\ef")
=> forward-word
|
read-key-sequenceと異なり、
この関数は、情報を欠落するようには指定されたイベントを修正しない
(see section 20.6.1 キー列の入力)。
特に、文字を小文字に変換したり、
ドラッグイベントをクリックイベントに変換したりはしない。
dingを呼び出すが、エラーにはならない。
nil。
引数accept-defaultsは、lookup-key(上記)と同様に、
デフォルトのバインディングを調べるかどうか制御する。
keyが文字列でもベクトルでもないとエラーを通知する。
(key-binding "\C-x\C-f")
=> find-file
|
nilを返す。
引数accept-defaultsは、lookup-key(上記)と同様に、
デフォルトのバインディングを調べるかどうか制御する。
nilを返す。
引数accept-defaultsは、lookup-key(上記)と同様に、
デフォルトのバインディングを調べるかどうか制御する。
(modename . binding)を要素とする
連想リストを返す。
ここで、modenameはマイナモードをオンにする変数であり、
bindingは当該モードにおけるkeyのバインディングである。
keyにマイナモードでのバインディングがなければ、
値はnilである。
最初にみつかったバインディングがプレフィックスの定義 (キーマップかキーマップとしてのシンボル)でなければ、 残りのマイナモードからのバインディングは完全に隠されてしまうので それらは省略する。 同様に、プレフィックスバインディングに 続く非プレフィックスバインディングも省略する。
引数accept-defaultsは、lookup-key(上記)と同様に、
デフォルトのバインディングを調べるかどうか制御する。
meta-prefix-charの値が27である限り、
キー探索ではM-bをESC bに変換し、
通常、これはコマンドbackward-wordと定義されている。
しかし、meta-prefix-charにC-xのコードである24を設定すると、
EmacsはM-bをC-x bに変換し、
その標準のバインディングはコマンドswitch-to-bufferである。
これを以下に示す。
meta-prefix-char ; デフォルト値
=> 27
(key-binding "\M-b")
=> backward-word
?\C-x ; 文字の表示表現
=> 24
(setq meta-prefix-char 24)
=> 24
(key-binding "\M-b")
=> switch-to-buffer ; ここでM-bと打つと
; C-x bと打つのと同じ
(setq meta-prefix-char 27) ; 混乱を避けるために
=> 27 ; デフォルト値に戻す!
|
キーを再バインドするには、キーマップにおける当該項目を変更します。
グローバルキーマップでバインディングを変更すると、
その変更はすべてのバッファで効果を発揮します
(ただし、ローカルキーマップでグローバルバインディングを
隠しているバッファでは直接の効果はない)。
カレントバッファのローカルキーマップで変更すると、
通常、同じメジャーモードを使っているすべてのバッファに影響します。
関数global-set-keyやlocal-set-keyは、
これらの操作を行うための便利なインターフェイスです
(see section 21.10 キーをバインドするためのコマンド)。
より汎用の関数define-keyを使うこともできますが、
変更対象のキーマップを明示する必要があります。
キー列の再バインドを書くときには、
コントロール文字やメタ文字向けの
特別なエスケープシーケンスを使うのがよいです(see section 2.3.8 文字列型)。
構文`\C-'は後続の文字がコントロール文字であること、
構文`\M-'は後続の文字がメタ文字であることを意味します。
したがって、文字列"\M-x"は単一のM-xを含むと読まれ、
"\C-f"は単一のC-fを含むと読まれ、
"\M-\C-x"や"\C-\M-x"はいずれも単一のC-M-xを
含むと読まれます。
同じエスケープシーケンスは、
ベクトルでも使え、文字列が許されない他の場面でも使えます。
たとえば、`[?\C-\H-x home]'です。
See section 2.3.3 文字型。
キーを定義したり探索する関数では、
ベクトルで表したキー列内のイベント型に対して別の構文、
つまり、修飾子名と1つの基本イベント(文字やファンクションキー名)
から成るリストを受け付けます。
たとえば、(control ?a)は?\C-aに等価であり、
(hyper control left)はC-H-leftに等価です。
このようなリストの利点の1つは、
コンパイル済みのファイルに修飾ビットの数値が現れないことです。
以下の関数では、keymapがキーマップでなかったり、 keyがキー列を表す文字列やベクトルでないと、エラーを通知します。 リストであるイベントの省略形としてイベント型(シンボル)を使えます。
define-keyが返す値はbindingである。
keyのおのおののプレフィックスはプレフィックスキーである
(キーマップにある)か未定義であること。
さもなければ、エラーを通知する。
keyのプレフィックスに未定義なものがあると、
define-keyは当該プレフィックスをプレフィックスキーと定義し、
keyの残りの部分を指定どおりに定義できるようにする。
keymapにkeyのバインディングがなければ、 新たなバインディングをkeymapの先頭に追加する。 キーマップ内のバインディングの順序は多くの場合関係ないが、 メニューキーマップでは意味を持つ(see section 21.12 メニューキーマップ)。
疎なキーマップを作成し、そこにバインディングを作る例を示します。
(setq map (make-sparse-keymap))
=> (keymap)
(define-key map "\C-f" 'forward-char)
=> forward-char
map
=> (keymap (6 . forward-char))
;; C-x用の疎なサブマップを作り、
;; そこにfのバインディングを入れる
(define-key map "\C-xf" 'forward-word)
=> forward-word
map
=> (keymap
(24 keymap ; C-x
(102 . forward-word)) ; f
(6 . forward-char)) ; C-f
;; C-pを |
C-p C-fに対する新しいバインディングは、
実際にはctl-x-mapの項目を変更していて、
これには、C-p C-fとデフォルトのグローバルキーマップ内の
C-x C-fの両方のバインディングを変更する効果がある
ことに注意してください。
nilを返す。
たとえば、Emacsの標準のバインディングであると、 つぎの例はC-x C-fを再定義する。
(substitute-key-definition 'find-file 'find-file-read-only (current-global-map)) |
oldmapがnil以外であると、
そのバインディングによってどのキーを再バインドするかを決定する。
再バインディングはkeymapで行い、oldmapではない。
つまり、別のキーマップ内のバインディングの制御のもとに、
キーマップを変更できる。
たとえば、
(substitute-key-definition 'delete-backward-char 'my-funny-delete my-map global-map) |
では、グローバルには標準の削除コマンドにバインドされているキーに対しては、
my-mapでは特別な削除コマンドにする。
変更前後のキーマップを以下に示す。
(setq map '(keymap
(?1 . olddef-1)
(?2 . olddef-2)
(?3 . olddef-1)))
=> (keymap (49 . olddef-1) (50 . olddef-2) (51 . olddef-1))
(substitute-key-definition 'olddef-1 'newdef map)
=> nil
map
=> (keymap (49 . newdef) (50 . olddef-2) (51 . newdef))
|
undefinedをバインドする。
これにより、通常のテキストの挿入を不可能にする。
suppress-keymapはnilを返す。
nodigitsがnilであると、
suppress-keymapは、
数字文字ではdigit-argumentを実行し、
-ではnegative-argumentを実行するように定義する。
さもなければ、それらも他の印字文字と同様に未定義にする。
関数suppress-keymapは、
yankやquoted-insertなどのコマンドを抑制しないので、
バッファを変更不可能にするわけではない。
バッファの変更を禁止するには、バッファを読み出し専用にする
(see section 26.7 読み出し専用バッファ)。
この関数はkeymapを変更するため、
読者は、通常、新たに作成したキーマップに対して使うであろう。
ある目的で使用中の既存のキーマップを操作すると、
問題を引き起こすことがある。
たとえば、global-mapに適用するとEmacsをほとんど使用不能にしてしまう。
多くの場合、テキストの挿入が必要なくバッファを読み出し専用で使う
rmailやdiredなどのモードのローカルキーマップの初期化に
suppress-keymapを使う。
ファイル`emacs/lisp/dired.el'から持ってきた例を示す。
これは、diredモード用のローカルキーマップの設定方法である。
(setq dired-mode-map (make-keymap)) (suppress-keymap dired-mode-map) (define-key dired-mode-map "r" 'dired-rename-file) (define-key dired-mode-map "\C-d" 'dired-flag-file-deleted) (define-key dired-mode-map "d" 'dired-flag-file-deleted) (define-key dired-mode-map "v" 'dired-view-file) (define-key dired-mode-map "e" 'dired-find-file) (define-key dired-mode-map "f" 'dired-find-file) ... |
本節では、キーのバインディングを変更する
便利で対話的なインターフェイスについて述べます。
これらは、define-keyを呼び出して動作します。
単純なカスタマイズのために
ファイル`.emacs'でglobal-set-keyをしばしば使います。
たとえば、
(global-set-key "\C-x\C-\\" 'next-line) |
や
(global-set-key [?\C-x ?\C-\\] 'next-line) |
や
(global-set-key [(control ?x) (control ?\\)] 'next-line) |
は、1行下がるようにC-x C-\を再定義します。
(global-set-key [M-mouse-1] 'mouse-set-point) |
は、メタキーを押し下げながらマウスの第1ボタン(左端)をクリックすると クリック位置にポイントを設定するように再定義します。
(global-set-key key definition) == (define-key (current-global-map) key definition) |
この関数の1つの用途は、 keyに非プレフィックスのバインディングがあると再定義できないため、 keyをプレフィックスとして使う長いキーを定義する前準備である。 たとえば、つぎのとおり。
(global-unset-key "\C-l")
=> nil
(global-set-key "\C-l\C-l" 'redraw-display)
=> nil
|
この関数は単にdefine-keyを使って実装してある。
(global-unset-key key) == (define-key (current-global-map) key nil) |
(local-set-key key definition) == (define-key (current-local-map) key definition) |
(local-unset-key key) == (define-key (current-local-map) key nil) |
本節では、ヘルプ情報を表示するために 現在のキーマップをすべて走査する関数について述べます。
(key . map)の形の要素から成る
連想リストである。
ここで、keyはプレフィックスキーであり、
keymap内でのその定義はmapである。
連想リスト内での要素の順番は、keyの長さが増える順である。
指定したキーマップkeymapはプレフィックスのイベントなしに参照できるので、
最初の要素はつねに("" . keymap)である。
prefixを与える場合、それはプレフィックスキー列であること。
すると、accessible-keymapsは、
prefixで始まるプレフィックスに対応したサブマップのみを含める。
それらの要素は、(accessible-keymaps)の値と同じに見えるが、
違いは、いくつかの要素が省略されることである。
つぎの例では、返された連想リストにおいては、
`^['と表示されたキーESCはプレフィックスキーであり、
その定義は疎なキーマップ
(keymap (83 . center-paragraph) (115 . foo))であることを表す。
(accessible-keymaps (current-local-map))
=>(("" keymap
(27 keymap ; Note this keymap for ESC is repeated below.
(83 . center-paragraph)
(115 . center-line))
(9 . tab-to-tab-stop))
("^[" keymap
(83 . center-paragraph)
(115 . foo)))
|
つぎの例では、C-hは、
疎なキーマップ(keymap (118 . describe-variable)...)を
使うプレフィックスキーである。
別のプレフィックスC-x 4は、
変数ctl-x-4-mapの値でもあるキーマップを使う。
イベントmode-lineは、
ウィンドウの特別な箇所におけるマウス操作を表すための
疑似イベントの1つである。
(accessible-keymaps (current-global-map))
=> (("" keymap [set-mark-command beginning-of-line ...
delete-backward-char])
("^H" keymap (118 . describe-variable) ...
(8 . help-for-help))
("^X" keymap [x-flush-mouse-queue ...
backward-kill-sentence])
("^[" keymap [mark-sexp backward-sexp ...
backward-kill-word])
("^X4" keymap (15 . display-buffer) ...)
([mode-line] keymap
(S-mouse-2 . mouse-split-window-horizontally) ...))
|
実際に表示されるキーマップはこれらだけとは限らない。
where-is
(see section `ヘルプ機能' in GNU Emacs マニュアル)が使う
サブルーティンである。
キーマップにおいてcommandにバインドされた
(任意長の)キー列のリストを返す。
引数commandは任意のオブジェクトであり、
キーマップ項目とはeqで比較する。
keymapがnilであると、
overriding-local-mapを無視
(つまり、その値はnilとみな)して、
現在活性なキーマップを使う。
keymapがnil以外であると、
keymapとグローバルキーマップから辿れるキーマップを使う。
通常、keymapに対する式にはoverriding-local-mapを使うのが
最良である。
そうすると、where-is-internalは正確に活性なキーマップを走査する。
グローバルキーマップのみを走査するには、
keymapとして(keymap)(空のキーマップ)を渡す。
firstonlyがnon-asciiであると、
戻り値は、可能なキー列のリストではなく、
最初にみつかったキー列を表す1つの文字列である。
firstonlyがtであると、
値は最初のキー列であるが、
ASCII文字(あるいはASCII文字のメタ変種)のみから成るキー列が
他のキー列より優先される。
noindirectがnil以外であると、
where-is-internalは間接項目を辿らない。
これにより、間接項目そのものを探すことができる。
(where-is-internal 'describe-function)
=> ("\^hf" "\^hd")
|
prefixがnil以外であると、それはプレフィックスキーであること。
そうすると、prefixで始まるキーのみの一覧を作る。
一覧では、メタ文字は、ESCに続けて対応する非メタ文字で表す。
連続したASCIIコードの一連の文字が同じ定義である場合には、
それらをまとめて`firstchar..lastchar'と表示する。
この場合、どの文字であるか理解するには、
ASCIIコードを知っている必要がある。
たとえば、デフォルトのグローバルキーマップでは、
`SPC.. ~'の文字が1行に表示される。
SPCはASCIIコード32、~はASCIIコード126であり、
そのあいだには普通の印字文字(英文字、数字文字、句読点文字など)が
すべて含まれる。
これらの文字はすべてself-insert-commandにバインドされている。
キーマップは、キーボードのキーやマウスボタンに対するバインディングに加えて メニューも定義できます。
| 21.12.1 メニューの定義 | How to make a keymap that defines a menu. | |
| 21.12.2 メニューとマウス | How users actuate the menu with the mouse. | |
| 21.12.3 メニューとキーボード | How they actuate it with the keyboard. | |
| 21.12.4 メニューの例 | Making a simple menu. | |
| 21.12.5 メニューバー | How to customize the menu bar. | |
| 21.12.6 メニューの修正 | How to add new items to a menu. |
キーマップに全面プロンプト文字列(overall prompt string)、
つまり、キーマップの要素として文字列が現れれば、
メニューとして使えます。
その文字列でメニューの目的を記述します。
プロンプト文字列を持ったキーマップを作成するもっとも簡単な方法は、
make-keymapやmake-sparse-keymap(see section 21.3 キーマップの作成)を
呼ぶときに、引数として文字列を指定します。
メニュー上での項目の順番は、
キーマップ内のバインディングの順番と同じです。
define-keyは、新たなバインディングを先頭に追加するので、
順番を気にするのならば、メニューの底の項目から始めて
上の項目へ向かってメニュー項目の定義を入れます。
既存のメニューに項目を追加する場合には、
define-key-after(see section 21.12.6 メニューの修正)を使って
メニュー内での位置を指定できます。
| 21.12.1.1 単純なメニュー項目 | A simple kind of menu key binding, limited in capabilities. | |
| 21.12.1.3 メニュー項目の別名 | Using command aliases in menu items. | |
| 21.12.1.2 拡張メニュー項目 | More powerful menu item definitions let you specify keywords to enable various features. |
メニューキーマップのバインディングを定義する単純で旧式の方法は つぎのとおりです。
(item-string . real-binding) |
CARのitem-stringは、メニューに表示される文字列です。 3単語までの短いものにし、対応するコマンドの動作を記述します。
つぎのように、ヘルプ文字列となる2つめの文字列も指定できます。
(item-string help-string . real-binding) |
現状では、Emacsは実際にはhelp-stringを使いません。 real-bindingを取り出すためにhelp-stringを無視する方法を 知っているだけです。 将来、ユーザーの要望に応じてメニュー項目に対する追加説明として help-stringを使うかもしれません。
define-keyに関する限り、
item-stringとhelp-stringは
イベントのバインディングの一部分です。
しかし、lookup-keyはreal-bindingのみを返し、
キーの実行にはreal-bindingのみが使われます。
real-bindingがnilであると、
item-stringはメニューに現れますが、それは選択できません。
real-bindingがシンボルであり、
その属性menu-enableがnil以外であると、
当該属性は、メニュー項目を活性にするかどうかを制御する式です。
Emacsは、メニューを表示するためにキーマップを使うたびに、
その式を評価し、式の値がnil以外である場合に限り、
当該メニュー項目をオンにします。
メニュー項目がオフであると、『薄く』表示し、それは選択できません。
メニューバーでは、読者がメニューを見るたびにどの項目がオンであるかを
再計算しません。
Xツールキットがあらかじめメニューの木構造全体を必要とするからです。
メニューバーの再計算を強制するには、
force-mode-line-updateを呼び出します。
(see section 22.3 モード行の書式)。
メニュー項目には、同じコマンドを起動する等価なキーボードのキー列が (あれば)表示されていることに気づいたと思います。 再計算の時間を節約するために、 メニューの表示では、この情報をつぎのように バインディングの部分リストに隠し持っています。
(item-string [help-string] (key-binding-data) . real-binding) |
読者は、メニュー項目にこれらの部分リストを入れないでください。 それらはメニューの表示で自動的に計算されます。 冗長になるので、項目の文字列には、等価なキーボード入力を 含めないでください。
拡張形式のメニュー項目は、より柔軟性があり、
単純な形式より見通しがよい代替方法です。
それらは、シンボルmenu-itemで始まるリストから成ります。
選択不可の文字列を定義するには、項目をつぎのようにします。
(menu-item item-name) |
ここで、文字列item-nameは区切り行を表す複数個のダッシュから成ります。
選択可能な実際のメニュー項目を定義するには、 拡張形式の項目はつぎのようになります。
(menu-item item-name real-binding
. item-property-list)
|
ここで、item-nameは、メニュー項目の文字列に評価される式です。 つまり、(項目の)文字列は定数である必要はありません。 3番目の要素item-property-listは実行すべきコマンドです。 リストの残りitem-property-listは、 他の情報を含んだ属性リストの形式です。 指定できる属性はつぎのとおりです。
:enable FORM
nil以外だとオン)。
:visible FORM
nil以外だと含める)。
項目を含めない場合、当該項目が定義されていないかのようにメニューを表示する。
:help help
:button (type . selected)
:toggleか:radioであり、
どちらであるかを指定する。
CDRのselectedはフォームであること。
その評価結果が、現在ボタンが選択されているかどうかを決定する。
トグル(toggle)は、selectedの値に応じて
『on』か『off』と書かれるメニュー項目である。
コマンド自身では、selectedがnilならば
selectedにtを設定し、
tならばnilを設定すること。
以下は、debug-on-errorが定義されていれば
debug-on-errorをオン/オフするメニュー項目の書き方である。
(menu-item "Debug on Error" toggle-debug-on-error
:button (:toggle
. (and (boundp 'debug-on-error)
debug-on-error))
|
これは、変数debug-on-errorをオン/オフするコマンドとして
toggle-debug-on-errorが定義されているので動作する。
ラジオボタン(radio button)はメニュー項目のグループであり、 ある時点ではそれらのうちの1つだけを『選択』できる。 どれを選択しているかを表す変数が必要である。 グループ内の各ラジオボタンに対するフォームselectedは、 当該変数の値が当該ボタンを選択している値かどうかを検査する。 ボタンをクリックすると、クリックしたボタンが選択されるように 当該変数に設定すること。
:key-sequence key-sequence
まちがったキー列を指定しても、その効果はない。 メニューにkey-sequenceを表示するまえに、 Emacsはkey-sequenceがこのメニュー項目に実際に等価かどうか調べる。
:key-sequence nil
しかし、ユーザーがこの項目の定義に対してキー列を再バインドすると、
Emacsは属性:keysを無視して等価なキーボード入力を探す。
:keys string
:filter filter-fn
『同じ』コマンドを使いながらオン条件が異なるメニュー項目を
作れると便利なことがあります。
現状のEmacsでこれを行う最良の方法は、拡張メニュー項目を使うことです。
この機能がなかった頃には、コマンドの別名を定義し、
それをメニュー項目で使うことで可能でした。
異なるオン条件でtoggle-read-onlyを
使う2つの別名の作り方を以下に示します。
(defalias 'make-read-only 'toggle-read-only) (put 'make-read-only 'menu-enable '(not buffer-read-only)) (defalias 'make-writable 'toggle-read-only) (put 'make-writable 'menu-enable 'buffer-read-only) |
メニューに別名を使うときには、
(典型的にはメニュー以外にはキーバインディングがない)別名ではなく
『本物の』コマンド名に対する等価なキーバインディングを
表示しするのがしばしば有用です。
これを行うには、別名のシンボルには
nil以外の属性menu-aliasを与えます。
(put 'make-read-only 'menu-alias t) (put 'make-writable 'menu-alias t) |
こうすると、make-read-onlyとmake-writableのメニュー項目には
toggle-read-onlyに対するキーバインディングが表示されます。
メニューキーマップがメニューを表示するようにする普通の方法は、 メニューキーマップをプレフィックスキーの定義にすることです。 (Lispプログラムから明示的にメニューをポップアップして、 ユーザーの選択を受け取れる。 28.15 ポップアップメニューを参照。)
プレフィックスキーがマウスイベントで終っていると、 Emacsはメニューをポップアップすることでメニューキーマップを扱います。 これで、ユーザーはマウスで選択できるようになります。 ユーザーがメニュー項目をクリックすると、 当該メニュー項目をバインディングとする文字やシンボルが イベントとして生成されます。 (メニューが複数レベルになっていたりメニューバーから開いたときには、 メニュー項目は一連のイベントを生成する。)
メニューの開始にはボタン押し下げイベントを使うのがしばしば最良です。 そうすると、ユーザーはボタンを離すことでメニュー項目を選べます。
明示的に配置すれば、1つのキーマップをメニューペインとして表示できます。 それには、各ペインに対するキーマップを作成し、 つぎに、メニューのメインのキーマップにおいて、 (各ペインの)各キーマップに対するバインディングを作ります。 なお、これらのバインディングには、 `@'で始まる項目文字列を指定します。 項目文字列の残りの部分がペインの名前になります。 この例についてはファイル`lisp/mouse.el'を参照してください。 `@'で始まらない項目文字列の他の普通のバインディングは 1つのペインにまとめられ、サブマップに対して明示的に作られた 他のペインとともに表示されます。
Xツールキットのメニューにはペインはありませんが、 そのかわりに、サブメニューがあります。 項目文字列が`@'で始まるかどうかに関わらず、 入れ子になった各キーマップがサブメニューになります。 Emacsのツールキット版では、項目文字列の先頭の`@'に関して特別なことは、 `@'がメニュー項目に表示されないことです。
個別のキーマップからも複数ペインやサブメニューを作成できます。 プレフィックスキーの完全な定義は、 さまざまな活性のキーマップ(マイナモード、ローカル、グローバル)が与える 定義を併合することで得られます。 これらのキーマップのうち複数個がメニューであるとき、 そのおのおのが別々のペイン(Xツールキットを使わないEmacs)や 別々のサブメニュー(Xツールキットを使ったEmacs)になります。 See section 21.6 活性なキーマップ。
キーボードイベント(文字や関数)で終るプレフィックスキーに、 メニューキーマップであるような定義があると、 ユーザーはメニュー項目を選ぶためにキーボードを使えます。
Emacsはメニューの選択項目(バインディングの項目文字列)を
エコー領域に表示します。
それらが1行に収まらなければ、
ユーザーはSPCを打つことで選択項目のつぎの行を見ることができます。
SPCを連続して使うと最終的にはメニューの最後に達し、
そうするとメニューの先頭に戻ります。
(変数menu-prompt-more-charに、このために用いる文字を指定する。
デフォルトはSPC。)
ユーザーは、メニューから望みの項目をみつけたら、 対応する文字、つまり、その項目のバインディングを持つ文字を打ちます。
Emacs類似エディタにおけるこのようなメニューの使い方は、 システムHierarkeyに触発されたからです。
以下に、メニューキーマップの完全な定義の例を示します。 これは、メニューバーのメニュー`Tools'の サブメニュー`Print'の定義であり、 単純なメニュー項目を使います (see section 21.12.1.1 単純なメニュー項目)。 まず、キーマップを作成し名前を与えます。
(defvar menu-bar-print-menu (make-sparse-keymap "Print")) |
つぎに、メニュー項目を定義します。
(define-key menu-bar-print-menu [ps-print-region]
'("Postscript Print Region" . ps-print-region-with-faces))
(define-key menu-bar-print-menu [ps-print-buffer]
'("Postscript Print Buffer" . ps-print-buffer-with-faces))
(define-key menu-bar-print-menu [separator-ps-print]
'("--"))
(define-key menu-bar-print-menu [print-region]
'("Print Region" . print-region))
(define-key menu-bar-print-menu [print-buffer]
'("Print Buffer" . print-buffer))
|
バインディングが『作られる対象』のシンボルに注意してください。
定義されるキー列の角括弧の内側に現れています。
そのシンボルはコマンド名に等しい場合もあればそうでない場合もあります。
これらのシンボルは『ファンクションキー』として扱われますが、
キーボード上の本物のファンクションキーではありません。
それらはメニュー項目の機能には影響ありませんが、
ユーザーがメニューから選ぶとそれらはエコー領域に『表示』され、
where-isやaproposの出力にも現れます。
定義が("--")であるようなバインディングは区切り行です。
実際のメニュー項目のように、区切りにもキーシンボルがあり、
例ではseparator-ps-printです。
1つのメニューに複数の区切りがある場合、
それらはすべて異なるキーシンボルでなければなりません。
つぎには、メニュー内の2つのコマンドのオン条件を定義するコードです。
(put 'print-region 'menu-enable 'mark-active) (put 'ps-print-region-with-faces 'menu-enable 'mark-active) |
つぎは、このメニューを親メニューの項目に現れるようにする方法です。
(define-key menu-bar-tools-menu [print] (cons "Print" menu-bar-print-menu)) |
ここで使っているのは、サブメニューのキーマップ、つまり、
変数menu-bar-print-menuの値であって、
変数そのものではないことに注意してください。
menu-bar-print-menuはコマンドではないので、
このシンボルを親メニューの項目に使っても意味がありません。
同じ印刷メニューをマウスクリックに対応付けたければ、 つぎのようにしてできます。
(define-key global-map [C-S-down-mouse-1] menu-bar-print-menu) |
つぎのようにして、print-regionに対して拡張メニュー項目
(see section 21.12.1.2 拡張メニュー項目)を使うこともできます。
(define-key menu-bar-print-menu [print-region]
'(menu-item "Print Region" print-region
:enable (mark-active)))
|
拡張メニュー項目では、オン条件はメニュー項目自体の内側に指定します。 マークがないときにはメニューからこの項目が消えるようにするには つぎのようにします。
(define-key menu-bar-print-menu [print-region]
'(menu-item "Print Region" print-region
:visible (mark-active)))
|
ほとんどのウィンドウシステムでは、
各フレームにメニューバー(menu bar)、
つまり、フレームの先頭に水平方向に延びているメニューを恒久的に表示できます。
メニューバーの項目は、すべての活性なキーマップで定義された
疑似『ファンクションキー』menu-barのサブコマンドです。
メニューバーに項目を追加するには、
読者独自の疑似『ファンクションキー』を考え(これをkeyとする)、
キー列[menu-bar key]に対するバインディングを作ります。
多くの場合、バインディングはメニューキーマップであって、
メニューバーの項目上でボタンを押すと別のメニューへ至るようにします。
メニューバーに対する同じ疑似ファンクションキーを 複数の活性なキーマップで定義していても、1つの項目だけが表示されます。 ユーザーがメニューバーの当該項目をクリックすると、 当該項目のすべてのサブコマンド、つまり、 グローバルのサブコマンド、ローカルのサブコマンド、 マイナモードのサブコマンドを含む1つの複合メニューが表示されます。
メニューバーの内容を決定する際には、
通常、変数overriding-local-mapは無視されます。
つまり、overriding-local-mapがnilであるときに
活性になるキーマップからメニューバーを計算します。
See section 21.6 活性なキーマップ。
フレームにメニューバーを表示するには、
フレームのパラメータmenu-bar-linesが0より大きい必要があります。
Emacsはメニューバーそのものには1行だけ使います。
読者が2行以上を指定すると、
残りの行はフレームのウィンドウとメニューバーを区切る行になります。
menu-bar-linesの値には1か2を勧めます。
See section 28.3.3 ウィンドウフレームのパラメータ。
メニューバーの項目の設定例を示します。
(modify-frame-parameters (selected-frame)
'((menu-bar-lines . 2)))
;; (プロンプト文字列を持つ)メニューキーマップを作り
;; それをメニューバーの項目の定義にする
(define-key global-map [menu-bar words]
(cons "Words" (make-sparse-keymap "Words")))
;; このメニュー内のサブコマンドを定義する
(define-key global-map
[menu-bar words forward]
'("Forward word" . forward-word))
(define-key global-map
[menu-bar words backward]
'("Backward word" . backward-word))
|
グローバルキーマップに作ったメニューバー項目を
ローカルキーマップで取り消すには、
ローカルキーマップの当該疑似ファンクションキーのバインディングを
undefinedで再バインドします。
たとえば、つぎのようにしてdiredはメニューバーの項目`Edit'を抑制します。
(define-key dired-mode-map [menu-bar edit] 'undefined) |
editは、メニューバー項目`Edit'に対して
グローバルキーマップで使う疑似ファンクションキーです。
グローバルなメニューバー項目を抑制する主な理由は、
モード固有の項目向けに場所を確保するためです。
この変数は、通常の順ではなくメニューバーの底に表示する項目に
対する疑似ファンクションキーのリストを保持する。
デフォルト値は(help-menu)であり、
したがって、ローカルのメニュー項目に続いて、
メニュー項目`Help'はメニューバーの最後に通常表示される。
既存のメニューに新たな項目を挿入するとき、
メニューの既存の項目の特定の場所に挿入したいでしょう。
define-keyで項目を追加すると、通常、メニューの先頭に入ります。
メニューのそれ以外の場所に挿入するには、
define-key-afterを使います。
tであると、新たなバインディングは最後、
つまり、キーマップの末尾に入る。
例を示す。
(define-key-after my-menu [drink]
'("Drink" . drink-command) 'eat)
|
これは、疑似ファンクションキーDRINKに対するバインディングを作り、 EATに対するバインディングのあとに入れる。
shellモードのメニュー`Signals'において、
項目breakのあとに項目`Work'を入れる方法はつぎのとおりである。
(define-key-after
(lookup-key shell-mode-map [menu-bar signals])
[work] '("Work" . work-command) 'break)
|
| [ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |