Previous: , Up: Minor Modes   [Contents][Index]


24.3.3 マイナーモードの定義

マクロdefine-minor-modeは、自己完結した単一定義内にモードを実装する便利な方法を提供します。

Macro: define-minor-mode mode doc keyword-args… body…

このマクロは名前がmode(シンボル)の新たなマイナーモードを定義する。これはドキュメント文字列としてdocをもつマイナーモードをトグルするためにmodeという名前のコマンドを定義する。

トグルコマンドは1つのオプション(プレフィクス)引数を受け取る。引数なしでinteractiveに呼び出されると、そのモードのオンとオフをトグルする。正のプレフィクス引数はモードを有効にして、それ以外のプレフィクス引数はモードを無効にする。Lispから呼び出すと引数がtoggleならモードをトグルして、引数が省略かnilならモードを有効にする。これはたとえばメジャーモードフック内でマイナーモードを有効にするのを簡便にする。docnilなら、このマクロは上記を記述したデフォルトのドキュメント文字列を提供する。

デフォルトではこれはモードを有効にするとt、無効にするとnilにセットされる、modeという名前の変数も定義する。

keyword-argsはキーワードとその後の対応する値により構成され、いくつかのキーワードは特別な意味をもつ:

:global global

nilならそのマイナーモードがバッファーローカルでなくグローバルであることを指定する。デフォルトはnil

マイナーモードをグローバルにしたときの効果の1つは、mode変数がカスタマイズ変数になることである。Customizeインターフェイスを通じてこの変数をトグルするとモードがオンやオフになり、変数の値は将来のEmacsセッション用に保存できるようになる(Saving Customizations in The GNU Emacs Manualを参照)。保存された変数が機能するためには、Emacsが開始されるたびにマイナーモード関数が利用できるようにする必要がある。これは通常はdefine-minor-modeフォームをautoloadすることにより行われる。

:init-value init-value

これはmode変数を初期化するための値。特殊な状況(以下参照)を除き、この値はnilでなければならない。

:lighter lighter

文字列lighterはモード有効時にモードライン内に何を表示するか指定する。これがnilならこのモードはモードライン内に表示されない。

:keymap keymap

オプション引数keymapはそのマイナーモードにたいするキーマップを指定する。非nilなら、それは(値がキーマップであるような)変数の名前かキーマップ、または以下の形式のalistであること

(key-sequence . definition)

ここでkey-sequencedefinitiondefine-keyに渡すのに適した引数である(Changing Key Bindingsを参照)。keymapはキーマップかalistであり、これは変数mode-mapも定義する。

:variable place

これはそのモードの状態を格納するために使用されるデフォルトの変数modeを置き換える。これを指定するとmode変数は定義されず、すべてのinit-value引数は使用されない。placeは異なる名前の変数(あなた自身が定義しなければならない)、またはsetf関数とともに使用され得るすべてのもの(Generalized Variablesを参照)。placeにはコンス(get . set)も指定できる。ここでgetはカレント状態をリターンする式であり、setはそれをセットする1つの引数(placeに割り当てられる状態)をとる関数。

:after-hook after-hook

これはモードフック実行後に評価される単一のLispフォームを定義する。これをクォートしないこと。

:interactive value

デフォルトではインタラクティブコマンドであるようなマイナーモード。nil値を指定するとこれを抑制。valueがシンボルのリストなら、そのマイナーモードが有用なメジャーモードを指定するために使用される。

その他のすべてのキーワード引数は変数modeにたいして生成されたdefcustomに直接渡される。

modeという名前のコマンドは最初にmodeという名前の変数をセットする等の標準的な動作を処理した後に、もしあればbodyフォームを実行する。それからモードフック変数mode-hookを実行してから:after-hook内のフォームを評価して終了する(フック実行を含めて、これらすべてはモードの有効化と無効化の両方で行われることに注意)。

init-valueの値はnilでなければなりません。ただし、(1)Emacsによりそのモードが事前ロードされている、または(2)たとえユーザーが要求しなくともモードを有効にするためにロードするのが容易な場合を除きます。たとえば他の何かが有効でなければそのモードの効果がなく、常にそのタイミングでロードされるような場合には、デフォルトでそのモードを有効にすることに害はありません。しかしこの状況は通常はあり得ません。通常はinit-valueの値はnilでなければなりません。

easy-mmode-define-minor-modeという名前はこのマクロにたいするエイリアスです。

以下はdefine-minor-modeの使い方の例です:

(define-minor-mode hungry-mode
  "Hungryモードをトグルする
引数なしでinteractiveに呼び出すとモードをトグルする
正のプレフィクス引数でモードを有効に、その他のプレフィクス引数で
無効にする。Lispから呼び出す場合、引数を省略、またはnilなら
モードを有効に、`toggle'なら状態をトグルする

Hungryモードが有効なときは、C-DELキーは、
最後を除く先行するすべての空白を飲み込む
コマンド \\[hungry-electric-delete] を参照"
 ;; 初期値
 nil
 ;; モードラインの標示
 " Hungry"
 ;; マイナーモードのバインディング
 '(([C-backspace] . hungry-electric-delete)))

これは“Hungry mode”という名前のマイナーモード、モードをトグルするhungry-modeという名前のコマンド、モードが有効かどうかを示すhungry-modeという名前の変数、モードが有効なときそのキーマップを保持するhungry-mode-mapという名前の変数を定義します。これはC-DELにたいするキーバインディングでキーマップを初期化します。bodyフォームはありません — 多くのマイナーモードはそれを必要としません。

以下はこれを記述する等価な方法です:

(define-minor-mode hungry-mode
  "Hungryモードをトグルする
...省略..."
 ;; 初期値
 :init-value nil
 ;; モードラインへのインジケーター
 :lighter " Hungry"
 ;; マイナーモードのバインディング
 :keymap
 '(([C-backspace] . hungry-electric-delete)
   ([C-M-backspace]
    . (lambda ()
        (interactive)
        (hungry-electric-delete t)))))
Macro: define-globalized-minor-mode global-mode mode turn-on keyword-args… body…

これはglobal-modeという名前をグローバルにトグルする。これはmodeという名前のバッファーローカルなマイナーモードをすべてのバッファー(または一部のバッファー。以下参照)で有効か無効にするということを意味する。bodyフォームの実行も行う。あるバッファー内でそのマイナーモードをオンにするには関数turn-onを使用する。マイナーモードをオフにするには-1を引数としてmodeを呼び出す。

モードをグローバルに有効にすると、それ以降ファイルをvisitすることによって作成されるバッファーやFundamental以外のメジャーモードを使用するバッファーにも影響がある。しかしFundamentalで作成される新たなバッファーは検知しない。

これはCustomizeインターフェイス内でそのマイナーモードのオン/オフを切り替えるカスタムオプションglobal-mode (Customizationを参照)を定義する。define-minor-modeと同様に、たとえば:requireを与える等によってEmacs開始時に毎回確実にdefine-globalized-minor-modeフォームが評価されるようにすること。

グローバルマイナーモードのモード変数にたいしてカスタムグループを指定するにはkeyword-args内で:group groupを使用する。

モードのオンかオフかを示すバッファーローカルなマイナーモード変数は、デフォルトではモード自身の名前なまと同じ。これが該当しない場合(状態情報を異なる変数に格納するいくつかのモード)には、:variable variableを使用すること。

一般的にはグローバル化されたマイナーモードを定義するときは、ユーザーがバッファーごとにモードを使用(または無効に)できるように非グローバル版も定義すること。これにより特定のメジャーモード内でそのモードのフックを使用すればグローバルに有効化されたマイナーモードを無効にすることができるようになる。

:predicateキーワードが与えられた場合には、ユーザーオプションはグローバルモード変数と同様に呼び出されるが、終端が-modesのかわりに-modeのものが作成される。この変数はマイナーモードをアクティブにするべきメジャーモードが何かを指定する述語として使用される。有効な値としてt (すべてのメジャーモードで使用)、nil (どのメジャーモードでも使用されない)、またはモード名要素(同様にtnil)からなるリスト(あるいは(not mode-name ...)のような否定)。

(c-mode (not mail-mode message-mode) text-mode)

これは“c-modeの派生モードで使用、message-modemail-modeの派生モードでは使用せず、text-modeの派生モードでは使用,それ以外に使用するモードはない”ことを意味する。

((not c-mode) t)

c-modeの派生モードでは使用しないが、それ以外なら使用する”ことを意味する。

(text-mode)

これは“text-modeの派生モードでは使用するが他では使用しない”ことを意味する(終端にnil要素が暗に存在する)。