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

19. キーマップ

入力イベントとコマンドとのバインドはキーマップ(keymap)と呼ばれる データ構造に記録されています。キーマップの中のそれぞれのバインドは、個々 のイベント・タイプを別のキーマップやコマンドに関連づけ(またはバイン ド(bind)(15)し)ます。あるイベントがキーマップにバインドされたときは、次の入力 イベントを調べるのにそのキーマップを使います。これはコマンドが見つかるま で続けられます。この処理全体のことをキー検索(key lookup)と呼びます。


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

19.1 キーマップの用語

キーマップ(keymap)はイベント・タイプと定義(どんなLispオブジェクト でも構いませんが、コマンド・ループで実行することができる型でなければなりま せん)を対応づける表です。イベント(またはイベント・タイプ)とキーマップが 与えられれば、Emacsはそのイベントの定義を得ることができます。イベントに は通常ASCII文字、ファンクション・キー、マウスの動作が含まれます (see section 入力イベント)。

一つの単位を構成する一連の入力イベントをキー・シーケンス(key sequence)、または略し てキー(key)と呼びます。一つのイベントは常にキー・シーケンスですし、ある複 数のイベントのまとまりもそうです。

キーマップはどんなキー・シーケンスに対してもバインドや定義を決定します。 キー・シーケンスが一つのイベントの場合、そのイベントの定義は最初のキーマッ プのバインドです。複数のイベントからなるキー・シーケンスのバインドは、反 復処理で求めます。まず、最初のイベントのバインドを探します。それはキーマッ プのはずです。次に2番目のイベントのバインドをそのキーマップの中から探し ます。これをキー・シーケンスの全てのイベントを使い切るまで繰り返します。

あるキー・シーケンスのバインドがキーマップであるとき、そのキー・シーケン スを前置キー(prefix key)と呼びます。そうでなければ、完結キー (complete key)と呼びます(つけ加えるイベントがないので)。バインドが nilのときは未定義の(undefined)キーと呼びます。前置キーの例 としては、C-cC-xC-x 4があります。定義済みの完結キー の例としては、XRETC-x 4 C-fがあります。未定義の完 結キーの例としては、C-x C-gC-c 3があります。詳細は See section 前置キー

キー・シーケンスのバインドを探す規則により、中間のバインド(最後のイベント より前のイベントのバインド)は全てキーマップだとみなします。そうでないなら その一連のイベントは一つの単位ではありません。つまり本当のキー・シーケンス ではありません。言い替えると、正しいキーの後ろの方からいくつかのイベント を取り除くと、必ず前置キーになります。たとえば、C-f C-n はキーではありません。C-fは前置キーではないので、 C-fではじまる、より長いシーケンスもキーになることはありません。

複数のイベントからなる可能なキー・シーケンスの集合は、前置キー のバインドに依存していることに注意してください。したがって、違うキーマッ プでは違う集合になり得ますし、バインドを変更すれば変わり得ます。しかし、 単独のイベントが正しいキーかどうかはどの前置キーにも依存しない ので、常にキー・シーケンスです。

どんなときでも、いくつかの基本キーマップがアクティブ(active)になっ ています--すなわち、キー・バインドを探すのに使われます。それらは全ての バッファで共有されるグローバル・マップ(global map)と、通常指定され ている主モードのローカル・キーマップ(local keymap)と、現在使用して いる副モードに付随する副モード・キーマップ(minor mode keymap)です (全ての副モードがキーマップをもつわけではありません)。副モード・キーマッ プはないかもしれませんし、複数あるかもしれません。ローカル・キーマップの バインドは対応するグローバル・マップのバインドを隠します(すなわち優先さ れます)。副モード・キーマップはローカルとグローバルのキーマップの両方を 隠します。詳しくはSee section アクティブ・キーマップ


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

19.2 キーマップのフォーマット

キーマップはそのCARがシンボルkeymapであるリストです。リスト の残りの要素がそのキーマップのキー・バインドを定義します。あるオブジェク トがキーマップかどうかをテストするには、関数keymapp(以下を見てくだ さい)を使ってください。

それぞれの普通のバインドは特定のイベント・タイプ(event type)(たいて い文字やシンボルです)のイベントに適用されます。See section イベントの分類

キーマップの普通の要素は(type . binding)という形式の コンス・セルです。これはイベント・タイプtypeに対するバインドを一つ指定 します。

CARtであるようなコンス・セルはデフォルト・キー・バインド (default key binding)です。キーマップのほかの要素でバインドされない全て のイベントは、与えられたbindingにバインドされます。デフォルト・バイ ンドを使うと、起こりうる全てのイベント・タイプをいちいち列挙しないでもバイ ンドすることができます。デフォルト・バインドがあるキーマップは、より低い優 先度のキーマップを完全に隠してしまいます。

キーマップのある要素がベクタならば、そのベクタは全てのASCII文字 のバインドとみなされます。ベクタの要素nはコードnの文字のバ インドになります。これはたくさんのバインドを記録するコンパクトなやり方で す。このようなベクタを含むキーマップを密なキーマップ(full keymap)と呼びます。そうでないキーマップは疎なキーマップ(sparse keymap)といいます。

キーマップがベクタを含んでいる場合は、そのベクタは、もし要素が nilだったとしても常に全てのASCII文字のバインドを定義します。 そのようなnilのバインドは、そのキーマップのどんなデフォルト・バイン ドも無効にします。しかし、デフォルト・バインドはASCII文字以外のイベン トに対しては依然として有効です。nilのバインドは優先度の低いキーマッ プを無効にしません。したがって、ローカル・マップにnilのバイ ンドがある場合、Emacsはグローバル・マップのバインドを使います。

バインドはさておき、キーマップは文字列も要素としてもつことができます。こ れを見出し文字列(overall prompt string)と呼び、キーマップをメニュー として使えるようにしています。See section メニュー・キーマップ

キーマップにはメタ文字(コードが128から255の文字)のバインドを直接記録する ことはできません。その代わり、キー検索のためにメタ文字を最初の文字が ESC(または、現在のmeta-prefix-charの値)である2文字のシーケ ンスとみなします。したがって、M-aというキーは実際には ESC aと表され、そのグローバル・バインドはesc-mapの中の aの位置に見い出されます(see section 前置キー)。

次に示すのはLispモードのローカル・キーマップの例です。これは疎なキーマップ で、DELTABに加えてC-c C-lM-C-qM-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-qESC C-qとして扱われる
     (17 . indent-sexp)                 
     ;; M-C-xESC C-xとして扱われる
     (24 . lisp-send-defun)))           
Function: keymapp object

この関数はobjectがキーマップのときはtを、そうでないときは nilを返します。もっと正確にいうと、この関数はリストのCARkeymapであるかどうかテストをします。

 
(keymapp '(keymap))
    ⇒ t
(keymapp (current-global-map))
    ⇒ t

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

19.3 キーマップの作成

ここではキーマップを作成するための関数について説明します。

Function: make-keymap &optional prompt

この関数は、新しい密な(すなわち、全てのASCII文字を定義するための長 さが128のベクタの含む)キーマップを作成し、返します。新しいキーマップの 全てのASCII文字のバインドの初期値はnilで、それ以外のどの種類 のイベントもバインドしません。

 
(make-keymap)
    ⇒ (keymap [nil nil nil … nil nil])

promptを指定すると、そのキーマップの見出し文字列になります。見出し 文字列はメニュー・キーマップのために役立ちます。(see section メニュー・キーマップ)。

Function: make-sparse-keymap &optional prompt

この関数は何も登録されていない新しい疎なキーマップを作成し、返します。新 しいキーマップはどんなイベントもバインドしません。引数promptには make-keymapと同様に見出し文字列を指定します。

 
(make-sparse-keymap)
    ⇒ (keymap)
Function: copy-keymap keymap

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

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

19.4 継承とキーマップ

キーマップは、別のキーマップのバインドを継承することができます。これを 行なうには、キーマップの"最後"を別に存在する継承したいキーマップにし ます。キーマップはこのようになります:

 
(keymap bindings… . other-keymap)

このキーマップは、キーを検索するときにother-keymapに存在する すべてのバインドを受け継ぎますが、bindingsでそれらのバインド を上書きしたりつけ加えたりすることができます。

other-keymapのバインドをdefine-keyやほかのキー・バインド関数を 使って変更すると、その変更がbindingsで隠されていないかぎり継承してい るキーマップにも反映されます。逆は真ではありません。define-keyを 使って継承しているキーマップを変更した場合はbindingsに作用し、 other-keymapには何の影響もありません。

text-mode-mapを継承するキーマップの作り方の例を次に示します:

 
(setq my-mode-map (cons 'keymap text-mode-map))

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

19.5 前置キー

前置キー(prefix key)は、その前置キーではじま るキー・シーケンスが何をするのかを定義するキーマップと結びつけられています。 たとえば、C-xは前置キーで、変数ctl-x-mapに入っ ているキーマップを使います。Emacsの標準の前置キーとそれらの キーマップの一覧を示します:

前置キーのバインドは、その前置キーに続くイベントを検 索するために使うキーマップです(キーマップの代わりに、関数定義がキー マップであるようなシンボルでも構いません。効果は同じですが、シンボルは前置キーの名前になります)。そういうわけで、C-xのバインド は、関数定義がC-xコマンドのキーマップであるシンボル Control-X-prefixとなります(ctl-x-mapの値も同じキーマップ になります)。

前置キーの定義はどのアクティブなキーマップにも存在することがで きます。C-cC-xC-hESCの前置キーと しての定義はグローバル・マップに存在しますので、これらの前置キー は常に使えます。主モードと副モードは、ローカル・マップまたは副モードのマップで前置キーとして定義することによって、ある キーを前置キーとして定義し直すことができます。See section アクティブ・キーマップ

あるキーが複数のアクティブなマップで前置キーとして定義されている場 合は、実際にはそのさまざまな定義は合成されます。副モード・キーマップで定 義されたコマンドが最初に来て、次にローカル・キーマップの、最後にグローバ ル・マップのが来ます。

下記の例では、C-pC-xと等価にすることによってローカル・キーマップでC-pを前置キーにしています。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
Function: define-prefix-command symbol

この関数はsymbolを前置コマンドとして定義します。すなわち、 密なキーマップを作成して、それをsymbolの関数定義とします。あるキー のバインドをシンボルにすると、そのキーは名前つきの前置キーに なります。また、この関数はsymbolをそのキーマップを値とする変数にし ます。返り値はsymbolです。

Emacsバージョン18では、この関数はsymbolの関数定義をセットするだけ で、変数の値はセットしません。


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

19.6 アクティブ・キーマップ

通常、Emacsはたくさんのキーマップを持っていますが、任意の時点でその中のい くつかがアクティブ(active)、すなわちユーザの入力を解釈するのに関係 しています。そのいくつかとは、グローバル・キーマップ、カレント・バッファ のローカル・キーマップ、使用中の全ての副モードのキーマップです。

グローバル・キーマップ(global keymap)には、C-fのような、カレ ント・バッファに関係なしに定義されるキーのバインドが入っています。変数 global-mapにこのキーマップが納められています。このキーマップは常 にアクティブです。

バッファはそれぞれローカル・キーマップ(local keymap)という、キーの 新たな定義や更新を行なう別のマップをもつことができます。カレント・バッファの ローカル・キーマップは、overriding-local-mapによって無効にされな いかぎり常にアクティブです。テキスト属性によって、バッファの特定部分に対 して別のローカル・マップを指定することができます。特殊な意味をもつ属性参照。

それぞれの副モードはキーマップをもつことができます。ある副モードが使用されると、そのモードがキーマップを持っていればアクティブになりま す。

変数overriding-local-mapが非nilで、別のローカル・キーマップ を指定している場合、バッファのローカル・マップと全ての副モード・キーマッ プは無効になり、その指定されたキーマップが使われます。

キーが入力されたとき、どのコマンドを実行すればいいかを決定するために、全 てのアクティブなキーマップが一緒に使われます。Emacsは、どれかのマップで バインドが見つかるまで、優先順位にしたがってこれらのマップを順々に探して いきます。

通常、Emacsは最初に副モード・マップ群(一度には一つのマップ)でキー を探します。そのキーのバインドがその中では見つからないときは、ローカル・ マップで探します。そこでも見つからなければ、グローバル・マップで探します。 ですが、overriding-local-mapが非nilのときは、最初にそのマッ プで探して、次にグローバル・マップで探します。

単独のキーマップで探す手続きのことをキー検索(key lookup)といいます。 キー検索参照。

同じ主モードを使っている全てのバッファは、通常同じローカル・キーマップを使っているので、ローカル・キーマップはモードごとに存在すると考えられま す。あるバッファのローカル・キーマップを(たとえば、local-set-keyを 使って)変更すると、同じキーマップを共有している別のバッファにも影響しま す。

LispモードやCモードなどいくつかの主モードで使われるローカル・キーマップ は、それらのモードが一度も使われていなくても存在します。これらのローカル・ マップは変数lisp-mode-mapc-mode-mapというような変数の値 です。そのほかのほとんどのモード、あまり頻繁には使われないモードのローカ ル・キーマップはそのモードがセッション中ではじめて使われたときにだけ作ら れます。

ミニバッファにもローカル・キーマップがあり、その中には補完や脱出のコマンド があります。See section ミニバッファの紹介

標準キーマップの一覧は、See section 標準のキーマップ

Variable: global-map

この変数にはEmacsのキーボード入力とコマンドを対応させるデフォルトのグロー バル・キーマップが入っています。通常、グローバル・キーマップはこのキーマッ プです。デフォルトのグローバル・キーマップは、全ての印字可能文字を self-insert-commandにバインドする、密なキーマップです。

グローバル・マップのバインドを変更することはよく行なわれますが、この変数を起 動時のキーマップ以外の値に割り当ててはいけません。

Function: current-global-map

この関数は現在のグローバル・キーマップを返します。グローバル・マップの値を変 更していないかぎりglobal-mapの値と同じです。

 
(current-global-map)
⇒ (keymap [set-mark-command beginning-of-line … 
            delete-backward-char])
Function: current-local-map

この関数はカレント・バッファのローカル・キーマップか、それが存在しない場 合はnilを返します。以下に示す例は、`*scratch*'バッファ(Lisp Interactionモードを使用しています)のキーマップで、疎なキーマップになって います。ESC、すなわちASCIIコード27のエントリーが別の疎なキー マップになっています。

 
(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)))
Function: current-minor-mode-maps

この関数は現在使用中の副モードのキーマップのリストを返します。

Function: use-global-map keymap

この関数はkeymapを新しい現在のグローバル・キーマップにします。 nilを返します。

グローバル・キーマップを変更するのは非常にまれなことです。

Function: use-local-map keymap

この関数はkeymapをカレント・バッファの新しいローカル・キーマップに します。keymapnilなら、バッファはローカル・キーマップを持 ちません。use-local-mapnilを返します。ほとんどの主モー ド・コマンドはこの関数を使用しています。

Variable: minor-mode-map-alist

この変数は、ある変数の値にしたがってアクティブになったりならなかったりす るキーマップを記述するalistです。この変数の要素はこのようになっています:

 
(variable . keymap)

キーマップkeymapvariableが非nilの値を持っているとき にアクティブになります。一般的に、variableは副モードの使用、 不使用を切替える変数です。See section キーマップと副モード

minor-mode-map-alistの要素はminor-mode-alistの要素と同じ構 造ではないことに注意してください。マップは要素のCDRでなくてはなりま せん。マップのリストが2番目の要素になっているのでは駄目です。

さらに、キーマップ自身がCDRになっていなくてはなりません。マップが入っ ている変数がCDRになっていても駄目です。

複数の副モード・キーマップがアクティブになっているとき、それらの優先 順位はminor-mode-map-alistの順番です。ですが、お互いの邪魔をしな いように副モードを設計しなくてはなりません。これをちゃんと守れば、 順番は問題になりません。

下記のminor-mode-key-bindingも参照してください。副モードに ついての詳細はキーマップと副モードを参照してください。

Variable: overriding-local-map

nilの場合、この変数にはバッファのローカル・キーマップと全ての副 モード・キーマップの代わりに使われるキーマップが入っています。このキー マップは、もし存在すれば、現在のグローバル・マップ以外の全てのアクティブな マップを無効にします。

Variable: overriding-local-map-menu-flag

この変数が非nilのとき、overriding-local-mapの値はメニュー・バーの表示に影響します。デフォルト値はnilですので、 overriding-local-mapはメニュー・バーには何の影響も与えません。

overriding-local-mapは、メニュー・バー表示に影響を与えないときで も、メニュー・バーを使って入力されたキー・シーケンスの実行には影響を及ぼ すことに注意してください。ですから、メニュー・バー・キー・シーケンスが入 力されるときには、そのキー・シーケンスが検索されて実行される前に overriding-local-mapをクリアしなければなりません。一般的に、 overriding-local-mapを使うモードは何らかの方法でこれを行ないます。 普通は扱わないイベントを受けとったときに"読み戻して"抜けることによって行 ないます。


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

19.7 キー検索

キー検索(key lookup)とは与えられたキーマップからキー・シーケンスの バインドを探す処理のことをいいます。バインドの実際の実行はキー検索には含 まれません。(16)

キー検索ではキー・シーケンス中のイベントそれぞれのイベント・タイプのみを使い、 イベントの残りの部分は無視します。実際、キー検索に使うキー・シーケンスでは、 マウス・イベント全体(リスト)の代わりにそれらのタイプ(シンボル)だけで、マウ ス・イベントを指示しても構いません。See section 入力イベント。このような疑似キー・シーケンスはcommand-executeには不十分ですが、キーを検索したりバイ ンドし直すには十分です。

キー・シーケンスが複数のイベントから成り立っている場合は、キー検索はイベン トを順々に処理していきます。まず、最初のイベントのバインドを探します。そ れはキーマップのはずです。次に2番目のイベントのバインドをそのキーマップ の中から探します。これをキー・シーケンスの全てのイベントを使い切るまで繰り 返します(このように探し出された最後のイベントのバインドは、キーマップ のこともありますし、そうでないこともあります)。このようにキー検索の処理 は、あるキーマップから一つのイベントを捜し出す単純な処理と定義できます。 どのようにそれを行なうかは、キーマップでイベントと結びつけられているオブ ジェクトのタイプによります。

キーマップでイベント・タイプに結びつけられている値をキーマップ・エント リー(keymap entry)という用語で呼ぶことにしましょう(これにはメニュー・キー・バインドの項目文字列やほかの特別な要素は含まれません。lookup-key やほかのキー検索の関数の返り値にはそれらは含まれないからです)。どんな Lispオブジェクトがキーマップにキーマップ・エントリーとして納められていても 構いませんが、全てが意味をなすわけではありません。有効なキーマップ・エント リーの種類の一覧を示します:

nil

nilは、検索中にここまで使われたイベント群は未定義のキーになること を意味します。あるキーマップ中であるイベント・タイプを探すのに失敗し、さら にデフォルトのバインドがなかった場合は、そのイベント・タイプはnilに バインドされているのと等価です。

keymap

検索中にここまで使われたイベント群は前置キーになります。キー・シーケンスの次のイベントはkeymap中で探します。

command

検索中にここまで使われたイベント群は完結キーになり、commandが そのバインドです。See section 関数とは

array

配列(文字列またはベクタのどちらでも)はキーボード・マクロです。検索中に ここまで使われたイベント群は完結キーになり、この配列がそのバインドです。 詳しくはキーボード・マクロ参照。

list

リストの意味はリストの要素のタイプによります。

symbol

symbolの代わりにsymbolの関数定義が使われます。それもシンボル だったら、この処理が何度でも繰り返されます。最終的には、キーマップかコマ ンドかキーボード・マクロかのいずれかのオブジェクトが出てくるはずです。リス トは、それがキーマップかコマンドならば許されますが、間接エントリーはシン ボル経由で出てきた場合は認識されません。

注意して欲しいのは、キーマップやキーボード・マクロ(文字列とベクタ)は正し い関数ではなく、同様にその関数定義がキーマップ、文字列、ベクタであるよ うなシンボルは関数としては正しくないことです。しかしながら、キー・バインド としては正当です。関数定義がキーボード・マクロであるようなシンボルは、 command-executeの引数としても正しいものです。

シンボルundefinedは、特別に言及する価値があります。このシンボルは キーが未定義扱いになることを意味します。正確にいえば、キーは定義されてい て、そのバインドはコマンドundefinedです。しかし、このコマンドは未 定義キーが自動的に行なうのと同じことを行ないます。(dingを呼び出す ことによって)ベルを鳴らしますが、エラーのシグナルは発生しません。

undefinedはローカル・キーマップで、グローバル・キー・バインドを無 効にして、あるキーをローカルに"未定義"にするために使われます。ローカル でnilにバインドしても、グローバル・バインドを無効にできないのでう まくいきません。

anything else

これら以外のタイプのオブジェクトが出てきたら、ここまでの検索に使われたイ ベント群は完結キーになり、そのバインドはそのオブジェクトになりますが、そ れはコマンドとしては実行できないバインドです。

要するに、キーマップ・エントリーは、キーマップ、コマンド、キーボード・マクロ、 またはそれらのどれかを導くシンボル、もしくは間接エントリーかnilに なります。 次の例は、コマンドにバインドされた二つの文字と別のキーマップにバインドさ れた一つの文字をもつ疎なキーマップです。このマップは 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)))

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

19.8 キー検索のための関数

これらはキー検索関連の関数と変数です。

Function: lookup-key keymap key &optional accept-defaults

この関数はkeymapでのkeyの定義を返します。文字列またはベクタ であるkeyが、keymapで指定された前置キーにしたがっても正しい キー・シーケンスにならないときは(つまり、"長過ぎ"て余分なイベントが最 後にある)、返り値はkeyの先頭から完結キーをなすイベントの数になりま す。

accept-defaultsが非nilならば、lookup-keykey で指定されたイベントのバインドと同様にデフォルト・バインドも考慮します。そ うでなければ、lookup-keyは指定されたシーケンスkeyのバインド しか報告せず、デフォルト・バインドは明示的にそれを聞かれた場合(keyの 要素としてtを与えます。キーマップのフォーマット参照)を除いて無視 します。

この章で述べるキーを検索する関数は全てlookup-keyを使っています。

 
(lookup-key (current-global-map) "\C-x\C-f")
    ⇒ find-file
(lookup-key (current-global-map) "\C-x\C-f12345")
    ⇒ 2

keyにメタ文字が含まれているときは、その文字は暗に2文字のシーケンス、 meta-prefix-charの値に続けて対応する非メタ文字、に置き換えられま す。したがって、下の1番目の例は、2番目の例に変換されて扱われます。

 
(lookup-key (current-global-map) "\M-f")
    ⇒ forward-word
(lookup-key (current-global-map) "\ef")
    ⇒ forward-word

read-key-sequenceとは違って、この関数は情報を捨てるようなイベント の修正は行ないません(see section キー・シーケンス入力)。特に、英文字を小文字に 変換したり、ドラッグ・イベントをクリックに変えたりしません。

Command: undefined

キーマップ中でキーを未定義にするのに使われます。dingを呼び出しま すが、エラーは起きません。

Function: key-binding key &optional accept-defaults

この関数は、全てのアクティブなキーマップを調べて、現在のキーマップでの keyのバインドを返します。keyがそれらのキーマップで未定義の場 合は、結果はnilになります。

引数accept-defaultsは、lookup-key(上記)と同様に、デフォルト・バインドを調べるかどうかを制御します。

keyが文字列やベクタでない場合は、エラーになります。

 
(key-binding "\C-x\C-f")
    ⇒ find-file
Function: local-key-binding key &optional accept-defaults

この関数は現在のローカル・キーマップでのkeyのバインドを返します。 そこでは未定義ならnilを返します。

引数accept-defaultsは、lookup-key(上記)と同様に、デフォルト・ バインドを調べるかどうかを制御します。

Function: global-key-binding key &optional accept-defaults

この関数は現在のグローバル・キーマップでのkeyのバインドを返します。 そこでは未定義なら、nilを返します。

引数accept-defaultsは、lookup-key(上記)と同様に、デフォルト・ バインドを調べるかどうかを制御します。

Function: minor-mode-key-binding key &optional accept-defaults

この関数は、keyの全てのアクティブな副モード・バインドのリスト を返します。もっと詳しくいうと、次のような対のalist (modename . binding)を返します。modenameはその 副モードを使用中にする変数で、bindingkeyのそのモード におけるバインドです。

最初のバインドが前置コマンドでなければ、そのあとのほかの副モー ドの全てのバインドは、完全に無効になるので無視されます。同様に、前置バインドのあとの非前置バインドはリスト上では省略されま す。

引数accept-defaultsは、lookup-key(上記)と同様に、デフォルト・ バインドを調べるかどうかを制御します。

Variable: meta-prefix-char

この変数はメタ接頭辞の文字コードを示します。メタ文字をキーマッ プで検索できるように2文字のキー・シーケンスに変換するときに使われます。値 は前置イベントでなくてはうまくいきません(see section 前置キー)。 デフォルト値は27で、これはESCASCIIコードです。

meta-prefix-charの値が27である間は、キー検索時にM-bESC bに変換されます。ESC bは通常は backward-wordコマンドとして定義されています。しかし、 meta-prefix-charを24(C-xのコードです)にすると、Emacsは M-bC-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-bC-x b
                                    ;   とタイプするのと同じになる.

(setq meta-prefix-char 27)          ; 混乱を避けるため
     ⇒ 27                          ; デフォルト値に戻す!

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

19.9 キー・バインドの変更

キーをバインドし直す方法は、キーマップ中のエントリを変更することです。グ ローバル・キーマップのバインドを変更すれば、全てのバッファに影響がおよび ます(ですが、ローカル・バインドによってグローバル・バインドが隠されてい るバッファには直接の影響はありません)。カレント・バッファのローカル・マッ プを変更すれば、通常は同じ主モードを使っている全てのバッファに影響します。 global-set-keylocal-set-key関数はこれらの操作を行なうた めの便利なインターフェースです(see section キー・バインド用コマンド)。もっと一般 的な関数としてdefine-keyも使えます。このときは、変更するマップを 明示的に指定しなくてはいけません。

キー・シーケンスのバインドし直しを記述するときに、制御文字やメタ文 字のための特殊なエスケープ・シーケンスが便利です(see section 文字列型)。構 文`\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 文字型

キー定義と検索の関数ではキー・シーケンスがベクタの場合、イベント・タイ プの別な構文としていつくかの修飾子名と一つの基本イベント(文字またはファ ンクション・キー名)を含むリストを使うことができます。たとえば、 (control ?a)?\C-aと等価で、(hyper control left)C-H-leftと等価です。

イベント・タイプの表現としてリストを使う利点の一つに、コンパイル後のファ イルに修飾ビットの数値コードがあからさまに出てこないということがあげら れます。

以下の関数では、keymapがキーマップでない場合や、keyがキー・ シーケンスを表す文字列かベクタでない場合にエラーが発生します。 リストであるようなイベントの代わりにそのイベントタイプ(つまりシンボル)で 済ますこともできます。

Function: define-key keymap key binding

この関数はkeymapkeyのバインドを設定します(keyが複 数のイベントのときは、変更は実際にはkeymapから到達する別のキーマッ プで行なわれます)。引数bindingはどんなLispオブジェクトでも構いませんが、 ある限られたタイプのものだけが有効です(有効なタイプの一覧はキー検索参照)。define-keyが返す値はbindingです。

keyの全ての接頭辞は前置キー(すなわちキーマップ にバインドされている)か、未定義でなくてはなりません。そうでなければエラー が発生します。

keyのある接頭辞が未定義なら、define-keykey の残りの部分が指定されたように定義できるように、それを前置キー として定義します。

以下は、疎なキーマップを作りいくつかのバインドを設定する例です:

 
(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-pctl-x-mapにバインドする。
(define-key map "\C-p" ctl-x-map)
;; ctl-x-map
⇒ [nil … find-file … backward-kill-sentence] 

;; ctl-x-mapの中でC-ffooにバインドする。
(define-key map "\C-p\C-f" 'foo)
⇒ 'foo
map
⇒ (keymap     ; ctl-x-mapの中にfooがあることに注目。
    (16 keymap [nil … foo … backward-kill-sentence])
    (24 keymap 
        (102 . forward-word))
    (6 . forward-char))

注意して欲しいのは、C-p C-fに新しいバインドを設定することは実際に はctl-x-mapのエントリーを変更すること、そしてこれはC-p C-f とデフォルトのグローバル・マップのC-x C-fの両方のバインドを変更す ることになることです。

Function: substitute-key-definition olddef newdef keymap &optional oldmap

この関数は、keymapの中でolddefにバインドされている全てのキー のolddefnewdefで置き換えます。言い替えると、olddefは それがどこにあろうともnewdefで置き換えられます。この関数は nilを返します。

たとえば、この例は標準のバインドのEmacsではC-x C-fを再定義します:

 
(substitute-key-definition 
 'find-file 'find-file-read-only (current-global-map))

oldmapが非nilなら、そのバインドによってどのキーをバインドし 直すかが決まります。バインドし直されるのはnewmapであって、 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))
Function: suppress-keymap keymap &optional nodigits

この関数は、密なキーマップkeymapを全ての印字可能文字が未定義になる ように変更します。もっと正確にいうと、それらをundefinedにバインド します。通常、これはテキストの挿入を不可能にします。 suppress-keymapnilを返します。 (17)

nodigitsnilなら、suppress-keymapは数字を digit-argumentを実行するように、-negative-argument を実行するように定義します。そうでない場合は、それらをほかの印字可能文字と 同じように未定義にします。

suppress-keymap関数は、yankquoted-insertのような コマンドを抑制しませんので、バッファの変更を不可能にするわけではありませ ん。バッファの変更を一切できなくするには、バッファを読出し専用にして ください(see section 読みだし専用バッファ)。

この関数はkeymapを変更するので、普通は新しく作ったキーマップに対し て使用します。別の目的で使われている既存のキーマップに対して使用した場合 は、たいていトラブルが起きるでしょう。たとえば、global-mapを抑制し たなら、Emacsはほとんど使えなくなるでしょう。

ほとんどの場合、suppress-keymapはRmailやDiredのようなテキストの挿 入が必要でなく読出し専用のモードのローカル・キーマップの初期化に使われ ます。これは`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)
  …

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

19.10 キー・バインド用コマンド

この節ではキー・バインドを変更するのに便利な対話的インターフェースについて 述べます。それらはdefine-keyを呼び出すことによって動作します。

global-set-key`.emacs'の中で簡単なカスタマイズのために よく使われます。たとえば、

 
(global-set-key "\C-x\C-\\" 'next-line)

 
(global-set-key [?\C-x ?\C-\\] 'next-line)

 
(global-set-key [(control ?x) (control ?\\)] 'next-line)

は、C-x C-\を一行下へ動くように再定義しています。

 
(global-set-key [M-mouse-1] 'mouse-set-point)

これはメタ・キーを押しながら第1(左端)マウス・ボタンを押されたときに、ク リックした場所へポイントが移動するように再定義しています。

Command: global-set-key key definition

この関数は現在のグローバル・マップのkeyのバインドにdefinition をセットします。

 
(global-set-key key definition)
≡
(define-key (current-global-map) key definition)
Command: global-unset-key key

この関数は現在のグローバル・マップからkeyのバインドを取り除きます。

この関数の使い道の一つに、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)
Command: local-set-key key definition

この関数は現在のローカル・キーマップのkeyのバインドに definitionをセットします。

 
(local-set-key key definition)
≡
(define-key (current-local-map) key definition)
Command: local-unset-key key

この関数は現在のローカル・マップからkeyのバインドを取り除きます。

 
(local-unset-key key)
≡
(define-key (current-local-map) key nil)

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

19.11 キーマップのスキャン

この節ではヘルプ情報を表示するために全ての現在のキーマップをスキャンするの に使われる関数について述べます。

Function: accessible-keymaps keymap &optional prefix

この関数は、keymapから(前置キー経由で)アクセスできる全て のキーマップのリストを返します。値は(key . map)と いう形式の要素の連想リストで、keyはそのkeymap中の定義が mapであるような前置キーです。

alistの要素はkeyの長さが長くなるような順番になっています。指定され たキーマップはそれ自身から空の前置キーによってアクセス可能なので、 最初の要素は常に("" . keymap)です。

prefixが与えられた場合、それは前置キー・シーケンスでなけれ ばなりません、accessible-keymapsはその前置キーが prefixではじまるサブマップだけを返します。これらの要素は (accessible-keymaps)の値とほとんど同じで、違うのはいくつかの要素 が省かれていることだけです。

下の例では、返されたalistは、`^['として表示されているキーESC が前置キーで、その定義が疎なキーマップ(keymap (83 . center-paragraph) (115 . foo))であることを示しています。

 
(accessible-keymaps (current-local-map))
⇒(("" keymap 
      (27 keymap   ; このESCのためのキーマップは以下にも現れる。
          (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は、ウィンドウの特別な部分でのマウスの動作のための 前置キーとして使われる、いつくかあるダミー・イベントのうちの一つで す。

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

実際のケースで現れるキーマップは、これらだけではありません。

Function: where-is-internal command &optional keymap firstonly noindirect

この関数は、あるキーマップの集合の中でcommandにバインドされている (いろんな長さの)キー・シーケンスのリストを返します。

引数commandはどんなオブジェクトでも構いません。これを、全てのキー マップ・エントリーとeqを使って比較します。

keymapnilならば、overriding-local-mapを無視して(値 がnilであるとみなして)現在のアクティブ・キーマップを使います。 keymapが非nilなら、探すマップはkeymapとグローバル・キー マップになります。

普通は、overriding-local-mapkeymapとして使うのがよいでしょ う。そうすれば、where-is-internalはアクティブなキーマップを正確に 探します。グローバル・マップだけを探したいときは、keymapとして (keymap)(空のキーマップ)を渡せばよいでしょう。

firstonlynon-asciiのときは、全てのキー・シーケンスのリス トの代わりに、最初に見つけたキー・シーケンスを表す一つの文字列が返す値に なります。firstonlytならば、返す値は最初のキー・シーケン スになりますが、全てがASCII文字(またはASCIIのメタ文字)からなる キー・シーケンスはそれ以外のキー・シーケンスより優先されます。

nonindirectが非nilなら、where-is-internalは間接キー マップ・バインドをたどりません。このことにより、間接定義自身を探すことが できます。

この関数はwhere-isで使われています(see (emacs)Help section `Help' in The GNU Emacs Manual)。

 
(where-is-internal 'describe-function)
    ⇒ ("\^hf" "\^hd")
Command: describe-bindings prefix

この関数は定義済みの全てのキーとそれらの定義の一覧を作成します。 `*Help*'という名前のバッファに一覧を書き込みそれをどれかのウインド ウに表示します。

prefixが非nilなら、それは前置キーでなくてはなりま せん、一覧にはprefixではじまるキーだけが含まれます。

一覧では、メタ文字はESCの後に対応する非メタ文字が続く形式で表さ れます。

いくつかの連続するASCIIコードの文字が同じ定義のときは、 `firstchar..lastchar'というようにまとめて表示します。こ の場合、ASCIIコードを知らないと、これがどの文字群を表しているのかわ かりません。たとえば、デフォルトのグローバル・マップでは、 `SPC.. ~'の文字群が1行で記述されています。SPCASCIIの32、~ASCIIの126、そしてその間の文字には全ての通 常の印字可能文字(つまり、英文字(letter)や数字や句読点など)が含まれます。 これらの全ての文字はself-insert-commandにバインドされています。


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

19.12 メニュー・キーマップ

キーマップは、キーボードのキーやマウス・ボタンのバインドを定義するのと同様 に、メニューを定義することもできます。メニューは通常マウスから起動されま すが、キーボードで使うこともできます。


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

19.12.1 メニューの定義

キーマップは見出し文字列(overall prompt string)、これはキーマップ の要素として現れる文字列です、が含まれていればメニューのために使えます (See section キーマップのフォーマット)。 この文字列はそのメニューの目的を表していなくてはなりません。見出し文字列 つきのキーマップを作る最も簡単な方法は、make-keymapmake-sparse-keymapを呼び出すときに文字列を引数として指定すること です(see section キーマップの作成)。

メニュー中の項目の順番は、キーマップ中のバインドの順番と同じです。 define-keyは新しいバインドを先頭に入れるので、順番を気にするなら メニューの項目は下のものからはじめて上のものへと定義していかなくてはなりま せん。すでに存在するメニューに項目を追加するときは、 define-key-afterを使って位置を指定することができます (see section メニューの変更)。

メニュー・キーマップの中の個々のバインドには項目文字列が含まれていなくては いけません。これらの文字列は、メニューに表示される項目になります。項目文 字列を含むバインドはこんな感じです:

 
(string . real-binding)

バインドの項目文字列は短く(単語一つか二つ)なくてはなりません。また、対 応するコマンドの動作を表していなくてはいけません。

define-keyにとっては、stringはイベントのバインドの一部分で すが、lookup-keyreal-bindingのみを返し、また real-bindingだけがキーを実行するときに使われます。

また、下のようにヘルプ文字列と呼ばれる2番目の文字列も与えることができま す:

 
(string help-string . real-binding)

現在のEmacsはhelp-stringを実際には使いません。real-bindingを 取り出すためにhelp-stringを無視する方法を知っているだけです。将来 はhelp-stringsを、要求に応じてメニューの項目の拡張ドキュメントとし て使えるようになるでしょう。

real-bindingnilならstringはメニューに現れますが選択 できません。

real-bindingがシンボルでそのmenu-enable属性が非nilな ら、その属性はそのメニュー項目を使用可にするかどうかを制御する式になりま す。Emacsは、メニューを表示するためにキーマップが使われると毎回その式を 評価して、式の値が非nilのときだけそのメニュー項目を使用可にします。 メニュー項目が使用不可のときは、"曖昧"な形式で表示されマウスで選択する ことはできません。

メニュー・バーはあなたがメニューを見るたびにどの項目が使用可なのかを再算出 したりはしません。これはX toolkitがあらかじめメニューのツリー全体を要求 するからです。強制的にメニュー・バーを再算出するには、 force-mode-line-updateを呼び出してください(see section モード行の書式)。

"同じ"コマンドを実行するけど違う条件で使用可になるメニューの項目を作る ことが便利なときがあります。コマンドの別名を定義することによって、これを 行なうことができます。次の例は、toggle-read-onlyの二つの別名を作り、 違う条件で使用可になるようにしています:

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

メニュー項目に同じコマンドを起動するキーボードのキー・シーケンスが(もしあ れば)表示されていることに多分気がついたと思います。再算出の時間を節約す るため、メニューを表示するときにこの情報をバインドのサブリストにキャッシュ します。このように:

 
(string [help-string] (key-binding-data) . real-binding)

これらのサブリストをメニュー項目に自分で入れてはいけません。メニューを表 示すると自動的にこれらを算出します。マウス・メニューの項目文字列に等価な キー・シーケンスをつけ加えないでください、冗長になります。

別名コマンド自身と等価なキー・シーケンスがないときは、本体のコマンドと等価 なキー・シーケンスをメニューに表示します。上の例では、 make-read-onlymake-writalbeを実行するように定義されたメ ニュー項目には、toggle-read-onlyと等価なキー・シーケンスが表示され ます。


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

19.12.2 メニューとマウス

メニュー・キーマップを使ってメニューを出すためには、それを前置キー の定義にします。

前置キーがマウス・イベントで終っていれば、Emacsはユーザがマウス を使って選択できるように、メニュー・キーマップを使って可視のメニューをポッ プアップします。 ユーザがあるメニュー項目をクリックすると、発生するイベントは文字であって もシンボルであってもそのメニュー項目がもたらすバインドを持っています (メニューが複数の階層だったりメニュー・バーから呼び出された場合は、メニュー 項目はひと続きのイベントを発生するかも知れません)。

たいていの場合、ボタン押下のイベントでメニューを起動するのがいいでしょう。 こうすると、ユーザはボタンを離すことによってメニューの項目を選択すること ができます。

一つのキーマップで複数のメニューの枠(pane)を出すことが、明示的に指示すれ ばできます。そのやり方は、それぞれの枠のキーマップを作り、メニューのメイ ンのキーマップにそれらのマップそれぞれのバインドを作ります。これらのバイ ンドそれぞれに`@'ではじまる項目文字列を与えてください。項目文字列の 残りの部分は枠の名前になります。`lisp/mouse.el'を見れば、これの例が あります。`@'抜きの項目文字列をもつ普通のバインドは、明示的に作ら れたほかのサブマップの枠と一緒に現れる別の一つの枠にまとめられます。

X toolkitのメニューは枠を複数出すことはできません。代わりにサブメニュー を使うことができます。ネストされたキーマップは、項目文字列が`@'で はじまっているかどうかにかかわらず全てサブメニューになります。toolkit版の Emacsでは、項目文字列の先頭にある`@'に関して特別なことは、 `@'はメニューの項目には表示されないということだけです。

別々のキーマップも複数の枠を出すことができます。前置キーの完全 な定義は常にいくつかのアクティブ・キーマップ(副モード、ローカル、グ ローバル)から得られる定義を合成したものになります。これらのキーマップの うち複数がメニューのときは、それぞれのメニューは別の枠を出します。 See section アクティブ・キーマップ

toolkit版のEmacsでは、メニューは枠を複数出すことができないため、別のキー マップはサブメニューとして表現されます。それぞれのキーマップがサブメニュー になります。

Lispプログラムから明示的にメニューをポップアップしてユーザの選択を受けと ることができます。このときにもキーマップが使えます。See section ポップアップ・メニュー


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

19.12.3 メニューとキーボード

最後がキーボード・イベント(文字とかファンクション・キー)の前置キー の定義がメニュー・キーマップのときは、ユーザはキーボードでメニューの項目を 選択することができます。

Emacsはメニューの選択肢(バインドの項目文字列)をエコー領域に表示します。 全部が一度に入り切らないときは、ユーザはSPCをタイプして次の行の選 択肢を見ることができます。SPCを何度もタイプしてメニューの最後まで きたら、最初に戻ります(変数menu-prompt-more-charはこれに使う文 字を指定します。SPCがデフォルトです)。

ユーザは望む選択肢を見つけたら、対応する文字(バインドはその選択肢です)を タイプします。

Emacsライクなエディターのこのようなメニューの使い方は、Hierarkeyシステム の影響を受けています。

Variable: menu-prompt-more-char

この変数は、メニューの次の行を見るのに使う文字を指定します。初期値は32、 SPCのコードです。


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

19.12.4 メニューの例

これはマウス用メニューの設定方法の簡単な例です。

 
(defvar my-menu-map
  (make-sparse-keymap "Key Commands <==> Functions"))
(fset 'help-for-keys my-menu-map)

(define-key my-menu-map [bindings]
  '("List all keystroke commands" . describe-bindings))
(define-key my-menu-map [key]
  '("Describe key briefly" . describe-key-briefly))
(define-key my-menu-map [key-verbose]
  '("Describe key verbose" . describe-key))
(define-key my-menu-map [function]
  '("Describe Lisp function" . describe-function))
(define-key my-menu-map [where-is]
  '("Where is this command" . where-is))

(define-key global-map [C-S-down-mouse-1] 'help-for-keys)

メニューの中でバインドされているキー・シーケンスの中のシンボルは、架空の" ファンクション・キー"です。それらはキーボード上には現れませんが、そのこと はメニューの中でそれらを使うことを妨げるわけではありません。それらの名前 は、覚えやすいように選ばれています。where-isaproposの出 力の中に対応するメニューの項目を示すために現れるからです。

しかしながら、キーボードからも使えるようなメニューにしたければ、架空のファ ンクション・キーと同じように実在のASCII文字にバインドしておかなくて はなりません。


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

19.12.5 メニュー・バー

ほとんどのウインドウ・システムではフレームはそれぞれメニュー・バー (menu bar)をもつことができます。メニュー・バーとは、フレームの上部に横 いっぱいに広がっていて、常時メニューを表示しています。メニュー・バーの項 目は偽"ファンクション・キー"menu-barのサブコマンドで、全てのア クティブ・キーマップで定義されています。

メニュー・バーに項目を追加するためには、まず自分の偽"ファンクション・キー" (keyと呼びましょう)を考えましょう。そして、キー・シーケンス [menu-bar key]のバインドを作ってください。たいていの場合は、 そのメニュー・バーの項目の上でボタンを押したときに別のメニューが出てくるよ うにするので、そのバインドはメニュー・キーマップになります。

複数のアクティブ・キーマップでメニュー・バーに同じ偽ファンクション・キー が定義されていても、その項目は一つしか現れません。そのメニュー・バーの項 目をクリックすると、その項目の全てのサブコマンド(グローバル・サブコマン ド、ローカル・サブコマンド、副モード・サブコマンド、全て一緒)を含む、一 つに合成されたサブメニューが出てきます。

メニュー・バーの中身を決定する際には、変数overriding-local-mapは通 常無視されます。すなわち、メニュー・バーはoverriding-local-mapnilのときにアクティブになるキーマップから算出されます。 See section アクティブ・キーマップ

フレームにメニュー・バーを表示するためには、そのフレームの menu-bar-linesパラメータが0より大きくなくてはいけません。Emacsは 自分のメニュー・バーのために1行だけ使うので、複数行を指定した場合は、残り の行はフレーム中のメニュー・バーとウインドウの間に入ります。 menu-bar-linesの値は1か2をお奨めします。See section Xウインドウ・フレーム・パラメータ

これはメニュー・バーの項目を設定する例です:

 
(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'メニュー・バー項目に使っている偽 ファンクション・キーです。グローバルのメニュー・バー項目を抑制する主な理由は、 モード固有の項目のために場所を空けることです。

Variable: menu-bar-final-items

通常、メニュー・バーにはグローバルの項目の次にローカル・マップで定義された項 目が表示されます。

この変数には、通常の順番にかかわらずメニュー・バーの最後に表示する項目の偽 ファンクション・キーのリストが入っています。デフォルト値は(help)で す。したがって、普通は`Help'メニュー項目がローカル・メニュー項目の次 にメニュー・バーの最後に現れます。


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

19.12.6 メニューの変更

存在するメニューに新しい項目を挿入するときは、多分そのメニューの項目の中 のある特定の場所に挿入したいでしょう。項目を追加するのに define-keyを使うと、普通はメニューの先頭に置かれます。ほかの場所に 置くためには、define-key-afterを使ってください:

Function: define-key-after map key binding after

map中のkeyのバインドを値bindingに定義します。 define-keyとほとんど同じですが、バインドのmap中の位置がイベ ントafterのバインドの後ろになります。引数keyは長さが1、要素 が一つのベクタまたは文字列、でなくてはなりません。

たとえば、

 
(define-key-after my-menu [drink]
                  '("Drink" . drink-command) 'eat)

偽ファンクション・キーdrinkのバインドを作り、それをeatのバイン ドのすぐ後ろに置きます。

これは、Shellモードの`Signals'メニューに`Work'という項目を項目 breakの後ろに挿入するやり方です:

 
(define-key-after
  (lookup-key shell-mode-map [menu-bar signals])
  [work] '("Work" . work-command) 'break)

keyは、ただ一つのイベント・タイプを含むシーケンスであるのに対し、 afterはただのイベント・タイプである(シーケンスではない)ことに注意し てください。


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

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