Skip to content

Commit

Permalink
Initial support for Emacs 29 built-in tree sitter library
Browse files Browse the repository at this point in the history
* Define new functions or aliases for tree sitter functionality
depending on the available support from Emacs.

* Replace all occurrences of library function calls with calls to the
new aliases/functions.

TODO: change usage `tsc-changed-ranges', use
`treesit-parser-add-notifier'.
  • Loading branch information
polaris64 authored and countvajhula committed Feb 19, 2025
1 parent dba18b7 commit edb604c
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 91 deletions.
4 changes: 3 additions & 1 deletion dev/dev-utils.el
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
"Update the highlight overlay to match the start/end position of NODE."
(when symex-ts--current-overlay
(delete-overlay symex-ts--current-overlay))
(setq-local symex-ts--current-overlay (make-overlay (tsc-node-start-position node) (tsc-node-end-position node)))
(setq-local symex-ts--current-overlay
(make-overlay (symex-ts--node-start-position node)
(symex-ts--node-end-position node)))
(overlay-put symex-ts--current-overlay 'face 'symex-ts-current-node-face))

(defun symex-ts--hydra-exit ()
Expand Down
32 changes: 16 additions & 16 deletions symex-primitives.el
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,15 @@

(defun symex--adjust-point ()
"Helper to adjust point to indicate the correct symex."
(if (symex-tree-sitter-p)
(if (symex-ts-available-p)
(symex-ts--adjust-point)
(symex-lisp--adjust-point)))

;;; Predicates

(defun symex--point-at-root-symex-p ()
"Check if point is at a root symex."
(if (symex-tree-sitter-p)
(if (symex-ts-available-p)
;; note that tree-sitter has a global
;; root for the whole file -- that's
;; not the one we mean here, but
Expand All @@ -67,31 +67,31 @@

(defun symex--point-at-first-symex-p ()
"Check if point is at the first symex at some level."
(if (symex-tree-sitter-p)
(if (symex-ts-available-p)
(symex-ts--at-first-p)
(symex-lisp--point-at-first-symex-p)))

(defun symex--point-at-last-symex-p ()
"Check if point is at the last symex at some level."
(if (symex-tree-sitter-p)
(if (symex-ts-available-p)
(symex-ts--at-last-p)
(symex-lisp--point-at-last-symex-p)))

(defun symex--point-at-final-symex-p ()
"Check if point is at the last symex in the buffer."
(if (symex-tree-sitter-p)
(if (symex-ts-available-p)
(symex-ts--at-final-p)
(symex-lisp--point-at-final-symex-p)))

(defun symex--point-at-initial-symex-p ()
"Check if point is at the first symex in the buffer."
(if (symex-tree-sitter-p)
(if (symex-ts-available-p)
(symex-ts--at-initial-p)
(symex-lisp--point-at-initial-symex-p)))

(defun symex--point-at-start-p ()
"Check if point is at the start of a symex."
(if (symex-tree-sitter-p)
(if (symex-ts-available-p)
(symex-ts--point-at-start-p)
(symex-lisp--point-at-start-p)))

Expand Down Expand Up @@ -127,7 +127,7 @@ should be used in all internal operations _above_ the primitive layer
(e.g. favoring it over Emacs internal utilities like `forward-sexp`)
that are not primarily user-directed."
(interactive)
(if (symex-tree-sitter-p)
(if (symex-ts-available-p)
(symex-ts-move-next-sibling count)
(symex-lisp--forward count)))

Expand All @@ -142,7 +142,7 @@ should be used in all internal operations _above_ the primitive layer
(e.g. favoring it over Emacs internal utilities like `forward-sexp`)
that are not primarily user-directed."
(interactive)
(if (symex-tree-sitter-p)
(if (symex-ts-available-p)
(symex-ts-move-prev-sibling count)
(symex-lisp--backward count)))

Expand All @@ -157,7 +157,7 @@ should be used in all internal operations _above_ the primitive layer
(e.g. favoring it over Emacs internal utilities like `forward-sexp`)
that are not primarily user-directed."
(interactive)
(if (symex-tree-sitter-p)
(if (symex-ts-available-p)
(symex-ts-move-child count)
(symex-lisp--go-up count)))

Expand All @@ -172,7 +172,7 @@ should be used in all internal operations _above_ the primitive layer
(e.g. favoring it over Emacs internal utilities like `forward-sexp`)
that are not primarily user-directed."
(interactive)
(if (symex-tree-sitter-p)
(if (symex-ts-available-p)
(symex-ts-move-parent count)
(symex-lisp--go-down count)))

Expand Down Expand Up @@ -315,13 +315,13 @@ This will always be zero for symex-oriented languages such as Lisp,
but in languages like Python where the same point position could
correspond to multiple hierarchy levels, this function computes the
difference from the lowest such level."
(if (symex-tree-sitter-p)
(if (symex-ts-available-p)
(symex-ts--point-height-offset)
(symex-lisp--point-height-offset)))

(defun symex--get-starting-point ()
"Get the point value at the start of the current symex."
(if (symex-tree-sitter-p)
(if (symex-ts-available-p)
(symex-ts--get-starting-point)
(symex-lisp--get-starting-point)))

Expand All @@ -330,7 +330,7 @@ difference from the lowest such level."
If the containing expression terminates earlier than COUNT
symexes, returns the end point of the last one found."
(if (symex-tree-sitter-p)
(if (symex-ts-available-p)
;; TODO: implement include-whitespace for ts
(symex-ts--get-end-point count)
(symex-lisp--get-end-point count include-whitespace)))
Expand All @@ -348,7 +348,7 @@ symexes, returns the end point of the last one found."

(defun symex-select-nearest ()
"Select symex nearest to point."
(if (symex-tree-sitter-p)
(if (symex-ts-available-p)
(symex-ts-set-current-node-from-point)
(symex-lisp-select-nearest))
(point))
Expand All @@ -372,7 +372,7 @@ symexes, returns the end point of the last one found."
(defun symex--primitive-exit ()
"Take necessary actions as part of exiting Symex mode, at a primitive level."
(symex--delete-overlay)
(if (symex-tree-sitter-p)
(if (symex-ts-available-p)
(symex-ts-exit)
(symex-lisp-exit)))

Expand Down
72 changes: 42 additions & 30 deletions symex-transformations-ts.el
Original file line number Diff line number Diff line change
Expand Up @@ -69,37 +69,31 @@ selected according to the ranges that have changed."
;; Return the result of evaluating BODY
,res)))))

(defun symex-ts-change-node-forward (&optional count)
"Delete COUNT nodes forward from the current node and enter Insert state."
(interactive "p")
(save-excursion (symex-ts-delete-node-forward count t))
(evil-insert-state 1))

(defun symex-ts-clear ()
"Clear contents of symex."
(when symex-ts--current-node
(let ((child-count (tsc-count-named-children symex-ts--current-node)))
(let ((child-count (symex-ts--count-named-children symex-ts--current-node)))

;; If the node has children, delete them. Otherwise, just delete
;; the current node using `symex-ts-delete-node-forward'.
(if (> child-count 0)
(let ((first-child (tsc-get-nth-named-child symex-ts--current-node 0))
(last-child (tsc-get-nth-named-child symex-ts--current-node (1- child-count))))
(let ((first-child (symex-ts--get-nth-named-child symex-ts--current-node 0))
(last-child (symex-ts--get-nth-named-child symex-ts--current-node (1- child-count))))
(when (and first-child last-child)
(kill-region (tsc-node-start-position first-child) (tsc-node-end-position last-child))))
(kill-region (symex-ts--node-start-position first-child) (symex-ts--node-end-position last-child))))
(symex-ts-delete-node-forward 1)))))

(defun symex-ts-comment (&optional count)
"Comment out COUNT expressions."
(when (symex-tree-sitter-p)
(when (symex-ts-available-p)
(let* ((count (or count 1))
(node (symex-ts-get-current-node))
(start-pos (tsc-node-start-position node))
(end-pos (tsc-node-end-position
(start-pos (symex-ts--node-start-position node))
(end-pos (symex-ts--node-end-position
(if (> count 1)
(symex-ts--get-nth-sibling-from-node
node
#'tsc-get-next-named-sibling count)
#'symex-ts--get-next-named-sibling count)
node))))
(save-excursion (set-mark start-pos)
(goto-char end-pos)
Expand All @@ -115,19 +109,34 @@ If the deletion results in an empty line it will be removed."
(symex--join-to-non-whitespace)
(symex--delete-whole-line))))

(defun symex-ts-delete-node-backward (&optional count)
"Delete COUNT nodes backward from the current node."
(interactive "p")
(let* ((count (or count 1))
(node (symex-ts--get-prev-named-sibling (symex-ts-get-current-node))))
(when node
(let ((end-pos (symex-ts--node-end-position node))
(start-pos (symex-ts--node-start-position
(if (> count 1)
(symex-ts--get-nth-sibling-from-node node #'symex-ts--get-prev-named-sibling count)
node))))
(kill-region start-pos end-pos)
(symex-ts--delete-current-line-if-empty start-pos)
(symex-ts-set-current-node-from-point)))))

(defun symex-ts-delete-node-forward (&optional count)
"Delete COUNT nodes forward from the current node."
(interactive "p")
;; TODO: this is no longer used outside of this module
(symex-ts--handle-tree-modification
(let* ((count (or count 1))
(node (symex-ts-get-current-node))
(start-pos (tsc-node-start-position node))
(end-pos (tsc-node-end-position
(start-pos (symex-ts--node-start-position node))
(end-pos (symex-ts--node-end-position
(if (> count 1)
(symex-ts--get-nth-sibling-from-node
node
#'tsc-get-next-named-sibling count)
#'symex-ts--get-next-named-sibling count)
node))))

;; Delete the node's region
Expand All @@ -138,19 +147,21 @@ If the deletion results in an empty line it will be removed."
"Insert at beginning of symex."
(interactive)
(when (symex-ts-get-current-node)
(goto-char (tsc-node-start-position (symex-ts-get-current-node)))))
(goto-char (symex-ts--node-start-position (symex-ts-get-current-node)))
(evil-insert-state)))

(defun symex-ts-insert-at-end ()
"Insert at end of symex."
(interactive)
(when (symex-ts-get-current-node)
(goto-char (tsc-node-end-position (symex-ts-get-current-node)))))
(goto-char (symex-ts--node-end-position (symex-ts-get-current-node)))
(evil-insert-state)))

(defun symex-ts-insert-before ()
"Insert before symex (instead of vim's default at the start of line)."
(interactive)
(when (symex-ts-get-current-node)
(goto-char (tsc-node-start-position (symex-ts-get-current-node)))
(goto-char (symex-ts--node-start-position (symex-ts-get-current-node)))
(insert " ")
(backward-char)))

Expand All @@ -167,14 +178,15 @@ alias for inserting at the end."
"Open new line after symex."
(interactive)
(when (symex-ts-get-current-node)
(goto-char (tsc-node-end-position (symex-ts-get-current-node)))
(newline-and-indent)))
(goto-char (symex-ts--node-end-position (symex-ts-get-current-node)))
(newline-and-indent)
(evil-insert-state)))

(defun symex-ts-open-line-before ()
"Open new line before symex."
(interactive)
(when (symex-ts-get-current-node)
(goto-char (tsc-node-start-position (symex-ts-get-current-node)))
(goto-char (symex-ts--node-start-position (symex-ts-get-current-node)))
(newline-and-indent)
(forward-line -1)
(indent-according-to-mode)
Expand All @@ -188,8 +200,8 @@ DIRECTION should be either the symbol `before' or `after'."
(when (symex-ts-get-current-node)
(symex-ts--handle-tree-modification
(let* ((node (symex-ts-get-current-node))
(start (tsc-node-start-position node))
(end (tsc-node-end-position node))
(start (symex-ts--node-start-position node))
(end (symex-ts--node-end-position node))
(indent-start (save-excursion (back-to-indentation) (point)))
(block-node (or (not (= (line-number-at-pos start) (line-number-at-pos end)))
(and (= start indent-start)
Expand Down Expand Up @@ -218,13 +230,13 @@ DIRECTION should be either the symbol `before' or `after'."
(defun symex-ts-replace ()
"Replace contents of symex."
(when symex-ts--current-node
(let* ((child-count (tsc-count-named-children symex-ts--current-node))
(let* ((child-count (symex-ts--count-named-children symex-ts--current-node))

;; Get new position for insertion: if the node has children
;; then the start of the first child node, otherwise the
;; current point.
(new-pos (if (> child-count 0)
(tsc-node-start-position (tsc-get-nth-named-child symex-ts--current-node 0))
(symex-ts--node-start-position (symex-ts--get-nth-named-child symex-ts--current-node 0))
(point))))

(symex-ts-clear)
Expand All @@ -239,10 +251,10 @@ DIRECTION should be either the symbol `before' or `after'."
(when (symex-ts-get-current-node)
(let* ((last-command nil)
(node (symex-ts-get-current-node))
(start (tsc-node-start-position node))
(end (tsc-node-end-position
(start (symex-ts--node-start-position node))
(end (symex-ts--node-end-position
(if (> count 1)
(symex-ts--get-nth-sibling-from-node node #'tsc-get-next-named-sibling count)
(symex-ts--get-nth-sibling-from-node node #'symex-ts--get-next-named-sibling count)
node))))
(copy-region-as-kill start end))))

Expand Down
20 changes: 10 additions & 10 deletions symex-transformations.el
Original file line number Diff line number Diff line change
Expand Up @@ -153,14 +153,14 @@
(symex-define-insertion-command symex-replace ()
"Replace contents of symex."
(interactive)
(if (symex-tree-sitter-p)
(if (symex-ts-available-p)
(symex-ts-replace)
(symex-lisp-replace)))

(symex-define-command symex-clear ()
"Clear contents of symex."
(interactive)
(if (symex-tree-sitter-p)
(if (symex-ts-available-p)
(symex-ts-clear)
(symex-lisp-clear)))

Expand Down Expand Up @@ -269,7 +269,7 @@ by default, joins next symex to current one."
(defun symex-yank (count)
"Yank (copy) COUNT symexes."
(interactive "p")
(if (symex-tree-sitter-p)
(if (symex-ts-available-p)
(symex-ts-yank count)
(symex-lisp-yank count)))

Expand Down Expand Up @@ -318,42 +318,42 @@ by default, joins next symex to current one."
(symex-define-insertion-command symex-open-line-after ()
"Open new line after symex."
(interactive)
(if (symex-tree-sitter-p)
(if (symex-ts-available-p)
(symex-ts-open-line-after)
(symex-lisp-open-line-after)))

(symex-define-insertion-command symex-open-line-before ()
"Open new line before symex."
(interactive)
(if (symex-tree-sitter-p)
(if (symex-ts-available-p)
(symex-ts-open-line-before)
(symex-lisp-open-line-before)))

(symex-define-insertion-command symex-append-after ()
"Append after symex (instead of vim's default of line)."
(interactive)
(if (symex-tree-sitter-p)
(if (symex-ts-available-p)
(symex-ts-append-after)
(symex-lisp-append-after)))

(symex-define-insertion-command symex-insert-before ()
"Insert before symex (instead of vim's default at the start of line)."
(interactive)
(if (symex-tree-sitter-p)
(if (symex-ts-available-p)
(symex-ts-insert-before)
(symex-lisp-insert-before)))

(symex-define-insertion-command symex-insert-at-beginning ()
"Insert at beginning of symex."
(interactive)
(if (symex-tree-sitter-p)
(if (symex-ts-available-p)
(symex-ts-insert-at-beginning)
(symex-lisp-insert-at-beginning)))

(symex-define-insertion-command symex-insert-at-end ()
"Insert at end of symex."
(interactive)
(if (symex-tree-sitter-p)
(if (symex-ts-available-p)
(symex-ts-insert-at-end)
(symex-lisp-insert-at-end)))

Expand Down Expand Up @@ -555,7 +555,7 @@ then no action is taken."
(symex-define-command symex-comment (count)
"Comment out COUNT symexes."
(interactive "p")
(if (symex-tree-sitter-p)
(if (symex-ts-available-p)
(symex-ts-comment count)
(progn
(mark-sexp count)
Expand Down
Loading

0 comments on commit edb604c

Please sign in to comment.