Previous: , Up: マイナーモード   [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に渡すのに適した引数である(キーバインディングの変更を参照)。keymapはキーマップかalistであり、これは変数mode-mapも定義する。

:variable place

これはそのモードの状態を格納するために使用されるデフォルトの変数modeを置き換える。これを指定するとmode変数は定義されず、すべてのinit-value引数は使用されない。placeは異なる名前の変数(あなた自身が定義しなければならない)、またはsetf関数とともに使用され得るすべてのもの(ジェネリック変数を参照)。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を呼び出す(turn-onは別の関数なのでそのマイナーモードを有効にすべきか先験的に明確でない場合でも有効にするかどうかを決定できる)。

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

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

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

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

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

キーワード:predicateが与えられると、このマクロはグローバルモード変数と似ているが-modeではなく-modesで終わるユーザーオプションを作成する(つまりglobal-modesということ)。この変数は特定のメジャーモードにおいてそのメジャーモードをアクティブにするかどうかを判断する述語関数で使用される。ユーザーは変数の値をカスタマイズして、そのマイナーモードをオンに切り替えるモードを制御できる。:predicateにたいする有効な値 (つまりこれが作成するユーザーオプションの有効な値)にはt (すべてのメジャーモードで使用)、nil (どのメジャーモードでも使用しない)、あるいはモード名のリスト(オプションで(not mode-name …)のようにnotを前置して否定)が含まれる。以下の例のようにこれらの要素を混合させることもできる。

(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要素が暗に存在する)。

Macro: buffer-local-set-state variable value...

Emacsの一部機能に影響を与えるようなバッファーローカル変数をマイナーモードがセットすることがよくある。あるモードをオフに切り替えた際には、これらの変数の元の状態へのリストアがモードには求められる。これはそれらのことを行う助けとなる利便的なマクロである。これはsetq-localと同じように機能するが、(相方となる関数buffer-local-restore-stateを使って)これらの変数を以前の値や状態をリストアするために使用できるオブジェクトをリターンする。