Next: , Previous: , Up: メジャーモードとマイナーモード   [Contents][Index]


24.7 コードの自動インデント

プログラミング言語のメジャーモードにとって、自動的なインデントの提供は重要な機能です。これには2つのパートがあります。1つ目は正しい行のインデントが何か、そして2つ目はいつ行を再インデントするかの判断です。デフォルトではelectric-indent-charsに含まれる文字(デフォルトでは改行のみ)をタイプしたとき、Emacsは常に行を再インデントします。メジャーモードはその言語の構文に合わせてelectric-indent-charsに文字を追加できます。

正しいインデントの決定はindent-line-functionによりEmacs内で制御されます(メジャーモードが制御するインデントを参照)。いくつかのモードではへのインデントは信頼性がないことが知られています。これは通常は複数のインデントが有効であり、それぞれが異なる意味をもつのでインデント自体が重要だからです。そのような場合には、そのモードは行が常にユーザーの意に反して行が毎回再インデントされないことを保証するためにelectric-indent-inhibitをセットするべきです。

よいインデント関数の記述は難しく、その広範な領域において未だ黒魔術の域を脱していません。メジャーモード作者の多くは、単純なケース(たとえば前のテキスト行のインデントとの比較)にたいして機能する、単純な関数の記述からスタートすることでしょう。実際には行ベースではないほとんどのプログラミング言語にたいして、これは貧弱なスケールになりがちです。そのような関数にたいして、より多様な状況を処理するような改良を行うと関数はより一層複雑になり、最終的な結果は誰にも触れようとする気を起こさせない、巨大で複雑な保守不可能のインデント関数になる傾向があります。

よいインデント関数は、通常はその言語の構文に応じて実際にテキストをパースする必要があるでしょう。幸運なことにこのテキストパースはコンパイラーが要するほど詳細である必要はないでしょうが、その一方でインデントコードに埋め込まれたパーサーは構文的に不正なコードにたいして、コンパイラーより幾分寛容な振る舞いを求められるでしょう。

保守可能なよいインデント関数は、通常は2つのカテゴリーに落ち着きます。どちらも何らかの安全な開始ポイントから、関心のある位置まで前方か後方へパースを行います。この2つの方法は、いずれも一方が他方に明快に優る選択ではありません。後方へのパースはプログラミング言語が前方にパースされるようデザインされているため、前方へのパースに比べて難しいことが多々ありますが、インデントという目的においては安全な開始ポイントを推測する必要がないという利点があり、一般的にある行のインデントの判断のために分析を要するのは最小限のテキストだけという特性に恵まれているので、前の無関係なコード片内にある何らかの構文エラーの影響をインデントが受けにくくなる傾向があります。一方で前方へのパースは通常はより簡単であり、一度のパースでリージョン全体を効果的に再インデントすることが可能になるという利点があります。

インデント関数をスクラッチから記述するよりも、既存のインデント関数の使用と再利用、または一般的なインデントエンジンに委ねるほうが優る場合がしばしばあります。しかしそのようなエンジンは悲しむべきほど少数しかありません。(C、C++、Java、Awk、およびその類のモードに使用される)CCモードのインデントコードは年月を経てより一般化されてきているので、あなたの言語にこれらの言語と何らかの類似点があるなら、このエンジンの使用を試みるかもしれません。もう一方のSMIEはLispのsexp精神によるアプローチを採用して、それを非Lisp言語に適応します。他にもたとえばtree-sitterライブラリーのような本格的なパーサーに頼る方法もあります。