and parents. In that case, only 1 3 4 8 would be traversed.
@end defun
-@defun treesit-search-forward-goto start predicate side &optional all backward up
-For those who want to not only search for a node but also move to it,
-this is the function to use. Parameter @var{start}, @var{predicate},
-@var{all}, @var{backward}, and @var{up} are the same as in
+@defun treesit-search-forward-goto predicate side &optional all backward up
+This function jumps to the start or end of the next node in buffer
+that matches @var{predicate}. Parameters @var{predicate}, @var{all},
+@var{backward}, and @var{up} are the same as in
@code{treesit-search-forward}. And @var{side} controls which side of
the matched no do we stop at, it can be @code{'start} or @code{'end}.
-
-Beware of this common pitfall:
-
-@example
-@group
-;; This will not move point forward.
-(while (treesit-search-forward-goto
- (treesit-node-at (point))
- "xxx"
- 'start)
- ...)
-
-;; This is will move point forward.
-(let ((node (treesit-node-at (point))))
- (while (setq node (treesit-search-forward-goto
- node "xxx" 'start))
- ...))
-@end group
-@end example
-
-The exact reason why is left as an exercise for the reader.
@end defun
@defun treesit-induce-sparse-tree root predicate &optional process-fn limit
;;; Search
(defun treesit-search-forward-goto
- (start predicate side &optional all backward up)
- "Search for node in the parse tree and move point to it.
+ (predicate side &optional all backward up)
+ "Search forward for a node and move to it.
-Start traversing the tree from node START, and match PREDICATE with
-each node along the way (except START). PREDICATE can be either a
-regexp that matches against each node's type, or a function that takes
-a node and returns nil/non-nil for match/no match.
+Stops at the first node after point that matches PREDICATE.
+PREDICATE can be either a regexp that matches against each node's
+type, or a function that takes a node and returns nil/non-nil for
+match/no match.
If a node matches, move to that node and return the node,
otherwise return nil. SIDE controls whether we move to the start
\\='end.
ALL, BACKWARD, and UP are the same as in `treesit-search-forward'."
- (when-let ((node (treesit-search-forward
- start predicate all backward up)))
- (pcase side
- ('start (goto-char (treesit-node-start node)))
- ('end (goto-char (treesit-node-end node))))
+ (let ((node (treesit-node-at (point)))
+ (start (point)))
+ ;; When searching forward, it is possible for (point) < start,
+ ;; because `treesit-search-forward' goes to parents.
+ (while (and node (if backward
+ (>= (point) start)
+ (<= (point) start)))
+ (setq node (treesit-search-forward
+ node predicate all backward up))
+ (if-let ((pos (pcase side
+ ('start (treesit-node-start node))
+ ('end (treesit-node-end node)))))
+ (goto-char pos)))
+ ;; If we made reverse progress, go back to where we started.
+ (when (if backward
+ (>= (point) start)
+ (<= (point) start))
+ (goto-char start))
node))
;;; Debugging