]> git.eshelyaron.com Git - emacs.git/commitdiff
Improve treesit-search-forward-goto
authorYuan Fu <casouri@gmail.com>
Sun, 25 Sep 2022 03:42:03 +0000 (20:42 -0700)
committerYuan Fu <casouri@gmail.com>
Sun, 25 Sep 2022 04:11:31 +0000 (21:11 -0700)
* doc/lispref/parsing.texi (Retrieving Node): Update manual.
* lisp/treesit.el (treesit-search-forward-goto): Instead of taking a
node, use the node at point, and make sure we make progress.

doc/lispref/parsing.texi
lisp/treesit.el

index 868b9bc0744ed1c7bc674cbbe85a4a105c050251..32fc6a69a5474dc5f0da05bde0494cb8d5ef88a4 100644 (file)
@@ -623,33 +623,12 @@ If @var{up} is non-nil, this function will only traverse to siblings
 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
index def2e6259e96b33eeba686aba67c3353ed79020a..001404d88d212839985fb5fd01425a669e8f87d3 100644 (file)
@@ -723,13 +723,13 @@ indentation (target) is in green, current indentation is in red."
 ;;; 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
@@ -737,11 +737,24 @@ or end of the matches node, it can be either \\='start or
 \\='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