Redefine treesit-node-at
The old 'treesit-node-at' becomes 'treesit-node-on'. The new 'treesit-node-at' has slightly different semantics. Now 'treesit-node-on' gets the smallest node covering a range and 'treesit-node-at' gets the smallest node after a position. The reason of change can be found in the docstring of 'treesit-node-on' (the BEWARE part): its result can be sometimes surprising/unexpected. * doc/lispref/parsing.texi (Retrieving Node): Update manual. * lisp/treesit.el (treesit-node-at): Change to new definition. (treesit-node-on): Inherits the old definition of 'treesit-node-at'. Parameter END is now mandatory. (treesit-language-at, treesit-node-field-name): Use the new '-on' function. (treesit-font-lock-fontify-region, treesit-simple-indent-presets, treesit-indent): Use the new '-at' function. * test/src/treesit-tests.el (treesit-node-supplemental): Update tests.
This commit is contained in:
parent
eebe5a1d61
commit
78df03329d
3 changed files with 69 additions and 16 deletions
|
@ -471,11 +471,10 @@ is retrieved. Using an outdated node throws
|
|||
|
||||
@heading Retrieving node from syntax tree
|
||||
|
||||
@defun treesit-node-at beg &optional end parser-or-lang named
|
||||
This function returns the @emph{smallest} node that covers the span
|
||||
from @var{beg} to @var{end}. In other words, the start of the node
|
||||
@code{<=} @var{beg}, and the end of the node @code{>=} @var{end}. If
|
||||
@var{end} is omitted, it defaults to the value of @var{beg}.
|
||||
@defun treesit-node-at beg end &optional parser-or-lang named
|
||||
This function returns the @emph{smallest} node that starts at or after
|
||||
the @var{point}. In other words, the start of the node is equal or
|
||||
greater than @var{point}.
|
||||
|
||||
When @var{parser-or-lang} is nil, this function uses the first parser
|
||||
in @var{treesit-parser-list} in the current buffer. If
|
||||
|
@ -489,12 +488,34 @@ instead (@pxref{tree-sitter named node, named node}).
|
|||
@example
|
||||
@group
|
||||
;; Find the node at point in a C parser's syntax tree.
|
||||
(treesit-node-at (point) (point) 'c)
|
||||
(treesit-node-on (point) 'c)
|
||||
@c @result{} #<treesit-node from 1 to 4 in *scratch*>
|
||||
@end group
|
||||
@end example
|
||||
@end defun
|
||||
|
||||
@defun treesit-node-on beg end &optional parser-or-lang named
|
||||
This function returns the @emph{smallest} node that covers the span
|
||||
from @var{beg} to @var{end}. In other words, the start of the node is
|
||||
less or equal to @var{beg}, and the end of the node is greater or
|
||||
equal to @var{end}.
|
||||
|
||||
@emph{Beware}, Calling this function on an empty line that is not
|
||||
inside any top-level construct (function definition, etc) most
|
||||
probably will give you the root node, because the root node is the
|
||||
smallest node that covers that empty line. You probably want to use
|
||||
@code{treesit-node-at} instead.
|
||||
|
||||
When @var{parser-or-lang} is nil, this function uses the first parser
|
||||
in @var{treesit-parser-list} in the current buffer. If
|
||||
@var{parser-or-lang} is a parser object, it use that parser; if
|
||||
@var{parser-or-lang} is a language, it finds the first parser using
|
||||
that language in @var{treesit-parser-list} and use that.
|
||||
|
||||
If @var{named} is non-nil, this function looks for a named node
|
||||
instead (@pxref{tree-sitter named node, named node}).
|
||||
@end defun
|
||||
|
||||
@defun treesit-parser-root-node parser
|
||||
This function returns the root node of the syntax tree generated by
|
||||
@var{parser}.
|
||||
|
|
|
@ -90,7 +90,7 @@ Return the root node of the syntax tree."
|
|||
(defun treesit-language-at (point)
|
||||
"Return the language used at POINT."
|
||||
(cl-loop for parser in treesit-parser-list
|
||||
if (treesit-node-at point nil parser)
|
||||
if (treesit-node-on point point parser)
|
||||
return (treesit-parser-language parser)))
|
||||
|
||||
(defun treesit-set-ranges (parser-or-lang ranges)
|
||||
|
@ -128,11 +128,40 @@ Return the root node of the syntax tree."
|
|||
(treesit-parser-language
|
||||
(treesit-node-parser node)))
|
||||
|
||||
(defun treesit-node-at (beg &optional end parser-or-lang named)
|
||||
(defun treesit-node-at (point &optional parser-or-lang named)
|
||||
"Return the smallest node that starts at or after POINT.
|
||||
|
||||
\"Starts at or after POINT\" means the start of the node is
|
||||
greater or larger than POINT. Return nil if none find. If NAMED
|
||||
non-nil, only look for named node.
|
||||
|
||||
If PARSER-OR-LANG is nil, use the first parser in
|
||||
`treesit-parser-list'; if PARSER-OR-LANG is a parser, use
|
||||
that parser; if PARSER-OR-LANG is a language, find a parser using
|
||||
that language in the current buffer, and use that."
|
||||
(let ((node (if (treesit-parser-p parser-or-lang)
|
||||
(treesit-parser-root-node parser-or-lang)
|
||||
(treesit-buffer-root-node parser-or-lang))))
|
||||
;; TODO: We might want a `treesit-node-decendant-for-pos' in C.
|
||||
(while (cond ((< (treesit-node-end node) point)
|
||||
(setq node (treesit-node-next-sibling node))
|
||||
t)
|
||||
((treesit-node-child node 0 named)
|
||||
(setq node (treesit-node-child node 0 named))
|
||||
t)))
|
||||
node))
|
||||
|
||||
(defun treesit-node-on (beg end &optional parser-or-lang named)
|
||||
"Return the smallest node covering BEG to END.
|
||||
|
||||
If omitted, END defaults to BEG. Return nil if none find. If
|
||||
NAMED non-nil, only look for named node. NAMED defaults to nil.
|
||||
BEWARE! Calling this function on an empty line that is not
|
||||
inside any top-level construct (function definition, etc) most
|
||||
probably will give you the root node, because the root node is
|
||||
the smallest node that covers that empty line. You probably want
|
||||
to use `treesit-node-at' instead.
|
||||
|
||||
Return nil if none find. If NAMED non-nil, only look for named
|
||||
node.
|
||||
|
||||
If PARSER-OR-LANG is nil, use the first parser in
|
||||
`treesit-parser-list'; if PARSER-OR-LANG is a parser, use
|
||||
|
@ -358,7 +387,7 @@ If LOUDLY is non-nil, message some debugging information."
|
|||
(when-let* ((language (nth 0 setting))
|
||||
(match-pattern (nth 1 setting))
|
||||
(parser (treesit-get-parser-create language)))
|
||||
(when-let ((node (treesit-node-at start end parser)))
|
||||
(when-let ((node (treesit-node-on start end parser)))
|
||||
(let ((captures (treesit-query-capture
|
||||
node match-pattern
|
||||
;; Specifying the range is important. More
|
||||
|
@ -500,7 +529,7 @@ See `treesit-simple-indent-presets'.")
|
|||
(forward-line -1)
|
||||
(skip-chars-forward " \t")
|
||||
(treesit-node-start
|
||||
(treesit-node-at (point) nil nil t))))))
|
||||
(treesit-node-at (point) nil t))))))
|
||||
"A list of presets.
|
||||
These presets that can be used as MATHER and ANCHOR in
|
||||
`treesit-simple-indent-rules'.
|
||||
|
@ -622,8 +651,7 @@ of the current line.")
|
|||
(point)))
|
||||
(smallest-node
|
||||
(cl-loop for parser in treesit-parser-list
|
||||
for node = (treesit-node-at
|
||||
bol nil parser)
|
||||
for node = (treesit-node-at bol parser)
|
||||
if node return node))
|
||||
(node (treesit-parent-while
|
||||
smallest-node
|
||||
|
@ -639,7 +667,7 @@ of the current line.")
|
|||
(parent (cond ((and node parser)
|
||||
(treesit-node-parent node))
|
||||
(parser
|
||||
(treesit-node-at bol nil parser))
|
||||
(treesit-node-at bol parser))
|
||||
(t nil)))
|
||||
(`(,anchor . ,offset)
|
||||
(funcall treesit-indent-function node parent bol)))
|
||||
|
|
|
@ -331,7 +331,11 @@
|
|||
'json))
|
||||
;; `treesit-node-at'.
|
||||
(should (equal (treesit-node-string
|
||||
(treesit-node-at 1 2 'json))
|
||||
(treesit-node-at 1 'json))
|
||||
"(\"[\")"))
|
||||
;; `treesit-node-on'
|
||||
(should (equal (treesit-node-string
|
||||
(treesit-node-on 1 2 'json))
|
||||
"(\"[\")"))
|
||||
;; `treesit-buffer-root-node'.
|
||||
(should (treesit-node-eq
|
||||
|
|
Loading…
Add table
Reference in a new issue