Use the new tree-sitter commands
* lisp/progmodes/c-ts-mode.el (c-ts-mode--defun-valid-p) (c-ts-mode--defun-skipper): New functions. (c-ts-base-mode): Setup defun navigation. * lisp/progmodes/sh-script.el (bash-ts-mode): Setup defun navigation. * lisp/treesit.el (treesit-beginning-of-defun) (treesit-end-of-defun): Change to new implementation, which is intended to be used as commands. (treesit-major-mode-setup): Setup remap for beginning/end-of-defun commands.
This commit is contained in:
parent
037407ad95
commit
cb761eb7ac
3 changed files with 65 additions and 41 deletions
|
@ -531,6 +531,27 @@ the subtrees."
|
|||
(if (looking-at "\\s<\\|\n")
|
||||
(forward-line 1)))))
|
||||
|
||||
(defun c-ts-mode--defun-valid-p (node)
|
||||
(if (string-match-p
|
||||
(rx (or "struct_specifier"
|
||||
"enum_specifier"
|
||||
"union_specifier"))
|
||||
(treesit-node-type node))
|
||||
(null
|
||||
(treesit-node-top-level
|
||||
node (rx (or "function_definition"
|
||||
"type_definition"))))
|
||||
t))
|
||||
|
||||
(defun c-ts-mode--defun-skipper ()
|
||||
"Custom defun skipper for `c-ts-mode' and friends.
|
||||
Structs in C ends with a semicolon, but the semicolon is not
|
||||
considered part of the struct node, so point would stop before
|
||||
the semicolon. This function skips the semicolon."
|
||||
(when (looking-at (rx (* (or " " "\t")) ";"))
|
||||
(goto-char (match-end 0)))
|
||||
(treesit-default-defun-skipper))
|
||||
|
||||
(defun c-ts-mode-indent-defun ()
|
||||
"Indent the current top-level declaration syntactically.
|
||||
|
||||
|
@ -559,12 +580,14 @@ the subtrees."
|
|||
|
||||
;; Navigation.
|
||||
(setq-local treesit-defun-type-regexp
|
||||
(regexp-opt '("function_definition"
|
||||
"type_definition"
|
||||
"struct_specifier"
|
||||
"enum_specifier"
|
||||
"union_specifier"
|
||||
"class_specifier")))
|
||||
(cons (regexp-opt '("function_definition"
|
||||
"type_definition"
|
||||
"struct_specifier"
|
||||
"enum_specifier"
|
||||
"union_specifier"
|
||||
"class_specifier"))
|
||||
#'c-ts-mode--defun-valid-p))
|
||||
(setq-local treesit-defun-skipper #'c-ts-mode--defun-skipper)
|
||||
|
||||
;; Nodes like struct/enum/union_specifier can appear in
|
||||
;; function_definitions, so we need to find the top-level node.
|
||||
|
|
|
@ -1613,6 +1613,7 @@ This mode automatically falls back to `sh-mode' if the buffer is
|
|||
not written in Bash or sh."
|
||||
:syntax-table sh-mode-syntax-table
|
||||
(when (treesit-ready-p 'bash)
|
||||
(treesit-parser-create 'bash)
|
||||
(setq-local treesit-font-lock-feature-list
|
||||
'(( comment function)
|
||||
( command declaration-command keyword string)
|
||||
|
@ -1620,6 +1621,7 @@ not written in Bash or sh."
|
|||
( bracket delimiter misc-punctuation operator)))
|
||||
(setq-local treesit-font-lock-settings
|
||||
sh-mode--treesit-settings)
|
||||
(setq-local treesit-defun-type-regexp "function_definition")
|
||||
(treesit-major-mode-setup)))
|
||||
|
||||
(advice-add 'bash-ts-mode :around #'sh--redirect-bash-ts-mode
|
||||
|
|
|
@ -1624,40 +1624,37 @@ For the detailed semantic see `treesit-defun-prefer-top-level'."
|
|||
finally return node))))
|
||||
|
||||
(defun treesit-beginning-of-defun (&optional arg)
|
||||
"Tree-sitter `beginning-of-defun' function.
|
||||
ARG is the same as in `beginning-of-defun'."
|
||||
(let ((arg (or arg 1))
|
||||
(node (treesit-node-at (point))))
|
||||
(if (> arg 0)
|
||||
;; Go backward.
|
||||
(while (and (> arg 0)
|
||||
(setq node (treesit-search-forward-goto
|
||||
node treesit-defun-type-regexp t t)))
|
||||
(setq node (treesit--defun-maybe-top-level node))
|
||||
(setq arg (1- arg)))
|
||||
;; Go forward.
|
||||
(while (and (< arg 0)
|
||||
(setq node (treesit-search-forward-goto
|
||||
node treesit-defun-type-regexp)))
|
||||
(setq node (treesit--defun-maybe-top-level node))
|
||||
(setq arg (1+ arg))))
|
||||
(when node
|
||||
(goto-char (treesit-node-start node))
|
||||
t)))
|
||||
"Move backward to the beginning of a defun.
|
||||
|
||||
(defun treesit-end-of-defun ()
|
||||
"Tree-sitter `end-of-defun' function."
|
||||
;; Why not simply get the largest node at point: when point is at
|
||||
;; (point-min), that gives us the root node.
|
||||
(let* ((node (treesit-search-forward
|
||||
(treesit-node-at (point)) treesit-defun-type-regexp t t))
|
||||
(top (treesit--defun-maybe-top-level node)))
|
||||
;; Technically `end-of-defun' should only call this function when
|
||||
;; point is at the beginning of a defun, so TOP should always be
|
||||
;; non-nil, but things happen, and we want to be safe, so check
|
||||
;; for TOP anyway.
|
||||
(when top
|
||||
(goto-char (treesit-node-end top)))))
|
||||
With argument ARG, do it that many times. Negative ARG means
|
||||
move forward to the ARGth following beginning of defun.
|
||||
|
||||
If search is successful, return t, otherwise return nil.
|
||||
|
||||
This is a tree-sitter equivalent of `beginning-of-defun'.
|
||||
Behavior of this function depends on `treesit-defun-type-regexp'
|
||||
and `treesit-defun-skipper'."
|
||||
(interactive "^p")
|
||||
(when-let ((dest (treesit--navigate-defun (point) (- arg) 'beg)))
|
||||
(goto-char dest)
|
||||
(when treesit-defun-skipper
|
||||
(funcall treesit-defun-skipper))
|
||||
t))
|
||||
|
||||
(defun treesit-end-of-defun (&optional arg _)
|
||||
"Move forward to next end of defun.
|
||||
|
||||
With argument ARG, do it that many times.
|
||||
Negative argument -N means move back to Nth preceding end of defun.
|
||||
|
||||
This is a tree-sitter equivalent of `end-of-defun'. Behavior of
|
||||
this function depends on `treesit-defun-type-regexp' and
|
||||
`treesit-defun-skipper'."
|
||||
(interactive "^p\nd")
|
||||
(when-let ((dest (treesit--navigate-defun (point) arg 'end)))
|
||||
(goto-char dest)
|
||||
(when treesit-defun-skipper
|
||||
(funcall treesit-defun-skipper))))
|
||||
|
||||
(defun treesit-default-defun-skipper ()
|
||||
"Skips spaces after navigating a defun.
|
||||
|
@ -1953,8 +1950,10 @@ before calling this function."
|
|||
(setq-local indent-region-function #'treesit-indent-region))
|
||||
;; Navigation.
|
||||
(when treesit-defun-type-regexp
|
||||
(setq-local beginning-of-defun-function #'treesit-beginning-of-defun)
|
||||
(setq-local end-of-defun-function #'treesit-end-of-defun)))
|
||||
(keymap-set (current-local-map) "<remap> <beginning-of-defun>"
|
||||
#'treesit-beginning-of-defun)
|
||||
(keymap-set (current-local-map) "<remap> <end-of-defun>"
|
||||
#'treesit-end-of-defun)))
|
||||
|
||||
;;; Debugging
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue