メジャーモードと同様に、マイナーモードを記述するための慣習があります(メジャーモードを参照)。これらの慣習については以下で説明します。最も簡単に従う方法は、マクロ
define-minor-mode を使用することです。マイナーモードの定義を参照してください。
nil となり、有効な場合は非 nil
となります。マイナーモードがバッファローカルである場合、この変数もバッファローカルである必要があります。
この変数は minor-mode-alist
と組み合わせて、モードラインにマイナーモード名を表示するために使用されます。また、minor-mode-map-alist を介してマイナーモードのキーマップが有効かどうかを判定します(アクティブなキーマップの制御を参照)。個別のコマンドやフックでも、この値を確認できます。
modeコマンドは、1つのオプション引数を受け付ける必要があります。プレフィックス引数なしで対話的に呼び出された場合は、モードを切り替える(すなわち、無効であれば有効に、有効であれば無効にする)必要があります。プレフィックス引数付きで対話的に呼び出された場合は、引数が正であればモードを有効にし、そうでなければ無効にする必要があります。
modeコマンドをLispから(すなわち非対話的に)呼び出した場合、引数が省略されているかnilであればモードを有効にし、引数がシンボルtoggleであればモードを切り替え、それ以外の場合は、前述の通り、数値のプレフィックス引数を伴う対話的な呼び出しと同様に引数を処理する必要があります。
以下の例では、この動作を実装する方法を示しています(define-minor-mode
マクロによって生成されるコードと同様です)。
(interactive (list (or current-prefix-arg 'toggle)))
(let ((enable
(if (eq arg 'toggle)
(not foo-mode) ; this is the mode’s mode variable
(> (prefix-numeric-value arg) 0))))
(if enable
do-enable
do-disable))
この少々複雑な挙動の理由は、ユーザーがマイナーモードをインタラクティブに簡単に切り替えられるほか、次のようにモードフックでマイナーモードを簡単に有効化できるためです。
(add-hook 'text-mode-hook 'foo-mode)
foo-mode
が既に有効であったかどうかにかかわらず、これは正しく動作します。というのも、foo-mode
モードコマンドは、Lisp
から引数なしで呼び出された際に無条件でマイナーモードを有効にするからです。モードフックでマイナーモードを無効にする処理は、少々見栄えが悪くなります:
(add-hook 'text-mode-hook (lambda () (foo-mode -1)))
しかし、これはあまり一般的ではありません。
マイナーモードを2回連続して有効または無効にしても、失敗せず、1回だけ有効または無効にした場合と同じ動作をする必要があります。言い換えれば、マイナーモードのコマンドはべき等であるべきです。
minor-mode-alist に要素を追加してください(minor-mode-alist
の定義を参照)。この要素は、以下の形式のリストである必要があります:
(mode-variable string)
ここで、mode-variableはマイナーモードの有効化を制御する変数であり、stringはモードライン上でそのモードを表す、スペースで始まる短い文字列です。これらの文字列は、一度に複数を記述できる余裕を持たせるため、短くなければなりません。
minor-mode-alistに要素を追加する際は、重複を避けるため、assqを使用して既存の要素がないか確認してください。例えば:
(unless (assq 'leif-mode minor-mode-alist) (push '(leif-mode " Leif") minor-mode-alist))
あるいはこのように、add-to-list を使う方法もあります(リスト変数の変更を参照):
(add-to-list 'minor-mode-alist '(leif-mode " Leif"))
さらに、いくつかの主要なモード規約(主要なモード規約を参照)はマイナーモードにも適用されます。具体的には、グローバルシンボルの名称、初期化関数の末尾でのフックの使用、およびキーマップやその他のテーブルの使用に関するものです。
マイナーモードは、可能であれば Custom 経由での有効化・無効化をサポートすべきです(カスタマイズ設定を参照)。これを実現するには、モード変数を defcustom(通常は :type
'boolean)で定義する必要があります。単に変数を設定するだけではモードを有効にするのに不十分な場合は、モードコマンドを呼び出してモードを有効にする
:set メソッドも指定してください。変数のドキュメント文字列には、Custom
経由以外で変数を設定しても反映されない可能性がある旨を記載してください。また、定義にオートロードクッキー(オートロードクッキーを参照)を付与し、変数をカスタマイズした際にモードを定義するライブラリがロードされるよう
:require を指定してください。例えば:
;;;###autoload (defcustom msb-mode nil "Toggle msb-mode. Setting this variable directly does not take effect; use either \\[customize] or the function `msb-mode'." :set 'custom-set-minor-mode :initialize 'custom-initialize-default :version "20.4" :type 'boolean :group 'msb :require 'msb)