From: Yuan Fu Date: Fri, 24 Mar 2023 20:13:05 +0000 (-0700) Subject: Add treesit-node-get X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=73a320801e9af61a48fd0e803afcd02b059b2338;p=emacs.git Add treesit-node-get * doc/lispref/parsing.texi (Retrieving Nodes): Add manual entry. * lisp/treesit.el (treesit-node--get): New function. --- diff --git a/doc/lispref/parsing.texi b/doc/lispref/parsing.texi index 86a5d9f2e52..38c9ec8c2f0 100644 --- a/doc/lispref/parsing.texi +++ b/doc/lispref/parsing.texi @@ -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}. diff --git a/lisp/treesit.el b/lisp/treesit.el index e3c7d569ea6..4c4ba4ad6ac 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -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)