提供された文法にもとづき、他に特別なことを行わなくてもSMIEは自動的なインデントを提供できるでしょう。しかし恐らく実際にはこのデフォルトのインデントスタイルでは十分ではありません。多くの異なる状況においてこれを微調整したいと思うかもしれません。
SMIEのインデントは、インデントルールは可能な限りローカルであるべきという考えにもとづきます。バーチャルインデント(virtual
indentation)という考えによってこの目的を達成しています。これは特定のプログラムポイント(program
point)は行頭にバーチャルインデントがあれば、それをもつだろう、という発想です。もちろんそのプログラムポイントが正に行頭にあれば、そのプログラムポイントのバーチャルインデントはプログラムポイントのカレントのインデントです。しかしそうでなければSMIEがそのポイントのバーチャルインデントを計算するためにインデントアルゴリズムを使用します。ところで実際にはあるプログラムポイントのバーチャルインデントは、その前に改行を挿入した場合にプログラムポイントがもつであろうインデントと等しい必要はありません。これが機能する方法を確認するためには、Cにおける{
の後のSMIEのインデントルールは{
がインデントする行自体にあるか、あるいは前の行の終端にあるかを配慮しないことが挙げられます。かわりにこれらの異なるケースは{
の前のインデントを決定するインデントルール内で処理されます。
他の重要な考え方としてparentの概念があります。あるトークンparentは周囲にある直近の構文構造の代表トークン(head
token)です。たとえばelse
のparentはそれが属するif
であり、if
のparentは周囲を取り囲む構造の先導トークン(lead
token)です。コマンドbackward-sexp
は、あるトークンからトークンのparentにジャンプしますが注意する点がいくつかあります。他のトークンではそのトークンの後のポイントから開始する必要があるのにたいして、opener
(if
のようなある構造を開始するトークン)ではそのトークンの前のポイントから開始する必要があります。backward-sexp
はparentトークンがそのトークンのopenerならparentトークンの前のポイントで停止し、それ以外ではparentトークンの後のポイントで停止します。
SMIEのインデントルールは、2つの引数methodとargを受け取る関数により指定されます。ここでargの値と期待されるリターン値はmethodに依存します。
methodには以下のいずれかを指定できます:
:after
:
この場合、argはトークンであり関数はargの後に使用するインデントにたいするoffsetをリターンすること。
:before
:
この場合、argはトークンであり関数はarg自体に使用するインデントのoffsetをリターンすること。
:elem
:
この場合、関数は関数の引数に使用するインデントのオフセット(argがシンボルarg
の場合)、または基本的ナインデントステップ(argがシンボルbasic
の場合)のいずれかをリターンすること。
:list-intro
:
この場合、argはトークンであり関数はそのトークンの後が単一の式ではなく、(任意のトークンにより区切られない)式のリストが続くなら非nil
をリターンすること。
argがトークンのとき関数はそのトークンの直前のポイントで呼び出されます。リターン値nil
は常にデフォルトの振る舞いへのフォールバックを意味するので、関数は期待した引数でないときはnil
をリターンするべきです。
offsetには以下のいずれかを指定できます:
nil
: デフォルトのインデントルールを使用する。
(column . column)
: 列columnにインデントする。
:after
にたいするカレントトークンであり、かつ:before
にたいしてparentであるようなトークン)にたいして相対的なnumberによるオフセット。