From: Juri Linkov Date: Sun, 29 Dec 2024 17:42:40 +0000 (+0200) Subject: Add new variable 'forward-list-function' for 'treesit-forward-list' X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=4f2670814b8e79d7e934468cb810210e87a27641;p=emacs.git 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'. (cherry picked from commit 3db984c72b8609c84f06a0fd62e59b4823ea0876) --- diff --git a/etc/NEWS b/etc/NEWS index d37a7254b61..d1a0b2ebe50 100644 --- 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 diff --git a/lisp/emacs-lisp/lisp.el b/lisp/emacs-lisp/lisp.el index a0c50bda84b..dac9dbcd83d 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 d29b84be739..21375475d9a 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -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))