emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 3db984c72b8 1/3: Add new variable 'forward-list-function' for 'tr


From: Juri Linkov
Subject: master 3db984c72b8 1/3: Add new variable 'forward-list-function' for 'treesit-forward-list'
Date: Sun, 29 Dec 2024 12:59:11 -0500 (EST)

branch: master
commit 3db984c72b8609c84f06a0fd62e59b4823ea0876
Author: Juri Linkov <juri@linkov.net>
Commit: Juri Linkov <juri@linkov.net>

    Add new variable 'forward-list-function' for 'treesit-forward-list'
    
    * 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'.
---
 etc/NEWS                |  5 +++++
 lisp/emacs-lisp/lisp.el | 14 +++++++++++++-
 lisp/treesit.el         | 51 +++++++++++++++++++++++++++++--------------------
 3 files changed, 48 insertions(+), 22 deletions(-)

diff --git a/etc/NEWS b/etc/NEWS
index ed17a7a2bb9..a66899e83e0 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1002,6 +1002,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
diff --git a/lisp/emacs-lisp/lisp.el b/lisp/emacs-lisp/lisp.el
index c9e27e78c33..e45064a459b 100644
--- a/lisp/emacs-lisp/lisp.el
+++ b/lisp/emacs-lisp/lisp.el
@@ -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")
diff --git a/lisp/treesit.el b/lisp/treesit.el
index eb3e26fff7e..7ded154eba8 100644
--- a/lisp/treesit.el
+++ b/lisp/treesit.el
@@ -2420,29 +2420,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'.
@@ -2541,6 +2522,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'.
@@ -3465,7 +3473,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))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]