]> git.eshelyaron.com Git - emacs.git/commitdiff
Add treesit-node-enclosed-p
authorYuan Fu <casouri@gmail.com>
Fri, 10 Nov 2023 04:49:30 +0000 (20:49 -0800)
committerYuan Fu <casouri@gmail.com>
Fri, 10 Nov 2023 04:49:30 +0000 (20:49 -0800)
* 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.

doc/lispref/parsing.texi
lisp/treesit.el
test/src/treesit-tests.el

index bac5a864bf89830d08a1b516019b14af510e1d9b..df81a805e67e0b8c6cc693279be07d5924662f83 100644 (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
index e1fcf1a8b04544df8e4e19f8299facb524c2a23b..826e719172d756bfdd8d2e06e016451bc3b9a4ce 100644 (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)
index 4308e4048f698e7bd0ca95349475e44c55112ea0..791e902bd0a9ca11aff852cfaf4610557c3685f3 100644 (file)
       ;; `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)