feature/evil: new code-folding system
This commit is contained in:
parent
a1fa0a7dfe
commit
f49a507ec8
6 changed files with 104 additions and 45 deletions
|
@ -116,16 +116,8 @@ local value, whether or not it's permanent-local. Therefore, we cycle
|
|||
;; Plugins
|
||||
;;
|
||||
|
||||
;; I modified the built-in `hideshow' package to enable itself when needed. A
|
||||
;; better, more vim-like code-folding plugin would be the `origami' plugin, but
|
||||
;; until certain breaking bugs are fixed in it, I won't switch over.
|
||||
(def-package! hideshow ; built-in
|
||||
:commands (hs-minor-mode hs-toggle-hiding hs-already-hidden-p)
|
||||
:init
|
||||
(defun doom*autoload-hideshow ()
|
||||
(unless (bound-and-true-p hs-minor-mode)
|
||||
(hs-minor-mode 1)))
|
||||
(advice-add #'evil-toggle-fold :before #'doom*autoload-hideshow)
|
||||
:config
|
||||
(setq hs-hide-comments-when-hiding-all nil))
|
||||
|
||||
|
|
|
@ -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 "")
|
||||
|
|
89
modules/feature/evil/autoload/folds.el
Normal file
89
modules/feature/evil/autoload/folds.el
Normal 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))))
|
|
@ -388,6 +388,13 @@ the new algorithm is confusing, like in python or ruby."
|
|||
:config (global-evil-surround-mode 1))
|
||||
|
||||
|
||||
(def-package! evil-vimish-fold
|
||||
:commands evil-vimish-fold-mode
|
||||
:init
|
||||
(setq vimish-fold-dir (concat doom-cache-dir "vimish-fold/")
|
||||
vimish-fold-indication-mode 'right-fringe))
|
||||
|
||||
|
||||
;; Without `evil-visualstar', * and # grab the word at point and search, no
|
||||
;; matter what mode you're in. I want to be able to visually select a region and
|
||||
;; search for other occurrences of it.
|
||||
|
|
|
@ -16,5 +16,6 @@
|
|||
(package! evil-textobj-anyblock)
|
||||
(package! evil-snipe)
|
||||
(package! evil-surround)
|
||||
(package! evil-vimish-fold)
|
||||
(package! evil-visualstar)
|
||||
(package! neotree)
|
||||
|
|
|
@ -128,6 +128,13 @@
|
|||
(setq hs-set-up-overlay
|
||||
(lambda (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 '+doom-folded-face))))))
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue