Function: treesit-induce-sparse-tree

treesit-induce-sparse-tree is a function defined in treesit.c.

Signature

(treesit-induce-sparse-tree ROOT PREDICATE &optional PROCESS-FN DEPTH)

Documentation

Create a sparse tree of ROOT's subtree.

This takes the subtree under ROOT, and combs it so only the nodes that match PREDICATE are left, like picking out grapes on the vine. PREDICATE is a regexp string that matches against each node's type.

For a subtree on the left that consist of both numbers and letters, if PREDICATE is "is letter", the returned tree is the one on the right.

a a a
| | |
    +---+---+ +---+---+ +---+---+
    | | | | | | | | |
    b 1 2 b | | b c d
| | => | | => |
c +--+ c + e
| | | | |
     +--+ d 4 +--+ d
     | | |
     e 5 e

If PROCESS-FN is non-nil, it should be a function of one argument. In that case, instead of returning the matched nodes, pass each node to PROCESS-FN, and use its return value instead.

If non-nil, DEPTH is the number of levels to go down the tree from ROOT. If DEPTH is nil or omitted, it defaults to 1000.

Each node in the returned tree looks like (NODE . (CHILD ...)). The root of this tree might be nil, if ROOT doesn't match PREDICATE.

If no node matches PREDICATE, return nil.

PREDICATE can also be a function that takes a node and returns nil/non-nil, but it is slower and more memory consuming than using a regexp.

Other relevant functions are documented in the treesit group.

View in manual

Shortdoc

;; treesit
(treesit-induce-sparse-tree node "function_definition")
    e.g. => (nil (#<treesit-node (function_definition) in 57-146>) (#<treesit-node (function_definition) in 259-296>) (#<treesit-node (function_definition) in 303-659>))

Source Code

// Defined in /usr/src/emacs/src/treesit.c
{
  CHECK_TS_NODE (root);
  CHECK_TYPE (STRINGP (predicate) || FUNCTIONP (predicate),
	      list3 (Qor, Qstringp, Qfunctionp), predicate);

  if (!NILP (process_fn))
    CHECK_TYPE (FUNCTIONP (process_fn), Qfunctionp, process_fn);

  /* We use a default limit of 1000.  See bug#59426 for the
     discussion.  */
  ptrdiff_t the_limit = treesit_recursion_limit;
  if (!NILP (depth))
    {
      CHECK_FIXNUM (depth);
      the_limit = XFIXNUM (depth);
    }

  treesit_initialize ();

  Lisp_Object parser = XTS_NODE (root)->parser;
  Lisp_Object parent = Fcons (Qnil, Qnil);
  /* In this function we never traverse above NODE, so we don't need
     to use treesit_cursor_helper.  */
  TSTreeCursor cursor = ts_tree_cursor_new (XTS_NODE (root)->node);

  specpdl_ref count = SPECPDL_INDEX ();
  record_unwind_protect_ptr (treesit_traverse_cleanup_cursor, &cursor);

  treesit_build_sparse_tree (&cursor, parent, predicate, process_fn,
			     the_limit, parser);

  unbind_to (count, Qnil);

  Fsetcdr (parent, Fnreverse (Fcdr (parent)));
  if (NILP (Fcdr (parent)))
    return Qnil;
  else
    return parent;
}