@item standalone-parent
This anchor is a function that is called with 3 arguments: @var{node},
-@var{parent}, and @var{bol}. It finds the first ancestor node
-(parent, grandparent, etc.@:) of @var{node} that starts on its own
-line, and return the start of that node. ``Starting on its own line''
-means there is only whitespace character before the node on the line
-which the node's start is on.
+@var{parent}, and @var{bol}. It finds the first ancestor node (parent,
+grandparent, etc.@:) of @var{node} that starts on its own line, and
+return the start of that node. ``Starting on its own line'' means there
+is only whitespace character before the node on the line which the
+node's start is on. The exact definition of ``Starting on its own
+line'' can be relaxed by setting
+@code{treesit-simple-indent-standalone-predicate}, some major mode might
+want to do that for easier indentation for method chaining.
@item prev-sibling
This anchor is a function that is called with 3 arguments: @var{node},
"Find the first parent that starts on a new line.
Start searching from PARENT, so if PARENT satisfies the condition, it'll
be returned. Return the starting position of the parent, return nil if
-no parent satisfies the condition."
+no parent satisfies the condition.
+
+Unlike simple-indent's standalone preset, this function handles method
+chaining like
+
+ func
+ .method() <-- Considered standalone even if there's a \".\" in
+ .method() front of the node.
+
+But ff `treesit-simple-indent-standalone-predicate' is non-nil, use that
+for determining standlone line."
(save-excursion
(catch 'term
(while parent
(goto-char (treesit-node-start parent))
- (when (looking-back (rx bol (* whitespace))
- (line-beginning-position))
+ (when (if treesit-simple-indent-standalone-predicate
+ (funcall treesit-simple-indent-standalone-predicate
+ parent)
+ (looking-back (rx bol (* whitespace) (? "."))
+ (line-beginning-position)))
(throw 'term (point)))
(setq parent (treesit-node-parent parent))))))
(defun c-ts-common--prev-standalone-sibling (node)
"Return the previous sibling of NODE that starts on a new line.
-Return nil if no sibling satisfies the condition."
+Return nil if no sibling satisfies the condition.
+
+Unlike simple-indent's standalone preset, this function handles method
+chaining like
+
+ func
+ .method() <-- Considered standalone even if there's a \".\" in
+ .method() front of the node.
+
+But ff `treesit-simple-indent-standalone-predicate' is non-nil, use that
+for determining standlone line."
(save-excursion
(setq node (treesit-node-prev-sibling node 'named))
(goto-char (treesit-node-start node))
(while (and node
(goto-char (treesit-node-start node))
- (not (looking-back (rx bol (* whitespace))
- (pos-bol))))
+ (not (if treesit-simple-indent-standalone-predicate
+ (funcall treesit-simple-indent-standalone-predicate
+ node)
+ (looking-back (rx bol (* whitespace) (? "."))
+ (pos-bol)))))
(setq node (treesit-node-prev-sibling node 'named)))
node))
situations. By default, any node that has \"proproc\" 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 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
(back-to-indentation)
(treesit--indent-largest-node-at (point)))))
+(defvar treesit-simple-indent-standalone-predicate nil
+ "Function used to determine if a node is \"standalone\".
+
+\"Standalone\" means the node starts on a new line. For example, if we
+look at the opening bracket, then it's standalone in this case:
+
+ { <-- Standalone.
+ return 1;
+ }
+
+but not in this case:
+
+ if (true) { <-- Not standalone.
+ return 1;
+ }
+
+The value of this variable affects the `standalone-parent' indent preset
+for treesit-simple-indent. If the value is nil, the standlone condition
+is as described. Some major mode might want to relax the condition a
+little bit, so that it ignores some punctuation like \".\". For
+example, a Javascript mode might want to consider the method call below
+to be standalone too:
+
+ obj
+ .method(() => { <-- Consider \".method\" to be standalone,
+ return 1; <-- so this line anchors on \".method\".
+ });
+
+The value should be a function that takes a node, and return t if it's
+standalone.")
+
(defvar treesit-simple-indent-presets
(list (cons 'match
(lambda
(catch 'term
(while parent
(goto-char (treesit-node-start parent))
- (when (looking-back (rx bol (* whitespace))
- (line-beginning-position))
+ (when (if (null treesit-simple-indent-standalone-predicate)
+ (looking-back (rx bol (* whitespace))
+ (line-beginning-position))
+ (funcall parent))
(throw 'term (point)))
(setq parent (treesit-node-parent parent)))))))
(cons 'prev-sibling (lambda (node parent bol &rest _)
standalone-parent
Finds the first ancestor node (parent, grandparent, etc.) that
- starts on its own line, and returns the start of that node.
+ starts on its own line, and returns the start of that node. The
+ definition of \"standalone\" can be customized by setting
+ `treesit-simple-indent-standalone-predicate'. Some major mode might
+ want to do that for easier indentation for method chaining.
prev-sibling