summaryrefslogtreecommitdiff
path: root/lisp
diff options
context:
space:
mode:
authorYuan Fu <casouri@gmail.com>2023-04-13 19:48:57 -0700
committerYuan Fu <casouri@gmail.com>2023-04-14 15:52:30 -0700
commit293029458c87d6ec18a6f6a5958d0b499310ca3b (patch)
tree0cc43727b42ab9617fafb6fa366a3e8a93c8482c /lisp
parenta4de6d8dd3b6a5ac39737812e17a2a8d766e9f3a (diff)
downloademacs-293029458c87d6ec18a6f6a5958d0b499310ca3b.tar.gz
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.
Diffstat (limited to 'lisp')
-rw-r--r--lisp/treesit.el86
1 files changed, 27 insertions, 59 deletions
diff --git a/lisp/treesit.el b/lisp/treesit.el
index 3932920a962..e7e336f4609 100644
--- a/lisp/treesit.el
+++ b/lisp/treesit.el
@@ -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 ()