メジャーモードにも監修があるように(メジャーモードを参照)、マイナーモードの記述にも慣習があります。その慣習について以下で説明します。これらの慣習にしたがうにはマクロdefine-minor-mode
を使用するのがもっとも簡単な方法です。マイナーモードの定義を参照してください。
nil
、有効なら非nil
になる。そのマイナーモードがバッファーローカルならこの変数もバッファーローカルであること。
この変数はモードラインにマイナーモードの名前を表示するためにminor-mode-alist
と結合して使用される。これはminor-mode-map-alist
を通じて、そのマイナーモードのキーマップがアクティブかどうかも判定する(アクティブなキーマップの制御を参照)。個々のコマンドやフックもこの変数の値をチェックできる。
モードコマンドは1つのオプション引数を受け入れること。プレフィクス引数なしでinteractiveに呼び出されたらモードをトグルする(toggle: 切り替える。たとえば無効なら有効に、有効なら無効にする)こと。プレフィクス引数とともにinteractiveに呼び出された場合にはその引数が正であればモードを有効にして、それ以外なら無効にすること。
モードコマンドがLispから(つまり非interactiveに)呼び出された場合は、引数が省略またはnil
ならモードを有効にすること。引数がシンボルtoggle
ならモードをトグルして、それ以外なら上述の数引数とともにinteractiveに呼び出されたときと同じ方法によってその引数を扱うこと。
以下はこの挙動の実装方法を示す例である(define-minor-mode
マクロが生成するコードもこれに類似する)。
(interactive (list (or current-prefix-arg 'toggle)))
(let ((enable
(if (eq arg 'toggle)
(not foo-mode) ; そのモードのモード変数
(> (prefix-numeric-value arg) 0))))
(if enable
do-enable
do-disable))
やや複雑なこの挙動の理由は、ユーザーが簡単かつinteractiveにマイナーモードをトグルできることと、以下のようにモードフック内で簡単にマイナーモードを有効にできるからである:
(add-hook 'text-mode-hook 'foo-mode)
foo-mode
モードコマンドは引数なしでLispから呼び出されたときは無条件にそのマイナーモードを有効にするので、これはfoo-mode
がすでに有効でもそうでなくても正しく振る舞う。モードフック内でマイナーモードを無効にする場合は少々醜くなる:
(add-hook 'text-mode-hook (lambda () (foo-mode -1)))
しかしこれは頻繁には行われない。
マイナーモードを2回連続で直接有効(や無効)にしても失敗せずに、1回だけ有効(や無効)にしたときと同じことを行うこと。言い換えるとマイナーモードコマンドはべき等であること。
minor-mode-alist
に追加する(Definition of 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(カスタマイゼーション設定を参照)を通じた有効化と無効化をサポートするべきです。これを行うには、モード変数は:type
'boolean
とともにdefcustom
で通常は定義されるべきです。その変数をセットするだけではモードの有効化に不足なら、モードコマンドを呼び出すことによりモードを有効にする:set
メソッドも指定するべきです。そしてその変数のドキュメント文字列にCustomを通じて変数をセットしなければ効果がないことを注記してください。さらにその定義をautoload
cookie(autoload cookieを参照)でマークして、その変数のカスタマイズによりモードを定義するライブラリーがロードされるように:require
を指定します。たとえば:
;;;###autoload (defcustom msb-mode nil "msb-modeをトグルする この変数を直接セットしても効果がない \\[customize]か関数`msb-mode'を使用すること" :set 'custom-set-minor-mode :initialize 'custom-initialize-default :version "20.4" :type 'boolean :group 'msb :require 'msb)