feature/evil: new code-folding system

This commit is contained in:
Henrik Lissner 2017-05-15 20:20:06 +02:00
parent a1fa0a7dfe
commit f49a507ec8
6 changed files with 104 additions and 45 deletions

View file

@ -169,43 +169,6 @@ evil-window-move-* (e.g. `evil-window-move-far-left')"
(doom-narrow-buffer beg end bang))
;; --- code folding -----------------------
;; I wrote these for two reasons:
;; 1. To facilitate lazy-loading of hideshow.el (otherwise, evil wouldn't know what mode to use)
;; 2. To allow level-based folding (parity with vim), e.g. 2zr will open all
;; folds up to 2nd level folds.
;;;###autoload (autoload '+evil:open-folds-recursively "feature/evil/autoload/evil" nil t)
(evil-define-command +evil:open-folds-recursively (level)
"Opens all folds recursively, up to LEVEL."
(interactive "<c>")
(unless (bound-and-true-p hs-minor-mode)
(hs-minor-mode 1))
(if level (hs-hide-level level) (evil-open-folds)))
;;;###autoload (autoload '+evil:close-folds-recursively "feature/evil/autoload/evil" nil t)
(evil-define-command +evil:close-folds-recursively (level)
"Closes all folds recursively, up to LEVEL."
(interactive "<c>")
(unless (bound-and-true-p hs-minor-mode)
(hs-minor-mode 1))
(if level (hs-hide-level level) (evil-close-folds)))
;;;###autoload
(defun +evil/matchit-or-toggle-fold ()
"Do what I mean. If on a fold-able element, toggle the fold with
`hs-toggle-hiding'. Otherwise, if on a delimiter, jump to the matching one with
`evilmi-jump-items'. If in a magit-status buffer, use `magit-section-toggle'."
(interactive)
(cond ((eq major-mode 'magit-status-mode)
(call-interactively 'magit-section-toggle))
((ignore-errors (hs-already-hidden-p))
(hs-toggle-hiding))
(t
(call-interactively 'evilmi-jump-items))))
;; --- custom arg handlers ----------------
(defvar +evil--buffer-match-global evil-ex-substitute-global "")

View file

@ -0,0 +1,89 @@
;;; feature/evil/autoload/folds.el
;; It's frustrating how hideshow is a decent code folding implementation, but it
;; won't let you create custom folds. Meanwhile, evil-vimish-fold offers custom
;; folds, but essentially ignores any other type of folding (indent or custom
;; markers, which hs-minor-mode gives you).
;;
;; So this is my effort to combine them.
;; Initialize the two modes
(evil-vimish-fold-mode +1)
(defun +evil*fold-hs-minor-mode (&rest args)
"Lazily activate buffer-local hs-minor-mode."
(unless (bound-and-true-p hs-minor-mode)
(hs-minor-mode +1)))
(advice-add #'evil-fold-action :before #'+evil*fold-hs-minor-mode)
(add-to-list
'evil-fold-list
'((evil-vimish-mode hs-minor-mode)
:delete vimish-fold-delete
:open-all +evil/fold-open-all
:close-all +evil/fold-close-all
:toggle +evil/fold-toggle
:open +evil/fold-open
:open-rec nil
:close +evil/fold-close))
;; --- fold functions ---------------------
(defun +evil--vimish-fold-p ()
(cl-some #'vimish-fold--vimish-overlay-p (overlays-at (point))))
;;;###autoload
(defun +evil-fold-p ()
(or (+evil--vimish-fold-p)
(hs-already-hidden-p)))
;;;###autoload (autoload '+evil/fold-toggle "feature/evil/autoload/folds" nil t)
(evil-define-command +evil/fold-toggle ()
(interactive)
(if (+evil--vimish-fold-p)
(vimish-fold-toggle)
(hs-toggle-hiding)))
;;;###autoload (autoload '+evil/fold-open "feature/evil/autoload/folds" nil t)
(evil-define-command +evil/fold-open ()
(interactive)
(if (+evil--vimish-fold-p)
(vimish-fold-unfold)
(hs-hide-block)))
;;;###autoload (autoload '+evil/fold-close "feature/evil/autoload/folds" nil t)
(evil-define-command +evil/fold-close ()
(interactive)
(if (+evil--vimish-fold-p)
(vimish-fold-refold)
(hs-hide-block)))
;;;###autoload (autoload '+evil/fold-open-all "feature/evil/autoload/folds" nil t)
(evil-define-command +evil/fold-open-all (&optional level)
(interactive "<c>")
(vimish-fold-unfold-all)
(if level (hs-hide-level level) (hs-show-all)))
;;;###autoload (autoload '+evil/fold-close-all "feature/evil/autoload/folds" nil nil)
(evil-define-command +evil/fold-close-all (&optional level)
(interactive "<c>")
(vimish-fold-refold-all)
(if level (hs-hide-level level) (hs-hide-all)))
;; --- misc -------------------------------
;;;###autoload
(defun +evil/matchit-or-toggle-fold ()
"Do what I mean. If on a fold-able element, toggle the fold with
`hs-toggle-hiding'. Otherwise, if on a delimiter, jump to the matching one with
`evilmi-jump-items'. If in a magit-status buffer, use `magit-section-toggle'."
(interactive)
(call-interactively
(cond ((eq major-mode 'magit-status-mode)
#'magit-section-toggle)
((+evil-fold-p)
#'+evil/fold-toggle)
(t
#'evilmi-jump-items))))