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.
This commit is contained in:
Yuan Fu 2022-10-23 18:05:10 -07:00
parent e45d8dbeea
commit 591759d508
No known key found for this signature in database
GPG key ID: 56E19BC57664A442
2 changed files with 51 additions and 15 deletions

View file

@ -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

View file

@ -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);