emacs-diffs
[Top][All Lists]
Advanced

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

feature/tree-sitter 78df03329d 1/5: Redefine treesit-node-at


From: Yuan Fu
Subject: feature/tree-sitter 78df03329d 1/5: Redefine treesit-node-at
Date: Sat, 14 May 2022 01:12:00 -0400 (EDT)

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

    Redefine treesit-node-at
    
    The old 'treesit-node-at' becomes 'treesit-node-on'.  The new
    'treesit-node-at' has slightly different semantics.  Now
    'treesit-node-on' gets the smallest node covering a range and
    'treesit-node-at' gets the smallest node after a position.
    
    The reason of change can be found in the docstring of
    'treesit-node-on' (the BEWARE part): its result can be sometimes
    surprising/unexpected.
    
    * doc/lispref/parsing.texi (Retrieving Node): Update manual.
    * lisp/treesit.el (treesit-node-at): Change to new definition.
    (treesit-node-on): Inherits the old definition of
    'treesit-node-at'.  Parameter END is now mandatory.
    (treesit-language-at, treesit-node-field-name): Use the new '-on'
    function.
    (treesit-font-lock-fontify-region, treesit-simple-indent-presets,
    treesit-indent): Use the new '-at' function.
    * test/src/treesit-tests.el (treesit-node-supplemental): Update tests.
---
 doc/lispref/parsing.texi  | 33 +++++++++++++++++++++++++++------
 lisp/treesit.el           | 46 +++++++++++++++++++++++++++++++++++++---------
 test/src/treesit-tests.el |  6 +++++-
 3 files changed, 69 insertions(+), 16 deletions(-)

diff --git a/doc/lispref/parsing.texi b/doc/lispref/parsing.texi
index bbe70ff9b1..72be91877b 100644
--- a/doc/lispref/parsing.texi
+++ b/doc/lispref/parsing.texi
@@ -471,11 +471,10 @@ is retrieved.  Using an outdated node throws
 
 @heading Retrieving node from syntax tree
 
-@defun treesit-node-at beg &optional end parser-or-lang named
-This function returns the @emph{smallest} node that covers the span
-from @var{beg} to @var{end}.  In other words, the start of the node
-@code{<=} @var{beg}, and the end of the node @code{>=} @var{end}.  If
-@var{end} is omitted, it defaults to the value of @var{beg}.
+@defun treesit-node-at beg end &optional parser-or-lang named
+This function returns the @emph{smallest} node that starts at or after
+the @var{point}.  In other words, the start of the node is equal or
+greater than @var{point}.
 
 When @var{parser-or-lang} is nil, this function uses the first parser
 in @var{treesit-parser-list} in the current buffer.  If
@@ -489,12 +488,34 @@ instead (@pxref{tree-sitter named node, named node}).
 @example
 @group
 ;; Find the node at point in a C parser's syntax tree.
-(treesit-node-at (point) (point) 'c)
+(treesit-node-on (point) 'c)
     @c @result{} #<treesit-node from 1 to 4 in *scratch*>
 @end group
 @end example
 @end defun
 
+@defun treesit-node-on beg end &optional parser-or-lang named
+This function returns the @emph{smallest} node that covers the span
+from @var{beg} to @var{end}.  In other words, the start of the node is
+less or equal to @var{beg}, and the end of the node is greater or
+equal to @var{end}.
+
+@emph{Beware}, Calling this function on an empty line that is not
+inside any top-level construct (function definition, etc) most
+probably will give you the root node, because the root node is the
+smallest node that covers that empty line.  You probably want to use
+@code{treesit-node-at} instead.
+
+When @var{parser-or-lang} is nil, this function uses the first parser
+in @var{treesit-parser-list} in the current buffer.  If
+@var{parser-or-lang} is a parser object, it use that parser; if
+@var{parser-or-lang} is a language, it finds the first parser using
+that language in @var{treesit-parser-list} and use that.
+
+If @var{named} is non-nil, this function looks for a named node
+instead (@pxref{tree-sitter named node, named node}).
+@end defun
+
 @defun treesit-parser-root-node parser
 This function returns the root node of the syntax tree generated by
 @var{parser}.
diff --git a/lisp/treesit.el b/lisp/treesit.el
index eaaa1316af..dbbe0e409a 100644
--- a/lisp/treesit.el
+++ b/lisp/treesit.el
@@ -90,7 +90,7 @@ Return the root node of the syntax tree."
 (defun treesit-language-at (point)
   "Return the language used at POINT."
   (cl-loop for parser in treesit-parser-list
-           if (treesit-node-at point nil parser)
+           if (treesit-node-on point point parser)
            return (treesit-parser-language parser)))
 
 (defun treesit-set-ranges (parser-or-lang ranges)
@@ -128,11 +128,40 @@ Return the root node of the syntax tree."
   (treesit-parser-language
    (treesit-node-parser node)))
 
-(defun treesit-node-at (beg &optional end parser-or-lang named)
+(defun treesit-node-at (point &optional parser-or-lang named)
+  "Return the smallest node that starts at or after POINT.
+
+\"Starts at or after POINT\" means the start of the node is
+greater or larger than POINT.  Return nil if none find.  If NAMED
+non-nil, only look for named node.
+
+If PARSER-OR-LANG is nil, use the first parser in
+`treesit-parser-list'; if PARSER-OR-LANG is a parser, use
+that parser; if PARSER-OR-LANG is a language, find a parser using
+that language in the current buffer, and use that."
+  (let ((node (if (treesit-parser-p parser-or-lang)
+                  (treesit-parser-root-node parser-or-lang)
+                (treesit-buffer-root-node parser-or-lang))))
+    ;; TODO: We might want a `treesit-node-decendant-for-pos' in C.
+    (while (cond ((< (treesit-node-end node) point)
+                  (setq node (treesit-node-next-sibling node))
+                  t)
+                 ((treesit-node-child node 0 named)
+                  (setq node (treesit-node-child node 0 named))
+                  t)))
+    node))
+
+(defun treesit-node-on (beg end &optional parser-or-lang named)
   "Return the smallest node covering BEG to END.
 
-If omitted, END defaults to BEG.  Return nil if none find.  If
-NAMED non-nil, only look for named node.  NAMED defaults to nil.
+BEWARE!  Calling this function on an empty line that is not
+inside any top-level construct (function definition, etc) most
+probably will give you the root node, because the root node is
+the smallest node that covers that empty line.  You probably want
+to use `treesit-node-at' instead.
+
+Return nil if none find.  If NAMED non-nil, only look for named
+node.
 
 If PARSER-OR-LANG is nil, use the first parser in
 `treesit-parser-list'; if PARSER-OR-LANG is a parser, use
@@ -358,7 +387,7 @@ If LOUDLY is non-nil, message some debugging information."
     (when-let* ((language (nth 0 setting))
                 (match-pattern (nth 1 setting))
                 (parser (treesit-get-parser-create language)))
-      (when-let ((node (treesit-node-at start end parser)))
+      (when-let ((node (treesit-node-on start end parser)))
         (let ((captures (treesit-query-capture
                          node match-pattern
                          ;; Specifying the range is important. More
@@ -500,7 +529,7 @@ See `treesit-simple-indent-presets'.")
                      (forward-line -1)
                      (skip-chars-forward " \t")
                      (treesit-node-start
-                      (treesit-node-at (point) nil nil t))))))
+                      (treesit-node-at (point) nil t))))))
   "A list of presets.
 These presets that can be used as MATHER and ANCHOR in
 `treesit-simple-indent-rules'.
@@ -622,8 +651,7 @@ of the current line.")
                 (point)))
          (smallest-node
           (cl-loop for parser in treesit-parser-list
-                   for node = (treesit-node-at
-                               bol nil parser)
+                   for node = (treesit-node-at bol parser)
                    if node return node))
          (node (treesit-parent-while
                 smallest-node
@@ -639,7 +667,7 @@ of the current line.")
          (parent (cond ((and node parser)
                         (treesit-node-parent node))
                        (parser
-                        (treesit-node-at bol nil parser))
+                        (treesit-node-at bol parser))
                        (t nil)))
          (`(,anchor . ,offset)
           (funcall treesit-indent-function node parent bol)))
diff --git a/test/src/treesit-tests.el b/test/src/treesit-tests.el
index eb6e85c3fd..c995542a2a 100644
--- a/test/src/treesit-tests.el
+++ b/test/src/treesit-tests.el
@@ -331,7 +331,11 @@
                 'json))
     ;; `treesit-node-at'.
     (should (equal (treesit-node-string
-                    (treesit-node-at 1 2 'json))
+                    (treesit-node-at 1 'json))
+                   "(\"[\")"))
+    ;; `treesit-node-on'
+    (should (equal (treesit-node-string
+                    (treesit-node-on 1 2 'json))
                    "(\"[\")"))
     ;; `treesit-buffer-root-node'.
     (should (treesit-node-eq



reply via email to

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