提供された文法に基づき、SMIEは追加の手間なく自動的にインデントを行うことができます。しかし実際には、このデフォルトのインデントスタイルでは不十分な場合が多いでしょう。さまざまなケースに応じて、微調整を行う必要があるはずです。
SMIEのインデントは、インデント規則は可能な限り局所的であるべきだという考え方に基づいています。このため、仮想インデントという概念を採用しています。これは、ある特定のプログラムポイントが行頭にあった場合に持つであろうインデントのことです。当然ながら、そのプログラムポイントが実際に行頭にある場合、その仮想インデントは現在のインデントとなります。そうでない場合、SMIEはインデントアルゴリズムを用いて、そのポイントの仮想インデントを算出します。実際には、プログラムポイントの仮想インデントは、その前に改行を挿入した場合に得られるインデントと必ずしも一致する必要はありません。これがどのように機能するかを見ると、C言語における{の後のインデントに関するSMIEの規則では、{が単独の行にあるか、あるいは直前の行の末尾にあるかは問いません。代わりに、これらの異なるケースは、{の前にどのようにインデントするかを決定するインデント規則の中で処理されます。
もう一つの重要な概念は、親という概念です。トークンの親とは、それを最も近く囲む構文構造の先頭トークンのことです。例えば、elseの親はそれに属するifであり、さらにifの親は、それを囲む構造の先頭トークンとなります。コマンドbackward-sexpはトークンからその親へとジャンプしますが、いくつか注意点があります。オープナー(ifのように構造を開始するトークン)の場合は、トークンの手前からポイントを開始する必要があり、それ以外のトークンの場合は、トークンの後からポイントを開始する必要があります。backward-sexpは、親トークンが対象トークンのオープナーである場合は親トークンの手前でポイントを停止し、そうでない場合は親トークンの後からポイントを停止します。
SMIEのインデント規則は、2つの引数 method と arg を取る関数を用いて指定され、arg の意味と期待される戻り値は method に依存します。
method には以下が指定できます:
:after の場合、arg はトークンとなり、関数は
arg の後にインデントとして使用するための offset
を返す必要があります。
:before の場合、arg
はトークンとなり、関数は arg 自体をインデントするために使用する offset を返す必要があります。
:elem。この場合、関数は、関数引数のインデントに使用するオフセット(arg がシンボル args
の場合)、または基本インデントステップ(arg がシンボル basic の場合)のいずれかを返す必要があります。
:list-intro。この場合、argはトークンとなり、そのトークンの後に式ではなく式のリスト(いかなるトークンによっても区切られていないもの)が続くときは、関数はnil以外の値を返す必要があります。
arg がトークンである場合、関数はそのトークンの直前のポイントを引数として呼び出されます。nil
という戻り値は常にデフォルトの動作にフォールバックすることを意味するため、関数は想定していない引数に対して nil を返す必要があります。
offset には以下が指定できます:
nil: デフォルトのインデント規則を使用する。
(column . column): 列 column までインデント。
:afterの現在のトークンおよび:beforeの親トークンを基準トークンとして、number分だけオフセットしたもの。