mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-16 17:24:23 +00:00
Make use of the new pred shapes in treesit.el
treesit-search-forward and friends now accept more shapes for PRED, make use of it in navigation functions. * lisp/treesit.el (treesit-node-top-level): Use treesit-node-match-p. (treesit--thing-unpack-pattern): Remove function. (treesit-beginning-of-thing) (treesit-end-of-thing): Remove PRED argument. (treesit--things-around): Remove PRED argument, use treesit-node-match-p. (treesit--top-level-thing): Remove function. (treesit--navigate-thing): Remove PRED argument. (treesit-thing-at-point): Update docstring, don't unpack PATTERN. * test/src/treesit-tests.el: (treesit--ert-test-defun-navigation): Don't unpack pattern.
This commit is contained in:
parent
a4de6d8dd3
commit
293029458c
2 changed files with 28 additions and 62 deletions
|
|
@ -88,6 +88,7 @@
|
|||
(declare-function treesit-search-forward "treesit.c")
|
||||
(declare-function treesit-induce-sparse-tree "treesit.c")
|
||||
(declare-function treesit-subtree-stat "treesit.c")
|
||||
(declare-function treesit-node-match-p "treesit.c")
|
||||
|
||||
(declare-function treesit-available-p "treesit.c")
|
||||
|
||||
|
|
@ -245,21 +246,19 @@ is nil, try to guess the language at BEG using `treesit-language-at'."
|
|||
Specifically, return the highest parent of NODE that has the same
|
||||
type as it. If no such parent exists, return nil.
|
||||
|
||||
If PRED is non-nil, match each parent's type with PRED as a
|
||||
regexp, rather than using NODE's type. PRED can also be a
|
||||
function that takes the node as an argument, and return
|
||||
non-nil/nil for match/no match.
|
||||
If PRED is non-nil, match each parent's type with PRED rather
|
||||
than using NODE's type. PRED can also be a predicate function,
|
||||
and more. See `treesit-things-definition' for detail.
|
||||
|
||||
If INCLUDE-NODE is non-nil, return NODE if it satisfies PRED."
|
||||
(let ((pred (or pred (treesit-node-type node)))
|
||||
(let ((pred (or pred (rx-to-string
|
||||
`(bos ,(treesit-node-type node) eos))))
|
||||
(result nil))
|
||||
(cl-loop for cursor = (if include-node node
|
||||
(treesit-node-parent node))
|
||||
then (treesit-node-parent cursor)
|
||||
while cursor
|
||||
if (if (stringp pred)
|
||||
(string-match-p pred (treesit-node-type cursor))
|
||||
(funcall pred cursor))
|
||||
if (treesit-node-match-p cursor pred)
|
||||
do (setq result cursor))
|
||||
result))
|
||||
|
||||
|
|
@ -1887,17 +1886,6 @@ nil.")
|
|||
"The delimiter used to connect several defun names.
|
||||
This is used in `treesit-add-log-current-defun'.")
|
||||
|
||||
(defsubst treesit--thing-unpack-pattern (pattern)
|
||||
"Unpack PATTERN in the shape of `treesit-defun-type-regexp'.
|
||||
|
||||
Basically,
|
||||
|
||||
(unpack REGEXP) = (REGEXP . nil)
|
||||
(unpack (REGEXP . PRED)) = (REGEXP . PRED)"
|
||||
(if (consp pattern)
|
||||
pattern
|
||||
(cons pattern nil)))
|
||||
|
||||
(defun treesit-beginning-of-thing (pattern &optional arg tactic)
|
||||
"Like `beginning-of-defun', but generalized into things.
|
||||
|
||||
|
|
@ -1916,10 +1904,8 @@ should there be one. If omitted, TACTIC is considered to be
|
|||
|
||||
Return non-nil if successfully moved, nil otherwise."
|
||||
(pcase-let* ((arg (or arg 1))
|
||||
(`(,regexp . ,pred) (treesit--thing-unpack-pattern
|
||||
pattern))
|
||||
(dest (treesit--navigate-thing
|
||||
(point) (- arg) 'beg regexp pred tactic)))
|
||||
(point) (- arg) 'beg pattern tactic)))
|
||||
(when dest
|
||||
(goto-char dest))))
|
||||
|
||||
|
|
@ -1941,10 +1927,8 @@ should there be one. If omitted, TACTIC is considered to be
|
|||
|
||||
Return non-nil if successfully moved, nil otherwise."
|
||||
(pcase-let* ((arg (or arg 1))
|
||||
(`(,regexp . ,pred) (treesit--thing-unpack-pattern
|
||||
pattern))
|
||||
(dest (treesit--navigate-thing
|
||||
(point) arg 'end regexp pred tactic)))
|
||||
(point) arg 'end pattern tactic)))
|
||||
(when dest
|
||||
(goto-char dest))))
|
||||
|
||||
|
|
@ -2069,7 +2053,7 @@ the current line if the beginning of the defun is indented."
|
|||
;; parent:
|
||||
;; 1. node covers pos
|
||||
;; 2. smallest such node
|
||||
(defun treesit--things-around (pos regexp &optional pred)
|
||||
(defun treesit--things-around (pos regexp)
|
||||
"Return the previous, next, and parent thing around POS.
|
||||
|
||||
Return a list of (PREV NEXT PARENT), where PREV and NEXT are
|
||||
|
|
@ -2077,7 +2061,8 @@ previous and next sibling things around POS, and PARENT is the
|
|||
parent thing surrounding POS. All of three could be nil if no
|
||||
sound things exists.
|
||||
|
||||
REGEXP and PRED are the same as in `treesit-thing-at-point'."
|
||||
REGEXP can be a regexp, a predicate function, and more. See
|
||||
`treesit-things-definition' for details."
|
||||
(let* ((node (treesit-node-at pos))
|
||||
(result (list nil nil nil)))
|
||||
;; 1. Find previous and next sibling defuns.
|
||||
|
|
@ -2100,9 +2085,7 @@ REGEXP and PRED are the same as in `treesit-thing-at-point'."
|
|||
when node
|
||||
do (let ((cursor node)
|
||||
(iter-pred (lambda (node)
|
||||
(and (string-match-p
|
||||
regexp (treesit-node-type node))
|
||||
(or (null pred) (funcall pred node))
|
||||
(and (treesit-node-match-p node regexp)
|
||||
(funcall pos-pred node)))))
|
||||
;; Find the node just before/after POS to start searching.
|
||||
(save-excursion
|
||||
|
|
@ -2120,9 +2103,7 @@ REGEXP and PRED are the same as in `treesit-thing-at-point'."
|
|||
;; 2. Find the parent defun.
|
||||
(let ((cursor (or (nth 0 result) (nth 1 result) node))
|
||||
(iter-pred (lambda (node)
|
||||
(and (string-match-p
|
||||
regexp (treesit-node-type node))
|
||||
(or (null pred) (funcall pred node))
|
||||
(and (treesit-node-match-p node regexp)
|
||||
(not (treesit-node-eq node (nth 0 result)))
|
||||
(not (treesit-node-eq node (nth 1 result)))
|
||||
(< (treesit-node-start node)
|
||||
|
|
@ -2132,15 +2113,6 @@ REGEXP and PRED are the same as in `treesit-thing-at-point'."
|
|||
(treesit-parent-until cursor iter-pred)))
|
||||
result))
|
||||
|
||||
(defun treesit--top-level-thing (node regexp &optional pred)
|
||||
"Return the top-level parent thing of NODE.
|
||||
REGEXP and PRED are the same as in `treesit-thing-at-point'."
|
||||
(treesit-node-top-level
|
||||
node (lambda (node)
|
||||
(and (string-match-p regexp (treesit-node-type node))
|
||||
(or (null pred) (funcall pred node))))
|
||||
t))
|
||||
|
||||
;; The basic idea for nested defun navigation is that we first try to
|
||||
;; move across sibling defuns in the same level, if no more siblings
|
||||
;; exist, we move to parents's beg/end, rinse and repeat. We never
|
||||
|
|
@ -2168,7 +2140,7 @@ REGEXP and PRED are the same as in `treesit-thing-at-point'."
|
|||
;; -> Obviously we don't want to go to parent's end, instead, we
|
||||
;; want to go to parent's prev-sibling's end. Again, we recurse
|
||||
;; in the function to do that.
|
||||
(defun treesit--navigate-thing (pos arg side regexp &optional pred tactic recursing)
|
||||
(defun treesit--navigate-thing (pos arg side regexp &optional tactic recursing)
|
||||
"Navigate thing ARG steps from POS.
|
||||
|
||||
If ARG is positive, move forward that many steps, if negative,
|
||||
|
|
@ -2179,7 +2151,8 @@ This function doesn't actually move point, it just returns the
|
|||
position it would move to. If there aren't enough things to move
|
||||
across, return nil.
|
||||
|
||||
REGEXP and PRED are the same as in `treesit-thing-at-point'.
|
||||
REGEXP can be a regexp, a predicate function, and more. See
|
||||
`treesit-things-definition' for detail.
|
||||
|
||||
TACTIC determines how does this function move between things. It
|
||||
can be `nested', `top-level', `restricted', or nil. `nested'
|
||||
|
|
@ -2208,14 +2181,13 @@ function is called recursively."
|
|||
(while (> counter 0)
|
||||
(pcase-let
|
||||
((`(,prev ,next ,parent)
|
||||
(treesit--things-around pos regexp pred)))
|
||||
(treesit--things-around pos regexp)))
|
||||
;; When PARENT is nil, nested and top-level are the same, if
|
||||
;; there is a PARENT, make PARENT to be the top-level parent
|
||||
;; and pretend there is no nested PREV and NEXT.
|
||||
(when (and (eq tactic 'top-level)
|
||||
parent)
|
||||
(setq parent (treesit--top-level-thing
|
||||
parent regexp pred)
|
||||
(setq parent (treesit-node-top-level parent regexp t)
|
||||
prev nil
|
||||
next nil))
|
||||
;; If TACTIC is `restricted', the implementation is very simple.
|
||||
|
|
@ -2247,7 +2219,7 @@ function is called recursively."
|
|||
;; the end of next before recurring.)
|
||||
(setq pos (or (treesit--navigate-thing
|
||||
(treesit-node-end (or next parent))
|
||||
1 'beg regexp pred tactic t)
|
||||
1 'beg regexp tactic t)
|
||||
(throw 'term nil)))
|
||||
;; Normal case.
|
||||
(setq pos (funcall advance (or next parent))))
|
||||
|
|
@ -2259,7 +2231,7 @@ function is called recursively."
|
|||
;; Special case: go to prev end-of-defun.
|
||||
(setq pos (or (treesit--navigate-thing
|
||||
(treesit-node-start (or prev parent))
|
||||
-1 'end regexp pred tactic t)
|
||||
-1 'end regexp tactic t)
|
||||
(throw 'term nil)))
|
||||
;; Normal case.
|
||||
(setq pos (funcall advance (or prev parent))))))
|
||||
|
|
@ -2272,18 +2244,14 @@ function is called recursively."
|
|||
(defun treesit-thing-at-point (pattern tactic)
|
||||
"Return the thing node at point or nil if none is found.
|
||||
|
||||
\"Thing\" is defined by PATTERN, which can be either a string
|
||||
REGEXP or a cons cell (REGEXP . PRED): if a node's type matches
|
||||
REGEXP, it is a thing. The \"thing\" could be further restricted
|
||||
by PRED: if non-nil, PRED should be a function that takes a node
|
||||
and returns t if the node is a \"thing\", and nil if not.
|
||||
\"Thing\" is defined by PATTERN, which can be a regexp, a
|
||||
predication function, and more, see `treesit-things-definition'
|
||||
for detail.
|
||||
|
||||
Return the top-level defun if TACTIC is `top-level', return the
|
||||
immediate parent thing if TACTIC is `nested'."
|
||||
(pcase-let* ((`(,regexp . ,pred)
|
||||
(treesit--thing-unpack-pattern pattern))
|
||||
(`(,_ ,next ,parent)
|
||||
(treesit--things-around (point) regexp pred))
|
||||
(pcase-let* ((`(,_ ,next ,parent)
|
||||
(treesit--things-around (point) pattern))
|
||||
;; If point is at the beginning of a thing, we
|
||||
;; prioritize that thing over the parent in nested
|
||||
;; mode.
|
||||
|
|
@ -2291,7 +2259,7 @@ immediate parent thing if TACTIC is `nested'."
|
|||
next)
|
||||
parent)))
|
||||
(if (eq tactic 'top-level)
|
||||
(treesit--top-level-thing node regexp pred)
|
||||
(treesit-node-top-level node pattern t)
|
||||
node)))
|
||||
|
||||
(defun treesit-defun-at-point ()
|
||||
|
|
|
|||
|
|
@ -916,8 +916,6 @@ and \"]\"."
|
|||
collect
|
||||
(cl-loop for pos in record
|
||||
collect (alist-get pos marker-alist))))
|
||||
(`(,regexp . ,pred) (treesit--thing-unpack-pattern
|
||||
treesit-defun-type-regexp))
|
||||
;; Collect positions each function returns.
|
||||
(positions
|
||||
(treesit--ert-collect-positions
|
||||
|
|
@ -929,7 +927,7 @@ and \"]\"."
|
|||
(if-let ((pos (funcall
|
||||
#'treesit--navigate-thing
|
||||
(point) (car conf) (cdr conf)
|
||||
regexp pred tactic)))
|
||||
treesit-defun-type-regexp tactic)))
|
||||
(save-excursion
|
||||
(goto-char pos)
|
||||
(funcall treesit-defun-skipper)
|
||||
|
|
|
|||
Loading…
Reference in a new issue