diff --git a/modules/emacs/hideshow/autoload.el b/modules/emacs/hideshow/autoload.el index d676d57bc..a2bc009e5 100644 --- a/modules/emacs/hideshow/autoload.el +++ b/modules/emacs/hideshow/autoload.el @@ -5,6 +5,12 @@ "Face to hightlight `hideshow' overlays." :group 'doom-themes) +;;;###autoload +(defun +hideshow*ensure-mode (&rest _) + "Ensure hs-minor-mode is enabled." + (unless (bound-and-true-p hs-minor-mode) + (hs-minor-mode +1))) + ;;;###autoload (defun +hideshow-haml-forward-sexp (arg) (haml-forward-sexp arg) diff --git a/modules/emacs/hideshow/config.el b/modules/emacs/hideshow/config.el index 900f2cd4b..b68fb1157 100644 --- a/modules/emacs/hideshow/config.el +++ b/modules/emacs/hideshow/config.el @@ -25,7 +25,14 @@ enh-ruby-forward-sexp nil) (matlab-mode "if\\|switch\\|case\\|otherwise\\|while\\|for\\|try\\|catch" "end" - nil (lambda (arg) (matlab-forward-sexp)))) + nil (lambda (_arg) (matlab-forward-sexp)))) hs-special-modes-alist '((t)))))) + +;; Ensure `hs-minor-mode' is active when triggering these commands +(advice-add #'hs-toggle-hiding :before #'+hideshow*ensure-mode) +(advice-add #'hs-hide-block :before #'+hideshow*ensure-mode) +(advice-add #'hs-hide-level :before #'+hideshow*ensure-mode) +(advice-add #'hs-show-all :before #'+hideshow*ensure-mode) +(advice-add #'hs-hide-all :before #'+hideshow*ensure-mode) diff --git a/modules/feature/evil/autoload/folds.el b/modules/feature/evil/autoload/folds.el index 99daa6466..99de9190d 100644 --- a/modules/feature/evil/autoload/folds.el +++ b/modules/feature/evil/autoload/folds.el @@ -1,38 +1,34 @@ ;;; feature/evil/autoload/folds.el -*- lexical-binding: t; -*- -(require 'evil-vimish-fold) (require 'hideshow) ;; `hideshow' is a decent code folding implementation, but it won't let you -;; create custom folds. `evil-vimish-fold' offers custom folds, but essentially +;; create custom folds. `vimish-fold' offers custom folds, but essentially ;; ignores any other type of folding (indent or custom markers, which -;; hs-minor-mode gives you). +;; hs-minor-mode and `outline-mode' give you). ;; ;; So this is my effort to combine them. (defun +evil--vimish-fold-p () - (cl-some #'vimish-fold--vimish-overlay-p (overlays-at (point)))) + (and (featurep 'vimish-fold) + (cl-some #'vimish-fold--vimish-overlay-p + (overlays-at (point))))) -(defun +evil--ensure-modes (&rest _) - "Ensure hs-minor-mode is enabled." - (unless (bound-and-true-p hs-minor-mode) - (hs-minor-mode +1))) +(defun +evil--outline-fold-p () + (and (or (bound-and-true-p outline-minor-mode) + (derived-mode-p 'outline-mode)) + (outline-on-heading-p))) -(advice-add #'hs-toggle-hiding :before #'+evil--ensure-modes) -(advice-add #'hs-hide-block :before #'+evil--ensure-modes) -(advice-add #'hs-hide-level :before #'+evil--ensure-modes) -(advice-add #'hs-show-all :before #'+evil--ensure-modes) -(advice-add #'hs-hide-all :before #'+evil--ensure-modes) +(defun +evil--hideshow-fold-p () + (hs-minor-mode +1) + (save-excursion + (ignore-errors + (or (hs-looking-at-block-start-p) + (hs-find-block-beginning))))) -;; --- fold commands ---------------------- - -;;;###autoload -(defun +evil-fold-p () - (or (+evil--vimish-fold-p) - (ignore-errors - (+evil--ensure-modes) - (hs-already-hidden-p)))) +;; +;; Code folding (defmacro +evil-from-eol (&rest body) "Perform action after moving to the end of the line." @@ -40,47 +36,87 @@ (end-of-line) ,@body)) -;;;###autoload (autoload '+evil:fold-toggle "feature/evil/autoload/folds" nil t) -(evil-define-command +evil:fold-toggle () +;;;###autoload +(defun +evil/fold-toggle () (interactive) - (if (+evil--vimish-fold-p) - (vimish-fold-toggle) - (+evil-from-eol (hs-toggle-hiding)))) + (save-excursion + (cond ((+evil--vimish-fold-p) (vimish-fold-toggle)) + ((+evil--hideshow-fold-p) (+evil-from-eol (hs-toggle-hiding))) + ((+evil--outline-fold-p) (outline-toggle-children))))) -;;;###autoload (autoload '+evil:fold-open "feature/evil/autoload/folds" nil t) -(evil-define-command +evil:fold-open () +;;;###autoload +(defun +evil/fold-open () (interactive) - (if (+evil--vimish-fold-p) - (vimish-fold-unfold) - (+evil-from-eol (hs-show-block)))) + (save-excursion + (cond ((+evil--vimish-fold-p) (vimish-fold-unfold)) + ((+evil--hideshow-fold-p) (+evil-from-eol (hs-show-block))) + ((+evil--outline-fold-p) + (outline-show-children) + (outline-show-entry))))) -;;;###autoload (autoload '+evil:fold-close "feature/evil/autoload/folds" nil t) -(evil-define-command +evil:fold-close () +;;;###autoload +(defun +evil/fold-close () (interactive) - (if (+evil--vimish-fold-p) - (vimish-fold-refold) - (+evil-from-eol (hs-hide-block)))) + (save-excursion + (cond ((+evil--vimish-fold-p) (vimish-fold-refold)) + ((+evil--hideshow-fold-p) (+evil-from-eol (hs-hide-block))) + ((+evil--outline-fold-p) (outline-hide-subtree))))) -;;;###autoload (autoload '+evil:fold-open-all "feature/evil/autoload/folds" nil t) -(evil-define-command +evil:fold-open-all (&optional level) +;;;###autoload +(defun +evil/fold-open-all (&optional level) "Open folds at LEVEL (or all folds if LEVEL is nil)." - (interactive "") - (vimish-fold-unfold-all) - (if (integerp level) - (hs-hide-level (1- level)) - (hs-show-all))) + (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 (autoload '+evil:fold-close-all "feature/evil/autoload/folds" nil t) -(evil-define-command +evil:fold-close-all (&optional level) +;;;###autoload +(defun +evil/fold-close-all (&optional level) "Close folds at LEVEL (or all folds if LEVEL is nil)." - (interactive "") - (vimish-fold-refold-all) - (if (integerp level) - (hs-hide-level (1- level)) - (hs-hide-all))) + (interactive + (list (if current-prefix-arg (prefix-numeric-value current-prefix-arg)))) + (save-excursion + (when (featurep 'vimish-fold) + (vimish-fold-refold-all)) + (if (integerp level) + (progn + (when (fboundp 'outline-hide-sublevels) + (outline-hide-sublevels (max 1 (1- level)))) + (hs-life-goes-on + (hs-hide-level-recursive (1- level) (point-min) (point-max)))) + (when (fboundp 'outline-hide-sublevels) + (outline-hide-sublevels 1)) + (hs-hide-all)))) + +(defun +evil--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)) -;; --- misc ------------------------------- + +;; +;; Misc ;;;###autoload (defun +evil/matchit-or-toggle-fold () diff --git a/modules/feature/evil/config.el b/modules/feature/evil/config.el index a0e61fafd..5f8384d13 100644 --- a/modules/feature/evil/config.el +++ b/modules/feature/evil/config.el @@ -73,14 +73,14 @@ line with a linewise comment.") ;; `evil-delete' in wgrep buffers. (define-key wgrep-mode-map [remap evil-delete] #'+evil-delete)) - ;; replace native folding commands + ;; Add vimish-fold, outline-mode & hideshow support to folding commands (define-key! 'global - [remap evil-toggle-fold] #'+evil:fold-toggle - [remap evil-close-fold] #'+evil:fold-close - [remap evil-open-fold] #'+evil:fold-open - [remap evil-open-fold-rec] #'+evil:fold-open - [remap evil-close-folds] #'+evil:fold-close-all - [remap evil-open-folds] #'+evil:fold-open-all) + [remap evil-toggle-fold] #'+evil/fold-toggle + [remap evil-close-fold] #'+evil/fold-close + [remap evil-open-fold] #'+evil/fold-open + [remap evil-open-fold-rec] #'+evil/fold-open + [remap evil-close-folds] #'+evil/fold-close-all + [remap evil-open-folds] #'+evil/fold-open-all) (defun +evil|disable-highlights () "Disable ex search buffer highlights."