Improve treesit-node-top-level and treesit-parent-until

* lisp/treesit.el (treesit-node-top-level): Now it can accept a
predicate function.  Add an optional argument INCLUDE-NODE.
(treesit-parent-until): Add an optional argument INCLUDE-NODE.
This commit is contained in:
Yuan Fu 2022-12-27 15:07:03 -08:00
parent 637f5b164f
commit 5326b04198
No known key found for this signature in database
GPG key ID: 56E19BC57664A442

View file

@ -234,19 +234,27 @@ is nil, try to guess the language at BEG using `treesit-language-at'."
(or parser-or-lang (treesit-language-at beg)))))) (or parser-or-lang (treesit-language-at beg))))))
(treesit-node-descendant-for-range root beg (or end beg) named))) (treesit-node-descendant-for-range root beg (or end beg) named)))
(defun treesit-node-top-level (node &optional type) (defun treesit-node-top-level (node &optional pred include-node)
"Return the top-level equivalent of NODE. "Return the top-level equivalent of NODE.
Specifically, return the highest parent of NODE that has the same Specifically, return the highest parent of NODE that has the same
type as it. If no such parent exists, return nil. type as it. If no such parent exists, return nil.
If TYPE is non-nil, match each parent's type with TYPE as a If PRED is non-nil, match each parent's type with PRED as a
regexp, rather than using NODE's type." regexp, rather than using NODE's type. PRED can also be a
(let ((type (or type (treesit-node-type node))) function that takes the node as an argument, and return
non-nil/nil for match/no match.
If INCLUDE-NODE is non-nil, return NODE if it satisfies PRED."
(let ((pred (or pred (treesit-node-type node)))
(result nil)) (result nil))
(cl-loop for cursor = (treesit-node-parent node) (cl-loop for cursor = (if include-node node
(treesit-node-parent node))
then (treesit-node-parent cursor) then (treesit-node-parent cursor)
while cursor while cursor
if (string-match-p type (treesit-node-type cursor)) if (if (stringp pred)
(string-match-p pred (treesit-node-type cursor))
(funcall pred cursor))
do (setq result cursor)) do (setq result cursor))
result)) result))
@ -290,11 +298,16 @@ properties."
(treesit-node-start node) (treesit-node-start node)
(treesit-node-end node)))))) (treesit-node-end node))))))
(defun treesit-parent-until (node pred) (defun treesit-parent-until (node pred &optional include-node)
"Return the closest parent of NODE that satisfies PRED. "Return the closest parent of NODE that satisfies PRED.
Return nil if none was found. PRED should be a function that Return nil if none was found. PRED should be a function that
takes one argument, the parent node." takes one argument, the parent node, and return non-nil/nil for
(let ((node (treesit-node-parent node))) match/no match.
If INCLUDE-NODE is non-nil, return NODE if it satisfies PRED."
(let ((node (if include-node node
(treesit-node-parent node))))
(while (and node (not (funcall pred node))) (while (and node (not (funcall pred node)))
(setq node (treesit-node-parent node))) (setq node (treesit-node-parent node)))
node)) node))