emacs-diffs
[Top][All Lists]
Advanced

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

feature/tree-sitter 591759d508 2/7: Make treesit-node-child and fiends a


From: Yuan Fu
Subject: feature/tree-sitter 591759d508 2/7: Make treesit-node-child and fiends accept negative index
Date: Sun, 23 Oct 2022 22:07:03 -0400 (EDT)

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

    Make treesit-node-child and fiends accept negative index
    
    * doc/lispref/parsing.texi (Retrieving Node): Update manual.
    * src/treesit.c (Ftreesit_node_child)
    (Ftreesit_node_field_name_for_child): Accept and process negative
    index.
---
 doc/lispref/parsing.texi | 21 +++++++++++++++------
 src/treesit.c            | 45 ++++++++++++++++++++++++++++++++++++---------
 2 files changed, 51 insertions(+), 15 deletions(-)

diff --git a/doc/lispref/parsing.texi b/doc/lispref/parsing.texi
index e26090be1d..3a19b1b7ca 100644
--- a/doc/lispref/parsing.texi
+++ b/doc/lispref/parsing.texi
@@ -567,11 +567,16 @@ This function returns the immediate parent of @var{node}.
 @defun treesit-node-child node n &optional named
 This function returns the @var{n}'th child of @var{node}.  If
 @var{named} is non-@code{nil}, it counts only named nodes
-(@pxref{tree-sitter named node, named node}).  For example, in a node
-that represents a string @code{"text"}, there are three children
-nodes: the opening quote @code{"}, the string text @code{text}, and
-the closing quote @code{"}.  Among these nodes, the first child is the
-opening quote @code{"}, and the first named child is the string text.
+(@pxref{tree-sitter named node, named node}).
+
+For example, in a node that represents a string @code{"text"}, there
+are three children nodes: the opening quote @code{"}, the string text
+@code{text}, and the closing quote @code{"}.  Among these nodes, the
+first child is the opening quote @code{"}, and the first named child
+is the string text.
+
+This function returns @code{nil} if there is no @var{n}'th child.
+@var{n} could be negative, e.g., -1 represents the last child.
 @end defun
 
 @defun treesit-node-children node &optional named
@@ -880,7 +885,11 @@ of @var{node} as a child of its parent.
 
 @defun treesit-node-field-name-for-child node n
 This function returns the field name of the @var{n}'th child of
-@var{node}.
+@var{node}.  It returns @code{nil} if there is no @var{n}'th child, or
+the @var{n}'th child doesn't have a field name.
+
+Note that @var{n} counts both named and anonymous child.  And @var{n}
+could be negative, e.g., -1 represents the last child.
 @end defun
 
 @defun treesit-child-count node &optional named
diff --git a/src/treesit.c b/src/treesit.c
index b0e7d0e211..3ac0a0c7b2 100644
--- a/src/treesit.c
+++ b/src/treesit.c
@@ -1529,20 +1529,36 @@ DEFUN ("treesit-node-child",
        Ftreesit_node_child, Streesit_node_child, 2, 3, 0,
        doc: /* Return the Nth child of NODE.
 
-Return nil if there is no Nth child.  If NAMED is non-nil, look for named
-child only.  NAMED defaults to nil.  If NODE is nil, return nil.  */)
+Return nil if there is no Nth child.  If NAMED is non-nil, look for
+named child only.  NAMED defaults to nil.  If NODE is nil, return
+nil.
+
+N could be negative, e.g., -1 represents the last child.  */)
   (Lisp_Object node, Lisp_Object n, Lisp_Object named)
 {
   if (NILP (node)) return Qnil;
   treesit_check_node (node);
-  treesit_check_positive_integer (n);
+  CHECK_INTEGER (n);
   EMACS_INT idx = XFIXNUM (n);
-  if (idx > UINT32_MAX)
-    xsignal1 (Qargs_out_of_range, n);
+
   treesit_initialize ();
 
   TSNode treesit_node = XTS_NODE (node)->node;
   TSNode child;
+
+  /* Process negative index.  */
+  if (idx < 0)
+    {
+      if (NILP (named))
+       idx = ts_node_child_count (treesit_node) + idx;
+      else
+       idx = ts_node_named_child_count (treesit_node) + idx;
+    }
+  if (idx < 0)
+    return Qnil;
+  if (idx > UINT32_MAX)
+    xsignal1 (Qargs_out_of_range, n);
+
   if (NILP (named))
     child = ts_node_child (treesit_node, (uint32_t) idx);
   else
@@ -1606,19 +1622,30 @@ DEFUN ("treesit-node-field-name-for-child",
        doc: /* Return the field name of the Nth child of NODE.
 
 Return nil if there's no Nth child, or if it has no field.
-If NODE is nil, return nil.  */)
+If NODE is nil, return nil.
+
+N counts all children, i.e., named ones and anonymous ones.
+
+N could be negative, e.g., -1 represents the last child.  */)
   (Lisp_Object node, Lisp_Object n)
 {
   if (NILP (node))
     return Qnil;
   treesit_check_node (node);
-  treesit_check_positive_integer (n);
+  CHECK_INTEGER (n);
   EMACS_INT idx = XFIXNUM (n);
-  if (idx > UINT32_MAX)
-    xsignal1 (Qargs_out_of_range, n);
   treesit_initialize ();
 
   TSNode treesit_node = XTS_NODE (node)->node;
+
+  /* Process negative index.  */
+  if (idx < 0)
+    idx = ts_node_child_count (treesit_node) + idx;
+  if (idx < 0)
+    return Qnil;
+  if (idx > UINT32_MAX)
+    xsignal1 (Qargs_out_of_range, n);
+
   const char *name
     = ts_node_field_name_for_child (treesit_node, (uint32_t) idx);
 



reply via email to

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