feat(emacs-tree-sitter-move): Add tree-sitter-move-reset

Resets the cursor to the named node under the cursor.
`-right` does not do it anymore, so it’s possible to navigate on
higher levels of the tree instead of always resetting to a leaf.

Change-Id: Id330854c72ea24da0cc8611f30f5617e0f127c1b
Reviewed-on: https://cl.tvl.fyi/c/depot/+/2259
Reviewed-by: Profpatsch <mail@profpatsch.de>
Tested-by: BuildkiteCI
This commit is contained in:
Profpatsch 2020-12-19 20:05:35 +01:00
parent 806c281b34
commit 9da760fba4
2 changed files with 27 additions and 20 deletions

View file

@ -7,6 +7,7 @@
'((python-mode . python))) '((python-mode . python)))
(define-key evil-normal-state-map (kbd "C-.") #'tree-sitter-move-reset)
(define-key evil-normal-state-map (kbd "C-<right>") #'tree-sitter-move-right) (define-key evil-normal-state-map (kbd "C-<right>") #'tree-sitter-move-right)
;; (define-key evil-normal-state-map (kbd "C-<left>") 'sp-backward-parallel-sexp) ;; (define-key evil-normal-state-map (kbd "C-<left>") 'sp-backward-parallel-sexp)
;; (define-key evil-normal-state-map (kbd "C-<down>") 'sp-down-sexp) ;; (define-key evil-normal-state-map (kbd "C-<down>") 'sp-down-sexp)

View file

@ -44,34 +44,31 @@
(tree-sitter-mode nil)) (tree-sitter-mode nil))
;; Get the syntax node the cursor is on. ;; Get the syntax node the cursor is on.
(defun tsc-node-named-node-at-point () (defun tsc-get-named-node-at-point ()
(let ((p (point))) (let ((p (point)))
(tsc-get-named-descendant-for-position-range (tsc-get-named-descendant-for-position-range
(tsc-root-node tree-sitter-tree) p p))) (tsc-root-node tree-sitter-tree) p p)))
(defun tsc-get-node-at-point ()
(let ((p (point)))
(tsc-get-descendant-for-position-range
(tsc-root-node tree-sitter-tree) p p)))
(defun tsc-get-first-named-node-with-siblings-up (node) (defun tsc-get-first-named-node-with-siblings-up (node)
"Returns the first 'upwards' node that has siblings. That includes the current "Returns the first 'upwards' node that has siblings. That includes the current
node, so if the given node has siblings, it is returned." node, so if the given node has siblings, it is returned. Returns nil if there
(let ((has-siblings-p is no such node until the root"
(lambda (n) (when-let ((has-siblings-p
(> (tsc-count-named-children (tsc-get-parent n)) (lambda (parent-node)
(> (tsc-count-named-children parent-node)
1))) 1)))
(res node)) (cur node)
(while (not (funcall has-siblings-p res)) (parent (tsc-get-parent node)))
;; TODO tsc-get-parent is called twice, nicer somehow? (while (not (funcall has-siblings-p parent))
(setq res (tsc-get-parent res))) (setq cur parent)
res)) (setq parent (tsc-get-parent cur)))
cur))
(defun tree-sitter-move--set-cursor-to-node (node) (defun tree-sitter-move--set-cursor-to-node (node)
(setq tree-sitter-move--cursor node)) (setq tree-sitter-move--cursor node))
(defun tree-sitter-move--set-cursor-to-node-at-point () (defun tree-sitter-move--set-cursor-to-node-at-point ()
(tree-sitter-move--set-cursor-to-node (tsc-get-node-at-point))) (tree-sitter-move--set-cursor-to-node (tsc-get-named-node-at-point)))
(defun tree-sitter-move--move-point-to-node (node) (defun tree-sitter-move--move-point-to-node (node)
(set-window-point (set-window-point
@ -81,13 +78,22 @@
;; interactive commands (“do what I expect” section) ;; interactive commands (“do what I expect” section)
(defun tree-sitter-move-reset ()
(interactive)
(tree-sitter-move--set-cursor-to-node-at-point))
(defun tree-sitter-move-right () (defun tree-sitter-move-right ()
"Moves to the next sibling. If the current node does not have siblings, go "Moves to the next sibling. If the current node does not have siblings, go
upwards until something has siblings and then move right." upwards until something has siblings and then move right."
(interactive) (interactive)
(tree-sitter-move--set-cursor-to-node-at-point) (tree-sitter-move--move-if-possible
(let ((next (tsc-get-next-named-sibling (lambda (cur)
(tsc-get-first-named-node-with-siblings-up tree-sitter-move--cursor)))) (when-let ((with-siblings
(tsc-get-first-named-node-with-siblings-up cur)))
(tsc-get-next-named-sibling with-siblings)))))
(defun tree-sitter-move--move-if-possible (dir-fn)
(let ((next (funcall dir-fn tree-sitter-move--cursor)))
(when next (when next
(tree-sitter-move--set-cursor-to-node next) (tree-sitter-move--set-cursor-to-node next)
(tree-sitter-move--move-point-to-node next)))) (tree-sitter-move--move-point-to-node next))))