2019-02-18 00:01:58 -05:00
|
|
|
;;; editor/fold/autoload/fold.el -*- lexical-binding: t; -*-
|
2018-07-28 01:35:47 +02:00
|
|
|
|
2019-05-15 16:09:53 -04:00
|
|
|
;; `hideshow' is a decent code folding implementation, but it won't let you
|
|
|
|
;; create custom folds. `vimish-fold' offers custom folds, but essentially
|
|
|
|
;; ignores any other type of folding (indent or custom markers, which hideshow
|
|
|
|
;; and `outline-mode' give you). This is my effort to combine them.
|
2018-08-03 18:20:27 +02:00
|
|
|
|
2019-05-15 16:09:53 -04:00
|
|
|
;;
|
|
|
|
;;; Helpers
|
|
|
|
|
|
|
|
(defun +fold--ensure-hideshow-mode ()
|
2018-09-20 22:23:33 -04:00
|
|
|
(unless (bound-and-true-p hs-minor-mode)
|
|
|
|
(hs-minor-mode +1)))
|
|
|
|
|
2019-05-15 16:09:53 -04:00
|
|
|
(defun +fold--vimish-fold-p ()
|
|
|
|
(and (featurep 'vimish-fold)
|
|
|
|
(cl-some #'vimish-fold--vimish-overlay-p
|
|
|
|
(overlays-at (point)))))
|
2018-07-28 01:35:47 +02:00
|
|
|
|
2019-05-15 16:09:53 -04:00
|
|
|
(defun +fold--outline-fold-p ()
|
|
|
|
(and (or (bound-and-true-p outline-minor-mode)
|
|
|
|
(derived-mode-p 'outline-mode))
|
|
|
|
(outline-on-heading-p)))
|
2018-07-28 01:35:47 +02:00
|
|
|
|
2019-05-15 16:09:53 -04:00
|
|
|
(defun +fold--hideshow-fold-p ()
|
|
|
|
(+fold--ensure-hideshow-mode)
|
|
|
|
(save-excursion
|
|
|
|
(ignore-errors
|
|
|
|
(or (hs-looking-at-block-start-p)
|
2020-02-06 14:14:36 -05:00
|
|
|
(hs-find-block-beginning)
|
|
|
|
(unless (eolp)
|
|
|
|
(end-of-line)
|
|
|
|
(+fold--hideshow-fold-p))))))
|
2019-05-15 16:09:53 -04:00
|
|
|
|
2021-10-23 02:16:15 +01:00
|
|
|
;; NOTE: does this need more?
|
|
|
|
(defun +fold--ts-fold-p ()
|
2021-10-28 14:46:22 +01:00
|
|
|
(and tree-sitter-mode
|
|
|
|
(featurep 'ts-fold)))
|
2021-10-23 02:16:15 +01:00
|
|
|
|
2019-05-15 16:09:53 -04:00
|
|
|
(defun +fold--invisible-points (count)
|
|
|
|
(let (points)
|
|
|
|
(save-excursion
|
|
|
|
(catch 'abort
|
|
|
|
(if (< count 0) (beginning-of-line))
|
|
|
|
(while (re-search-forward hs-block-start-regexp nil t
|
|
|
|
(if (> count 0) 1 -1))
|
|
|
|
(unless (invisible-p (point))
|
|
|
|
(end-of-line)
|
|
|
|
(when (hs-already-hidden-p)
|
|
|
|
(push (point) points)
|
|
|
|
(when (>= (length points) count)
|
|
|
|
(throw 'abort nil))))
|
|
|
|
(forward-line (if (> count 0) 1 -1)))))
|
|
|
|
points))
|
|
|
|
|
|
|
|
(defmacro +fold-from-eol (&rest body)
|
|
|
|
"Perform action after moving to the end of the line."
|
|
|
|
`(save-excursion
|
|
|
|
(end-of-line)
|
|
|
|
,@body))
|
2018-08-03 18:20:27 +02:00
|
|
|
|
2018-07-28 01:35:47 +02:00
|
|
|
|
|
|
|
;;
|
2019-05-15 16:09:53 -04:00
|
|
|
;;; Commands
|
2018-07-28 01:35:47 +02:00
|
|
|
|
2019-05-15 16:09:53 -04:00
|
|
|
;;;###autoload
|
|
|
|
(defun +fold/toggle ()
|
|
|
|
"Toggle the fold at point.
|
2018-07-28 01:35:47 +02:00
|
|
|
|
2021-10-23 02:16:15 +01:00
|
|
|
Targets `vimmish-fold', `hideshow', `ts-fold' and `outline' folds."
|
2019-05-15 16:09:53 -04:00
|
|
|
(interactive)
|
|
|
|
(save-excursion
|
|
|
|
(cond ((+fold--vimish-fold-p) (vimish-fold-toggle))
|
|
|
|
((+fold--outline-fold-p)
|
|
|
|
(cl-letf (((symbol-function #'outline-hide-subtree)
|
|
|
|
(symbol-function #'outline-hide-entry)))
|
|
|
|
(outline-toggle-children)))
|
2021-10-23 02:16:15 +01:00
|
|
|
((+fold--ts-fold-p) (ts-fold-toggle))
|
2019-05-15 16:09:53 -04:00
|
|
|
((+fold--hideshow-fold-p) (+fold-from-eol (hs-toggle-hiding))))))
|
2018-07-28 01:35:47 +02:00
|
|
|
|
2019-05-15 16:09:53 -04:00
|
|
|
;;;###autoload
|
|
|
|
(defun +fold/open ()
|
|
|
|
"Open the folded region at point.
|
2018-07-28 01:35:47 +02:00
|
|
|
|
2021-10-23 02:16:15 +01:00
|
|
|
Targets `vimmish-fold', `hideshow', `ts-fold' and `outline' folds."
|
2019-05-15 16:09:53 -04:00
|
|
|
(interactive)
|
2018-07-28 01:35:47 +02:00
|
|
|
(save-excursion
|
2019-05-15 16:09:53 -04:00
|
|
|
(cond ((+fold--vimish-fold-p) (vimish-fold-unfold))
|
|
|
|
((+fold--outline-fold-p)
|
|
|
|
(outline-show-children)
|
|
|
|
(outline-show-entry))
|
2021-10-23 02:16:15 +01:00
|
|
|
((+fold--ts-fold-p) (ts-fold-open))
|
2019-05-15 16:09:53 -04:00
|
|
|
((+fold--hideshow-fold-p) (+fold-from-eol (hs-show-block))))))
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
(defun +fold/close ()
|
|
|
|
"Close the folded region at point.
|
|
|
|
|
2021-10-23 02:16:15 +01:00
|
|
|
Targets `vimmish-fold', `hideshow', `ts-fold' and `outline' folds."
|
2019-05-15 16:09:53 -04:00
|
|
|
(interactive)
|
2018-07-28 01:35:47 +02:00
|
|
|
(save-excursion
|
2019-05-15 16:09:53 -04:00
|
|
|
(cond ((+fold--vimish-fold-p) (vimish-fold-refold))
|
2021-10-23 02:16:15 +01:00
|
|
|
((+fold--ts-fold-p) (ts-fold-close))
|
2019-05-15 16:09:53 -04:00
|
|
|
((+fold--hideshow-fold-p) (+fold-from-eol (hs-hide-block)))
|
|
|
|
((+fold--outline-fold-p) (outline-hide-subtree)))))
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
(defun +fold/open-all (&optional level)
|
|
|
|
"Open folds at LEVEL (or all folds if LEVEL is nil)."
|
|
|
|
(interactive
|
|
|
|
(list (if current-prefix-arg (prefix-numeric-value current-prefix-arg))))
|
|
|
|
(when (featurep 'vimish-fold)
|
|
|
|
(vimish-fold-unfold-all))
|
|
|
|
(save-excursion
|
|
|
|
(+fold--ensure-hideshow-mode)
|
|
|
|
(if (integerp level)
|
|
|
|
(progn
|
|
|
|
(outline-hide-sublevels (max 1 (1- level)))
|
|
|
|
(hs-life-goes-on
|
|
|
|
(hs-hide-level-recursive (1- level) (point-min) (point-max))))
|
|
|
|
(hs-show-all)
|
|
|
|
(when (fboundp 'outline-show-all)
|
|
|
|
(outline-show-all)))))
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
(defun +fold/close-all (&optional level)
|
|
|
|
"Close folds at LEVEL (or all folds if LEVEL is nil)."
|
|
|
|
(interactive
|
|
|
|
(list (if current-prefix-arg (prefix-numeric-value current-prefix-arg))))
|
|
|
|
(save-excursion
|
|
|
|
(when (featurep 'vimish-fold)
|
|
|
|
(vimish-fold-refold-all))
|
|
|
|
(+fold--ensure-hideshow-mode)
|
|
|
|
(hs-life-goes-on
|
|
|
|
(if (integerp level)
|
|
|
|
(hs-hide-level-recursive (1- level) (point-min) (point-max))
|
|
|
|
(hs-hide-all)))))
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
(defun +fold/next (count)
|
|
|
|
"Jump to the next vimish fold, outline heading or folded region."
|
|
|
|
(interactive "p")
|
|
|
|
(cl-loop with orig-pt = (point)
|
|
|
|
for fn
|
|
|
|
in (list (lambda ()
|
2019-10-14 13:19:32 -04:00
|
|
|
(when (bound-and-true-p hs-block-start-regexp)
|
2019-05-15 16:09:53 -04:00
|
|
|
(car (+fold--invisible-points count))))
|
|
|
|
(lambda ()
|
|
|
|
(when (featurep 'vimish-fold)
|
|
|
|
(if (> count 0)
|
|
|
|
(evil-vimish-fold/next-fold count)
|
|
|
|
(evil-vimish-fold/previous-fold (- count))))
|
|
|
|
(if (/= (point) orig-pt) (point))))
|
|
|
|
if (save-excursion (funcall fn))
|
|
|
|
collect it into points
|
|
|
|
finally do
|
|
|
|
(if-let* ((pt (car (sort points (if (> count 0) #'< #'>)))))
|
|
|
|
(goto-char pt)
|
|
|
|
(message "No more folds %s point" (if (> count 0) "after" "before"))
|
|
|
|
(goto-char orig-pt))))
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
(defun +fold/previous (count)
|
|
|
|
"Jump to the previous vimish fold, outline heading or folded region."
|
|
|
|
(interactive "p")
|
|
|
|
(+fold/next (- count)))
|