На основе предоставленной грамматики SMIE сможет обеспечить автоматический отступ без дополнительных усилий. Но на практике этот стиль отступа по умолчанию, вероятно, будет недостаточно хорош. Вам, вероятно, придется настроить его во многих разных случаях.
Отступ SMIE основан на идее, что правила отступов должны быть максимально локальными. С этой целью он опирается на идею виртуального отступа, который представляет собой отступ, который имел бы определенный программный пункт, если бы он находился в начале строки. Конечно, если этот программный пункт действительно находится в начале строки, его виртуальный отступ равен его текущему отступу. Но если нет, то SMIE использует алгоритм отступов для вычисления виртуального отступа этого пункта. Теперь на практике виртуальный отступ программного пункта не обязательно должен совпадать с отступом, который был бы у него, если бы мы вставили перенос строки перед ним. Чтобы увидеть, как это работает, правило SMIE для отступа после { в C не заботится о том, стоит ли { на отдельной строке или находится в конце предыдущей строки. Вместо этого эти разные случаи обрабатываются в правиле отступа, которое определяет, как отступать перед {.
Другая важная концепция — это понятие родитель: Родитель токена — это корневой токен ближайшей окружающей синтаксической конструкции. Например, родителем else является if, к которому он принадлежит, а родителем if, в свою очередь, является ведущий токен окружающей конструкции. Команда backward-sexp переходит от токена к его родителю, но есть некоторые оговорки: для открывающих (токены, которые начинаются конструкцию, например if) вам нужно начинать с точки перед токеном, в то время как для других вам нужно начинать с точки после токена.
backward-sexp останавливается с точкой перед родительским токеном, если это открывающий токен интересующего токена, и в противном случае останавливается с точкой после родительского токена.
Правила отступов SMIE определяются с помощью функции, которая принимает два аргумента method и arg, где значение arg и ожидаемое возвращаемое значение зависят от method.
method может быть:
:after, в этом случае arg — это токен, и функция должна вернуть offset, который следует использовать для отступа после arg.
:before, в этом случае arg — это токен, и функция должна вернуть offset, который следует использовать для отступа самого arg.
:elem, в этом случае функция должна вернуть либо смещение, которое следует использовать для отступа аргументов функции (если arg — это символ arg), либо базовый шаг отступа (если arg — это символ basic).
:list-intro, в этом случае arg — это токен, и функция должна вернуть не-nil, если токен за которым следует список выражений (не разделенный никаким токеном), а не выражение.
Когда arg — это токен, функция вызывается с точкой непосредственно перед этим токеном. Возврат nil всегда означает возврат к поведению по умолчанию, поэтому функция должна возвращать nil для аргументов, которые она не ожидает.
offset может быть:
nil: использовать правило отступа по умолчанию.
(column . column): отступить до столбца column.
:after и его родителем для :before.