Emacs には編集するファイルごとにファイル名に関係なく編集モードを指定したり、 ローカル変数を設定したりするための機能があります。 この機能に関する覚え書きのようなものです。
Emacs のマニュアルではこの機能を使って設定する変数を
File Variables
(ファイル変数) や単に
local variable
(ローカル変数) と呼んだりしていますが、
これだと他のバッファローカル変数や
Emacs-Lisp のローカルバインディングと紛らわしいので、ここでは
GNU Emacs Lisp Reference Manual
の 2.9版の表記 (File Local Variables
)
を参考にして「ファイルローカル変数」と書いています。
ここで単に Emacs と書いているのは GNU Emacs のことです。私がそれしか使ってないもんで…
基本的にバージョン 20.7〜22.1 の Emacs について調べたことを書いています。これ以外のバージョン (19.x やまだ出ていない 22.2 以降) でも大筋ではおそらく変わらないと思いますが細かい点で違う可能性があります。
ファイルの1行目に -*- (US-ASCII
のハイフン、アスタリスク、ハイフン) で挟んで
Emacs のメジャー/マイナーモードの名前を書いておくと、そのファイルを Emacs
で開いたときにそのモードになります。プログラム言語のソースファイルの場合はコメントの中になるようにするとよいでしょう。
/* -*- C -*- C 言語の場合 */
% -*- latex -*- LaTeX ソースの場合
// 1行目ならどこにあってもよい -*- C++ -*-
実際には Emacs は、 -*-
で挟まれた単語の大文字をすべて小文字に変換し、さらに -mode
をつなげてできる名前をもつ Emacs-Lisp の関数を呼び出しているだけです
(前の3つの例ならそれぞれ c-mode、 latex-mode、
c++-mode)。なので名前が -mode
で終わる関数であれば何でも呼び出せます。普通はそんな名前はメジャーモードかマイナーモードの関数にしか付けませんが。
「-*- モード名 -*-」の
モード名 の代わりに、
Emacs-Lisp の変数名と値のペアを : で区切って書くことができます。
このようにするとそのファイルを開いたときに自動的にその変数が指定された値に設定されます。
変数名と値のペアは ;
(セミコロン) で区切っていくつでも書くことができますが、全体を1行目
(画面上の1行ではなく最初の改行文字まで)
に収める必要があります。つまり途中で改行できません。
ただし : の後や ;
の前後にスペースやタブ文字を入れることはできるようです。また、最後の値の後ろ
(-*- の直前) には ;
を書いても書かなくてもかまいません。
/* -*- comment-column: 56; c-file-style: "bsd" -*- */
この例は変数 comment-column を数値 56
に設定し、 c-file-style を文字列 "bsd"
に設定します。
変数の値は、 Lisp リーダによって読まれた値がそのまま使われ、評価はされません。例えば -*- foo: bar -*- と書いたとき、変数 foo に設定されるのは bar というシンボルであって、変数 bar が参照されるわけではありません。また -*- hoge: (aho 1) -*- と書いてある場合は (aho 1) は関数の呼び出しではなくてシンボル aho と整数 1 からなるリストを表します (普通の Lisp プログラムで ' を付けたときと同じ)。モード指定を除き、変数名や値の大文字小文字は区別されます。
ただし、ここで設定された変数を使う Lisp ライブラリがこれらのシンボルやリストを変数や関数の呼び出しと解釈することはありえます。
ファイルが空白行 (空行やスペース、タブ文字だけの行) で始まっているときは、それらの行は読み飛ばされます。つまり最初の「内容がある」行が1行目になります。
さらに、その行が #! で始まっている場合は、その次の行に
-*- 〜 -*- を書くことができます。
これは #! で始まるファイルは Un*x
では1行目全体がそのファイルのインタプリタの指定として扱われるためです。
次のファイルは通常は「#! /bin/sh」に従って
shell-script-mode になりますが、
2行目に -*- Perl -*- があるので
perl-mode になります。
#! /bin/sh
# -*- Perl -*-
eval 'exec perl -S "$@"'
if 0;
いくつかの「変数名」には特殊な働きがあります。 実際にこのような名前の変数が設定されるわけではありません。
mode
-*- モード名
-*-」で指定する モード名 と同じもの
(つまり関数名から -mode を取ったもの、大文字小文字は自由)
を指定します。例えば「-*- mode: HTML -*-」は単に「-*-
HTML -*-」と書いた場合と同じです
(こっちの書き方を使うと、他のローカル変数の定義が同時にできます)。
eval
coding
unibyte
t を指定するように書かれていますが、少なくとも
Emacs 21.3 までの実装では値は関係ないようです (バグのような気が)。
ファイルローカル変数を指定するもう1つの方法が、 ファイルの末尾に「ローカル変数セクション」を置く方法です。 末尾に書くので設定する変数が多い場合にもファイルの先頭がゴチャゴチャになりません。 また複数行に分けて書くので見やすく書けます。
ローカル変数セクションは、
「Local Variables:」という文字列を含む行で始まり、
「End:」という文字列を含む行で終わります
(この2つの文字列では大文字小文字の違いは無視されます)。
それらの間には1行に1つずつ「変数名:値」の形式で変数と値を指定します。
(: の前後にはスペース/タブ文字を入れることができます
… ただし Local Variables: の :
の前を除く)。さきに説明した mode
などの特殊な変数名も使えます。また、これも同様に「値」は評価されません。
Local Variables: mode: Indented-Text coding: euc-jp fill-column: 70 End:
末尾といっても「末尾に近い所」であれば本当に末尾である必要はありません。
Emacs は、ファイル末尾から最大 3,000 文字遡って文字列「Local
Variables:」を探すのでこの範囲にあれば構いません。
ただし、この範囲のいずれかの行が改ページ文字 (ASCII コード 12、
^L) で始まっているとそこで検索を打ち切ります。
上のような原理から、ローカル変数セクション全体の長さは 3,000 文字を超えることはできません (普通は超えないと思いますが…)。ちなみにこの 3,000 という数字は Lisp ライブラリ (files.el) でハードコーディングされており簡単には変えられません。
ローカル変数セクションの各行には、 行頭・行末に一定の文字列があってもかまいません。 この機能を使えばプログラム言語のコメント中にローカル変数リストを入れられます。 例えば
/* Local variables: */ /* compile-command: "make" */ /* End: */
や
// Local variables: // compile-command: "make" // End:
や
/* * Local variables: * compile-command: "make" * End: */
のように書くことができます。ただし、これら行頭・行末の文字列は
Local variables:
の行から検出されるので、他の行もこの行と形式を揃える必要があります。
たとえば、
/* Local variables: compile-command: "make" End: */
のようには書けません (エラーになります)。
-*- 〜 -*-
やローカル変数セクションで指定される変数は、すべて
Emacs ではバッファローカル変数として扱われます。
したがってあるファイルで設定した値が編集中の (もしくはこれから編集される)
他のファイルに影響を及ぼすことは (普通は) ありません。
ただし、特殊な変数名「eval」を使うと
Emacs のすべての機能が実行できてしまうので、非常に危険です。このため
Emacs は eval に出会うと値を評価する前にユーザに確認を求めます。
ユーザが拒否したときは式は評価されません。
その他フック変数なども直接ではありませんが任意のコードを実行するために使えるので、自動的に設定されるのは好ましくありません。そこで Emacs では次のルールによって設定できる変数と値を制限しています。
risky-local-variable プロパティが
nil でない場合は設定を許可しません。
-hook(s)、
-function(s)、
-form(s)、
-program、 -command、 -predicate
で終わっている場合は許可しません。
safe-local-variable プロパティが関数
(関数シンボル、 lambda 式など)
である場合、設定しようとしている値を引数としてその関数を呼び出し、
nil が返ってきた場合は設定を許可しません。
safe-local-variable プロパティが関数、
t、 nil
のいずれでもない場合も設定を許可しません。
safe-local-variable-values (cons セルのリスト) に
(変数シンボル . 値)
と同じ (equal) 要素が含まれている場合は設定を許可します。
safe-local-variable
プロパティが関数 (関数シンボル、 lambda 式など)
である場合、設定しようとしている値を引数としてその関数を呼び出し、
nil でない値が返ってきた場合は設定を許可します。
risky-local-variable プロパティが
nil でない場合は設定を許可しません。
-hook(s)、
-function(s)、
-form(s)、
-program、 -command(s)、
-predicate(s)、
font-lock-keywords(-数字)、
font-lock-syntactic-keywords、
-frame-alist、 -mode-alist、
-map(-alist)、 -bindat-spec
font-lock-syntactic-keywords、
で終わっている場合は許可しません。
上で「許可しません」となっているものは設定する前にユーザに確認を求め、 ユーザが許可した場合は設定します (この動作は変えることができます)。 ただしユーザがスーパーユーザの場合は確認を求めず設定もしません。
さきの例でも使った変数 compile-command は変数名が
-command で終わっていますが、 safe-local-variable
プロパティが設定されておりローカル変数として自由に設定できます。
例外として、 eval: (put '関数名
'lisp-indent-hook 値) の形式で
値 が数値か 'defun の場合のみ、
ユーザに確認を求めずに実行されます。これは
(Emacs-)Lisp モードで特定の関数 (またはマクロ)
のインデント形式を設定するために使われます。
Emacs が新しくファイルを開くとき、 -*-
やローカル変数セクションは次の順序で処理されます。
-*- 〜 -*-
にコーディングシステムとユニバイト指定があるか調べ、ある場合はそれに従って設定します
-*- 〜 -*- で編集モードが指定されているか調べ、指定されていればそのモードコマンドを実行します
auto-mode-alist からモードを調べて設定します
interpreter-mode-alist からモードを調べて設定します
-*- 〜 -*- で指定された変数を設定します
各々の中では、単に現れた順に設定されます。同じ変数名が指定された場合は後に設定された値が有効になりますが、モード指定や
eval の場合は (最後の値だけでなく) 現れるたびに処理されます。
-*- では、 mode:
で指定された編集モードコマンドは、その他の変数の指定より後に書いていても、実際には先に実行されます。これに対して、ローカル変数セクションではモードコマンドの実行も変数の設定も合わせて現われた順に行われます。
ローカル変数セクションでメジャーモードを指定するときは、メジャーモードを一番最初に指定してください。メジャーモードコマンドは実行時にそのバッファのバッファローカル変数を消去することになっているので、これより前に変数を指定しても意味がありません。
複数のモードを指定すると (mode:
を複数回使ったり、「-*-モード-*-」とローカル変数セクションでの
mode: を併用したときなど)、指定されたモード関数全てが
(変数の優先順位と同じ順序で)
呼び出されます。ただし、エラーになったときはそこで中断されます。メジャーモードを複数呼び出してもあまり意味はありませんが、マイナーモードを設定するには便利です。
-*- mode: text; mode: auto-fill -*- テキストモードでオートフィルを使用する。
インデント付きテキストモードでアウトラインモードを使用する。 Local variables: mode: indented-text mode: outline-minor End:
このように使うときは必ずメジャーモードを先に指定します。マイナーモードをメジャーモードより先に指定しても意味がありません。
-*- 〜 -*-
を使って存在しないモードを指定すると、
default-major-mode で指定したモード)
になります。この場合はローカル変数セクションの処理も行われません。
ローカル変数セクションで存在しないモードを指定したときは、どのバージョンでも 「File local-variables error: (void-function hogehoge-mode)」というエラーになって処理は中断されます。エラーを起こしたモード指定以降のモード指定、ローカル変数指定は処理されません。
-*- 〜 -*- やローカル変数セクションが複数あるとき-*- 〜 -*- やローカル変数セクションはそれぞれ多くとも1つしか認識されません。
もし複数書かれていた場合は、どちらもファイル先頭に近いものだけが認識されます。ただし、ローカル変数セクションの場合はファイル末尾から最大3,000文字の範囲内
(ただし、この中に行頭が改ページ文字である行がある場合は、そのような行のうち最もファイル末尾に近い行からファイル末尾までの範囲内)
で先頭に近いもの、となります。
例えば次の例ではいずれも2番目の指定は無視されます。
-*- Text -*- -*- fill-column: 70 -*-
-*- mode: Text -*- -*- fill-column: 70 -*-
-*- Text -*- -*- HTML -*-
ファイル中にたまたま Local Variables:
という文字列が含まれていると、 Emacs
は後続の行をローカル変数リストとして解釈しようとして、解釈できないとエラー
(「File local-variables error: (...)」など)
を出してしまいます。
これを防ぐためには次のような方法があります。
enable-local-variables を nil
に設定しておく。この場合 -*-
を含めてファイルローカル変数は全く認識されなくなります。
Local Variables:
より後ろのどこかの行の頭に改ページ (フォームフィード) 文字を入れる。
Un*x 文化圏の多くのプログラム言語処理系は改ページ文字を空白文字の一種と見なすのでほとんど害はありません。
ただし、 HTML などはそうではないので使えません
(コメント中に入れるという方法はあります)。
またこの改ページ文字は行の一番頭に入れないと効果がありません。
なお改ページ文字は Emacs からは C-q C-l で入力できます
(画面上は ^L のように表示されます)。
Local Variables<!-- -->: (HTML の場合)、
"Local " "Variables:" (ANSI-C)
のようにダミーのコメントを挟んだり文字列を分割したりして、
キーワードが一続きにならないようにする
Local Variables\: や Local Variables\072
のようにエスケープシーケンスを使う
-*- 〜 -*- が書ける場合は、
-*- local-enable-local-variables: nil -*-
のように書く。この場合ローカル変数セクションは認識されません。ただし、
Emacs 22 以降ではこの変数をファイルローカル変数として設定しようとする
と「安全でない」と見なされてユーザに確認を求められます
(ただし、このときの確認に一度 !
で答えると以降は確認を求められなくなります)。
また、
-*- でファイル先頭でファイルローカル変数を指定するときは、
設定する値に文字列「-*-」、
<空白、タブまたは ;>
に続く「mode:」、文字「;」が現われていはいけません。
特に文字列を変数に設定する場合などはエスケープシーケンスなどの方法でこれらが現われないようにしてください。
メジャーモードは、ファイル先頭の -*-
で指定する方がファイル末尾のローカル変数セクションで指定するよりファイルの読み込みが速くなります
(大抵の場合、その違いは誤差の範囲と思いますが)。これは、ローカル変数セクションでモードを指定すると、いったんファイル名などからモードを決めてから指定されたモードに再設定することになり二度手間となってしまうからです。
#! や -*-
の指定、またローカル変数セクションを書き換えたときに便利です。このコマンドを実行すると、変数
enable-local-variables
の値に関わらずローカル変数が設定されます。ただし、
enable-local-variables が nil
のときは -*- でのモード指定は無視されます
(ローカル変数セクションでのモード指定には
enable-local-variables の値に関わらず従います)。
enable-local-variables (デフォルト: t)
nil に設定するとファイルを開いたときに -*-
やローカル変数セクションを認識しません。編集モードは他の方法
(ファイル名など) で決定されます。 nil でも t
でもない値に設定すると -*-
やローカル変数セクションに従って変数を設定したりモードを変更したりする前にユーザに確認をとります。
local-enable-local-variables (デフォルト: t)
nil であれば enable-local-variables
の値に関わらずローカル変数セクションをすべて無視します (-*-
の解釈には影響しません)。この変数はメジャーモードコマンドなどによって設定されることを意図しているようですが、そのファイルではローカル変数セクションを認識させないようにするという裏技的な使い方もできます
(enable-local-variables
はファイルローカル変数として設定することはできないようになっています)。
enable-local-eval (デフォルト: シンボル maybe)
eval:
S式」の指定や、フック変数などセキュリティ上危険度の高い変数の指定に従うかどうか指定します。
t であれば黙って従います (たいへん危険です)。
nil であれば黙って無視します。それ以外の値であれば
S式 を評価したり変数に設定する前にユーザに確認をとります。
ignored-local-variables (デフォルト: (enable-local-eval))
inhibit-first-line-modes-suffixes、 inhibit-first-line-modes-regexps
(初期値: それぞれ nil、("\\.tar\\'" "\\.tgz\\'"))
-*- によるモード指定を解釈するかどうかをファイル名から決定するパターンを指定します。どちらも正規表現のリストで指定し、次のルールで解釈するかどうかが決まります。
inhibit-first-line-modes-suffixes
のいずれかの要素にマッチすれば、 filename
からマッチした部分とそれ以降の部分を取り除き、新たに
filename とします。
inhibit-first-line-modes-regexps
のいずれかの要素にマッチすれば、そのファイルでは
-*- によるモード指定を行いません。
inhibit-first-line-modes-suffixes
に指定する正規表現には文字列終端にマッチさせるために「\'」
(Emacs-Lisp で書くなら \\') を含めておくほうがいいでしょう。
safe-local-variable-values
(Emacs 22 以降のみ、初期値: nil)
ignored-local-variables
にこの変数が追加されています)。
それぞれの変数について、詳しくはその変数のドキュメント (M-x describe-variable RET 変数名 RET) またはその変数を使う機能のドキュメントにあたってください。
c-file-style
fill-column
compile-command
-command で終わっていますが、標準でプロパティ
safe-local-variable
が設定されていて文字列であれば自由に値を設定できます。
version-control
t なら常に作り、 nil
なら既に番号つきのバックアップファイルがある場合のみ作ります。
never に設定すると全く作りません (foo.c~
のような通常のバックアップファイルを作ります)。
kept-new-versions、kept-old-versions