すべてのメジャーモードのコードは、ローカルキーマップや構文テーブルの初期化、関数名や変数名、フックに関する規約など、さまざまなコーディング規約に従う必要があります。
define-derived-mode
マクロを使用すれば、こうした規約の多くが自動的に処理されます。派生モードの定義を参照してください。また、ファンダメンタルモードは Emacs
のデフォルト状態を表すため、これらの規約の多くにおいて例外となる点にも注意してください。
以下の規約リストは一部に過ぎません。各メジャーモードは、全体としてのEmacsの一貫性を高めるため、原則として他のEmacsメジャーモードとの整合性を図るべきです。この問題が生じ得るあらゆる箇所をここに列挙することは不可能です。もしEmacsの開発者から、お使いのメジャーモードが通常の規約から逸脱している箇所を指摘された場合は、互換性を確保するようにしてください。
ドキュメント文字列には、特殊なドキュメント用部分文字列である ‘\[command]’、‘\{keymap}’、および ‘\<keymap>’ を含めることができ、これによりヘルプ表示をユーザー自身のキーバインドに合わせて自動的に調整できます。ドキュメント内でのキーバインドの置換を参照してください。
kill-all-local-variables
を呼び出すことから始めるべきです。これにより通常のフック change-major-mode-hook
が実行され、その後、以前に有効だったメジャーモードのバッファローカル変数が削除されます。バッファローカルバインディングの作成と削除 を参照してください。
major-mode
にメジャーモードコマンドのシンボルを設定する必要があります。これにより、describe-mode
はどのドキュメントを出力すべきかを判断します。
mode-name
にモードの「pretty」名(通常は文字列。ただし、その他の形式については モードラインのデータ構造 を参照)を設定します。モード名はモードラインに表示されます。
indent-line-function
を適切な関数に設定し、おそらくインデント用の他の変数もカスタマイズすべきです。コードの自動インデントを参照してください。
use-local-map を呼び出す必要があります。詳細については、アクティブキーマップ を参照してください。
このキーマップは、modename-mode-map
という名前のグローバル変数に永続的に格納しておく必要があります。通常は、このモードを定義するライブラリがこの変数を設定します。
モードのキーマップ変数を設定するためのコードの書き方については、変数を堅牢に定義するためのヒントを参照してください。
メジャーモードでは、キー M-n、M-p、M-s の再割り当ても可能です。M-n と M-p の割り当ては、通常は何らかの前後移動となるはずですが、必ずしもカーソル移動を意味するとは限りません。
メジャーモードが、そのモードで使用されるテキストにより適した方法で同様の機能を果たすコマンドを提供する場合、標準的なキーシーケンスを再バインドすることは正当な行為です。例えば、プログラミング言語を編集するためのメジャーモードでは、その言語により適した方法で関数の先頭に移動できるよう、C-M-aを再定義することがあります。C-M-aをメジャーモードのニーズに合わせて調整する推奨方法は、beginning-of-defun-function(バランス式をまたぐ移動を参照)を、そのモード固有の関数を呼び出すように設定することです。
また、メジャーモードにおいて、そのモードでの標準的な意味がほとんど役に立たない標準キーシーケンスを再バインドすることも妥当である。例えば、ミニバッファモードでは、ミニバッファ内で標準的な意味がほとんど役に立たない M-r を再バインドしている。テキストの自己挿入を許可しない Dired や Rmail のようなメジャーモードであれば、文字やその他の印字文字を特殊コマンドとして再定義しても合理的である。
modename-mode-syntax-table
という名前の変数に格納する必要があります。構文テーブルを参照してください。(tree-sitter
ライブラリをベースとしたメジャーモードでは、このため tree-sitter が提供するパーサーを使用しています。パーサーベースの Font Lockを参照してください。)
modename-mode-abbrev-table
という名前の変数に格納する必要があります。メジャーモードコマンド自体が略語を定義している場合は、define-abbrev の system-flag 引数として
t を渡す必要があります。略語の定義 を参照してください。
font-lock-defaults
にバッファローカルな値を設定することで、Font Lock モードにおけるハイライトの方法を指定する必要があります(Font Lock モード を参照)。Tree-sitter
ベースのメジャーモードについては、パーサーベースの Font Lock を参照してください。
context-menu-mode
をアクティブにした際に使用するため、そのモード専用のコンテキストメニューを追加することを検討してください(The
Emacs Manual の Menu
Mouse Clicks を参照)。そのために、バッファ内での mouse-3
クリック位置に応じて1つ以上のメニューを構築するモード専用関数を定義し、その関数を context-menu-functions のバッファローカル値に追加してください。
imenu-generic-expression、2つの変数 imenu-prev-index-position-function および imenu-extract-index-name-function、または変数 imenu-create-index-function に対してバッファローカルな値を設定することで、Imenu
がバッファの定義やセクションをどのように検索すべきかを指定する必要があります(Imenu を参照)。
outline-regexp または outline-search-function、および変数 outline-level にバッファローカルな値を設定することで、Outline minor mode
が見出し行をどのように検出するかを指定する必要があります(Outline Minor Mode を参照)。
eldoc-documentation-functions
に1つ以上のバッファローカルエントリを追加することで、現在ポイントにある対象について、さまざまな種類のドキュメントをどのように取得するかを ElDoc
モードに指示できます。
completion-at-point-functions
に1つ以上のバッファローカルエントリを追加することで、各種キーワードの補完方法を指定できます。通常バッファにおける補完を参照してください。
make-variable-buffer-local ではなく make-local-variable
を使用してください。後者の関数を使用すると、その変数がその後設定されたすべてのバッファでローカルになり、このモードを使用していないバッファにも影響が及びます。モードがこのようなグローバルな影響を及ぼすことは望ましくありません。バッファローカル変数を参照してください。
ごく稀な例外を除き、Lispパッケージでmake-variable-buffer-localを使用する合理的な方法は、そのパッケージ内のみで利用される変数に用いることだけです。他のパッケージでも利用される変数にこれを用いると、それらのパッケージに干渉することになります。
modename-mode-hook という名前の通常の モードフック があるべきです。メジャーモードコマンドが最後に行うべき処理は、run-mode-hooks を呼び出すことです。これにより、通常のフック change-major-mode-after-body-hook、モードフック、関数 hack-local-variables(バッファがファイルを参照している場合)、そして通常のフック after-change-major-mode-hook が順に実行されます。モードフック を参照してください。
define-derived-modeマクロを使用することですが、必須ではありません。このようなモードは、delay-mode-hooksフォーム内で親モードコマンドを呼び出す必要があります。(define-derived-modeを使用すると、自動的にこれが行われます。)派生モードの定義およびモードフックを参照してください。
change-major-mode-hook 用のバッファローカル値を設定できます(バッファローカルバインディングの作成と削除を参照)。
mode-class という名前で値 special を持つプロパティを設定する必要があります:
(put 'funny-mode 'mode-class 'special)
これにより、現在のバッファがFunnyモードである間に作成された新しいバッファは、major-modeのデフォルト値がnilであっても、Funnyモードに設定されないようEmacsに指示します。デフォルトでは、major-modeに対するnilの値は、新しいバッファを作成する際に現在のバッファのメジャーモードを使用することを意味しますが(Emacsがメジャーモードを選択する仕組みを参照)、このようなspecialモードの場合、代わりにFundamentalモードが使用されます。Dired、Rmail、Buffer
Listなどのモードはこの機能を利用しています。
関数 view-buffer は、モードクラスが special であるバッファでは View
モードを有効にしません。こうしたモードでは通常、独自の View 風のバインディングが提供されるためです。
define-derived-mode
マクロは、親モードがスペシャルモードである場合、派生モードを自動的にスペシャルモードとしてマークします。スペシャルモードは、こうしたモードが継承を行う際に便利な親モードとなります。詳細は
基本メジャーモード を参照してください。
auto-mode-alist に要素を追加して、それらのファイル名に対するモードを選択してください(Emacs がメジャーモードを選択する仕組み
を参照)。モードコマンドを autoload するように定義している場合は、autoload
を呼び出しているのと同じファイルにこの要素を追加してください。モードコマンドに autoload cookie
を使用している場合は、要素を追加するフォームにも autoload cookie を使用できます(autoload cookie を参照)。モードコマンドを
autoload しない場合は、モードの定義が含まれているファイルに要素を追加するだけで十分です。
defvar や defcustom
を使用し、すでに値がある場合は再初期化されないようにしてください(グローバル変数の定義 を参照)。