emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 0db75b80e1c 2/5: Add treesit-node-enclosed-p


From: Yuan Fu
Subject: master 0db75b80e1c 2/5: Add treesit-node-enclosed-p
Date: Fri, 10 Nov 2023 00:43:04 -0500 (EST)

branch: master
commit 0db75b80e1ce54f3597f7d19468157fd5ec2bd71
Author: Yuan Fu <casouri@gmail.com>
Commit: Yuan Fu <casouri@gmail.com>

    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.
---
 doc/lispref/parsing.texi  | 18 +++++++++++++++++-
 lisp/treesit.el           | 40 ++++++++++++++++++++++++++++++++++++++--
 test/src/treesit-tests.el |  7 +++++++
 3 files changed, 62 insertions(+), 3 deletions(-)

diff --git a/doc/lispref/parsing.texi b/doc/lispref/parsing.texi
index bac5a864bf8..df81a805e67 100644
--- a/doc/lispref/parsing.texi
+++ b/doc/lispref/parsing.texi
@@ -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
diff --git a/lisp/treesit.el b/lisp/treesit.el
index e1fcf1a8b04..826e719172d 100644
--- a/lisp/treesit.el
+++ b/lisp/treesit.el
@@ -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)
diff --git a/test/src/treesit-tests.el b/test/src/treesit-tests.el
index 4308e4048f6..791e902bd0a 100644
--- a/test/src/treesit-tests.el
+++ b/test/src/treesit-tests.el
@@ -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)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]