editor/fold: refactor & fix zm
This fixes an issue where zm wasn't auto-loading hideshow and hs-minor-mode, preventing it from working. Also reveals +fold/* commands to non-evil users (but as of yet, there are still no non-evil keybinds for it).
This commit is contained in:
parent
dd4e265a49
commit
fa664f4e28
4 changed files with 232 additions and 231 deletions
|
@ -1,150 +0,0 @@
|
|||
;;; editor/fold/autoload/evil.el -*- lexical-binding: t; -*-
|
||||
;;;###if (featurep! :editor evil)
|
||||
|
||||
(require 'hideshow)
|
||||
|
||||
;; `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
|
||||
;; hs-minor-mode and `outline-mode' give you).
|
||||
;;
|
||||
;; So this is my effort to combine them.
|
||||
|
||||
(defun +fold--vimish-fold-p ()
|
||||
(and (featurep 'vimish-fold)
|
||||
(cl-some #'vimish-fold--vimish-overlay-p
|
||||
(overlays-at (point)))))
|
||||
|
||||
(defun +fold--outline-fold-p ()
|
||||
(and (or (bound-and-true-p outline-minor-mode)
|
||||
(derived-mode-p 'outline-mode))
|
||||
(outline-on-heading-p)))
|
||||
|
||||
(defun +fold--hideshow-fold-p ()
|
||||
(hs-minor-mode +1)
|
||||
(save-excursion
|
||||
(ignore-errors
|
||||
(or (hs-looking-at-block-start-p)
|
||||
(hs-find-block-beginning)))))
|
||||
|
||||
|
||||
;;
|
||||
;; Code folding
|
||||
|
||||
(defmacro +fold-from-eol (&rest body)
|
||||
"Perform action after moving to the end of the line."
|
||||
`(save-excursion
|
||||
(end-of-line)
|
||||
,@body))
|
||||
|
||||
;;;###autoload
|
||||
(defun +fold/toggle ()
|
||||
"Toggle the fold at point.
|
||||
|
||||
Targets `vimmish-fold', `hideshow' and `outline' folds."
|
||||
(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)))
|
||||
((+fold--hideshow-fold-p) (+fold-from-eol (hs-toggle-hiding))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun +fold/open ()
|
||||
"Open the folded region at point.
|
||||
|
||||
Targets `vimmish-fold', `hideshow' and `outline' folds."
|
||||
(interactive)
|
||||
(save-excursion
|
||||
(cond ((+fold--vimish-fold-p) (vimish-fold-unfold))
|
||||
((+fold--outline-fold-p)
|
||||
(outline-show-children)
|
||||
(outline-show-entry))
|
||||
((+fold--hideshow-fold-p) (+fold-from-eol (hs-show-block))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun +fold/close ()
|
||||
"Close the folded region at point.
|
||||
|
||||
Targets `vimmish-fold', `hideshow' and `outline' folds."
|
||||
(interactive)
|
||||
(save-excursion
|
||||
(cond ((+fold--vimish-fold-p) (vimish-fold-refold))
|
||||
((+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
|
||||
(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))
|
||||
(hs-life-goes-on
|
||||
(if (integerp level)
|
||||
(hs-hide-level-recursive (1- level) (point-min) (point-max))
|
||||
(hs-hide-all)))))
|
||||
|
||||
(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))
|
||||
|
||||
;;;###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 ()
|
||||
(when hs-block-start-regexp
|
||||
(car (+fold--invisible-points count))))
|
||||
(lambda ()
|
||||
(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)))
|
|
@ -1,89 +1,155 @@
|
|||
;;; editor/fold/autoload/fold.el -*- lexical-binding: t; -*-
|
||||
|
||||
(defface +fold-hideshow-folded-face
|
||||
`((t (:inherit font-lock-comment-face :weight light)))
|
||||
"Face to hightlight `hideshow' overlays."
|
||||
:group 'doom-themes)
|
||||
;; `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.
|
||||
|
||||
;;;###autoload
|
||||
(defun +fold-hideshow*ensure-mode (&rest _)
|
||||
"Ensure hs-minor-mode is enabled."
|
||||
;;
|
||||
;;; Helpers
|
||||
|
||||
(defun +fold--ensure-hideshow-mode ()
|
||||
(unless (bound-and-true-p hs-minor-mode)
|
||||
(hs-minor-mode +1)))
|
||||
|
||||
;;;###autoload
|
||||
(defun +fold-hideshow-haml-forward-sexp (arg)
|
||||
(haml-forward-sexp arg)
|
||||
(move-beginning-of-line 1))
|
||||
(defun +fold--vimish-fold-p ()
|
||||
(and (featurep 'vimish-fold)
|
||||
(cl-some #'vimish-fold--vimish-overlay-p
|
||||
(overlays-at (point)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun +fold-hideshow-forward-block-by-indent (_arg)
|
||||
(let ((start (current-indentation)))
|
||||
(forward-line)
|
||||
(unless (= start (current-indentation))
|
||||
(let ((range (+fold-hideshow-indent-range)))
|
||||
(goto-char (cadr range))
|
||||
(end-of-line)))))
|
||||
(defun +fold--outline-fold-p ()
|
||||
(and (or (bound-and-true-p outline-minor-mode)
|
||||
(derived-mode-p 'outline-mode))
|
||||
(outline-on-heading-p)))
|
||||
|
||||
;;;###autoload
|
||||
(defun +fold-hideshow-set-up-overlay (ov)
|
||||
(when (eq 'code (overlay-get ov 'hs))
|
||||
(when (featurep 'vimish-fold)
|
||||
(overlay-put
|
||||
ov 'before-string
|
||||
(propertize "…" 'display
|
||||
(list vimish-fold-indication-mode
|
||||
'empty-line
|
||||
'vimish-fold-fringe))))
|
||||
(overlay-put
|
||||
ov 'display (propertize " [...] " 'face '+fold-hideshow-folded-face))))
|
||||
(defun +fold--hideshow-fold-p ()
|
||||
(+fold--ensure-hideshow-mode)
|
||||
(save-excursion
|
||||
(ignore-errors
|
||||
(or (hs-looking-at-block-start-p)
|
||||
(hs-find-block-beginning)))))
|
||||
|
||||
(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))
|
||||
|
||||
|
||||
;;
|
||||
;; Indentation detection
|
||||
;;; Commands
|
||||
|
||||
(defun +fold--hideshow-empty-line-p (_)
|
||||
(string= "" (string-trim (thing-at-point 'line))))
|
||||
;;;###autoload
|
||||
(defun +fold/toggle ()
|
||||
"Toggle the fold at point.
|
||||
|
||||
(defun +fold--hideshow-geq-or-empty-p (base-indent)
|
||||
(or (+fold--hideshow-empty-line-p base-indent)
|
||||
(>= (current-indentation) base-indent)))
|
||||
|
||||
(defun +fold--hideshow-g-or-empty-p (base-indent)
|
||||
(or (+fold--hideshow-empty-line-p base-indent)
|
||||
(> (current-indentation) base-indent)))
|
||||
|
||||
(defun +fold--hideshow-seek (start direction before skip predicate base-indent)
|
||||
"Seeks forward (if direction is 1) or backward (if direction is -1) from start, until predicate
|
||||
fails. If before is nil, it will return the first line where predicate fails, otherwise it returns
|
||||
the last line where predicate holds."
|
||||
Targets `vimmish-fold', `hideshow' and `outline' folds."
|
||||
(interactive)
|
||||
(save-excursion
|
||||
(goto-char start)
|
||||
(goto-char (point-at-bol))
|
||||
(let ((bnd (if (> 0 direction)
|
||||
(point-min)
|
||||
(point-max)))
|
||||
(pt (point)))
|
||||
(when skip (forward-line direction))
|
||||
(cl-loop while (and (/= (point) bnd) (funcall predicate base-indent))
|
||||
do (progn
|
||||
(when before (setq pt (point-at-bol)))
|
||||
(forward-line direction)
|
||||
(unless before (setq pt (point-at-bol)))))
|
||||
pt)))
|
||||
(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)))
|
||||
((+fold--hideshow-fold-p) (+fold-from-eol (hs-toggle-hiding))))))
|
||||
|
||||
(defun +fold-hideshow-indent-range (&optional point)
|
||||
"Return the point at the begin and end of the text block with the same (or
|
||||
greater) indentation. If `point' is supplied and non-nil it will return the
|
||||
begin and end of the block surrounding point."
|
||||
;;;###autoload
|
||||
(defun +fold/open ()
|
||||
"Open the folded region at point.
|
||||
|
||||
Targets `vimmish-fold', `hideshow' and `outline' folds."
|
||||
(interactive)
|
||||
(save-excursion
|
||||
(when point
|
||||
(goto-char point))
|
||||
(let ((base-indent (current-indentation))
|
||||
(begin (point))
|
||||
(end (point)))
|
||||
(setq begin (+fold--hideshow-seek begin -1 t nil #'+fold--hideshow-geq-or-empty-p base-indent)
|
||||
begin (+fold--hideshow-seek begin 1 nil nil #'+fold--hideshow-g-or-empty-p base-indent)
|
||||
end (+fold--hideshow-seek end 1 t nil #'+fold--hideshow-geq-or-empty-p base-indent)
|
||||
end (+fold--hideshow-seek end -1 nil nil #'+fold--hideshow-empty-line-p base-indent))
|
||||
(list begin end base-indent))))
|
||||
(cond ((+fold--vimish-fold-p) (vimish-fold-unfold))
|
||||
((+fold--outline-fold-p)
|
||||
(outline-show-children)
|
||||
(outline-show-entry))
|
||||
((+fold--hideshow-fold-p) (+fold-from-eol (hs-show-block))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun +fold/close ()
|
||||
"Close the folded region at point.
|
||||
|
||||
Targets `vimmish-fold', `hideshow' and `outline' folds."
|
||||
(interactive)
|
||||
(save-excursion
|
||||
(cond ((+fold--vimish-fold-p) (vimish-fold-refold))
|
||||
((+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 ()
|
||||
(when hs-block-start-regexp
|
||||
(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)))
|
||||
|
|
83
modules/editor/fold/autoload/hideshow.el
Normal file
83
modules/editor/fold/autoload/hideshow.el
Normal file
|
@ -0,0 +1,83 @@
|
|||
;;; editor/fold/autoload/hideshow.el -*- lexical-binding: t; -*-
|
||||
|
||||
(defface +fold-hideshow-folded-face
|
||||
`((t (:inherit font-lock-comment-face :weight light)))
|
||||
"Face to hightlight `hideshow' overlays."
|
||||
:group 'doom-themes)
|
||||
|
||||
;;;###autoload
|
||||
(defun +fold-hideshow-haml-forward-sexp (arg)
|
||||
(haml-forward-sexp arg)
|
||||
(move-beginning-of-line 1))
|
||||
|
||||
;;;###autoload
|
||||
(defun +fold-hideshow-forward-block-by-indent (_arg)
|
||||
(let ((start (current-indentation)))
|
||||
(forward-line)
|
||||
(unless (= start (current-indentation))
|
||||
(let ((range (+fold-hideshow-indent-range)))
|
||||
(goto-char (cadr range))
|
||||
(end-of-line)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun +fold-hideshow-set-up-overlay (ov)
|
||||
(when (eq 'code (overlay-get ov 'hs))
|
||||
(when (featurep 'vimish-fold)
|
||||
(overlay-put
|
||||
ov 'before-string
|
||||
(propertize "…" 'display
|
||||
(list vimish-fold-indication-mode
|
||||
'empty-line
|
||||
'vimish-fold-fringe))))
|
||||
(overlay-put
|
||||
ov 'display (propertize " [...] " 'face '+fold-hideshow-folded-face))))
|
||||
|
||||
|
||||
;;
|
||||
;;; Indentation detection
|
||||
|
||||
(defun +fold--hideshow-empty-line-p (_)
|
||||
(string= "" (string-trim (thing-at-point 'line))))
|
||||
|
||||
(defun +fold--hideshow-geq-or-empty-p (base-indent)
|
||||
(or (+fold--hideshow-empty-line-p base-indent)
|
||||
(>= (current-indentation) base-indent)))
|
||||
|
||||
(defun +fold--hideshow-g-or-empty-p (base-indent)
|
||||
(or (+fold--hideshow-empty-line-p base-indent)
|
||||
(> (current-indentation) base-indent)))
|
||||
|
||||
(defun +fold--hideshow-seek (start direction before skip predicate base-indent)
|
||||
"Seeks forward (if direction is 1) or backward (if direction is -1) from start, until predicate
|
||||
fails. If before is nil, it will return the first line where predicate fails, otherwise it returns
|
||||
the last line where predicate holds."
|
||||
(save-excursion
|
||||
(goto-char start)
|
||||
(goto-char (point-at-bol))
|
||||
(let ((bnd (if (> 0 direction)
|
||||
(point-min)
|
||||
(point-max)))
|
||||
(pt (point)))
|
||||
(when skip (forward-line direction))
|
||||
(cl-loop while (and (/= (point) bnd) (funcall predicate base-indent))
|
||||
do (progn
|
||||
(when before (setq pt (point-at-bol)))
|
||||
(forward-line direction)
|
||||
(unless before (setq pt (point-at-bol)))))
|
||||
pt)))
|
||||
|
||||
(defun +fold-hideshow-indent-range (&optional point)
|
||||
"Return the point at the begin and end of the text block with the same (or
|
||||
greater) indentation. If `point' is supplied and non-nil it will return the
|
||||
begin and end of the block surrounding point."
|
||||
(save-excursion
|
||||
(when point
|
||||
(goto-char point))
|
||||
(let ((base-indent (current-indentation))
|
||||
(begin (point))
|
||||
(end (point)))
|
||||
(setq begin (+fold--hideshow-seek begin -1 t nil #'+fold--hideshow-geq-or-empty-p base-indent)
|
||||
begin (+fold--hideshow-seek begin 1 nil nil #'+fold--hideshow-g-or-empty-p base-indent)
|
||||
end (+fold--hideshow-seek end 1 t nil #'+fold--hideshow-geq-or-empty-p base-indent)
|
||||
end (+fold--hideshow-seek end -1 nil nil #'+fold--hideshow-empty-line-p base-indent))
|
||||
(list begin end base-indent))))
|
|
@ -18,19 +18,21 @@
|
|||
;; Packages
|
||||
|
||||
(def-package! hideshow ; built-in
|
||||
:defer t
|
||||
:init
|
||||
;; Ensure `hs-minor-mode' is active when triggering these commands
|
||||
(advice-add #'hs-toggle-hiding :before #'+fold-hideshow*ensure-mode)
|
||||
(advice-add #'hs-hide-block :before #'+fold-hideshow*ensure-mode)
|
||||
(advice-add #'hs-hide-level :before #'+fold-hideshow*ensure-mode)
|
||||
(advice-add #'hs-show-all :before #'+fold-hideshow*ensure-mode)
|
||||
(advice-add #'hs-hide-all :before #'+fold-hideshow*ensure-mode)
|
||||
:commands (hs-toggle-hiding hs-hide-block hs-hide-level hs-show-all hs-hide-all)
|
||||
:config
|
||||
(setq hs-hide-comments-when-hiding-all nil
|
||||
;; Nicer code-folding overlays (with fringe indicators)
|
||||
hs-set-up-overlay #'+fold-hideshow-set-up-overlay)
|
||||
|
||||
(defun +fold-hideshow*ensure-mode (&rest _)
|
||||
"Ensure `hs-minor-mode' is enabled."
|
||||
(unless (bound-and-true-p hs-minor-mode)
|
||||
(hs-minor-mode +1)))
|
||||
(advice-add! '(hs-toggle-hiding
|
||||
hs-hide-block hs-hide-level
|
||||
hs-show-all hs-hide-all)
|
||||
:before #'+fold-hideshow*ensure-mode)
|
||||
|
||||
;; extra folding support for more languages
|
||||
(unless (assq 't hs-special-modes-alist)
|
||||
(setq hs-special-modes-alist
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue