Add treesit-node-top-level

Merge treesit-node-top-level-p and treesit--find-top-level-match into
treesit-node-top-level.

* doc/lispref/parsing.texi (Retrieving Node): Add manual entry for it.
* lisp/progmodes/js.el (js--treesit-imenu-1): Replace
treesit-node-top-level-p with treesit-node-top-level.
* lisp/treesit.el (treesit-node-top-level-p)
(treesit--find-top-level-match): Remove functions.
(treesit-node-top-level): New function.
* lisp/treesit.el (treesit-beginning-of-defun)
(treesit-end-of-defun): Replace treesit--find-top-level-match with
treesit-node-top-level.
This commit is contained in:
Yuan Fu 2022-10-29 14:11:52 -07:00
parent baacad1771
commit da87895df2
No known key found for this signature in database
GPG key ID: 56E19BC57664A442
3 changed files with 38 additions and 34 deletions

View file

@ -782,6 +782,16 @@ takes a node as the argument. That is, this function returns the
farthest parent that still satisfies @var{predicate}.
@end defun
@defun treesit-node-top-level node &optional type
This function returns the highest parent of @var{node} that has the
same type as @var{node}. If no such parent exists, it returns
@code{nil}. Therefore this function is also useful for testing
whether @var{node} is top-level.
If @var{type} is non-@code{nil}, this function matches each parent's
type with @var{type} as a regexp, rather than using @var{node}'s type.
@end defun
@node Accessing Node Information
@section Accessing Node Information
@cindex information of node, syntax trees

View file

@ -3670,8 +3670,9 @@ definition*\"."
(cond
((null ts-node)
subtrees)
;; Don't included non-top-level variable declarations.
((and (eq type 'variable)
(not (treesit-node-top-level-p ts-node)))
(treesit-node-top-level ts-node))
nil)
(subtrees
(let ((parent-label (js--treesit-imenu-label type name))

View file

@ -246,21 +246,21 @@ that language in the current buffer, and use that."
(treesit-buffer-root-node parser-or-lang))))
(treesit-node-descendant-for-range root beg (or end beg) named)))
(defun treesit-node-top-level-p (node &optional type)
"Return non-nil if NODE is top-level, and nil otherwise.
Being top-level means there is no parent of NODE that has the
same type.
(defun treesit-node-top-level (node &optional type)
"Return the top-level equivalent of NODE.
Specifically, return the highest parent of NODE that has the same
type as it. If no such parent exists, return nil.
If TYPE is non-nil, match each parent's type with TYPE as a regexp."
(when node
(catch 'term
(let ((plain-type (treesit-node-type node)))
(while (setq node (treesit-node-parent node))
(when (if type
(string-match-p type (treesit-node-type node))
(equal (treesit-node-type node) plain-type))
(throw 'term nil))))
t)))
If TYPE is non-nil, match each parent's type with TYPE as a
regexp, rather than using NODE's type."
(let ((type (or type (treesit-node-type node)))
(result nil))
(cl-loop for cursor = (treesit-node-parent node)
then (treesit-node-parent cursor)
while cursor
if (string-match-p type (treesit-node-type cursor))
do (setq result cursor))
result))
(defun treesit-buffer-root-node (&optional language)
"Return the root node of the current buffer.
@ -1162,17 +1162,6 @@ For example, \"(function|class)_definition\".
This is used by `treesit-beginning-of-defun' and friends.")
(defun treesit--find-top-level-match (node type)
"Return the top-level parent of NODE matching TYPE.
TYPE is a regexp, this function matches TYPE with each parent's
type."
(cl-loop for cursor = (treesit-node-parent node)
then (treesit-node-parent cursor)
while cursor
if (string-match-p type (treesit-node-type cursor))
do (setq node cursor)
finally return node))
(defun treesit-beginning-of-defun (&optional arg)
"Tree-sitter `beginning-of-defun' function.
ARG is the same as in `beginning-of-defun'."
@ -1183,15 +1172,17 @@ ARG is the same as in `beginning-of-defun'."
(while (and (> arg 0)
(setq node (treesit-search-forward-goto
node treesit-defun-type-regexp t t)))
(setq node (treesit--find-top-level-match
node treesit-defun-type-regexp))
(setq node (or (treesit-node-top-level
node treesit-defun-type-regexp)
node))
(setq arg (1- arg)))
;; Go forward.
(while (and (< arg 0)
(setq node (treesit-search-forward-goto
node treesit-defun-type-regexp)))
(setq node (treesit--find-top-level-match
node treesit-defun-type-regexp))
(setq node (or (treesit-node-top-level
node treesit-defun-type-regexp)
node))
(setq arg (1+ arg))))
(when node
(goto-char (treesit-node-start node))
@ -1201,10 +1192,12 @@ ARG is the same as in `beginning-of-defun'."
"Tree-sitter `end-of-defun' function."
;; Why not simply get the largest node at point: when point is at
;; (point-min), that gives us the root node.
(let ((node (treesit--find-top-level-match
(treesit-node-at (point))
treesit-defun-type-regexp)))
(goto-char (treesit-node-end node))))
(let* ((node (treesit-node-at (point)))
(top (or (treesit-node-top-level
node
treesit-defun-type-regexp)
node)))
(goto-char (treesit-node-end top))))
;;; Imenu