(or arg (setq arg 1))
(forward-list (- arg) interactive))
+(defun down-list-default-function (&optional arg)
+ "Default function for `down-list-function'."
+ (let ((inc (if (> arg 0) 1 -1)))
+ (while (/= arg 0)
+ (goto-char (or (scan-lists (point) inc -1) (buffer-end arg)))
+ (setq arg (- arg inc)))))
+
+(defvar down-list-function nil
+ "If non-nil, `down-list' delegates to this function.
+Should take the same arguments and behave similarly to `down-list'.")
+
(defun down-list (&optional arg interactive)
"Move forward down one level of parentheses.
This command will also work on other parentheses-like expressions
With ARG, do this that many times.
A negative argument means move backward but still go down a level.
This command assumes point is not in a string or comment.
+Calls `down-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")
- (when (ppss-comment-or-string-start (syntax-ppss))
+ (when (and (null down-list-function)
+ (ppss-comment-or-string-start (syntax-ppss)))
(user-error "This command doesn't work in strings or comments"))
(if interactive
(condition-case _
(down-list arg nil)
(scan-error (user-error "At bottom level")))
(or arg (setq arg 1))
- (let ((inc (if (> arg 0) 1 -1)))
- (while (/= arg 0)
- (goto-char (or (scan-lists (point) inc -1) (buffer-end arg)))
- (setq arg (- arg inc))))))
+ (if down-list-function
+ (funcall down-list-function arg)
+ (down-list-default-function arg))))
(defun backward-up-list (&optional arg escape-strings no-syntax-crossing)
"Move backward out of one level of parentheses.
however, smaller in scope than sentences. This is used by
`treesit-forward-sexp' and friends.")
+(defun treesit--scan-error (pred arg)
+ (when-let* ((parent (treesit-thing-at (point) pred t))
+ (boundary (treesit-node-child parent (if (> arg 0) -1 0))))
+ (signal 'scan-error (list (format-message "No more %S to move across" pred)
+ (treesit-node-start boundary)
+ (treesit-node-end boundary)))))
+
(defun treesit-forward-sexp (&optional arg)
"Tree-sitter implementation for `forward-sexp-function'.
;; the obstacle, like `forward-sexp' does. If we couldn't
;; find a parent, we simply return nil without moving point,
;; then functions like `up-list' will signal "at top level".
- (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 sexp to move across"
- (treesit-node-start boundary)
- (treesit-node-end boundary)))))))
+ (treesit--scan-error pred arg))))
(defun treesit-forward-sexp-list (&optional arg)
"Alternative tree-sitter implementation for `forward-sexp-function'.
(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)))))))
+ (treesit--scan-error pred arg))))
+
+(defun treesit-down-list (&optional arg)
+ "Move forward down one level of parentheses.
+What constitutes a level of parentheses is determined by
+`sexp-list' in `treesit-thing-settings' that usually defines
+parentheses-like expressions.
+
+This command is the tree-sitter variant of `down-list'
+redefined by the variable `down-list-function'.
+
+ARG is described in the docstring of `down-list'."
+ (interactive "^p")
+ (let* ((pred 'sexp-list)
+ (arg (or arg 1))
+ (inc (if (> arg 0) 1 -1)))
+ (while (/= arg 0)
+ (let* ((node (if (> arg 0)
+ (treesit-thing-next (point) pred)
+ (treesit-thing-prev (point) pred)))
+ (child (when node
+ (treesit-node-child node (if (> arg 0) 0 -1))))
+ (pos (when child
+ (if (> arg 0)
+ (treesit-node-end child)
+ (treesit-node-start child)))))
+ (if pos (goto-char pos) (treesit--scan-error pred arg)))
+ (setq arg (- arg inc)))))
(defun treesit-transpose-sexps (&optional arg)
"Tree-sitter `transpose-sexps' function.
(when (treesit-thing-defined-p 'sexp-list nil)
(setq-local forward-sexp-function #'treesit-forward-sexp-list)
- (setq-local forward-list-function #'treesit-forward-list))
+ (setq-local forward-list-function #'treesit-forward-list)
+ (setq-local down-list-function #'treesit-down-list))
(when (treesit-thing-defined-p 'sentence nil)
(setq-local forward-sentence-function #'treesit-forward-sentence))