Add 'forward-sexp-default-function' to be used by 'treesit-forward-sexp'
authorJuri Linkov <juri@linkov.net>
Sun, 14 Apr 2024 16:18:31 +0000 (19:18 +0300)
committerJuri Linkov <juri@linkov.net>
Sun, 14 Apr 2024 16:22:01 +0000 (19:22 +0300)
* lisp/emacs-lisp/lisp.el (forward-sexp-default-function):
New function with body from 'forward-sexp' (bug#68993).
(forward-sexp-function): Change the default value from nil to
'forward-sexp-default-function'.
(forward-sexp): Use either 'forward-sexp-function' or
'forward-sexp-default-function'.

* lisp/treesit.el (treesit-forward-sexp): In nodes of type 'text'
fall back to 'forward-sexp-default-function'.  Improve docstring.

* doc/lispref/positions.texi (List Motion): Fix pxref.

doc/lispref/positions.texi
etc/NEWS
lisp/emacs-lisp/lisp.el
lisp/treesit.el

index 5e0143c71317a0047ea973930630459ddee60495..9193c1063d17264b8420a79b6eb5c93068da5276 100644 (file)
@@ -892,8 +892,8 @@ parser information to move across syntax constructs.  Since what
 exactly is considered a sexp varies between languages, a major mode
 should set @code{treesit-thing-settings} to determine that.  Then
 the mode can get navigation-by-sexp functionality for free, by using
-@code{forward-sexp} and @code{backward-sexp}(@pxref{Moving by
-Sentences,,, emacs, The extensible self-documenting text editor}).
+@code{forward-sexp} and @code{backward-sexp}(@pxref{Expressions,
+,, emacs, The extensible self-documenting text editor}).
 
 @node Skipping Characters
 @subsection Skipping Characters
index bc8be5577113df7e8aeb1e17f43bf0ee62ac4af3..99f33a7b8dd4ce0f093d0c6f00c9104b4381c831 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -2103,6 +2103,10 @@ All tree-sitter enabled modes that define 'sentence' in
 
 ** Functions and variables to move by program sexps
 
+*** New function 'forward-sexp-default-function'.
+The previous implementation of 'forward-sexp' is moved into its
+own function, to be bound by 'forward-sexp-function'.
+
 *** New function 'treesit-forward-sexp'.
 Tree-sitter conditionally sets 'forward-sexp-function' for major modes
 that have defined 'sexp' in 'treesit-thing-settings' to enable
index c57b1357f63e9ad98b95dae1544f25ab29d60683..bd0b38db7eafb3b8e8413300d45418fe44129fea 100644 (file)
@@ -45,7 +45,12 @@ This affects `insert-parentheses' and `insert-pair'."
   :type 'boolean
   :group 'lisp)
 
-(defvar forward-sexp-function nil
+(defun forward-sexp-default-function (&optional arg)
+  "Default function for `forward-sexp-function'."
+  (goto-char (or (scan-sexps (point) arg) (buffer-end arg)))
+  (if (< arg 0) (backward-prefix-chars)))
+
+(defvar forward-sexp-function #'forward-sexp-default-function
   ;; FIXME:
   ;; - for some uses, we may want a "sexp-only" version, which only
   ;;   jumps over a well-formed sexp, rather than some dwimish thing
@@ -74,10 +79,9 @@ report errors as appropriate for this kind of usage."
                                     "No next sexp"
                                   "No previous sexp"))))
     (or arg (setq arg 1))
-    (if forward-sexp-function
-        (funcall forward-sexp-function arg)
-      (goto-char (or (scan-sexps (point) arg) (buffer-end arg)))
-      (if (< arg 0) (backward-prefix-chars)))))
+    (funcall (or forward-sexp-function
+                 #'forward-sexp-default-function)
+             arg)))
 
 (defun backward-sexp (&optional arg interactive)
   "Move backward across one balanced expression (sexp).
index 1443162f79cd4d34e61b3744d423c6b124a70268..2973aba771cd2514359e6a6c3714193548bafc26 100644 (file)
@@ -2138,14 +2138,24 @@ however, smaller in scope than sentences.  This is used by
 (defun treesit-forward-sexp (&optional arg)
   "Tree-sitter implementation for `forward-sexp-function'.
 
-ARG is described in the docstring of `forward-sexp-function'.  If
-there are no further sexps to move across, signal `scan-error'
-like `forward-sexp' does.  If point is already at top-level,
-return nil without moving point."
+ARG is described in the docstring of `forward-sexp-function'.
+
+If point is inside a text environment where tree-sitter is not
+supported, go forward a sexp using `forward-sexp-default-function'.
+If point is inside code, use tree-sitter functions with the
+following behavior.  If there are no further sexps to move across,
+signal `scan-error' like `forward-sexp' does.  If point is already
+at top-level, return nil without moving point.
+
+What constitutes as text and source code sexp is determined
+by `text' and `sexp' in `treesit-thing-settings'."
   (interactive "^p")
   (let ((arg (or arg 1))
         (pred (or treesit-sexp-type-regexp 'sexp)))
-    (or (if (> arg 0)
+    (or (when (treesit-node-match-p (treesit-node-at (point)) 'text t)
+          (funcall #'forward-sexp-default-function arg)
+          t)
+        (if (> arg 0)
             (treesit-end-of-thing pred (abs arg) 'restricted)
           (treesit-beginning-of-thing pred (abs arg) 'restricted))
         ;; If we couldn't move, we should signal an error and report