doomemacs/modules/editor/evil/init.el
Henrik Lissner ad6a3d0f33
refactor: deprecate featurep! for modulep!
featurep! will be renamed modulep! in the future, so it's been
deprecated. They have identical interfaces, and can be replaced without
issue.

featurep! was never quite the right name for this macro. It implied that
it had some connection to featurep, which it doesn't (only that it was
similar in purpose; still, Doom modules are not features). To undo such
implications and be consistent with its namespace (and since we're
heading into a storm of breaking changes with the v3 release anyway),
now was the best opportunity to begin the transition.
2022-08-14 20:43:35 +02:00

346 lines
9.5 KiB
EmacsLisp

;;; editor/evil/init.el -*- lexical-binding: t; -*-
(defvar evil-collection-key-blacklist)
;; We load evil-collection ourselves for these reasons:
;;
;; 1. To truly lazy load it. Some of its modules, like
;; evil-collection-{elisp-mode,buff-menu} are loaded immediately, because
;; Emacs loads their packages immediately, which pulls in all of
;; evil-collection (and other packages with it, sometimes).
;; 2. This ensures a predictable load order, versus lazy loading using :defer or
;; :after-call. This means users can use (after! org ...) and be sure that
;; their changes will override evil-collection's.
;; 3. Ideally, we'd do away with evil-collection entirely. It changes too often,
;; introduces breaking bugs too frequently, and I don't agree with all their
;; design choices. Regardless, it does more good than trouble, so it may be
;; here to stay.
;; 4. Adds `+evil-collection-disabled-list', to make it easier for users to
;; disable modules, and to reduce the effort required to maintain our copy of
;; `evil-collection-list' (now I can just copy it from time to time).
(when (and (not noninteractive)
(not doom-reloading-p)
(modulep! +everywhere))
(setq evil-collection-company-use-tng (modulep! :completion company +tng)
;; must be set before evil/evil-collection is loaded
evil-want-keybinding nil)
(defvar +evil-collection-disabled-list
'(anaconda-mode
buff-menu
calc
comint
company
custom
eldoc
elisp-mode
ert
free-keys
helm
help
indent
image
kotlin-mode
outline
replace
shortdoc
simple
slime
lispy)
"A list of `evil-collection' modules to ignore. See the definition of this
variable for an explanation of the defaults (in comments). See
`evil-collection-mode-list' for a list of available options.")
(defvar evil-collection-setup-minibuffer nil)
;; We do this ourselves, and better.
(defvar evil-collection-want-unimpaired-p nil)
;; Doom binds goto-reference on gD and goto-assignments on gA ourselves
(defvar evil-collection-want-find-usages-bindings-p nil)
;; Reduces keybind conflicts between outline-mode and org-mode (which is
;; derived from outline-mode).
(defvar evil-collection-outline-enable-in-minor-mode-p nil)
;; We handle loading evil-collection ourselves
(defvar evil-collection--supported-modes nil)
;; This has to be defined here since evil-collection doesn't autoload its own.
;; It must be updated whenever evil-collection updates theirs. Here's an easy
;; way to update it:
;;
;; (with-current-buffer
;; (url-retrieve-synchronously "https://raw.githubusercontent.com/emacs-evil/evil-collection/master/evil-collection.el" t t)
;; (goto-char (point-min))
;; (when (re-search-forward "^(defvar evil-collection--supported-modes\n[^(]+")
;; (let ((list (sexp-at-point)))
;; ;; Fixes
;; (when (assq 'pdf list)
;; (setf (alist-get 'pdf list) '(pdf-tools)))
;; (let ((diff (cl-set-difference evil-collection-mode-list list :test #'equal)))
;; (list (- (length list) (length evil-collection-mode-list))
;; diff)
;; (message "diff: %s" diff)
;; (kill-new (prin1-to-string list))))))
(defvar evil-collection-mode-list
`(2048-game
ag
alchemist
anaconda-mode
apropos
arc-mode
atomic-chrome
auto-package-update
beginend
bm
bookmark
(buff-menu "buff-menu")
calc
calendar
cider
cmake-mode
comint
company
compile
consult
corfu
(custom cus-edit)
cus-theme
daemons
dashboard
deadgrep
debbugs
debug
devdocs
dictionary
diff-hl
diff-mode
dired
dired-sidebar
disk-usage
doc-view
docker
ebib
ebuku
edbi
edebug
ediff
eglot
explain-pause-mode
elfeed
eldoc
elisp-mode
elisp-refs
elisp-slime-nav
embark
emms
,@(if (> emacs-major-version 28) '(emoji))
epa
ert
eshell
eval-sexp-fu
evil-mc
eww
fanyi
finder
flycheck
flymake
forge
free-keys
geiser
ggtags
git-timemachine
gnus
go-mode
grep
guix
hackernews
helm
help
helpful
hg-histedit
hungry-delete
ibuffer
image
image-dired
image+
imenu
imenu-list
(indent "indent")
indium
info
ivy
js2-mode
leetcode
lispy
log-edit
log-view
lsp-ui-imenu
lua-mode
kotlin-mode
macrostep
man
(magit magit-repos magit-submodule)
magit-section
magit-todos
markdown-mode
monky
mpc
mu4e
mu4e-conversation
neotree
newsticker
notmuch
nov
omnisharp
org
org-present
org-roam
osx-dictionary
outline
p4
(package-menu package)
pass
(pdf pdf-tools)
popup
proced
prodigy
profiler
python
quickrun
racer
racket-describe
realgud
reftex
replace
restclient
rg
ripgrep
rjsx-mode
robe
rtags
ruby-mode
scheme
scroll-lock
selectrum
sh-script
,@(if (> emacs-major-version 27) '(shortdoc))
simple
simple-mpc
slime
sly
snake
so-long
speedbar
tablist
tar-mode
telega
(term term ansi-term multi-term)
tetris
thread
tide
timer-list
transmission
trashed
tuareg
typescript-mode
vc-annotate
vc-dir
vc-git
vdiff
vertico
view
vlf
vterm
vundo
w3m
wdired
wgrep
which-key
woman
xref
xwidget
yaml-mode
youtube-dl
zmusic
(ztree ztree-diff)))
(defun +evil-collection-init (module &optional disabled-list)
"Initialize evil-collection-MODULE.
Unlike `evil-collection-init', this respects `+evil-collection-disabled-list',
and complains if a module is loaded too early (during startup)."
(unless (memq (or (car-safe module) module) disabled-list)
(doom-log "Initialized evil-collection-%s %s"
(or (car-safe module) module)
(if doom-init-time "" "(too early!)"))
(with-demoted-errors "evil-collection error: %s"
(evil-collection-init (list module)))))
(defadvice! +evil-collection-disable-blacklist-a (fn)
:around #'evil-collection-vterm-toggle-send-escape ; allow binding to ESC
(let (evil-collection-key-blacklist)
(funcall-interactively fn)))
;; These modes belong to packages that Emacs always loads at startup, causing
;; evil-collection and it's co-packages to all load immediately. We avoid this
;; by loading them after evil-collection has first loaded...
(with-eval-after-load 'evil-collection
;; Don't let evil-collection interfere with certain keys
(setq evil-collection-key-blacklist
(append (list doom-leader-key doom-localleader-key
doom-leader-alt-key)
evil-collection-key-blacklist
(when (modulep! :tools lookup)
'("gd" "gf" "K"))
(when (modulep! :tools eval)
'("gr" "gR"))
'("[" "]" "gz" "<escape>")))
(evil-define-key* 'normal process-menu-mode-map
"q" #'kill-current-buffer
"d" #'process-menu-delete-process)
(mapc #'+evil-collection-init '(comint custom)))
;; ...or on first invokation of their associated major/minor modes.
(after! evil
;; Emacs loads these two packages immediately, at startup, which needlessly
;; convolutes load order for evil-collection-help.
(add-transient-hook! 'help-mode
(+evil-collection-init 'help))
(add-transient-hook! 'Buffer-menu-mode
(+evil-collection-init '(buff-menu "buff-menu")))
(add-transient-hook! 'calc-mode
(+evil-collection-init 'calc))
(add-transient-hook! 'image-mode
(+evil-collection-init 'image))
(add-transient-hook! 'emacs-lisp-mode
(+evil-collection-init 'elisp-mode))
(add-transient-hook! 'occur-mode
(+evil-collection-init 'replace))
(add-transient-hook! 'indent-rigidly
(+evil-collection-init '(indent "indent")))
(add-transient-hook! 'minibuffer-setup-hook
(when evil-collection-setup-minibuffer
(+evil-collection-init 'minibuffer)
(evil-collection-minibuffer-insert)))
(add-transient-hook! 'process-menu-mode
(+evil-collection-init '(process-menu simple)))
(add-transient-hook! 'shortdoc-mode
(+evil-collection-init 'shortdoc))
(add-transient-hook! 'tabulated-list-mode
(+evil-collection-init 'tabulated-list))
(add-transient-hook! 'tab-bar-mode
(+evil-collection-init 'tab-bar))
;; HACK Do this ourselves because evil-collection break's `eval-after-load'
;; load order by loading their target plugin before applying keys. This
;; makes it hard for end-users to overwrite these keybinds with a
;; simple `after!' or `with-eval-after-load'.
(dolist (mode evil-collection-mode-list)
(dolist (req (or (cdr-safe mode) (list mode)))
(with-eval-after-load req
(+evil-collection-init mode +evil-collection-disabled-list))))))