Function: c-ts-common-baseline-indent-rule
c-ts-common-baseline-indent-rule is a byte-compiled function defined
in c-ts-common.el.gz.
Signature
(c-ts-common-baseline-indent-rule NODE PARENT BOL &rest _)
Documentation
Baseline indent rule for C-like languages.
NODE PARENT, BOL are like in other simple indent rules.
This rule works as follows:
Let PREV-NODE be the largest node that starts on previous line, basically the NODE we get if we were indenting previous line.
0. Closing brace aligns with first parent that starts on a new line.
1. If PREV-NODE and NODE are siblings, align this line to previous
line (PREV-NODE as the anchor, and offset is 0).
2. If PARENT is a list, ie, (...) [...], align with NODE's first
sibling. For the first sibling and the closing paren or bracket, indent
according to c-ts-common-list-indent-style. This rule also handles
initializer lists like {...}, but initializer lists doesn't respect
c-ts-common-list-indent-style--they always indent in the simple
style.
3. Otherwise, go up the parse tree from NODE and look for a parent that
starts on a new line. Use that parent as the anchor and indent one
level. But if the node is a top-level construct (ignoring preprocessor
nodes), don't indent it.
This rule works for a wide range of scenarios including complex situations. Major modes should use this as the fallback rule, and add exception rules before it to cover the cases it doesn't apply.
This rule tries to be smart and ignore preprocessor node in some
situations. By default, any node that has "preproc" in its type are
considered a preprocessor node. If that heuristic is inaccurate, define
a preproc thing in treesit-thing-settings, and this rule will use
the thing definition instead.
The rule also handles method chaining like
func
.method() <-- Considered "starts at a newline" even if there's
.method() a "." in front of the node.
Source Code
;; Defined in /usr/src/emacs/lisp/progmodes/c-ts-common.el.gz
(defun c-ts-common-baseline-indent-rule (node parent bol &rest _)
"Baseline indent rule for C-like languages.
NODE PARENT, BOL are like in other simple indent rules.
This rule works as follows:
Let PREV-NODE be the largest node that starts on previous line,
basically the NODE we get if we were indenting previous line.
0. Closing brace aligns with first parent that starts on a new line.
1. If PREV-NODE and NODE are siblings, align this line to previous
line (PREV-NODE as the anchor, and offset is 0).
2. If PARENT is a list, ie, (...) [...], align with NODE's first
sibling. For the first sibling and the closing paren or bracket, indent
according to `c-ts-common-list-indent-style'. This rule also handles
initializer lists like {...}, but initializer lists doesn't respect
`c-ts-common-list-indent-style'--they always indent in the `simple'
style.
3. Otherwise, go up the parse tree from NODE and look for a parent that
starts on a new line. Use that parent as the anchor and indent one
level. But if the node is a top-level construct (ignoring preprocessor
nodes), don't indent it.
This rule works for a wide range of scenarios including complex
situations. Major modes should use this as the fallback rule, and add
exception rules before it to cover the cases it doesn't apply.
This rule tries to be smart and ignore preprocessor node in some
situations. By default, any node that has \"preproc\" in its type are
considered a preprocessor node. If that heuristic is inaccurate, define
a `preproc' thing in `treesit-thing-settings', and this rule will use
the thing definition instead.
The rule also handles method chaining like
func
.method() <-- Considered \"starts at a newline\" even if there's
.method() a \".\" in front of the node."
(let ((prev-line-node (treesit--indent-prev-line-node bol))
(offset (symbol-value c-ts-common-indent-offset)))
(cond
;; Condition 0.
((and (treesit-node-match-p node "}")
(treesit-node-match-p (treesit-node-child parent 0) "{"))
(cons (c-ts-common--standalone-parent parent)
0))
;; Condition 1.
((and (treesit-node-eq (treesit-node-parent prev-line-node)
parent)
(not (treesit-node-match-p node (rx (or ")" "]")))))
(cons (treesit-node-start prev-line-node)
0))
;; Condition 2.
((treesit-node-match-p (treesit-node-child parent 0)
(rx (or "(" "[")))
(let ((first-sibling (treesit-node-child parent 0 'named)))
(while (treesit-node-match-p
first-sibling c-ts-common--comment-regexp 'ignore-missing)
(setq first-sibling (treesit-node-next-sibling first-sibling 'named)))
(cond
;; Closing delimiters.
((treesit-node-match-p node (rx (or ")" "]")))
(if (eq c-ts-common-list-indent-style 'align)
(cons (treesit-node-start (treesit-node-child parent 0))
0)
(cons (c-ts-common--standalone-parent parent)
0)))
;; First sibling.
((treesit-node-eq node first-sibling)
(if (eq c-ts-common-list-indent-style 'align)
(cons (treesit-node-start (treesit-node-child parent 0))
1)
(cons (c-ts-common--standalone-parent parent)
offset)))
;; Not first sibling
(t (cons (or (c-ts-common--prev-standalone-sibling node)
(treesit-node-start first-sibling))
0)))))
;; Condition 2 for initializer list, only apply to
;; second line. Eg,
;;
;; return { 1, 2, 3,
;; 4, 5, 6, --> Handled by this condition.
;; 7, 8, 9 }; --> Handled by condition 1.
((and (treesit-node-match-p (treesit-node-child parent 0) "{")
(treesit-node-prev-sibling node 'named))
;; If first sibling is a comment, indent like code; otherwise
;; align to first sibling.
(if (treesit-node-match-p
(treesit-node-child parent 0 'named)
c-ts-common--comment-regexp 'ignore-missing)
(cons (c-ts-common--standalone-parent parent)
offset)
(cons (treesit-node-start
(treesit-node-child parent 0 'named))
0)))
;; Before we fallback to condition 3, make sure we don't indent
;; top-level stuff.
((treesit-node-eq (treesit-parser-root-node
(treesit-node-parser parent))
(c-ts-common-parent-ignore-preproc node))
(cons (pos-bol) 0))
;; Condition 3.
(t (cons (c-ts-common--standalone-parent parent)
offset)))))