mirror of
https://github.com/doomemacs/doomemacs
synced 2025-08-17 13:33:36 -05:00
BREAKING CHANGE: This backports some architectural choices from v3.0. This changes Doom's module API, renaming some functions and removing others, in order to facilitate some new features, prepare to move Doom's modules into separate repos, and make way for two, much larger breaking commits coming in the next few days. This commit won't break anything for users unless they're tinkering with Doom's internals/using its `doom-module-*` API directly. I am avoiding broader backwards incompatibilities until the 3.0 release. What's new: - Negated flags. (modulep! :editor evil -everywhere) will return non-nil if :editor evil is active without its +everywhere flag. - `modulep!` now takes multiple flags to simplify AND checks. E.g. (and (modulep! +foo) (modulep! +bar) (not (modulep! +baz))) Can now be expressed with: (modulep! +foo +bar -baz) - Adds pcase matchers for `doom-module-context` and `doom-module` structs, making the following destructuring binds possible: (pcase-dolist ((doom-module group name flags features) (hash-table-values doom-modules)) ...) This will be used more in v3.0. - Adds file cookie support to module init.el and config.el files. Here's a summary of breaking changes made in this commit: - `doom-module-context` was changed from a vector to a struct (record). - `doom-modules` is now a table of `doom-module` structs, rather than free-form plists. - The following macros have been renamed: - `doom-context-with` -> `with-doom-context` - `doom-module-context-with` -> `with-doom-module` - The followings functions have been replaced/removed: - `doom-module-context`+`doom-module-context-get` -> `doom-module` - `doom-module-set` -> `doom-module--put` - `doom-module-p` -> `doom-module-active-p` - `doom-module-context-key` (is now a getter with the same name) - `doom-module-put` (removed) - `doom-module--context-field` (removed) - The signatures for these functions have changed: - `doom-module-get CATEGORY &optional MODULE PROP` -> `doom-module-get (GROUP . MODULE) &optional PROP` - `doom-module-locate-path CATEGORY &optional MODULE FILE` -> `doom-module-locate-path (GROUP . MODULE) &optional FILE` - `doom-module-expand-path CATEGORY MODULE &optional FILE` -> `doom-module-expand-path (GROUP . MODULE) &optional FILE` - Adds the following functions - `doom-module-exists-p` - `doom-module-key` - `doom-module->context` - `doom-module<-context` - Removes the following variables - `doom-module--empty-context` This commit results in a little redundancy, which I will address in parts 2/3 and/or v3.0.
369 lines
9.9 KiB
EmacsLisp
369 lines
9.9 KiB
EmacsLisp
;;; editor/evil/init.el -*- lexical-binding: t; -*-
|
|
;;;###if (modulep! +everywhere)
|
|
|
|
(defvar evil-collection-key-blacklist)
|
|
|
|
;; must be set before evil/evil-collection is loaded
|
|
(defvar evil-want-keybinding nil)
|
|
|
|
;; 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).
|
|
|
|
(unless (or noninteractive (doom-context-p 'reload))
|
|
|
|
(setq evil-collection-company-use-tng (modulep! :completion company +tng))
|
|
|
|
(defvar +evil-collection-disabled-list
|
|
'(anaconda-mode
|
|
buff-menu
|
|
calc
|
|
comint
|
|
company
|
|
custom
|
|
eldoc
|
|
elisp-mode
|
|
ert
|
|
free-keys
|
|
helm
|
|
help
|
|
image
|
|
indent
|
|
kmacro
|
|
kotlin-mode
|
|
lispy
|
|
outline
|
|
replace
|
|
shortdoc
|
|
simple
|
|
slime
|
|
tab-bar)
|
|
"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
|
|
bluetooth
|
|
bm
|
|
bookmark
|
|
(buff-menu "buff-menu")
|
|
bufler
|
|
calc
|
|
calendar
|
|
cider
|
|
cmake-mode
|
|
color-rg
|
|
comint
|
|
company
|
|
compile
|
|
consult
|
|
corfu
|
|
crdt
|
|
(csv "csv-mode")
|
|
(custom cus-edit)
|
|
cus-theme
|
|
dape
|
|
dashboard
|
|
daemons
|
|
deadgrep
|
|
debbugs
|
|
debug
|
|
devdocs
|
|
dictionary
|
|
diff-hl
|
|
diff-mode
|
|
dired
|
|
dired-sidebar
|
|
disk-usage
|
|
distel
|
|
doc-view
|
|
docker
|
|
eat
|
|
ebib
|
|
ebuku
|
|
edbi
|
|
edebug
|
|
ediff
|
|
eglot
|
|
elpaca
|
|
ement
|
|
explain-pause-mode
|
|
eldoc
|
|
elfeed
|
|
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
|
|
gited
|
|
gnus
|
|
go-mode
|
|
grep
|
|
guix
|
|
hackernews
|
|
helm
|
|
help
|
|
helpful
|
|
hg-histedit
|
|
hungry-delete
|
|
hyrolo
|
|
ibuffer
|
|
(image image-mode)
|
|
image-dired
|
|
image+
|
|
imenu
|
|
imenu-list
|
|
(indent "indent")
|
|
indium
|
|
info
|
|
ivy
|
|
js2-mode
|
|
,@(if (>= emacs-major-version 30) '(kmacro))
|
|
leetcode
|
|
lispy
|
|
lms
|
|
log-edit
|
|
log-view
|
|
lsp-ui-imenu
|
|
lua-mode
|
|
kotlin-mode
|
|
macrostep
|
|
man
|
|
(magit magit-repos magit-submodule)
|
|
magit-repos
|
|
magit-section
|
|
magit-todos
|
|
markdown-mode
|
|
monky
|
|
mpc
|
|
mpdel
|
|
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
|
|
tab-bar
|
|
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 "editor:evil: loading evil-collection-%s %s"
|
|
(or (car-safe module) module)
|
|
(if after-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")))
|
|
(when (>= emacs-major-version 30)
|
|
(add-transient-hook! 'kmacro-menu-mode
|
|
(+evil-collection-init 'kmacro)))
|
|
(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))))))
|