]> git.eshelyaron.com Git - emacs.git/commitdiff
Add new variable 'forward-list-function' for 'treesit-forward-list'
authorJuri Linkov <juri@linkov.net>
Sun, 29 Dec 2024 17:42:40 +0000 (19:42 +0200)
committerEshel Yaron <me@eshelyaron.com>
Sat, 4 Jan 2025 20:24:27 +0000 (21:24 +0100)
* lisp/emacs-lisp/lisp.el (forward-list-default-function): New function.
(forward-list-function): New variable (bug#73404).
(forward-list): Move meat to 'forward-list-default-function',
and call 'forward-list-function' when non-nil.

* lisp/treesit.el (treesit-forward-list): Rewrite to not rely on
'treesit-forward-sexp'.
(treesit-major-mode-setup): Set 'forward-list-function' to
'treesit-forward-list'.

(cherry picked from commit 3db984c72b8609c84f06a0fd62e59b4823ea0876)

etc/NEWS
lisp/emacs-lisp/lisp.el
lisp/treesit.el

index d37a7254b613939e4a77d4a4c3067a16748c5fb1..d1a0b2ebe503246bdcfc10d9fc77d2c101db03d3 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -842,6 +842,11 @@ The new function 'treesit-forward-sexp-list' uses 'sexp-list'
 to move across lists.  But to move across atoms inside the list
 it uses `forward-sexp-default-function'.
 
+*** New function 'treesit-forward-list'.
+Tree-sitter conditionally sets 'forward-list-function' for major modes
+that have defined 'sexp-list' in 'treesit-thing-settings' to enable
+the 'forward-list' motion command.
+
 +++
 *** New function 'treesit-language-display-name'.
 This new function returns the display name of a language given the
index a0c50bda84b34cc26036249ed98a9d9b3cea3c1c..dac9dbcd83dc99d328ec9a8df39a638f372049ef 100644 (file)
@@ -143,6 +143,14 @@ This command assumes point is not in a string or comment."
            (point))
          nil t))))
 
+(defun forward-list-default-function (&optional arg)
+  "Default function for `forward-list-function'."
+  (goto-char (or (scan-lists (point) arg 0) (buffer-end arg))))
+
+(defvar forward-list-function nil
+  "If non-nil, `forward-list' delegates to this function.
+Should take the same arguments and behave similarly to `forward-list'.")
+
 (defun forward-list (&optional arg interactive)
   "Move forward across one balanced group of parentheses.
 This command will also work on other parentheses-like expressions
@@ -150,6 +158,7 @@ defined by the current language mode.
 With ARG, do it that many times.
 Negative arg -N means move backward across N groups of parentheses.
 This command assumes point is not in a string or comment.
+Calls `forward-list-function' to do the work, if that is non-nil.
 If INTERACTIVE is non-nil, as it is interactively,
 report errors as appropriate for this kind of usage."
   (interactive "^p\nd")
@@ -160,7 +169,9 @@ report errors as appropriate for this kind of usage."
                                     "No next group"
                                   "No previous group"))))
     (or arg (setq arg 1))
-    (goto-char (or (scan-lists (point) arg 0) (buffer-end arg)))))
+    (if forward-list-function
+        (funcall forward-list-function arg)
+      (forward-list-default-function arg))))
 
 (defun backward-list (&optional arg interactive)
   "Move backward across one balanced group of parentheses.
@@ -169,6 +180,7 @@ defined by the current language mode.
 With ARG, do it that many times.
 Negative arg -N means move forward across N groups of parentheses.
 This command assumes point is not in a string or comment.
+Uses `forward-list' to do the work.
 If INTERACTIVE is non-nil, as it is interactively,
 report errors as appropriate for this kind of usage."
   (interactive "^p\nd")
index d29b84be73982ac361348d33b9def79a18b4302b..21375475d9a9b406c3e9a35707935c8de32a637b 100644 (file)
@@ -2412,29 +2412,10 @@ delimits medium sized statements in the source code.  It is,
 however, smaller in scope than sentences.  This is used by
 `treesit-forward-sexp' and friends.")
 
-(defun treesit-forward-list (&optional arg)
-  "Move forward across a list.
-What constitutes a list is determined by `sexp-list' in
-`treesit-thing-settings' that usually defines
-parentheses-like expressions.
-
-Unlike `forward-sexp', this command moves only across a list,
-but not across atoms (such as symbols or words) inside the list.
-
-This command is the tree-sitter variant of `forward-list'.  But since
-`forward-list' has no \"forward-list-function\" like there is
-`forward-sexp-function' for `forward-sexp', this command
-can be used on its own.
-
-ARG is described in the docstring of `forward-list'."
-  (interactive "^p")
-  (let ((treesit-sexp-type-regexp 'sexp-list))
-    (treesit-forward-sexp arg)))
-
 (defun treesit-forward-sexp (&optional arg)
   "Tree-sitter implementation for `forward-sexp-function'.
 
-ARG is described in the docstring of `forward-sexp-function'.
+ARG is described in the docstring of `forward-sexp'.
 
 If point is inside a text environment where tree-sitter is not
 supported, go forward a sexp using `forward-sexp-default-function'.
@@ -2533,6 +2514,33 @@ ARG is described in the docstring of `forward-sexp-function'."
           (goto-char default-pos))
         (treesit-forward-list arg))))
 
+(defun treesit-forward-list (&optional arg)
+  "Move forward across a list.
+What constitutes a list is determined by `sexp-list' in
+`treesit-thing-settings' that usually defines
+parentheses-like expressions.
+
+Unlike `forward-sexp', this command moves only across a list,
+but not across atoms (such as symbols or words) inside the list.
+
+This command is the tree-sitter variant of `forward-list'
+redefined by the variable `forward-list-function'.
+
+ARG is described in the docstring of `forward-list'."
+  (interactive "^p")
+  (let ((arg (or arg 1))
+        (pred 'sexp-list))
+    (or (if (> arg 0)
+            (treesit-end-of-thing pred (abs arg) 'restricted)
+          (treesit-beginning-of-thing pred (abs arg) 'restricted))
+        (when-let* ((parent (treesit-thing-at (point) pred t))
+                    (boundary (if (> arg 0)
+                                  (treesit-node-child parent -1)
+                                (treesit-node-child parent 0))))
+          (signal 'scan-error (list "No more group to move across"
+                                    (treesit-node-start boundary)
+                                    (treesit-node-end boundary)))))))
+
 (defun treesit-transpose-sexps (&optional arg)
   "Tree-sitter `transpose-sexps' function.
 ARG is the same as in `transpose-sexps'.
@@ -3457,7 +3465,8 @@ before calling this function."
     (setq-local transpose-sexps-function #'treesit-transpose-sexps))
 
   (when (treesit-thing-defined-p 'sexp-list nil)
-    (setq-local forward-sexp-function #'treesit-forward-sexp-list))
+    (setq-local forward-sexp-function #'treesit-forward-sexp-list)
+    (setq-local forward-list-function #'treesit-forward-list))
 
   (when (treesit-thing-defined-p 'sentence nil)
     (setq-local forward-sentence-function #'treesit-forward-sentence))