emacs-diffs
[Top][All Lists]
Advanced

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

feature/tree-sitter 524d10c86b 3/7: Make treesit-node-at return the last


From: Yuan Fu
Subject: feature/tree-sitter 524d10c86b 3/7: Make treesit-node-at return the last leaf node at EOB
Date: Sun, 23 Oct 2022 22:07:03 -0400 (EDT)

branch: feature/tree-sitter
commit 524d10c86b539ef6fe27f31ed3df2590d1849a83
Author: Yuan Fu <casouri@gmail.com>
Commit: Yuan Fu <casouri@gmail.com>

    Make treesit-node-at return the last leaf node at EOB
    
    * doc/lispref/parsing.texi (Retrieving Node): Update manual.
    * lisp/treesit.el (treesit-node-at): Add a (when node) form just to be
    explicit, return the last leaf node if there is no node after POS.
---
 doc/lispref/parsing.texi |  6 ++++++
 lisp/treesit.el          | 48 +++++++++++++++++++++++++++++++++---------------
 2 files changed, 39 insertions(+), 15 deletions(-)

diff --git a/doc/lispref/parsing.texi b/doc/lispref/parsing.texi
index 3a19b1b7ca..8919a3ea70 100644
--- a/doc/lispref/parsing.texi
+++ b/doc/lispref/parsing.texi
@@ -504,6 +504,12 @@ that.
 If @var{named} is non-@code{nil}, this function looks for a named node
 only (@pxref{tree-sitter named node, named node}).
 
+When @var{pos} is after all the text in the buffer, technically there
+is no node after @var{pos}.  But for convenience, this function will
+return the last leaf node in the parse tree.  If @var{strict} is
+non-nil, this function will strictly comply to the semantics and
+return @var{nil}.
+
 Example:
 
 @example
diff --git a/lisp/treesit.el b/lisp/treesit.el
index 17c9d3e8b9..f8ab96ddb2 100644
--- a/lisp/treesit.el
+++ b/lisp/treesit.el
@@ -101,7 +101,7 @@ Return the root node of the syntax tree."
   (treesit-parser-language
    (treesit-node-parser node)))
 
-(defun treesit-node-at (pos &optional parser-or-lang named largest)
+(defun treesit-node-at (pos &optional parser-or-lang named largest strict)
   "Return the smallest node that starts at or after buffer position POS.
 
 \"Starts at or after POS\" means the start of the node is greater or
@@ -115,20 +115,38 @@ that parser; if PARSER-OR-LANG is a language, find a 
parser using
 that language in the current buffer, and use that.
 
 If LARGEST is non-nil, return the largest node instead of the
-smallest."
-  (let ((node (if (treesit-parser-p parser-or-lang)
-                  (treesit-parser-root-node parser-or-lang)
-                (treesit-buffer-root-node parser-or-lang)))
-        next)
-    ;; This is very fast so no need for C implementation.
-    (while (setq next (treesit-node-first-child-for-pos
-                       node pos named))
-      (setq node next))
-    (if (not largest)
-        node
-      (treesit-parent-while
-       node (lambda (n) (eq (treesit-node-start n)
-                            (treesit-node-start node)))))))
+smallest.
+
+If POS is after all the text in the buffer, i.e., there is no
+node after POS, return the last leaf node in the parse tree, even
+though that node is before POS.  If STRICT is non-nil, return nil
+in this case."
+  (let* ((root (if (treesit-parser-p parser-or-lang)
+                   (treesit-parser-root-node parser-or-lang)
+                 (treesit-buffer-root-node parser-or-lang)))
+         (node root)
+         next)
+    (when node
+      ;; This is very fast so no need for C implementation.
+      (while (setq next (treesit-node-first-child-for-pos
+                         node pos named))
+        (setq node next))
+      ;; If we are at the end of buffer or after all the text, we will
+      ;; end up with NODE = root node.  For convenience, return the last
+      ;; leaf node in the tree.
+      (if (treesit-node-eq node root)
+          (if strict
+              nil
+            (while (setq next (treesit-node-child node -1 named))
+              (setq node next))
+            node)
+        ;; If LARGEST non-nil, find the largest node that has the same
+        ;; starting point as NODE.
+        (if (not largest)
+            node
+          (treesit-parent-while
+           node (lambda (n) (eq (treesit-node-start n)
+                                (treesit-node-start node)))))))))
 
 (defun treesit-node-on (beg end &optional parser-or-lang named)
   "Return the smallest node covering BEG to END.



reply via email to

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