ファイルを開くと、Emacsは自動的にメジャーモードを選択します。通常、ファイル名に基づいて選択が行われます—例えば、ファイル名が ‘.c’ で終わるファイルは通常Cモードで編集されます—しかし、ファイル内の特殊なテキストに基づいてメジャーモードが選択されることもあります。この特殊なテキストは、バッファローカルなマイナーモードを有効にするためにも利用できます。
具体的な手順は以下の通りです。
まず、Emacsはファイルにファイルローカルなモード変数が含まれているかを確認します。ファイル内のローカル変数を参照してください。メジャーモードを指定するファイルローカル変数が存在する場合、Emacsは他のすべての基準を無視して、そのメジャーモードを使用します。ファイルローカル変数を用いてメジャーモードを指定する方法はいくつかありますが、最も簡単なのは、最初の非空白行にモード名を記述し、その前後を‘-*-’で囲む方法です。同じ行に他のテキストが含まれていても構いません。例えば、
; -*-Lisp-*-
EmacsにLispモードを使用するよう指示します。セミコロンを用いて、この行をLispにコメントとして扱わせている点に注目してください。同様に、次のように記述することもできます。
; -*- mode: Lisp;-*-
また、eval
指定を用いることで、ファイルローカル変数を使用してバッファローカルなマイナーモードを指定することもできます。例えば、最初の非空白行では、バッファを
Lisp モードに設定し、Auto-Fill モードを有効にします:
; -*- mode: Lisp; eval: (auto-fill-mode 1); -*-
ただし、ほとんどのマイナーモードは個々のユーザーの好みを反映したものであるため、このような方法でマイナーモードを有効にするのは通常適切ではないことに注意してください。特定のファイルタイプに対して個人的にマイナーモードを使用したい場合は、メジャーモードフックを介してマイナーモードを有効にするのが得策です(メジャーモードを参照)。
次に、Emacsはファイルの拡張子がいずれかのディレクトリローカルなauto-mode-alistのエントリと一致するかどうかを確認します。これらは.dir-locals.el機能を用いて検出されます(ディレクトリごとのローカル変数を参照)。
第三に、メジャーモードを指定するファイル変数がない場合、Emacsはファイルの内容が ‘#!’
で始まっているかを確認します。そうであれば、そのファイルが実行可能なシェルコマンドとして機能することを示しており、これはファイルの1行目に指定されたインタプリタを実行することで動作します(ファイルの残りの部分はインタプリタへの入力として使用されます)。したがって、Emacsはそのインタプリタ名を用いてモードを選択しようとします。例えば、‘#!/usr/bin/perl’ で始まるファイルはPerlモードで開かれます。変数 interpreter-mode-alist
は、インタプリタプログラム名とメジャーモードの対応関係を指定します。
1行目が ‘#!’ で始まる場合、通常はその行で ‘-*-’ 機能を使うことはできません。インタープリタの実行時にシステムが混乱してしまうためです。そのため、Emacs はこのようなファイルにおいて、1行目だけでなく2行目の ‘-*-’ も探します。troff プリプロセッサのリストを指定するためのマジック文字列 ‘'\"’ で始まる man ページについても同様です。
第四に、Emacsは変数 magic-mode-alist
に基づき、バッファ先頭のテキストを参照してメジャーモードを判定しようとします。デフォルトではこの変数は nil(空のリスト)であるため、Emacsはこのステップをスキップしますが、initファイルでカスタマイズすることも可能です(Emacs初期化ファイルを参照)。値は、次のような形式の要素からなるリストである必要があります。
(regexp . mode-function)
ここで regexp は正規表現(正規表現の構文を参照)、mode-function はメジャーモードコマンドです。ファイル先頭のテキストが regexp に一致する場合、Emacs は mode-function で指定されたメジャーモードを選択します。
あるいは、magic-mode-alist の要素は以下の形式をとることがある。
(match-function . mode-function)
ここで match-function はバッファの先頭で呼び出される Lisp 関数であり、この関数が
nil 以外の値を返すと、Emacs はメジャーモードを mode-function に設定します。
5番目—Emacsがまだ適切なメジャーモードを見つけられていない場合—ファイル名を参照します。ファイル名とメジャーモードの対応関係は、変数
auto-mode-alist
によって制御されます。その値はリストであり、各要素は以下の形式となっています。
(regexp . mode-function)
またはこのフォーム、
(regexp mode-function flag)
例えば、リストに通常含まれる要素の一つに ( という形式のものがあり、これはファイル名が
.c で終わるファイルに対して C モードを選択する役割を担っています。(なお、Lisp
の構文で文字列内に \ を含めるには ‘\\’ が必要であり、これは正規表現における ‘.’ の特殊な意味を抑制するために使用されます。)
"\\.c\\'" . c-mode)
要素の形式が (regexp mode-function flag)
であり、flag が nil でない場合、mode-function を呼び出した後(それが nil
でない場合)、Emacs は regexp
に一致した接尾辞を破棄し、リストを再度検索して別の一致箇所を探します。この「再帰的な拡張子除去」は、複数の拡張子を持つファイルで利用されており、「外側」の拡張子が、実際に適切なモードを指定している「内側」の拡張子を隠蔽します。例えば、バックアップファイルや
.gpg 拡張子を持つ GPG 暗号化ファイルなどでこの機能が利用されています。
GNU/Linux やその他の大文字小文字を区別するファイル名を持つシステムでは、Emacs は auto-mode-alist に対して大文字小文字を区別する検索を行い、この検索が失敗した場合は、alist
に対して2回目の大文字小文字を区別しない検索を行います。2回目の検索を抑制するには、変数 auto-mode-case-fold を nil
に変更してください。Microsoft Windows のような大文字小文字を区別しないファイル名を持つシステムでは、Emacs は auto-mode-alist に対して1回だけ大文字小文字を区別しない検索を行います。
最後に、Emacsが依然として使用するメジャーモードを見つけられていない場合、バッファ先頭のテキストを変数
magic-fallback-mode-alist と比較します。この変数は、前述の magic-mode-alist と同様に動作しますが、参照されるのは auto-mode-alist の後
のみとなります。デフォルトでは、magic-fallback-mode-alist
には画像ファイル、HTML/XML/SGMLファイル、PostScriptファイル、およびUnix形式のConfファイルをチェックするフォームが含まれています。
メジャーモードが決定すると、Emacsはそのモードがmajor-mode-remap-alistによって再マッピングされていないか最終確認を行い、再マッピングされている場合は代わりにその再マッピング後のモードを使用します。これは、同一のファイルタイプに対して複数の異なるメジャーモードが使用可能な場合に、好みのモードを指定できるようにするための仕組みです。なお、この再マッピングは上述のすべての手法で決定されたメジャーモードに影響を与えるため、例えば、ファイルの1行目で指定されたモードが、必ずしもそのファイルを表示しているバッファで実際に有効になるモードになるとは限りません。(この再マッピングはrevert-bufferにも影響します。バッファの復元を参照してください。)同一のファイルタイプに対して複数のモードが利用可能な場合、major-mode-remap-alistをカスタマイズすることでメジャーモードの好みをEmacsに伝えることができます。例えば、これを~/.emacs初期化ファイル(Emacs初期化ファイルを参照)に記述してください。
(add-to-list 'major-mode-remap-alist '(c-mode . c-ts-mode))
auto-mode-alist またはファイルローカル変数によって c-mode が指定された際に、Emacs に c-ts-mode を呼び出させる。逆に、
(add-to-list 'major-mode-remap-alist '(c-mode))
Emacsがc-modeを他のどのモードにも再マッピングしないようにします。
major-mode-remap-alist のデフォルト値は nil であるため、リマッピングは行われません。ただし、一部の Lisp
パッケージや機能をロードするとモードのリマッピングが導入されることがあります。これは、それらをロードすることが、ユーザーが別のモードの使用を好んでいることを意味すると
Emacs が判断するためです。したがって、予測可能な動作を実現するために、常に major-mode-remap-alist
をカスタマイズして自身の明確な好みを反映させることを推奨します。この変数は、Emacs が内部的に行おうとするあらゆるリマッピングを上書きするためです。
Tree-sitterライブラリ(The Emacs Lisp Reference
ManualのParsing
Program Sourceを参照)に基づくメジャーモードを有効にするための便利な機能として、ユーザーオプション treesit-enabled-modes
をカスタマイズすることで、Tree-sitterベースのモードを選択的に有効または無効にできます。値が t
の場合は利用可能なすべてのTree-sitterベースのモードが有効になり、モード名のリストである場合はそれらのモードのみが有効になります。このオプションをカスタマイズすると、c-mode から c-ts-mode
へのリマッピング(後者を有効にした場合)など、対応するマッピングが major-mode-remap-alist に追加されます。デフォルトでは、このオプションの値は nil であるため、Tree-sitterベースのモードは有効になりません。
Tree-sitterベースのモードを有効にすると、対応するプログラミング言語のファイルを開いた際に、同じ言語のTree-sitterベースではないモードではなく、自動的にそのモードがオンになります。例えば、c-ts-modeを有効にした場合、C言語のソースファイルを開くとc-modeではなくc-ts-modeがオンになります。
バッファのメジャーモードを変更した場合、M-x normal-mode と入力することで、Emacs
が自動的に選択したはずのメジャーモードに戻すことができます。これは、find-file
がメジャーモードを選択する際に呼び出すのと同じ関数です。バッファがファイルを参照している場合、このコマンドはファイルの ‘-*-’ 行およびファイルローカル変数リスト(もしあれば)も処理します。ファイル内のローカル変数
を参照してください。バッファがファイルを参照していない場合、このコマンドは ‘-*-’
行およびファイルローカル変数リストにあるメジャーモードの指定(もしあれば)のみを処理します。M-x
normal-mode はモードの再マッピングを考慮するため、Emacs によってバッファのメジャーモードが選択された後に major-mode-remap-alist をカスタマイズした場合、normal-mode によって Emacs が元々選択したものとは異なるモードを有効にすることができます。
コマンド C-x C-w および set-visited-file-name
は、新しいファイル名がモードを示唆している場合に、新しいメジャーモードに変更します(ファイルの保存 を参照)。(バッファがファイルを参照していなかった場合、C-x C-s
も同様の動作をします。)ただし、バッファの内容でメジャーモードが指定されている場合や、特定の特殊なメジャーモードではモードの変更が許可されないため、この動作は行われません。change-major-mode-with-file-name を nil に設定することで、このモード変更機能を無効にできます。