マクロdefine-minor-mode
は、自己完結した単一定義内にモードを実装する便利な方法を提供します。
このマクロは名前がmode(シンボル)の新たなマイナーモードを定義する。これはドキュメント文字列としてdocをもつマイナーモードをトグルするためにmodeという名前のコマンドを定義する。
トグルコマンドは1つのオプション(プレフィクス)引数を受け取る。引数なしでinteractiveに呼び出されると、そのモードのオンとオフをトグルする。正のプレフィクス引数はモードを有効にして、それ以外のプレフィクス引数はモードを無効にする。Lispから呼び出すと引数がtoggle
ならモードをトグルして、引数が省略かnil
ならモードを有効にする。これはたとえばメジャーモードフック内でマイナーモードを有効にするのを簡便にする。docがnil
なら、このマクロは上記を記述したデフォルトのドキュメント文字列を提供する。
デフォルトではこれはモードを有効にすると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-sequenceとdefinitionはdefine-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
でなければなりません。
以下は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)))))
これはglobal-modeという名前をグローバルにトグルする。これはmodeという名前のバッファーローカルなマイナーモードをすべてのバッファー(または一部のバッファー。以下参照)で有効か無効にするということを意味する。bodyフォームの実行も行う。あるバッファー内でそのマイナーモードをオンにするには関数turn-onを使用する。マイナーモードをオフにするには−1を引数としてmodeを呼び出す(turn-onは別の関数なのでそのマイナーモードを有効にすべきか先験的に明確でない場合でも有効にするかどうかを決定できる)。
グローバルに有効化されたモードは、その後に作成されたバッファー、かつrun-mode-hooks
を実行するためのこの規約にしたがうメジャーモードを使用するバッファーにのみ効果を及ぼす。この規約にしたがわないメジャーモードでは、マイナーモードは有効にならないだろう。
これは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-mode
やmail-mode
の派生モードでは使用せず、text-mode
の派生モードでは使用,それ以外に使用するモードはない”ことを意味する。
((not c-mode) t)
“c-mode
の派生モードでは使用しないが、それ以外なら使用する”ことを意味する。
(text-mode)
これは“text-mode
の派生モードでは使用するが他では使用しない”ことを意味する(終端にnil
要素が暗に存在する)。
Emacsの一部機能に影響を与えるようなバッファーローカル変数をマイナーモードがセットすることがよくある。あるモードをオフに切り替えた際には、これらの変数の元の状態へのリストアがモードには求められる。これはそれらのことを行う助けとなる利便的なマクロである。これはsetq-local
と同じように機能するが、(相方となる関数buffer-local-restore-state
を使って)これらの変数を以前の値や状態をリストアするために使用できるオブジェクトをリターンする。