feat(fold): add treesit-fold support

This commit is contained in:
Henrik Lissner
2025-05-07 18:14:52 -04:00
parent 1ac1b70d4e
commit f2678b3ea2
3 changed files with 47 additions and 48 deletions

View File

@ -41,10 +41,11 @@ Return non-nil if successful in doing so."
(end-of-line) (end-of-line)
(+fold--hideshow-fold-p))))))) (+fold--hideshow-fold-p)))))))
;; NOTE: does this need more? (defun +fold--treesit-fold-p ()
(defun +fold--ts-fold-p () (and (treesit-available-p)
(and (bound-and-true-p tree-sitter-mode) (treesit-parser-list)
(featurep 'ts-fold))) (require 'treesit-fold nil t)
(treesit-fold-usable-mode-p)))
(defun +fold--invisible-points (count) (defun +fold--invisible-points (count)
(let (points) (let (points)
@ -102,18 +103,17 @@ Return non-nil if successful in doing so."
ov (hs-overlay-at start))) ov (hs-overlay-at start)))
(when ov (when ov
(list (cons (overlay-start ov) (overlay-end ov)))))) (list (cons (overlay-start ov) (overlay-end ov))))))
(when (+fold--ts-fold-p) (when (+fold--treesit-fold-p)
(when-let* ((node (ts-fold--foldable-node-at-pos)) (when-let* ((node (treesit-fold--foldable-node-at-pos))
(beg (tsc-node-start-position node)) (beg (treesit-node-start node))
(end (tsc-node-end-position node))) (end (treesit-node-end node)))
(list (cons beg end))))))) (list (cons beg end)))))))
(defun +fold--open-rec-between (beg end) (defun +fold--open-rec-between (beg end)
"Recursively open all folds betwen BEG and END." "Recursively open all folds betwen BEG and END."
(when (featurep 'vimish-fold) (when (featurep 'vimish-fold)
;; from `vimish-fold-unfold-all' ;; from `vimish-fold-unfold-all'
(mapc #'vimish-fold--unfold (mapc #'vimish-fold--unfold (vimish-fold--folds-in beg end)))
(vimish-fold--folds-in beg end)))
(and (+fold--outline-fold-p) (and (+fold--outline-fold-p)
(outline-show-subtree)) (outline-show-subtree))
(hs-life-goes-on (hs-life-goes-on
@ -121,13 +121,13 @@ Return non-nil if successful in doing so."
(let ((hs-allow-nesting nil)) (let ((hs-allow-nesting nil))
(hs-discard-overlays beg end)) (hs-discard-overlays beg end))
(run-hooks 'hs-show-hook)) (run-hooks 'hs-show-hook))
(when (bound-and-true-p ts-fold-mode) (when (+fold--treesit-fold-p)
;; from `ts-fold-open-all' (treesit-fold--ensure-ts
(ts-fold--ensure-ts ;; from `ts-fold-open-all'
(thread-last (overlays-in beg end) (thread-last (overlays-in beg end)
(seq-filter (seq-filter
(lambda (ov) (lambda (ov)
(eq (overlay-get ov 'invisible) 'ts-fold))) (eq (overlay-get ov 'invisible) 'treesit-fold)))
(mapc #'delete-overlay))))) (mapc #'delete-overlay)))))
;; ;;
@ -146,7 +146,7 @@ Targets `vimmish-fold', `hideshow', `ts-fold' and `outline' folds."
(symbol-function #'outline-hide-entry))) (symbol-function #'outline-hide-entry)))
(outline-toggle-children))) (outline-toggle-children)))
((+fold--hideshow-fold-p) (+fold-from-eol (hs-toggle-hiding))) ((+fold--hideshow-fold-p) (+fold-from-eol (hs-toggle-hiding)))
((+fold--ts-fold-p) (ts-fold-toggle))))) ((+fold--treesit-fold-p) (treesit-fold-toggle)))))
;;;###autoload ;;;###autoload
(defun +fold/open-rec () (defun +fold/open-rec ()
@ -169,7 +169,7 @@ Targets `vimmish-fold', `hideshow', `ts-fold' and `outline' folds."
(outline-show-branches) (outline-show-branches)
(outline-show-entry)) (outline-show-entry))
((+fold--hideshow-fold-p) (+fold-from-eol (hs-show-block))) ((+fold--hideshow-fold-p) (+fold-from-eol (hs-show-block)))
((+fold--ts-fold-p) (ts-fold-open))))) ((+fold--treesit-fold-p) (treesit-fold-open)))))
;;;###autoload ;;;###autoload
(defun +fold/close () (defun +fold/close ()
@ -181,15 +181,15 @@ Targets `vimmish-fold', `hideshow', `ts-fold' and `outline' folds."
(cond ((+fold--vimish-fold-p) (vimish-fold-refold)) (cond ((+fold--vimish-fold-p) (vimish-fold-refold))
((+fold--outline-fold-p) (outline-hide-subtree)) ((+fold--outline-fold-p) (outline-hide-subtree))
((+fold--hideshow-fold-p) (+fold-from-eol (hs-hide-block))) ((+fold--hideshow-fold-p) (+fold-from-eol (hs-hide-block)))
((+fold--ts-fold-p) (ts-fold-close))))) ((+fold--treesit-fold-p) (treesit-fold-close)))))
;;;###autoload ;;;###autoload
(defun +fold/open-all (&optional level) (defun +fold/open-all (&optional level)
"Open folds at LEVEL (or all folds if LEVEL is nil)." "Open folds at LEVEL (or all folds if LEVEL is nil)."
(interactive (interactive
(list (if current-prefix-arg (prefix-numeric-value current-prefix-arg)))) (list (if current-prefix-arg (prefix-numeric-value current-prefix-arg))))
(cond ((+fold--ts-fold-p) (cond ((+fold--treesit-fold-p)
(ts-fold-open-all)) (treesit-fold-open-all))
((and (featurep 'vimish-fold) (+fold--vimish-fold-p)) ((and (featurep 'vimish-fold) (+fold--vimish-fold-p))
(vimish-fold-unfold-all)) (vimish-fold-unfold-all))
((save-excursion ((save-excursion
@ -209,20 +209,19 @@ Targets `vimmish-fold', `hideshow', `ts-fold' and `outline' folds."
(interactive (interactive
(list (if current-prefix-arg (prefix-numeric-value current-prefix-arg)))) (list (if current-prefix-arg (prefix-numeric-value current-prefix-arg))))
(save-excursion (save-excursion
(if (+fold--ts-fold-p) (if (+fold--treesit-fold-p)
(ts-fold-close-all) (treesit-fold-close-all)
(progn (when (featurep 'vimish-fold)
(when (featurep 'vimish-fold) (vimish-fold-refold-all))
(vimish-fold-refold-all)) (when (+fold--ensure-hideshow-mode)
(when (+fold--ensure-hideshow-mode) (hs-life-goes-on
(hs-life-goes-on (if (integerp level)
(if (integerp level) (hs-hide-level-recursive level (point-min) (point-max))
(hs-hide-level-recursive level (point-min) (point-max)) (hs-hide-all))))
(hs-hide-all)))) (if (integerp level)
(if (integerp level) (outline--show-headings-up-to-level level)
(outline--show-headings-up-to-level level) (when (fboundp 'outline-hide-sublevels)
(when (fboundp 'outline-hide-sublevels) (outline-show-only-headings))))))
(outline-show-only-headings)))))))
;;;###autoload ;;;###autoload
(defun +fold/next (count) (defun +fold/next (count)
@ -260,8 +259,9 @@ region."
(outline-end-of-heading)))) (outline-end-of-heading))))
(point))) (point)))
(lambda () (lambda ()
;; ts-fold does not define movement functions so we need to do it ourselves ;; {ts,treesit}-fold does not define movement functions so
(when (+fold--ts-fold-p) ;; we need to do it ourselves
(when (+fold--treesit-fold-p)
(let* ((arg-list (if (> count 0) ;; depending on direction we need to change the ranges (let* ((arg-list (if (> count 0) ;; depending on direction we need to change the ranges
(list (point) (point-max)) (list (point) (point-max))
(list (point-min) (point)))) (list (point-min) (point))))
@ -270,9 +270,11 @@ region."
#'>)) #'>))
(ovs (cl-remove-if-not (ovs (cl-remove-if-not
(lambda (ov) (lambda (ov)
(eq (overlay-get ov 'creator) 'ts-fold)) (eq (overlay-get ov 'creator) 'treesit-fold))
;; `overlays-in' does not provide a list that is sorted ;; `overlays-in' does not provide a list
;; (in the way we need it atleast) so we need to sort it based on direction ;; that is sorted (in the way we need it
;; atleast) so we need to sort it based on
;; direction
(cl-sort (apply #'overlays-in arg-list) comp-fun :key #'overlay-start)))) (cl-sort (apply #'overlays-in arg-list) comp-fun :key #'overlay-start))))
(if (and ovs (<= (abs count) (length ovs))) (if (and ovs (<= (abs count) (length ovs)))
(goto-char (overlay-start (nth (- (abs count) 1) ovs)))))))) (goto-char (overlay-start (nth (- (abs count) 1) ovs))))))))

View File

@ -3,8 +3,7 @@
(defcustom +fold-ellipsis " [...] " (defcustom +fold-ellipsis " [...] "
"The ellipsis to show for ellided regions (folds). "The ellipsis to show for ellided regions (folds).
`org-ellipsis', `truncate-string-ellipsis', and `ts-fold-replacement' are set to `org-ellipsis' and `truncate-string-ellipsis' are set to this."
this."
:type 'string :type 'string
:group '+fold) :group '+fold)
@ -106,9 +105,8 @@ this."
(vimish-fold-global-mode +1)) (vimish-fold-global-mode +1))
(use-package! ts-fold ;; Will be autoloaded by fold commands
:when (modulep! :tools tree-sitter) (use-package! treesit-fold
:after tree-sitter :when (modulep! :tools tree-sitter -compat)
:config :defer t
(setq ts-fold-replacement +fold-ellipsis) :config (global-treesit-fold-mode +1))
(global-ts-fold-mode +1))

View File

@ -7,5 +7,4 @@
(when (modulep! :editor evil) (when (modulep! :editor evil)
(package! evil-vimish-fold :pin "b6e0e6b91b8cd047e80debef1a536d9d49eef31a")) (package! evil-vimish-fold :pin "b6e0e6b91b8cd047e80debef1a536d9d49eef31a"))
(when (modulep! :tools tree-sitter) (when (modulep! :tools tree-sitter)
(package! ts-fold :pin "6eed69cf2b97dce9c6ad329710ed42f0ad674f76" (package! treesit-fold :pin "6628b7cce585328e05d810b5505e4fdb9306f24f"))
:recipe (:host github :repo "emacs-tree-sitter/ts-fold")))