]> git.eshelyaron.com Git - emacs.git/commitdiff
Add treesit-subtree-stat
authorYuan Fu <casouri@gmail.com>
Sun, 29 Jan 2023 08:06:09 +0000 (00:06 -0800)
committerYuan Fu <casouri@gmail.com>
Sun, 29 Jan 2023 08:12:57 +0000 (00:12 -0800)
* src/treesit.c (Ftreesit_subtree_stat): New function.
* lisp/treesit.el (treesit): Add to shortdoc.

lisp/treesit.el
src/treesit.c

index 363692eabdfb6245797b7ad2942528e9cf5e8d4d..b302970737611296b94d88af321d04d3c2615a1d 100644 (file)
@@ -2972,10 +2972,10 @@ function signals an error."
    :no-value (treesit-parser-set-included-ranges parser '((1 . 4) (5 . 8))))
   (treesit-parser-included-ranges
    :no-eval (treesit-parser-included-ranges parser)
-   :eg-result '((1 . 4) (5 . 8)))
+   :eg-result ((1 . 4) (5 . 8)))
   (treesit-query-range
    :no-eval (treesit-query-range node '((script_element) @cap))
-   :eg-result-string '((1 . 4) (5 . 8)))
+   :eg-result ((1 . 4) (5 . 8)))
 
 
   "Retrieving a node"
@@ -3121,7 +3121,12 @@ function signals an error."
    :eg-result-string "#<treesit-node (translation_unit) in 1-11>")
   (treesit-query-string
    :no-eval (treesit-query-string "int c = 0;" '((identifier) @id) 'c)
-   :eg-result-string "((id . #<treesit-node (identifier) in 5-6>))"))
+   :eg-result-string "((id . #<treesit-node (identifier) in 5-6>))")
+
+  "Misc"
+  (treesit-subtree-stat
+   :no-eval (treesit-subtree-stat node)
+   :eg-result (6 33 487)))
 
 (provide 'treesit)
 
index 917db5826762464e57d35216d913f3d87d4fd8da..b210ec0923ace4c029a204a860ab7e5fc7d59c6a 100644 (file)
@@ -3312,6 +3312,68 @@ a regexp.  */)
     return parent;
 }
 
+DEFUN ("treesit-subtree-stat",
+       Ftreesit_subtree_stat,
+       Streesit_subtree_stat, 1, 1, 0,
+       doc: /* Return information about the subtree of NODE.
+
+Return a list (MAX-DEPTH MAX-WIDTH COUNT), where MAX-DEPTH is the
+maximum depth of the subtree, MAX-WIDTH is the maximum number of
+direct children of nodes in the subtree, and COUNT is the number of
+nodes in the subtree, including NODE.  */)
+  (Lisp_Object node)
+{
+  /* Having a limit on the depth to traverse doesn't have much impact
+     on the time it takes, so I left that out.  */
+  CHECK_TS_NODE (node);
+
+  treesit_initialize ();
+
+  TSTreeCursor cursor = ts_tree_cursor_new (XTS_NODE (node)->node);
+  ptrdiff_t max_depth = 1;
+  ptrdiff_t max_width = 0;
+  ptrdiff_t count = 0;
+  ptrdiff_t current_depth = 0;
+
+  /* Traverse the subtree depth-first.  */
+  while (true)
+    {
+      count++;
+
+      /* Go down depth-first.  */
+      while (ts_tree_cursor_goto_first_child (&cursor))
+       {
+         current_depth++;
+         count++;
+         /* While we're at here, measure the number of siblings.  */
+         ptrdiff_t width_count = 1;
+         while (ts_tree_cursor_goto_next_sibling (&cursor))
+           width_count++;
+         max_width = max (max_width, width_count);
+         /* Go back to the first sibling.  */
+         treesit_assume_true (ts_tree_cursor_goto_parent (&cursor));
+         treesit_assume_true (ts_tree_cursor_goto_first_child (&cursor));
+       }
+      max_depth = max (max_depth, current_depth);
+
+      /* Go to next sibling.  If there is no next sibling, go to
+         parent's next sibling, and so on.  If there is no more
+         parent, we've traversed the whole subtree, stop.  */
+      while (!ts_tree_cursor_goto_next_sibling (&cursor))
+       {
+         if (ts_tree_cursor_goto_parent (&cursor))
+           current_depth--;
+         else
+           {
+             ts_tree_cursor_delete (&cursor);
+             return list3 (make_fixnum (max_depth),
+                           make_fixnum (max_width),
+                           make_fixnum (count));
+           }
+       }
+    }
+}
+
 #endif /* HAVE_TREE_SITTER */
 
 DEFUN ("treesit-available-p", Ftreesit_available_p,
@@ -3511,6 +3573,7 @@ then in the system default locations for dynamic libraries, in that order.  */);
   defsubr (&Streesit_search_subtree);
   defsubr (&Streesit_search_forward);
   defsubr (&Streesit_induce_sparse_tree);
+  defsubr (&Streesit_subtree_stat);
 #endif /* HAVE_TREE_SITTER */
   defsubr (&Streesit_available_p);
 }