以下はインデント関数の例です:
(defun sample-smie-rules (kind token) (pcase (cons kind token) (`(:elem . basic) sample-indent-basic) (`(,_ . ",") (smie-rule-separator kind)) (`(:after . ":=") sample-indent-basic) (`(:before . ,(or `"begin" `"(" `"{")) (if (smie-rule-hanging-p) (smie-rule-parent))) (`(:before . "if") (and (not (smie-rule-bolp)) (smie-rule-prev-p "else") (smie-rule-parent)))))
注意すべき点がいくつかあります:
sample-indent-basic
がnil
なら、SMIEはグローバルセッティングsmie-indent-basic
を使用する。メジャーモードがかわりにsmie-indent-basic
をバッファーローカルにセットするかもしれないが推奨しない。
","
にたいするルールによってカンマセパレーターが行頭にある場合にSMIEをより賢明に振る舞わせようとしている。これはセパレーターのインデントを解除(outdent)、カンマの後のコードにアラインされるよう試みる。たとえば:
x = longfunctionname ( arg1 , arg2 );
":="
を2項演算子として扱い、左の引数に併せて右の引数をアラインするであろうから、":="
の後のインデントのルールが存在する。
"begin"
の前のインデントのルールはバーチャルインデントの使用例である。このルールは"begin"
がhangingのときだけ使用され、これは"begin"
が行頭にないときのみ発生し得る。そのためこれは"begin"
自体のインデントには使用されないが、この"begin"
に関連する何かをインデントするときだけ使用される。このルールは具体的には以下のフォームを:
if x > 0 then begin dosomething(x); end
以下に変更する
if x > 0 then begin dosomething(x); end
"if"
の前のインデントのルールは"begin"
のインデントルールと似ているが、ここでの目的は"else
if"
を1単位として扱うことにあり、それにより各テストより右にインデントされずに一連のテストにアラインされる。この関数はsmie-rule-bolp
をテストして"if"
が別の行にないときだけこれを行う。
"else"
がそれの属する"if"
にたいして常にアラインされて、かつそれが常に行頭であるることが判っていれば、より効果的なルールを使用できる:
((equal token "if") (and (not (smie-rule-bolp)) (smie-rule-prev-p "else") (save-excursion (sample-smie-backward-token) (cons 'column (current-column)))))
この式の利点はこれがシーケンスの最初の"if"
まで戻ってすべてをやり直すのではなく、前の"else"
のインデントを再利用することである。