Add treesit-node-enclosed-p

* doc/lispref/parsing.texi (Accessing Node Information):
Add manual entry.
* lisp/treesit.el (treesit-node-enclosed-p): New function.
(treesit): Add shortdoc entry.
* test/src/treesit-tests.el (treesit-node-api): Add tests.
This commit is contained in:
Yuan Fu 2023-11-09 20:49:30 -08:00
parent 1653389b57
commit 0db75b80e1
No known key found for this signature in database
GPG key ID: 56E19BC57664A442
3 changed files with 62 additions and 3 deletions

View file

@ -705,7 +705,7 @@ This function finds the previous sibling of @var{node}. If
To make the syntax tree easier to analyze, many language grammars
assign @dfn{field names} to child nodes (@pxref{tree-sitter node field
name, field name}). For example, a @code{function_definition} node
could have a @code{declarator} node and a @code{body} node.
could have a @code{declarator} child and a @code{body} child.
@defun treesit-node-child-by-field-name node field-name
This function finds the child of @var{node} whose field name is
@ -1081,6 +1081,22 @@ This function returns the number of children of @var{node}. If
(@pxref{tree-sitter named node, named node}).
@end defun
@heading Convenience functions
@defun treesit-node-enclosed-p smaller larger &optional strict
This function returns non-@code{nil} if @var{smaller} is enclosed in
@var{larger}. @var{smaller} and @var{larger} can be either a cons
@code{(@var{beg} . @var{end})} or a node.
Return non-@code{nil} if @var{larger}'s start <= @var{smaller}'s start
and @var{larger}'s end <= @var{smaller}'s end.
If @var{strict} is @code{t}, compare with < rather than <=.
If @var{strict} is @code{partial}, consider @var{larger} encloses
@var{smaller} when at least one side is strictly enclosing.
@end defun
@node Pattern Matching
@section Pattern Matching Tree-sitter Nodes
@cindex pattern matching with tree-sitter nodes

View file

@ -439,6 +439,41 @@ unlike in their original functions."
(treesit-node-prev-sibling node named)))))))
node)
(defun treesit-node-enclosed-p (smaller larger &optional strict)
"Return non-nil if SMALLER is enclosed in LARGER.
SMALLER and LARGER can be either (BEG . END) or a node.
Return non-nil if LARGER's start <= SMALLER's start and LARGER's
end <= SMALLER's end.
If STRICT is t, compare with < rather than <=.
If STRICT is \\='partial, consider LARGER encloses SMALLER when
at least one side is strictly enclosing."
(unless (and (or (consp larger) (treesit-node-p larger))
(or (consp smaller) (treesit-node-p smaller)))
(signal 'wrong-type-argument '((or cons treesit-node))))
(let ((larger-start (if (consp larger)
(car larger)
(treesit-node-start larger)))
(larger-end (if (consp larger)
(cdr larger)
(treesit-node-end larger)))
(smaller-start (if (consp smaller)
(car smaller)
(treesit-node-start smaller)))
(smaller-end (if (consp smaller)
(cdr smaller)
(treesit-node-end smaller))))
(pcase strict
('t (and (< larger-start smaller-start)
(< smaller-end larger-end)))
('partial (and (or (not (eq larger-start smaller-start))
(not (eq larger-end smaller-end)))
(<= larger-start smaller-start
smaller-end larger-end)))
(_ (<= larger-start smaller-start smaller-end larger-end)))))
;;; Query API supplement
(defun treesit-query-string (string query language)
@ -3523,7 +3558,6 @@ function signals an error."
(define-short-documentation-group treesit
"Parsers"
(treesit-parser-create
:no-eval (treesit-parser-create 'c)
@ -3669,7 +3703,9 @@ function signals an error."
(treesit-node-check
:no-eval (treesit-node-check node 'named)
:eg-result t)
(treesit-node-enclosed-p
:no-eval (treesit-node-enclosed-p node1 node2)
:no-eval (treesit-node-enclosed-p node1 '(12 . 18)))
(treesit-node-field-name-for-child
:no-eval (treesit-node-field-name-for-child node)

View file

@ -166,6 +166,13 @@
;; `treesit-node-eq'.
(should (treesit-node-eq root-node root-node))
(should (not (treesit-node-eq root-node doc-node)))
;; `treesit-node-enclosed-p'
(should (treesit-node-enclosed-p '(1 . 3) '(1 . 4)))
(should (treesit-node-enclosed-p '(1 . 3) '(1 . 3)))
(should (not (treesit-node-enclosed-p '(1 . 3) '(1 . 4) t)))
(should (treesit-node-enclosed-p '(1 . 3) '(1 . 4) 'partial))
(should (treesit-node-enclosed-p '(2 . 3) '(1 . 4) t))
(should (treesit-node-enclosed-p object-node root-node))
;; Further test for `treesit-node-check'.
(treesit-parser-delete parser)