branch: elpa/typst-ts-mode
commit b1deb2d667d4cc976e091d4d7194bb24149e600f
Author: Huan Nguyen <[email protected]>
Commit: Huan Nguyen <[email protected]>
feat: #16 code for reordering list items
---
typst-ts-editing.el | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 103 insertions(+)
diff --git a/typst-ts-editing.el b/typst-ts-editing.el
index d08cd40e97..5fc6087a89 100644
--- a/typst-ts-editing.el
+++ b/typst-ts-editing.el
@@ -57,12 +57,115 @@ Return the heading node when yes otherwise nil."
node
nil)))
+(defun test ()
+ (interactive)
+ (message "%s" (treesit-node-text
+ (treesit-node-child (treesit-parent-until
+ (treesit-node-at (point))
+ (lambda (x) (string= "item"
(treesit-node-type x))))
+ 0))))
+
+(defun typst-ts-mode-item--at-point-p ()
+ "Return (prev current next) items.
+
+When there are no item nodes return for the specific list index will be nil.
+Being a different item type does not count as sibling either, ex:
+1. foo
+- bar
+
+When point is not on an item node return nil."
+ (let* ((item-p (lambda (x) (string= (treesit-node-type x)
+ "item")))
+ (node (treesit-parent-until (treesit-node-at (point))
+ item-p))
+ (get-item-type (lambda (x)
+ (treesit-node-text (treesit-node-child x 0))))
+ (item-type (funcall get-item-type node))
+ (node-numbered-p (not (= (string-to-number item-type) 0)))
+ (same-item-type (lambda (x)
+ (let ((type (funcall get-item-type x)))
+ (or (string= type item-type)
+ ;; are they numbers?
+ (and node-numbered-p
+ (not (= (string-to-number type) 0)))))))
+ (only-if (lambda (x) (and (funcall item-p x)
+ (funcall same-item-type x)
+ x))))
+ (cond
+ ((not node) node)
+ (node (list (funcall only-if (treesit-node-prev-sibling node))
+ node
+ (funcall only-if (treesit-node-next-sibling node)))))))
+
+(defun typst-ts-mode--swap-regions (start1 end1 start2 end2)
+ "Swap region between START1 and END1 with region between START2 and END2."
+ (let ((text1 (buffer-substring start1 end1))
+ (text2 (buffer-substring start2 end2))
+ (marker1-start (make-marker))
+ (marker1-end (make-marker))
+ (marker2-start (make-marker))
+ (marker2-end (make-marker)))
+ (set-marker marker1-start start1)
+ (set-marker marker1-end end1)
+ (set-marker marker2-start start2)
+ (set-marker marker2-end end2)
+
+ (delete-region marker1-start marker1-end)
+ (delete-region marker2-start marker2-end)
+
+ (goto-char marker1-start)
+ (insert text2)
+
+ (goto-char marker2-start)
+ (insert text1)
+
+ (set-marker marker1-start nil)
+ (set-marker marker1-end nil)
+ (set-marker marker2-start nil)
+ (set-marker marker2-end nil)))
+
+(defun typst-ts-mode-item--move (direction)
+ "Moves item node up or down (swap).
+DIRECTION should be `up' or `down'."
+ (let (previous current next swap-with)
+ (seq-setq (previous current next) (typst-ts-mode-item--at-point-p))
+ (unless current
+ (error "Point is not on an item"))
+ (pcase direction
+ ('up
+ (setq swap-with previous))
+ ('down
+ (setq swap-with next))
+ (_ (error "%s is not one of: `up' `down'" direction)))
+ (unless swap-with
+ (user-error "There is no %s item to swap with"
+ (if (eq direction 'up) "previous" "next")))
+ (let ((current-begin (treesit-node-start current))
+ (current-end (treesit-node-end current))
+ (other-begin (treesit-node-start previous))
+ (other-end (treesit-node-end previous)))
+ (typst-ts-mode--swap-regions current-begin current-end
+ other-begin other-end))))
+
+(defun typst-ts-mode-item-up ()
+ "Move the item at point up."
+ (interactive)
+ (typst-ts-mode-item--move 'up))
+
+(defun typst-ts-mode-item-down ()
+ "Move the item at point down."
+ (interactive)
+ (typst-ts-mode-item--move 'down))
+
(defun typst-ts-mode-meta--dwim (direction)
"Do something depending on the context with meta key + DIRECTION.
+
+When point is at heading:
`left': `typst-ts-mode-heading-decrease',
`right': `typst-ts-mode-heading-increase',
`up': `typst-ts-mode-heading-up',
`down': `typst-ts-mode-heading-down'.
+
When there is no relevant action to do it will execute the relevant function in
the `GLOBAL-MAP' (example: `right-word')."
(let ((heading (typst-ts-mode-heading--at-point-p))