New treesit thing 'sexp-list' (bug#73404)
* lisp/treesit.el (treesit-forward-list): New command. (treesit-forward-sexp): Check the thing 'text' only when 'treesit-sexp-type-regexp' is nil. (treesit-forward-sexp-list): New function. (treesit-navigate-thing): Don't try moving to parent when thing is 'sexp-list'. (treesit-major-mode-setup): Set 'forward-sexp-function' to 'treesit-forward-sexp-list' when the 'sexp-list' thing is defined.
This commit is contained in:
parent
3281f8615a
commit
d930d7f865
2 changed files with 94 additions and 3 deletions
7
etc/NEWS
7
etc/NEWS
|
@ -954,6 +954,13 @@ override flag by 'treesit-font-lock-setting-query',
|
|||
'treesit-font-lock-setting-feature', 'treesit-font-lock-setting-enable',
|
||||
and 'treesit-font-lock-setting-override'.
|
||||
|
||||
*** New treesit thing 'sexp-list'.
|
||||
Unlike the existing thing 'sexp' that defines both lists and atoms,
|
||||
'sexp-list' defines only lists to be navigated by 'forward-sexp'.
|
||||
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 optional BUFFER argument for 'string-pixel-width'.
|
||||
If supplied, 'string-pixel-width' will use any face remappings from
|
||||
|
|
|
@ -2366,6 +2366,25 @@ 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'.
|
||||
|
||||
|
@ -2379,12 +2398,18 @@ 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'."
|
||||
by `text' and `sexp' in `treesit-thing-settings'.
|
||||
|
||||
There is an alternative implementation in `treesit-forward-sexp-list'
|
||||
that uses `sexp-list' in `treesit-thing-settings' to move only
|
||||
across lists, whereas uses `forward-sexp-default-function' to move
|
||||
across atoms (such as symbols or words) inside the list."
|
||||
(interactive "^p")
|
||||
(let ((arg (or arg 1))
|
||||
(pred (or treesit-sexp-type-regexp 'sexp))
|
||||
(node-at-point
|
||||
(treesit-node-at (point) (treesit-language-at (point)))))
|
||||
(when (null treesit-sexp-type-regexp)
|
||||
(treesit-node-at (point) (treesit-language-at (point))))))
|
||||
(or (when (and node-at-point
|
||||
;; Make sure point is strictly inside node.
|
||||
(< (treesit-node-start node-at-point)
|
||||
|
@ -2408,6 +2433,60 @@ by `text' and `sexp' in `treesit-thing-settings'."
|
|||
(treesit-node-start boundary)
|
||||
(treesit-node-end boundary)))))))
|
||||
|
||||
(defun treesit-forward-sexp-list (&optional arg)
|
||||
"Alternative tree-sitter implementation for `forward-sexp-function'.
|
||||
|
||||
Whereas `treesit-forward-sexp' moves across both lists and atoms
|
||||
using `sexp' in `treesit-thing-settings', this function uses
|
||||
`sexp-list' in `treesit-thing-settings' to move only across lists.
|
||||
But to move across atoms (such as symbols or words) inside the list
|
||||
it uses `forward-sexp-default-function' as long as it doesn't go
|
||||
outside of the boundaries of the current list.
|
||||
|
||||
ARG is described in the docstring of `forward-sexp-function'."
|
||||
(interactive "^p")
|
||||
(let* ((arg (or arg 1))
|
||||
(pred 'sexp-list)
|
||||
(default-pos
|
||||
(condition-case _
|
||||
(save-excursion
|
||||
(forward-sexp-default-function arg)
|
||||
(point))
|
||||
(scan-error nil)))
|
||||
(default-pos (unless (eq (point) default-pos) default-pos))
|
||||
(sibling-pos
|
||||
(when default-pos
|
||||
(save-excursion
|
||||
(and (if (> arg 0)
|
||||
(treesit-end-of-thing pred (abs arg) 'restricted)
|
||||
(treesit-beginning-of-thing pred (abs arg) 'restricted))
|
||||
(point)))))
|
||||
(sibling (when sibling-pos
|
||||
(if (> arg 0)
|
||||
(treesit-thing-prev sibling-pos pred)
|
||||
(treesit-thing-next sibling-pos pred))))
|
||||
(sibling (when (and sibling
|
||||
(if (> arg 0)
|
||||
(<= (point) (treesit-node-start sibling))
|
||||
(>= (point) (treesit-node-end sibling))))
|
||||
sibling))
|
||||
(current-thing (when default-pos
|
||||
(treesit-thing-at (point) pred t))))
|
||||
|
||||
;; 'forward-sexp-default-function' should not go out of the current thing,
|
||||
;; neither go inside the next thing or go over the next thing
|
||||
(or (when (and default-pos
|
||||
(or (null current-thing)
|
||||
(if (> arg 0)
|
||||
(< default-pos (treesit-node-end current-thing))
|
||||
(> default-pos (treesit-node-start current-thing))))
|
||||
(or (null sibling)
|
||||
(if (> arg 0)
|
||||
(<= default-pos (treesit-node-start sibling))
|
||||
(>= default-pos (treesit-node-end sibling)))))
|
||||
(goto-char default-pos))
|
||||
(treesit-forward-list arg))))
|
||||
|
||||
(defun treesit-transpose-sexps (&optional arg)
|
||||
"Tree-sitter `transpose-sexps' function.
|
||||
ARG is the same as in `transpose-sexps'.
|
||||
|
@ -2857,7 +2936,9 @@ function is called recursively."
|
|||
(if (eq tactic 'restricted)
|
||||
(setq pos (funcall
|
||||
advance
|
||||
(cond ((and (null next) (null prev)) parent)
|
||||
(cond ((and (null next) (null prev)
|
||||
(not (eq thing 'sexp-list)))
|
||||
parent)
|
||||
((> arg 0) next)
|
||||
(t prev))))
|
||||
;; For `nested', it's a bit more work:
|
||||
|
@ -3254,6 +3335,9 @@ before calling this function."
|
|||
(setq-local forward-sexp-function #'treesit-forward-sexp)
|
||||
(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))
|
||||
|
||||
(when (treesit-thing-defined-p 'sentence nil)
|
||||
(setq-local forward-sentence-function #'treesit-forward-sentence))
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue