From fa9bede36c18d063f6f599e102cd42f9d0afc071 Mon Sep 17 00:00:00 2001 From: Yuan Fu Date: Sun, 23 Oct 2022 14:56:17 -0700 Subject: [PATCH] Change function signiture of treesit search functions Justification: We want to make the SIDE argument in treesit-search-forward-goto optional, so I changed it to START. It makes more sense for BACKWARD to follow START so two common case, search for end forward and beginning backwards are (treesit-search-forward-goto node pred) (treesit-search-forward-goto node pred t t) Then since we swapped BACKWARD and ALL for treesit-search-forward-goto, it's best to swap them for treesit-search-forward and treesit-search-subtree, too. And BACKWARD will probably be used more frequently than ALL anyway. * doc/lispref/parsing.texi (Retrieving Node): Resolve FIXME and update function signitures. * lisp/treesit.el (treesit-search-forward-goto): Change SIDE to START, swap BACKWARD and ALL. (treesit-beginning-of-defun) (treesit-end-of-defun): Update use of treesit-search-forward-goto * src/treesit.c (Ftreesit_search_subtree) (Ftreesit_search_forward): Swap BACKWARD and ALL. --- doc/lispref/parsing.texi | 20 ++++++++--------- lisp/treesit.el | 47 ++++++++++++++++++++++------------------ src/treesit.c | 8 +++---- 3 files changed, 39 insertions(+), 36 deletions(-) diff --git a/doc/lispref/parsing.texi b/doc/lispref/parsing.texi index ec6cd2757d8..e26090be1d7 100644 --- a/doc/lispref/parsing.texi +++ b/doc/lispref/parsing.texi @@ -633,7 +633,7 @@ is non-@code{nil}, it looks for smallest named child. @heading Searching for node -@defun treesit-search-subtree node predicate &optional all backward limit +@defun treesit-search-subtree node predicate &optional backward all limit This function traverses the subtree of @var{node} (including @var{node} itself), looking for a node for which @var{predicate} returns non-@code{nil}. @var{predicate} is a regexp that is matched @@ -650,7 +650,7 @@ must be a number that limits the tree traversal to that many levels down the tree. @end defun -@defun treesit-search-forward start predicate &optional all backward +@defun treesit-search-forward start predicate &optional backward all Like @code{treesit-search-subtree}, this function also traverses the parse tree and matches each node with @var{predicate} (except for @var{start}), where @var{predicate} can be a (case-insensitive) regexp @@ -691,15 +691,13 @@ answering questions like ``what is the first node after @var{start} in the buffer that satisfies some condition?'' @end defun -@defun treesit-search-forward-goto predicate side &optional all backward -This function moves point to the beginning or end of the next node in -the buffer that matches @var{predicate}. Arguments @var{predicate}, -@var{all} and @var{backward} are the same as in -@code{treesit-search-forward}. @var{side} controls on which side of -the matched node we stop: it can be @code{start} or @code{end}. -@c FIXME: Wouldn't it be convenient to make SIDE optional argument, -@c and by default stop and the beginning (or end), whichever happens -@c most frequently? +@defun treesit-search-forward-goto predicate &optional start backward all +This function moves point to the start or end of the next node in +the buffer that matches @var{predicate}. If @var{start} is +non-nil, stop at the beginning rather than the end of a node. + +Arguments @var{predicate}, @var{backward} and @var{all} are the same +as in @code{treesit-search-forward}. @end defun @defun treesit-induce-sparse-tree root predicate &optional process-fn limit diff --git a/lisp/treesit.el b/lisp/treesit.el index 3557d00d667..2fe48b34aa0 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -809,8 +809,8 @@ indentation (target) is in green, current indentation is in red." ;;; Search (defun treesit-search-forward-goto - (predicate side &optional all backward) - "Search forward for a node and move to it. + (predicate &optional start backward all) + "Search forward for a node and move to its end position. Stops at the first node after point that matches PREDICATE. PREDICATE can be either a regexp that matches against each node's @@ -818,35 +818,40 @@ type case-insensitively, 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 -or end of the matches node, it can be either \\='start or -\\='end. +otherwise return nil. If START is non-nil, stop at the +beginning rather than the end of a node. -ALL and BACKWARD are the same as in `treesit-search-forward'." +BACKWARD and ALL are the same as in `treesit-search-forward'." (let ((node (treesit-node-at (point))) - (start (point))) + (start-pos (point))) ;; Often the EOF (point-max) is a newline, and `treesit-node-at' ;; will return nil at that point (which is fair). But we need a ;; node as the starting point to traverse the tree. So we try to ;; use the node before point. (when (and (not node) (eq (point) (point-max))) (setq node (treesit-node-at (max (1- (point)) (point-min))))) - ;; When searching forward, it is possible for (point) < start, - ;; because `treesit-search-forward' goes to parents. + ;; When searching forward and stopping at beginnings, or search + ;; backward stopping at ends, it is possible to "roll back" in + ;; position. Take three nodes N1, N2, N3 as an example, if we + ;; start at N3, search for forward for beginning, and N1 matches, + ;; we would stop at beg of N1, which is backwards! So we skip N1. + ;; + ;; |<--------N1------->| + ;; |<--N2-->| |<--N3-->| (while (and node (if backward - (>= (point) start) - (<= (point) start))) + (>= (point) start-pos) + (<= (point) start-pos))) (setq node (treesit-search-forward - node predicate all backward)) - (if-let ((pos (pcase side - ('start (treesit-node-start node)) - ('end (treesit-node-end node))))) + node predicate backward all)) + (if-let ((pos (if start + (treesit-node-start node) + (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)) + (>= (point) start-pos) + (<= (point) start-pos)) + (goto-char start-pos)) node)) ;;; Navigation @@ -867,17 +872,17 @@ ARG is the same as in `beginning-of-defun." ;; Go backward. (while (and (> arg 0) (treesit-search-forward-goto - treesit-defun-type-regexp 'start nil t)) + treesit-defun-type-regexp t t)) (setq arg (1- arg))) ;; Go forward. (while (and (< arg 0) (treesit-search-forward-goto - treesit-defun-type-regexp 'start)) + treesit-defun-type-regexp t t)) (setq arg (1+ arg)))))) (defun treesit-end-of-defun () "Tree-sitter `end-of-defun' function." - (treesit-search-forward-goto treesit-defun-type-regexp 'end)) + (treesit-search-forward-goto treesit-defun-type-regexp)) ;;; Imenu diff --git a/src/treesit.c b/src/treesit.c index a23ac7510da..b0e7d0e211a 100644 --- a/src/treesit.c +++ b/src/treesit.c @@ -2503,8 +2503,8 @@ all nodes. If BACKWARD is non-nil, traverse backwards. If LIMIT is non-nil, only traverse nodes up to that number of levels down in the tree. Return the first matched node, or nil if none matches. */) - (Lisp_Object node, Lisp_Object predicate, Lisp_Object all, - Lisp_Object backward, Lisp_Object limit) + (Lisp_Object node, Lisp_Object predicate, Lisp_Object backward, + Lisp_Object all, Lisp_Object limit) { CHECK_TS_NODE (node); CHECK_TYPE (STRINGP (predicate) || FUNCTIONP (predicate), @@ -2563,8 +2563,8 @@ numbered from 1 to 12: Note that this function doesn't traverse the subtree of START, and it always traverse leaf nodes first, then upwards. */) - (Lisp_Object start, Lisp_Object predicate, Lisp_Object all, - Lisp_Object backward) + (Lisp_Object start, Lisp_Object predicate, Lisp_Object backward, + Lisp_Object all) { CHECK_TS_NODE (start); CHECK_TYPE (STRINGP (predicate) || FUNCTIONP (predicate), -- 2.39.2