Skip to content

Commit f0a93d9

Browse files
committed
core: Add optional args props and output to tsc-current-node
1 parent d01853e commit f0a93d9

File tree

4 files changed

+44
-16
lines changed

4 files changed

+44
-16
lines changed

core/src/cursor.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -153,12 +153,6 @@ fn make_cursor(tree_or_node: TreeOrNode) -> Result<RCursor> {
153153
Ok(tree_or_node.walk())
154154
}
155155

156-
/// Return CURSOR's current node.
157-
#[defun]
158-
fn current_node(cursor: &RCursor) -> Result<RNode> {
159-
Ok(RNode::new(cursor.clone_tree(), |_| cursor.borrow().node()))
160-
}
161-
162156
/// Return the field id of CURSOR's current node.
163157
/// Return nil if the current node doesn't have a field.
164158
#[defun]
@@ -414,6 +408,7 @@ fn get<'e>(prop: Value<'e>, node: Node, cursor: &RCursor) -> Result<Value<'e>> {
414408
} else if eq!(_range) {
415409
node.lisp_range().into_lisp(env)
416410
} else {
411+
// FIX: Signal an error instead.
417412
().into_lisp(env)
418413
}
419414
}

core/tsc.el

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,25 @@ This function must be called in NODE's source buffer."
176176
Return the index of the child node if one was found, nil otherwise."
177177
(tsc-goto-first-child-for-byte cursor (position-bytes position)))
178178

179+
(defun tsc-current-node (cursor &optional props output)
180+
"Return CURSOR's current node.
181+
182+
If the optional arg PROPS is a vector of property names, this function returns a
183+
vector containing the node's corresponding properties. If the optional arg
184+
OUTPUT is also non-nil, it must be a vector of the same length, where the
185+
properties will be written into.
186+
187+
PROPS can also be a single property name, in which case this function returns
188+
only that property, and OUTPUT is ignored.
189+
190+
See `tsc-valid-node-props' for the list of available properties."
191+
(tsc--check-node-props props)
192+
;; TODO: Fix this.
193+
(when (or (eq props :depth)
194+
(and (seqp props) (cl-find :depth props)))
195+
(error "Cursor doesn't currently support :depth property"))
196+
(tsc--current-node cursor props output))
197+
179198
(defun tsc-lang-field-id (language field)
180199
"Return the numeric id of FIELD in LANGUAGE. FIELD should be a keyword."
181200
(unless (keywordp field)
@@ -292,7 +311,7 @@ e.g. automatically through escape analysis. How about porting ELisp to GraalVM?"
292311
props)))
293312
(error "Invalid node properties %s" invalid-props)))
294313
((null props) nil)
295-
(t (error "Expected vectors or keyword %s" props))))
314+
(t (error "Expected vectors, keyword, or nil %s" props))))
296315

297316
(defun tsc-traverse-mapc (func tree-or-node &optional props)
298317
"Call FUNC for each node of TREE-OR-NODE.

doc/emacs-tree-sitter.org

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -562,7 +562,11 @@ For more details, see Tree-sitter's documentation:
562562
:EXPORT_FILE_NAME: inspecting
563563
:END:
564564

565-
The result of parsing is a syntax tree of the entire source code (string, buffer). It contains syntax nodes that indicate the structure of the source code. Tree-sitter provides APIs to inspect and [[*Walking][traverse]] this structure, but does not support modifying it directly (for the purposes of source code transformation or generation).
565+
{{% notice info %}}
566+
If your code works with a large number of nodes, consider using the [[*Walking][traversal APIs]], which are more efficient.
567+
{{% /notice %}}
568+
569+
The result of parsing is a syntax tree of the entire source code (string, buffer). It contains syntax nodes that indicate the structure of the source code. Tree-sitter provides APIs to inspect and traverse this structure, but does not support modifying it directly (for the purposes of source code transformation or generation).
566570

567571
- ~tsc-root-node~ /~tree~/ :: Get the root node of a syntax tree.
568572
- ~tsc-changed-ranges~ /~old-tree new-tree~/ :: Compare an edited old syntax tree to a newly parsed one. It is typically used in ~tree-sitter-after-change-functions~ hook. This function returns a sequence of ranges whose syntactic structure has changed. Each range is a vector in the form of /~[start-bytepos end-bytepos start-point end-point]~/.
@@ -631,10 +635,7 @@ As described in the previous section, the ~-named-~ variants of the functions i
631635
:END:
632636
Tree-walking functions enable efficient traversal of the syntax tree.
633637

634-
*** Traversing All Descendant Nodes
635-
These functions are high-level APIs that allow traversing the syntax tree in depth-first pre-order.
636-
637-
When dealing with a large number of nodes, working with node objects creates a huge pressure on the garbage collector. For better performance, it's advisable to extract and work with individual node properties. The constant ~tsc-valid-node-props~ holds the list of all available property names.
638+
When dealing with a large number of nodes, working with node objects creates a huge pressure on the garbage collector. For better performance, it's advisable to extract and work with individual node properties. The constant ~tsc-valid-node-props~ holds the list of all available property names:
638639
# TODO: Make :exports results work with ox-hugo.
639640
#+begin_src emacs-lisp
640641
'(:type
@@ -645,6 +646,12 @@ When dealing with a large number of nodes, working with node objects creates a h
645646
:start-point :end-point
646647
:range :byte-range)
647648
#+end_src
649+
{{% notice note %}}
650+
Functions that accept a vector of property names can also accept a single property name, in which case only that property is returned/yielded, instead of a vector of properties.
651+
{{% /notice %}}
652+
653+
*** Traversing All Descendant Nodes
654+
These functions are high-level APIs that allow traversing the syntax tree in depth-first pre-order.
648655

649656
- ~tsc-traverse-do~ /~(vars tree-or-node) body~/ :: Evaluate ~body~ with ~vars~ bound to corresponding properties of each traversed node.
650657
#+begin_src emacs-lisp
@@ -683,8 +690,12 @@ These functions are the low-level APIs that allow walking through the syntax tre
683690
- ~tsc-goto-next-sibling~ /~cursor~/ :: Attempt to move the cursor to the parent node, the first child node, or the next sibling node. This function returns t if the move was successful, nil if the move is invalid.
684691
- ~tsc-goto-first-child-for-position~ /~cursor pos~/ :: Attempt to move the cursor to the first child node that extends beyond the given position. This function returns the index of the child node found, nil otherwise.
685692
- ~tsc-reset-cursor~ /~cursor node~/ :: Re-initialize the cursor to start on a different node.
686-
- ~tsc-current-node~ /~cursor~/ :: Get the node that the cursor is currently on.
687-
- ~tsc-current-field~ /~cursor~/ :: Get the field name (as a keyword) associated with the current node.
693+
- ~tsc-current-node~ /~cursor [props] [output]~/ :: Get the node that the cursor is currently on. If ~props~ is a vector of property names, return a vector containing the node's corresponding properties. If ~output~ is also non-nil, it must be a vector of the same length, where the properties will be written into.
694+
- ~tsc-current-field~ /~cursor~/ :: Get the field name (as a keyword) associated with the current node. This is equivalent to:
695+
#+begin_src emacs-lisp
696+
(tsc-current-node cursor :field)
697+
#+end_src
698+
688699

689700
** Querying
690701
:PROPERTIES:

tests/tree-sitter-tests.el

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,11 @@ tree is held (since nodes internally reference the tree)."
212212
(should-not (equal (tsc-node-type (tsc-current-node cursor)) 'source_file))
213213
(tsc-reset-cursor cursor node)
214214
(should (equal (tsc-node-type (tsc-current-node cursor)) 'source_file))
215-
(should (equal (tsc--current-node cursor [:type] nil) [source_file]))
216-
(message "->> %s" (tsc--current-node cursor [:start-byte :end-byte :type :field nil] nil)))))
215+
(should (equal (tsc-current-node cursor :type) 'source_file))
216+
(should (equal (tsc-current-node cursor [:start-byte :end-byte :type])
217+
`[,(point-min) ,(point-max) source_file]))
218+
(should-error (tsc-current-node cursor :depth))
219+
(should-error (tsc-current-node cursor [:depth])))))
217220

218221
(ert-deftest cursor::using-without-tree ()
219222
(tsc-test-with rust parser

0 commit comments

Comments
 (0)