From 79584a206b9b36e4937c32845464bfc9b438dade Mon Sep 17 00:00:00 2001 From: Yuan Fu Date: Sat, 24 Dec 2022 22:08:17 -0800 Subject: [PATCH] Further generalize treesit-defun functions Two new functions, treesit-beginning/end-of-thing. And treesit-thing-at-point's signature changes. * lisp/treesit.el (treesit-block-type-regexp): New variable. (treesit-beginning-of-thing) (treesit-end-of-thing): Generalized from treesit-beginning/end-of-defun. (treesit-beginning-of-defun) (treesit-end-of-defun): Use the new functions. (treesit-thing-at-point): Accept PATTERN rather than REGEXP and PRED. (treesit-defun-at-point): Adjust for the new signature of treesit-thing-at-point. --- lisp/treesit.el | 82 +++++++++++++++++++++++++++++++------------------ 1 file changed, 52 insertions(+), 30 deletions(-) diff --git a/lisp/treesit.el b/lisp/treesit.el index 40e70f47f59..e8e93d09de4 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -1582,7 +1582,7 @@ BACKWARD and ALL are the same as in `treesit-search-forward'." (goto-char current-pos))) node)) -;;; Navigation +;;; Navigation, defun, things (defvar-local treesit-defun-type-regexp nil "A regexp that matches the node type of defun nodes. @@ -1596,6 +1596,9 @@ for invalid node. This is used by `treesit-beginning-of-defun' and friends.") +(defvar-local treesit-block-type-regexp nil + "Like `treesit-defun-type-regexp', but for blocks.") + (defvar-local treesit-defun-tactic 'nested "Determines how does Emacs treat nested defuns. If the value is `top-level', Emacs only moves across top-level @@ -1632,6 +1635,36 @@ Basically, pattern (cons pattern nil))) +(defun treesit-beginning-of-thing (pattern &optional arg) + "Like `beginning-of-defun', but generalized into things. + +PATTERN is like `treesit-defun-type-regexp', ARG +is the same as in `beginning-of-defun'. + +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))) + (when dest + (goto-char dest)))) + +(defun treesit-end-of-thing (pattern &optional arg) + "Like `end-of-defun', but generalized into things. + +PATTERN is like `treesit-defun-type-regexp', ARG is the same as +in `end-of-defun'. + +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))) + (when dest + (goto-char dest)))) + (defun treesit-beginning-of-defun (&optional arg) "Move backward to the beginning of a defun. @@ -1644,16 +1677,10 @@ This is a tree-sitter equivalent of `beginning-of-defun'. Behavior of this function depends on `treesit-defun-type-regexp' and `treesit-defun-skipper'." (interactive "^p") - (pcase-let* ((arg (or arg 1)) - (`(,regexp . ,pred) - (treesit--thing-unpack-pattern treesit-defun-type-regexp)) - (dest (treesit--navigate-thing - (point) (- arg) 'beg regexp pred))) - (when dest - (goto-char dest) - (when treesit-defun-skipper - (funcall treesit-defun-skipper)) - t))) + (when (treesit-beginning-of-thing treesit-defun-type-regexp arg) + (when treesit-defun-skipper + (funcall treesit-defun-skipper)) + t)) (defun treesit-end-of-defun (&optional arg _) "Move forward to next end of defun. @@ -1665,15 +1692,9 @@ This is a tree-sitter equivalent of `end-of-defun'. Behavior of this function depends on `treesit-defun-type-regexp' and `treesit-defun-skipper'." (interactive "^p\nd") - (pcase-let* ((arg (or arg 1)) - (`(,regexp . ,pred) - (treesit--thing-unpack-pattern treesit-defun-type-regexp)) - (dest (treesit--navigate-thing - (point) arg 'end regexp pred))) - (when dest - (goto-char dest) - (when treesit-defun-skipper - (funcall treesit-defun-skipper))))) + (when (treesit-end-of-thing treesit-defun-type-regexp arg) + (when treesit-defun-skipper + (funcall treesit-defun-skipper)))) (defun treesit-default-defun-skipper () "Skips spaces after navigating a defun. @@ -1890,17 +1911,20 @@ function is called recursively." (if (eq counter 0) pos nil))) ;; TODO: In corporate into thing-at-point. -(defun treesit-thing-at-point (regexp tactic &optional pred) +(defun treesit-thing-at-point (pattern tactic) "Return the thing node at point or nil if none is found. -\"Thing\" is defined by REGEXP: 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 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. Return the top-level defun if TACTIC is `top-level', return the immediate parent thing if TACTIC is `nested'." - (pcase-let* ((`(,_ ,next ,parent) + (pcase-let* ((`(,regexp . ,pred) + (treesit--thing-unpack-pattern pattern)) + (`(,_ ,next ,parent) (treesit--things-around (point) regexp pred)) ;; If point is at the beginning of a thing, we ;; prioritize that thing over the parent in nested @@ -1921,10 +1945,8 @@ is `top-level', return the immediate parent defun if it is Return nil if `treesit-defun-type-regexp' is not set." (when treesit-defun-type-regexp - (pcase-let ((`(,regexp . ,pred) - (treesit--thing-unpack-pattern - treesit-defun-type-regexp))) - (treesit-thing-at-point regexp treesit-defun-tactic pred)))) + (treesit-thing-at-point + treesit-defun-type-regexp treesit-defun-tactic))) (defun treesit-defun-name (node) "Return the defun name of NODE. -- 2.39.2