Вот пример функции отступов:
(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 стараться быть умнее, когда
разделитель запятой находится в начале строк. Оно пытается сдвинуть разделитель влево, чтобы
выровнять код после запятой; например:
x = longfunctionname (
arg1
, arg2
);
":=" существует потому, что в противном
случае SMIE рассматривал бы ":=" как бинарный оператор и выравнивал бы
правый аргумент с левым.
"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"
как единое целое, чтобы выровнять последовательность тестов, а не отступать каждый тест
дальше вправо. Эта функция делает это только в том случае, если "if" не
находится на отдельной строке, отсюда и проверка smie-rule-bolp.
Если мы знаем, что "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)))))
Преимущество этой формулировки в том, что она повторно использует отступ предыдущего
"else", вместо того чтобы возвращаться к первому "if"
в последовательности.