]> git.eshelyaron.com Git - emacs.git/commitdiff
Add treesit-node-get
authorYuan Fu <casouri@gmail.com>
Fri, 24 Mar 2023 20:13:05 +0000 (13:13 -0700)
committerYuan Fu <casouri@gmail.com>
Fri, 31 Mar 2023 04:55:22 +0000 (21:55 -0700)
* doc/lispref/parsing.texi (Retrieving Nodes): Add manual entry.
* lisp/treesit.el (treesit-node--get): New function.

doc/lispref/parsing.texi
lisp/treesit.el

index 86a5d9f2e52ab4c6e7b5b80ee64fd52c9d91ee2f..38c9ec8c2f07b86ccb9fd9ff876113f74efc3dd8 100644 (file)
@@ -849,6 +849,53 @@ Each node in the returned tree looks like
 
 @heading More convenience functions
 
+@defun treesit-node-get node instructions
+This is a convenience function that chains together multiple node
+accessor functions together.  For example, to get @var{node}'s
+parent's next sibling's second child's text:
+
+@example
+@group
+(treesit-node-get node
+   '((parent 1)
+    (sibling 1 nil)
+    (child 1 nil)
+    (text nil)))
+@end group
+@end example
+
+@var{instruction} is a list of INSTRUCTIONs of the form
+@w{@code{(@var{fn} @var{arg}...)}}.  The following @var{fn}'s are
+supported:
+
+@table @code
+@item (child @var{idx} @var{named})
+Get the @var{idx}'th child.
+
+@item (parent @var{n})
+Go to parent @var{n} times.
+
+@item (field-name)
+Get the field name of the current node.
+
+@item (type)
+Get the type of the current node.
+
+@item (text @var{no-property})
+Get the text of the current node.
+
+@item (children @var{named})
+Get a list of children.
+
+@item (sibling @var{step} @var{named})
+Get the nth prev/next sibling, negative @var{step} means prev sibling,
+positive means next sibling.
+@end table
+
+Note that arguments like @var{named} and @var{no-property} can't be
+omitted, unlike in their original functions.
+@end defun
+
 @defun treesit-filter-child node predicate &optional named
 This function finds immediate children of @var{node} that satisfy
 @var{predicate}.
index e3c7d569ea6c72e54b16f74341732cf9bb190dc1..4c4ba4ad6ac864be02d4174101d611c04fa7a7cf 100644 (file)
@@ -363,6 +363,50 @@ If NAMED is non-nil, count named child only."
              (idx (treesit-node-index node)))
     (treesit-node-field-name-for-child parent idx)))
 
+(defun treesit-node-get (node instructions)
+  "Get things from NODE by INSTRUCTIONS.
+
+This is a convenience function that chains together multiple node
+accessor functions together.  For example, to get NODE's parent's
+next sibling's second child's text, call
+
+   (treesit-node-get node
+     \\='((parent 1)
+       (sibling 1 nil)
+       (child 1 nil)
+       (text nil)))
+
+INSTRUCTION is a list of INSTRUCTIONs of the form (FN ARG...).
+The following FN's are supported:
+
+\(child IDX NAMED)    Get the IDX'th child
+\(parent N)           Go to parent N times
+\(field-name)         Get the field name of the current node
+\(type)               Get the type of the current node
+\(text NO-PROPERTY)   Get the text of the current node
+\(children NAMED)     Get a list of children
+\(sibling STEP NAMED) Get the nth prev/next sibling, negative STEP
+                     means prev sibling, positive means next
+
+Note that arguments like NAMED and NO-PROPERTY can't be omitted,
+unlike in their original functions."
+  (declare (indent 1))
+  (while (and node instructions)
+    (pcase (pop instructions)
+      ('(field-name) (setq node (treesit-node-field-name node)))
+      ('(type) (setq node (treesit-node-type node)))
+      (`(child ,idx ,named) (setq node (treesit-node-child node idx named)))
+      (`(parent ,n) (dotimes (_ n)
+                      (setq node (treesit-node-parent node))))
+      (`(text ,no-property) (setq node (treesit-node-text node no-property)))
+      (`(children ,named) (setq node (treesit-node-children node named)))
+      (`(sibling ,step ,named)
+       (dotimes (_ (abs step))
+         (setq node (if (> step 0)
+                        (treesit-node-next-sibling node named)
+                      (treesit-node-prev-sibling node named)))))))
+  node)
+
 ;;; Query API supplement
 
 (defun treesit-query-string (string query language)