2017-11-07 11:04:12 +01:00
|
|
|
;;; evil-collection.el --- A set of keybindings for Evil mode -*- lexical-binding: t -*-
|
2017-11-05 17:05:46 +01:00
|
|
|
|
2023-08-28 17:29:53 +02:00
|
|
|
;; Copyright (C) 2017, 2023 James Nguyen
|
2017-11-05 17:05:46 +01:00
|
|
|
|
2017-11-07 11:04:12 +01:00
|
|
|
;; Author: James Nguyen <james@jojojames.com>
|
2018-08-27 10:41:51 +02:00
|
|
|
;; Pierre Neidhardt <mail@ambrevar.xyz>
|
2017-11-07 11:04:12 +01:00
|
|
|
;; Maintainer: James Nguyen <james@jojojames.com>
|
2018-08-27 10:41:51 +02:00
|
|
|
;; Pierre Neidhardt <mail@ambrevar.xyz>
|
2018-03-02 02:22:38 +01:00
|
|
|
;; URL: https://github.com/emacs-evil/evil-collection
|
2018-09-12 18:22:09 +02:00
|
|
|
;; Version: 0.0.2
|
2022-06-07 02:53:16 +02:00
|
|
|
;; Package-Requires: ((emacs "26.3") (evil "1.2.13") (annalist "1.0"))
|
2017-11-07 11:04:12 +01:00
|
|
|
;; Keywords: evil, tools
|
2017-11-05 17:05:46 +01:00
|
|
|
|
|
|
|
;; This program is free software; you can redistribute it and/or modify
|
|
|
|
;; it under the terms of the GNU General Public License as published by
|
|
|
|
;; the Free Software Foundation, either version 3 of the License, or
|
|
|
|
;; (at your option) any later version.
|
|
|
|
|
|
|
|
;; This program is distributed in the hope that it will be useful,
|
|
|
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
;; GNU General Public License for more details.
|
|
|
|
|
|
|
|
;; You should have received a copy of the GNU General Public License
|
|
|
|
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
;;; Commentary:
|
2017-11-06 15:12:40 +01:00
|
|
|
;; A set of keybindings for Evil mode.
|
|
|
|
;;
|
2017-12-07 12:20:36 +01:00
|
|
|
;; If you want to use Evil in the minibuffer, you'll have to enable it by
|
|
|
|
;; setting `evil-collection-setup-minibuffer' to t before loading this package.
|
2017-11-06 15:12:40 +01:00
|
|
|
;; This is so because many users find it confusing.
|
2018-06-11 08:18:54 +02:00
|
|
|
;; Some minibuffer-related packages such as Helm rely on this option.
|
2017-11-05 17:05:46 +01:00
|
|
|
|
|
|
|
;;; Code:
|
2022-06-01 00:33:18 +02:00
|
|
|
|
|
|
|
;; `evil' requires `seq-into'?
|
|
|
|
;; This require on `seq' before loading `evil 'prevents `evil' from erroring
|
|
|
|
;; out with the below message on Emacs 29.
|
|
|
|
;; Symbol's function definition is void: seq-into
|
|
|
|
;; Looks like this error can be traced through evil ->
|
|
|
|
;; Look at the commit that moved this line above `evil' to see the error message.
|
|
|
|
;; evil -> evil-vars -> read-kbd-macro -> seq-into -> error.
|
2022-06-01 01:28:16 +02:00
|
|
|
;; https://github.com/emacs-evil/evil/issues/1627
|
2022-06-01 00:33:18 +02:00
|
|
|
(require 'seq)
|
2017-12-18 04:26:31 +01:00
|
|
|
(require 'cl-lib)
|
2017-12-29 05:31:45 +01:00
|
|
|
(require 'evil)
|
2019-07-30 03:12:58 +02:00
|
|
|
(require 'annalist)
|
2018-01-06 20:25:33 +01:00
|
|
|
|
2018-07-12 21:05:50 +02:00
|
|
|
(defvar evil-collection-base-dir (file-name-directory load-file-name)
|
|
|
|
"Store the directory evil-collection.el was loaded from.")
|
|
|
|
|
2018-01-10 03:58:46 +01:00
|
|
|
(defvar evil-want-integration)
|
2018-09-12 02:49:49 +02:00
|
|
|
(defvar evil-want-keybinding)
|
2018-09-12 18:37:58 +02:00
|
|
|
(if (featurep 'evil-keybindings)
|
2018-09-12 02:49:49 +02:00
|
|
|
(if evil-want-keybinding
|
2018-01-07 20:04:27 +01:00
|
|
|
(display-warning
|
|
|
|
'(evil-collection)
|
2018-09-12 02:49:49 +02:00
|
|
|
"Make sure to set `evil-want-keybinding' to nil before loading evil \
|
|
|
|
or evil-collection.\
|
|
|
|
\n
|
2018-09-13 02:56:35 +02:00
|
|
|
See https://github.com/emacs-evil/evil-collection/issues/60 for more details.")
|
2018-01-07 20:04:27 +01:00
|
|
|
(display-warning
|
|
|
|
'(evil-collection)
|
2018-09-12 02:49:49 +02:00
|
|
|
"`evil-want-keybinding' was set to nil but not before loading evil.\
|
|
|
|
\n
|
|
|
|
Make sure to set `evil-want-keybinding' to nil before loading evil \
|
|
|
|
or evil-collection.\
|
|
|
|
\n
|
|
|
|
See https://github.com/emacs-evil/evil-collection/issues/60 for more details.")))
|
|
|
|
|
|
|
|
(unless (featurep 'evil-integration)
|
|
|
|
(message "Requiring evil-integration. Set evil-want-integration to t to\
|
|
|
|
remove this message.\
|
|
|
|
\n
|
|
|
|
See https://github.com/emacs-evil/evil-collection/issues/60 for more details.")
|
|
|
|
(require 'evil-integration))
|
2017-12-29 05:31:45 +01:00
|
|
|
|
2017-12-06 17:06:27 +01:00
|
|
|
(defgroup evil-collection nil
|
2021-09-18 01:07:07 +02:00
|
|
|
"A set of keybindings for Evil mode."
|
2017-12-06 17:06:27 +01:00
|
|
|
:group 'evil)
|
|
|
|
|
2017-12-07 12:20:36 +01:00
|
|
|
(defcustom evil-collection-setup-minibuffer nil
|
2017-12-07 19:55:13 +01:00
|
|
|
"Whether to setup Evil bindings in the minibuffer."
|
2017-12-07 12:20:36 +01:00
|
|
|
:type 'boolean
|
|
|
|
:group 'evil-collection)
|
|
|
|
|
2020-06-16 10:36:45 +02:00
|
|
|
(defcustom evil-collection-calendar-want-org-bindings nil
|
|
|
|
"Whether to bind Org functions in calendar keymap."
|
|
|
|
:type 'boolean
|
|
|
|
:group 'evil-collection)
|
|
|
|
|
2019-05-03 03:36:16 +02:00
|
|
|
(defcustom evil-collection-setup-debugger-keys t
|
|
|
|
"Whether to bind debugger keys when debugger is active.
|
|
|
|
|
|
|
|
Debugger in this case is dependent on mode.
|
|
|
|
|
|
|
|
This is only relevant for debug modes that are part of another mode,
|
|
|
|
|
|
|
|
e.g. `indium'. Modes like `edebug' or `realgud' needs to be explicitly disabled
|
|
|
|
|
|
|
|
through removing their entry from `evil-collection-mode-list'."
|
|
|
|
:type 'boolean
|
|
|
|
:group 'evil-collection)
|
|
|
|
|
2019-06-18 03:36:54 +02:00
|
|
|
(defcustom evil-collection-want-unimpaired-p t
|
|
|
|
"Whether to enable unimpaired style bindings globally."
|
|
|
|
:type 'boolean
|
|
|
|
:group 'evil-collection)
|
|
|
|
|
2021-02-03 20:47:59 +01:00
|
|
|
(defcustom evil-collection-want-find-usages-bindings t
|
|
|
|
"Whether to bind `xref-find-references'-like bindings.
|
|
|
|
|
|
|
|
This will bind additional find-* type commands, e.g. usages, assignments, etc.."
|
|
|
|
:type 'boolean
|
|
|
|
:group 'evil-collection)
|
|
|
|
|
2022-04-14 23:42:59 +02:00
|
|
|
(defvar evil-collection--modes-with-delayed-setup
|
2022-04-15 21:36:53 +02:00
|
|
|
`(emms
|
|
|
|
eshell)
|
2022-04-14 23:42:59 +02:00
|
|
|
"List of modes whose keybinds aren't completely set up after the mode is
|
|
|
|
loaded. This can be a problem for cases where we're doing key translations
|
|
|
|
using `evil-collection-setup-hook' which would result in an empty keymap.
|
|
|
|
|
|
|
|
Normally we run `evil-collection-setup-hook' right away after the mode
|
|
|
|
is loaded in `with-eval-after-load' (see `evil-collection-init') but for these
|
|
|
|
modes, we skip running that hook and let the corresponding `evil-collection'
|
|
|
|
package handle running `evil-collection-setup-hook'.
|
|
|
|
|
|
|
|
Elements in this list either match a target mode symbol or the car of a list in
|
|
|
|
`evil-collection--supported-modes'.
|
|
|
|
|
|
|
|
If `evil-collection-always-run-setup-hook-after-load' is t, this list isn't
|
|
|
|
read and `evil-collection-setup-hook' will be ran in the
|
|
|
|
`with-eval-after-load' block in `evil-collection-init'.")
|
|
|
|
|
|
|
|
(defcustom evil-collection-always-run-setup-hook-after-load nil
|
|
|
|
"Whether to always run `evil-collection-setup-hook' after mode is loaded.
|
|
|
|
|
|
|
|
See `evil-collection-init' and `evil-collection--modes-with-delayed-setup'."
|
|
|
|
:type 'boolean
|
|
|
|
:group 'evil-collection)
|
|
|
|
|
2019-09-23 16:37:08 +02:00
|
|
|
(defvar evil-collection--supported-modes
|
2019-05-30 02:09:33 +02:00
|
|
|
`(2048-game
|
|
|
|
ag
|
2017-11-27 08:47:23 +01:00
|
|
|
alchemist
|
2017-11-12 02:08:06 +01:00
|
|
|
anaconda-mode
|
2019-09-10 12:27:38 +02:00
|
|
|
apropos
|
2017-11-08 03:34:48 +01:00
|
|
|
arc-mode
|
2022-02-28 00:05:43 +01:00
|
|
|
atomic-chrome
|
2020-05-26 06:13:58 +02:00
|
|
|
auto-package-update
|
2021-09-12 06:52:46 +02:00
|
|
|
beginend
|
2022-06-12 04:56:53 +02:00
|
|
|
bluetooth
|
2020-05-10 18:23:28 +02:00
|
|
|
bm
|
2017-11-06 15:12:40 +01:00
|
|
|
bookmark
|
2018-01-28 00:47:44 +01:00
|
|
|
(buff-menu "buff-menu")
|
2023-12-15 11:58:42 +01:00
|
|
|
bufler
|
2018-02-23 17:51:52 +01:00
|
|
|
calc
|
2017-11-06 15:12:40 +01:00
|
|
|
calendar
|
|
|
|
cider
|
2018-01-20 21:47:52 +01:00
|
|
|
cmake-mode
|
2023-02-14 19:00:55 +01:00
|
|
|
color-rg
|
2017-11-12 20:16:09 +01:00
|
|
|
comint
|
2017-11-11 22:58:26 +01:00
|
|
|
company
|
2017-11-06 15:12:40 +01:00
|
|
|
compile
|
2020-12-06 02:07:27 +01:00
|
|
|
consult
|
2022-04-14 04:50:36 +02:00
|
|
|
corfu
|
2022-09-26 19:28:43 +02:00
|
|
|
crdt
|
2019-10-10 15:19:25 +02:00
|
|
|
(custom cus-edit)
|
2017-11-12 01:39:42 +01:00
|
|
|
cus-theme
|
2020-02-14 19:00:46 +01:00
|
|
|
dashboard
|
2018-03-18 05:28:43 +01:00
|
|
|
daemons
|
2018-07-21 19:22:34 +02:00
|
|
|
deadgrep
|
2017-11-06 17:51:24 +01:00
|
|
|
debbugs
|
2017-11-07 11:33:23 +01:00
|
|
|
debug
|
2021-06-07 21:54:44 +02:00
|
|
|
devdocs
|
2020-12-04 03:26:51 +01:00
|
|
|
dictionary
|
2021-09-23 17:21:31 +02:00
|
|
|
diff-hl
|
2017-11-06 15:12:40 +01:00
|
|
|
diff-mode
|
|
|
|
dired
|
2019-10-17 06:57:59 +02:00
|
|
|
dired-sidebar
|
2019-02-19 09:39:21 +01:00
|
|
|
disk-usage
|
2021-02-03 21:19:16 +01:00
|
|
|
distel
|
2017-11-07 07:17:14 +01:00
|
|
|
doc-view
|
2019-09-21 12:42:06 +02:00
|
|
|
docker
|
2018-12-05 15:57:09 +01:00
|
|
|
ebib
|
2022-05-13 04:16:32 +02:00
|
|
|
ebuku
|
2019-02-12 19:14:52 +01:00
|
|
|
edbi
|
2017-11-06 15:12:40 +01:00
|
|
|
edebug
|
2018-06-01 19:31:33 +02:00
|
|
|
ediff
|
2018-08-22 04:14:35 +02:00
|
|
|
eglot
|
2023-03-09 05:57:06 +01:00
|
|
|
elpaca
|
2023-06-01 02:50:21 +02:00
|
|
|
ement
|
2020-06-25 17:34:14 +02:00
|
|
|
explain-pause-mode
|
2022-04-13 17:27:03 +02:00
|
|
|
eldoc
|
2017-11-06 17:52:14 +01:00
|
|
|
elfeed
|
2017-11-14 19:06:39 +01:00
|
|
|
elisp-mode
|
2017-11-09 05:44:06 +01:00
|
|
|
elisp-refs
|
2019-05-26 19:34:51 +02:00
|
|
|
elisp-slime-nav
|
2021-04-22 11:36:21 +02:00
|
|
|
embark
|
2017-11-06 17:52:22 +01:00
|
|
|
emms
|
2021-12-19 16:27:54 +01:00
|
|
|
,@(when (>= emacs-major-version 29) '(emoji))
|
2018-02-01 16:54:26 +01:00
|
|
|
epa
|
2018-03-31 04:11:13 +02:00
|
|
|
ert
|
2017-11-06 15:12:40 +01:00
|
|
|
eshell
|
2017-11-29 04:14:43 +01:00
|
|
|
eval-sexp-fu
|
2018-09-13 04:09:04 +02:00
|
|
|
evil-mc
|
2017-12-13 14:34:51 +01:00
|
|
|
eww
|
2021-08-10 19:15:48 +02:00
|
|
|
fanyi
|
2020-08-23 17:28:23 +02:00
|
|
|
finder
|
2017-11-06 15:12:40 +01:00
|
|
|
flycheck
|
2018-09-12 05:51:02 +02:00
|
|
|
flymake
|
2021-11-07 19:31:41 +01:00
|
|
|
forge
|
2018-01-28 21:13:55 +01:00
|
|
|
free-keys
|
2017-11-28 08:28:47 +01:00
|
|
|
geiser
|
2017-11-06 15:12:40 +01:00
|
|
|
ggtags
|
2018-04-21 20:27:57 +02:00
|
|
|
git-timemachine
|
2022-11-26 06:19:25 +01:00
|
|
|
gited
|
2019-11-02 15:30:37 +01:00
|
|
|
gnus
|
2018-01-19 23:42:01 +01:00
|
|
|
go-mode
|
2018-07-12 09:37:17 +02:00
|
|
|
grep
|
2018-04-03 10:41:22 +02:00
|
|
|
guix
|
2018-10-17 11:57:13 +02:00
|
|
|
hackernews
|
2017-11-06 17:52:31 +01:00
|
|
|
helm
|
2018-12-18 09:20:43 +01:00
|
|
|
help
|
|
|
|
helpful
|
2019-07-07 02:11:42 +02:00
|
|
|
hg-histedit
|
2019-05-26 04:06:33 +02:00
|
|
|
hungry-delete
|
2017-11-06 15:12:40 +01:00
|
|
|
ibuffer
|
2023-08-28 17:54:33 +02:00
|
|
|
(image image-mode)
|
2018-08-13 15:39:13 +02:00
|
|
|
image-dired
|
2017-11-06 17:52:38 +01:00
|
|
|
image+
|
2020-05-05 17:23:45 +02:00
|
|
|
imenu
|
2018-07-12 12:17:45 +02:00
|
|
|
imenu-list
|
2020-10-14 20:51:52 +02:00
|
|
|
(indent "indent")
|
2017-12-24 19:40:26 +01:00
|
|
|
indium
|
2017-11-06 15:12:40 +01:00
|
|
|
info
|
|
|
|
ivy
|
2018-02-19 04:28:27 +01:00
|
|
|
js2-mode
|
2019-06-10 01:59:12 +02:00
|
|
|
leetcode
|
2019-10-20 19:16:55 +02:00
|
|
|
lispy
|
2021-10-07 23:44:31 +02:00
|
|
|
lms
|
2019-05-18 21:36:27 +02:00
|
|
|
log-edit
|
2018-01-23 07:15:41 +01:00
|
|
|
log-view
|
2018-04-21 20:10:23 +02:00
|
|
|
lsp-ui-imenu
|
2018-01-06 18:48:43 +01:00
|
|
|
lua-mode
|
2017-12-24 19:30:45 +01:00
|
|
|
kotlin-mode
|
2017-11-06 15:12:40 +01:00
|
|
|
macrostep
|
|
|
|
man
|
2022-04-14 17:16:29 +02:00
|
|
|
(magit magit-repos magit-submodule)
|
2022-04-28 18:48:07 +02:00
|
|
|
magit-section
|
2018-07-12 16:49:36 +02:00
|
|
|
magit-todos
|
2021-08-16 12:10:55 +02:00
|
|
|
markdown-mode
|
2017-12-07 12:20:36 +01:00
|
|
|
,@(when evil-collection-setup-minibuffer '(minibuffer))
|
2019-06-09 23:25:04 +02:00
|
|
|
monky
|
2022-01-13 17:56:58 +01:00
|
|
|
mpc
|
2021-01-03 02:43:14 +01:00
|
|
|
mpdel
|
2024-03-19 12:38:32 +01:00
|
|
|
mpdired
|
2018-06-16 19:09:01 +02:00
|
|
|
mu4e
|
2018-06-19 18:36:28 +02:00
|
|
|
mu4e-conversation
|
2018-01-31 14:49:19 +01:00
|
|
|
neotree
|
2020-09-17 18:23:05 +02:00
|
|
|
newsticker
|
2017-12-22 07:45:39 +01:00
|
|
|
notmuch
|
2018-01-14 20:30:26 +01:00
|
|
|
nov
|
2019-03-15 22:50:57 +01:00
|
|
|
omnisharp
|
2021-10-28 20:51:05 +02:00
|
|
|
org
|
2020-09-07 13:03:45 +02:00
|
|
|
org-present
|
2022-04-28 18:48:43 +02:00
|
|
|
org-roam
|
2020-08-04 17:58:43 +02:00
|
|
|
osx-dictionary
|
2017-11-06 15:12:40 +01:00
|
|
|
outline
|
|
|
|
p4
|
|
|
|
(package-menu package)
|
|
|
|
pass
|
2017-11-06 17:53:22 +01:00
|
|
|
(pdf pdf-view)
|
2018-01-20 09:37:48 +01:00
|
|
|
popup
|
2017-11-06 15:12:40 +01:00
|
|
|
proced
|
2020-06-16 02:44:40 +02:00
|
|
|
(process-menu simple)
|
2017-11-06 15:12:40 +01:00
|
|
|
prodigy
|
|
|
|
profiler
|
2017-12-13 04:31:20 +01:00
|
|
|
python
|
2018-01-19 23:41:42 +01:00
|
|
|
quickrun
|
2017-12-24 20:09:25 +01:00
|
|
|
racer
|
2020-11-17 01:32:57 +01:00
|
|
|
racket-describe
|
2018-01-12 04:26:08 +01:00
|
|
|
realgud
|
2018-01-26 18:38:26 +01:00
|
|
|
reftex
|
2022-06-07 03:05:36 +02:00
|
|
|
replace ;; For `occur'.
|
2018-09-28 03:14:34 +02:00
|
|
|
restclient
|
2020-09-05 14:36:27 +02:00
|
|
|
rg
|
2020-12-08 22:09:53 +01:00
|
|
|
ripgrep
|
2017-12-24 19:51:55 +01:00
|
|
|
rjsx-mode
|
2017-12-13 06:45:23 +01:00
|
|
|
robe
|
2017-11-28 09:04:18 +01:00
|
|
|
rtags
|
2019-09-23 15:42:41 +02:00
|
|
|
ruby-mode
|
2021-11-14 07:56:45 +01:00
|
|
|
scheme
|
2021-01-24 09:56:41 +01:00
|
|
|
scroll-lock
|
2021-09-11 18:28:15 +02:00
|
|
|
selectrum
|
2020-12-03 17:00:58 +01:00
|
|
|
sh-script
|
2020-11-14 21:03:47 +01:00
|
|
|
,@(when (>= emacs-major-version 28) '(shortdoc))
|
2018-01-30 02:45:42 +01:00
|
|
|
simple
|
2022-02-08 13:12:35 +01:00
|
|
|
simple-mpc
|
2017-11-06 15:12:40 +01:00
|
|
|
slime
|
2019-10-10 18:21:01 +02:00
|
|
|
sly
|
2022-06-06 07:51:18 +02:00
|
|
|
snake
|
2022-06-16 03:05:50 +02:00
|
|
|
so-long
|
2020-05-31 23:32:06 +02:00
|
|
|
speedbar
|
2020-08-12 18:22:29 +02:00
|
|
|
,@(when (>= emacs-major-version 27) '(tab-bar))
|
2019-09-23 10:44:12 +02:00
|
|
|
tablist
|
2020-08-31 22:52:07 +02:00
|
|
|
tabulated-list
|
2019-12-01 16:49:26 +01:00
|
|
|
tar-mode
|
2021-06-14 12:48:44 +02:00
|
|
|
telega
|
2017-11-06 15:12:40 +01:00
|
|
|
(term term ansi-term multi-term)
|
2018-12-06 12:15:55 +01:00
|
|
|
tetris
|
2020-09-27 18:47:36 +02:00
|
|
|
,@(when (>= emacs-major-version 27) '(thread))
|
2017-11-11 23:51:25 +01:00
|
|
|
tide
|
2020-09-27 18:47:36 +02:00
|
|
|
timer-list
|
2017-11-06 17:53:33 +01:00
|
|
|
transmission
|
2020-04-28 11:32:27 +02:00
|
|
|
trashed
|
2021-07-09 21:51:10 +02:00
|
|
|
tuareg
|
2017-12-24 19:51:45 +01:00
|
|
|
typescript-mode
|
2018-01-23 07:15:32 +01:00
|
|
|
vc-annotate
|
2018-08-30 07:00:04 +02:00
|
|
|
vc-dir
|
|
|
|
vc-git
|
2018-02-15 13:08:41 +01:00
|
|
|
vdiff
|
2021-10-07 00:45:13 +02:00
|
|
|
vertico
|
2018-03-03 16:52:16 +01:00
|
|
|
view
|
2017-11-06 15:12:40 +01:00
|
|
|
vlf
|
2019-05-21 02:24:36 +02:00
|
|
|
vterm
|
2022-04-14 17:00:51 +02:00
|
|
|
vundo
|
2018-11-09 11:56:10 +01:00
|
|
|
w3m
|
2018-03-31 04:11:19 +02:00
|
|
|
wdired
|
2018-03-31 04:11:17 +02:00
|
|
|
wgrep
|
2018-11-09 11:56:10 +01:00
|
|
|
which-key
|
2017-11-06 15:12:40 +01:00
|
|
|
woman
|
2017-11-06 17:53:44 +01:00
|
|
|
xref
|
2021-10-23 17:51:40 +02:00
|
|
|
xwidget
|
2021-09-15 20:28:01 +02:00
|
|
|
yaml-mode
|
2018-09-12 12:09:34 +02:00
|
|
|
youtube-dl
|
2021-10-23 17:51:40 +02:00
|
|
|
zmusic
|
2021-12-20 10:33:19 +01:00
|
|
|
(ztree ztree-diff ztree-dir))
|
2019-09-23 16:37:08 +02:00
|
|
|
"List of modes supported by evil-collection. Elements are
|
|
|
|
either target mode symbols or lists which `car' is the mode
|
|
|
|
symbol and `cdr' the packages to register.")
|
|
|
|
|
2019-10-20 19:16:55 +02:00
|
|
|
(dolist (mode evil-collection--supported-modes)
|
2019-09-23 16:37:08 +02:00
|
|
|
(let ((ec-mode-name (if (listp mode) (car mode) mode)))
|
|
|
|
(autoload
|
|
|
|
(intern (format "evil-collection-%s-setup" ec-mode-name))
|
|
|
|
(expand-file-name
|
|
|
|
(format "modes/%s/evil-collection-%s" ec-mode-name ec-mode-name)
|
|
|
|
evil-collection-base-dir))))
|
|
|
|
|
|
|
|
(defcustom evil-collection-mode-list evil-collection--supported-modes
|
2017-11-06 15:12:40 +01:00
|
|
|
"The list of modes which will be evilified by `evil-collection-init'.
|
|
|
|
Elements are either target mode symbols or lists which `car' is the
|
|
|
|
mode symbol and `cdr' the packages to register.
|
|
|
|
|
|
|
|
By default, `minibuffer' is not included because many users find
|
2017-12-07 12:20:36 +01:00
|
|
|
this confusing. It will be included if
|
|
|
|
`evil-collection-setup-minibuffer' is set to t."
|
2017-12-06 17:06:27 +01:00
|
|
|
:type '(repeat (choice symbol sexp))
|
|
|
|
:group 'evil-collection)
|
2017-11-05 17:05:46 +01:00
|
|
|
|
2022-06-06 07:53:34 +02:00
|
|
|
(defcustom evil-collection-config
|
2022-06-06 17:12:57 +02:00
|
|
|
'((buff-menu :defer t)
|
2022-06-06 07:53:34 +02:00
|
|
|
(calc :defer t)
|
|
|
|
(comint :defer t)
|
|
|
|
(debug :defer t)
|
|
|
|
(diff-mode :defer t)
|
|
|
|
(dired :defer t)
|
|
|
|
(edebug :defer t)
|
|
|
|
(eldoc :defer t)
|
|
|
|
(help :defer t)
|
|
|
|
(image :defer t)
|
|
|
|
(indent :defer t)
|
|
|
|
(dired :defer t)
|
|
|
|
(info :defer t)
|
|
|
|
(replace :defer t)
|
|
|
|
(outline :defer t)
|
|
|
|
(package :defer t)
|
|
|
|
(package-menu :defer t)
|
|
|
|
(process-menu :defer t)
|
|
|
|
(simple :defer t)
|
|
|
|
(tab-bar :defer t)
|
|
|
|
(tabulated-list :defer t)
|
|
|
|
(xref :defer t))
|
|
|
|
"The list of modes with special configuration.
|
|
|
|
|
|
|
|
These modes should match entries within `evil-collection-mode-list'.
|
|
|
|
|
|
|
|
This variable is consumed only by `evil-collection-setup'.
|
|
|
|
|
|
|
|
|
|
|
|
NOTE: The API of this variable may change drastically.
|
|
|
|
|
|
|
|
Currently supported keys:
|
|
|
|
|
|
|
|
:defer t or TIME in seconds to defer loading mode."
|
|
|
|
:type '(repeat (choice symbol sexp))
|
|
|
|
:group 'evil-collection)
|
|
|
|
|
2018-06-05 20:10:15 +02:00
|
|
|
(defcustom evil-collection-key-whitelist '()
|
2018-06-06 03:12:06 +02:00
|
|
|
"List of keys that may be used by Evil Collection.
|
2018-06-05 20:10:15 +02:00
|
|
|
This is a list of strings that are suitable for input to
|
2018-06-06 03:12:06 +02:00
|
|
|
`kbd'. If there are no keys in the list, the whitelist will be ignored."
|
2018-06-05 20:10:15 +02:00
|
|
|
:type '(repeat string)
|
|
|
|
:group 'evil-collection)
|
|
|
|
|
|
|
|
(defcustom evil-collection-key-blacklist '()
|
2018-06-06 03:12:06 +02:00
|
|
|
"List of keys that may not be used by Evil Collection.
|
2018-06-05 20:10:15 +02:00
|
|
|
This is a list of strings that are suitable for input to `kbd'."
|
|
|
|
:type '(repeat string)
|
|
|
|
:group 'evil-collection)
|
|
|
|
|
2021-06-23 15:20:56 +02:00
|
|
|
(defcustom evil-collection-state-passlist '()
|
|
|
|
"List of evil states that may be used by Evil Collection.
|
|
|
|
This is a list of symbols that are suitable for input to
|
|
|
|
`evil-define-key'. Ignore when there are no states in the list."
|
|
|
|
:type '(repeat symbol)
|
|
|
|
:group 'evil-collection)
|
|
|
|
|
|
|
|
(defcustom evil-collection-state-denylist
|
|
|
|
(if (bound-and-true-p evil-disable-insert-state-bindings)
|
|
|
|
'(insert)
|
|
|
|
'())
|
|
|
|
"List of evil states that may not be used by Evil Collection.
|
|
|
|
This is a list of symbols that are suitable for input to
|
|
|
|
`evil-define-key'."
|
|
|
|
:type '(repeat symbol)
|
|
|
|
:group 'evil-collection)
|
|
|
|
|
2017-12-18 04:26:31 +01:00
|
|
|
(defvar evil-collection-setup-hook nil
|
|
|
|
"Hook run by `evil-collection-init' for each mode that is evilified.
|
|
|
|
This hook runs after all setup (including keybindings) for a mode has already
|
|
|
|
taken place. The arguments passed to functions for this hook are the name of the
|
|
|
|
mode and a list of keymap names (i.e. symbols, not actual keymaps) customized by
|
|
|
|
Evil Collection for that mode. More arguments may be added in the future, so
|
|
|
|
functions added to this hook should include a \"&rest _rest\" for forward
|
|
|
|
compatibility.")
|
|
|
|
|
2021-02-01 05:51:39 +01:00
|
|
|
(defun evil-collection-define-operator-key (operator map-sym &rest bindings)
|
2023-08-28 17:29:53 +02:00
|
|
|
"Define a key on a specific OPERATOR e.g. yank or delete.
|
2021-02-01 05:51:39 +01:00
|
|
|
|
|
|
|
This function is useful for adding specific binds to operator maps
|
2023-08-28 17:29:53 +02:00
|
|
|
\(e.g. `evil-yank' or `evil-delete') without erasing the original bind.
|
2021-02-01 05:51:39 +01:00
|
|
|
|
|
|
|
For example, say one wants to bind \"yf\" to something but also wants to keep
|
|
|
|
\"yy\".
|
|
|
|
|
|
|
|
This function takes care of checking the whitelist/blacklist against the full
|
|
|
|
binding.
|
|
|
|
|
|
|
|
For example:
|
2023-08-28 17:29:53 +02:00
|
|
|
\(evil-collection-define-operator-key \='yank
|
2022-06-01 00:34:08 +02:00
|
|
|
\='pass-mode-map \"f\" \='pass-copy-field)
|
2021-02-01 05:51:39 +01:00
|
|
|
|
|
|
|
This will check \"yf\" against a user's white/blacklist and also record the
|
|
|
|
binding in `annalist' as so."
|
|
|
|
(declare (indent defun))
|
|
|
|
(let* ((prefix (if (eq operator 'yank) "y" "d"))
|
|
|
|
(operators (if (eq operator 'yank)
|
|
|
|
'evil-collection-yank-operators
|
|
|
|
'evil-collection-delete-operators))
|
|
|
|
(remap (if (eq operator 'yank) [remap evil-yank] [remap evil-delete]))
|
|
|
|
(whitelist (mapcar 'kbd evil-collection-key-whitelist))
|
|
|
|
(blacklist (mapcar 'kbd evil-collection-key-blacklist))
|
|
|
|
filtered-bindings)
|
|
|
|
(while bindings
|
|
|
|
(let* ((key (pop bindings))
|
|
|
|
(key-with-prefix (concat prefix key))
|
2021-02-04 11:39:46 +01:00
|
|
|
(def (pop bindings))
|
|
|
|
(def-with-menu-item
|
2022-04-14 16:16:13 +02:00
|
|
|
`(menu-item
|
|
|
|
""
|
|
|
|
nil
|
|
|
|
:filter
|
|
|
|
(lambda (&optional _)
|
|
|
|
(when (or
|
|
|
|
(eq evil-this-operator (key-binding ,remap))
|
|
|
|
(memq evil-this-operator ,operators))
|
|
|
|
(setq evil-inhibit-operator t)
|
|
|
|
',def)))))
|
2021-02-01 05:51:39 +01:00
|
|
|
(when (or (and whitelist (member key-with-prefix whitelist))
|
|
|
|
(not (member key-with-prefix blacklist)))
|
|
|
|
(annalist-record 'evil-collection 'keybindings
|
2021-02-04 11:39:46 +01:00
|
|
|
;; Record the binding as if it was in 'normal mode
|
|
|
|
;; instead of 'operator mode as the user would be in
|
|
|
|
;; normal mode when triggering the operator.
|
|
|
|
(list map-sym 'normal key-with-prefix def)
|
2021-02-01 05:51:39 +01:00
|
|
|
:local (or (eq map-sym 'local)
|
|
|
|
(local-variable-p map-sym)))
|
|
|
|
;; Use the original key declared when actually setting the binding.
|
|
|
|
(push key filtered-bindings)
|
2021-02-04 11:39:46 +01:00
|
|
|
;; Use the definition attached to the menu-item when setting the
|
|
|
|
;; binding.
|
|
|
|
(push def-with-menu-item filtered-bindings))))
|
2021-02-01 05:51:39 +01:00
|
|
|
(setq filtered-bindings (nreverse filtered-bindings))
|
|
|
|
(evil-collection--define-key 'operator map-sym filtered-bindings)))
|
|
|
|
|
2021-06-23 15:20:56 +02:00
|
|
|
(defun evil-collection--filter-states (state)
|
|
|
|
"Return a list states after filtering STATE (a single symbol or list of symbols).
|
|
|
|
The return value adheres to `evil-collection-state-passlist' and
|
2023-08-28 17:29:53 +02:00
|
|
|
`evil-collection-state-denylist'. When the STATE is nil, which
|
|
|
|
means all states for `evil-define-key', return nil."
|
2021-06-23 15:20:56 +02:00
|
|
|
(let ((states (if (listp state) state (list state))))
|
|
|
|
(seq-difference
|
|
|
|
(if evil-collection-state-passlist
|
|
|
|
(seq-intersection states evil-collection-state-passlist)
|
|
|
|
states)
|
|
|
|
evil-collection-state-denylist)))
|
|
|
|
|
2018-06-06 13:32:19 +02:00
|
|
|
(defun evil-collection-define-key (state map-sym &rest bindings)
|
2018-06-05 20:10:15 +02:00
|
|
|
"Wrapper for `evil-define-key*' with additional features.
|
2019-07-30 03:12:58 +02:00
|
|
|
Unlike `evil-define-key*' MAP-SYM should be a quoted keymap other than the
|
|
|
|
unquoted keymap required for `evil-define-key*'. This function adds the ability
|
|
|
|
to filter keys on the basis of `evil-collection-key-whitelist' and
|
|
|
|
`evil-collection-key-blacklist'. It also records bindings with annalist.el."
|
2018-06-05 20:10:15 +02:00
|
|
|
(declare (indent defun))
|
|
|
|
(let* ((whitelist (mapcar 'kbd evil-collection-key-whitelist))
|
|
|
|
(blacklist (mapcar 'kbd evil-collection-key-blacklist))
|
2021-06-23 15:20:56 +02:00
|
|
|
(states-to-bind (evil-collection--filter-states state))
|
2018-06-06 13:32:19 +02:00
|
|
|
filtered-bindings)
|
2021-06-23 15:20:56 +02:00
|
|
|
(when (or states-to-bind (null state))
|
|
|
|
(while bindings
|
|
|
|
(let ((key (pop bindings))
|
|
|
|
(def (pop bindings)))
|
|
|
|
(when (or (and whitelist (member key whitelist))
|
|
|
|
(not (member key blacklist)))
|
|
|
|
(annalist-record 'evil-collection 'keybindings
|
|
|
|
(list map-sym state key def)
|
|
|
|
:local (or (eq map-sym 'local)
|
|
|
|
(local-variable-p map-sym)))
|
|
|
|
(push key filtered-bindings)
|
|
|
|
(push def filtered-bindings))))
|
|
|
|
(setq filtered-bindings (nreverse filtered-bindings))
|
|
|
|
(evil-collection--define-key states-to-bind map-sym filtered-bindings))))
|
2021-02-01 05:18:13 +01:00
|
|
|
|
2022-05-29 00:12:16 +02:00
|
|
|
(defun evil-collection-can-bind-key (key)
|
|
|
|
"Return whether or not we should bind KEY."
|
|
|
|
(let* ((whitelist (mapcar 'kbd evil-collection-key-whitelist))
|
|
|
|
(blacklist (mapcar 'kbd evil-collection-key-blacklist)))
|
|
|
|
(or (and whitelist (member key whitelist))
|
|
|
|
(not (member key blacklist)))))
|
|
|
|
|
2021-02-01 05:18:13 +01:00
|
|
|
(defun evil-collection--define-key (state map-sym bindings)
|
|
|
|
"Workhorse function for `evil-collection-define-key'.
|
|
|
|
|
|
|
|
See `evil-collection-define-key' docstring for more details."
|
|
|
|
(cond ((null bindings))
|
|
|
|
((and (boundp map-sym) (keymapp (symbol-value map-sym)))
|
|
|
|
(condition-case-unless-debug err
|
|
|
|
(apply #'evil-define-key*
|
|
|
|
state (symbol-value map-sym) bindings)
|
|
|
|
(error
|
|
|
|
(message "evil-collection: error setting key in %s %S"
|
|
|
|
map-sym err))))
|
|
|
|
((boundp map-sym)
|
|
|
|
(user-error "evil-collection: %s is not a keymap" map-sym))
|
|
|
|
(t
|
|
|
|
(let* ((fname (format "evil-collection-define-key-in-%s" map-sym))
|
|
|
|
(fun (make-symbol fname)))
|
|
|
|
(fset fun `(lambda (&rest args)
|
|
|
|
(when (and (boundp ',map-sym) (keymapp ,map-sym))
|
|
|
|
(remove-hook 'after-load-functions #',fun)
|
|
|
|
(condition-case-unless-debug err
|
|
|
|
(apply #'evil-define-key*
|
|
|
|
',state ,map-sym ',bindings)
|
|
|
|
(error
|
|
|
|
(message
|
|
|
|
,(format
|
|
|
|
"evil-collection: error setting key in %s %%S"
|
|
|
|
map-sym)
|
|
|
|
err))))))
|
|
|
|
(add-hook 'after-load-functions fun t)))))
|
2018-06-06 20:34:45 +02:00
|
|
|
|
2018-06-28 19:11:17 +02:00
|
|
|
(defun evil-collection-inhibit-insert-state (map-sym)
|
|
|
|
"Unmap insertion keys from normal state.
|
|
|
|
This is particularly useful for read-only modes."
|
|
|
|
(evil-collection-define-key 'normal map-sym
|
|
|
|
[remap evil-append] #'ignore
|
|
|
|
[remap evil-append-line] #'ignore
|
|
|
|
[remap evil-insert] #'ignore
|
|
|
|
[remap evil-insert-line] #'ignore
|
|
|
|
[remap evil-change] #'ignore
|
|
|
|
[remap evil-change-line] #'ignore
|
|
|
|
[remap evil-substitute] #'ignore
|
|
|
|
[remap evil-change-whole-line] #'ignore
|
|
|
|
[remap evil-delete] #'ignore
|
|
|
|
[remap evil-delete-line] #'ignore
|
|
|
|
[remap evil-delete-char] #'ignore
|
|
|
|
[remap evil-delete-backward-char] #'ignore
|
|
|
|
[remap evil-replace] #'ignore
|
|
|
|
[remap evil-replace-state] #'ignore
|
|
|
|
[remap evil-open-below] #'ignore
|
|
|
|
[remap evil-open-above] #'ignore
|
|
|
|
[remap evil-paste-after] #'ignore
|
|
|
|
[remap evil-paste-before] #'ignore
|
|
|
|
[remap evil-join] #'ignore
|
|
|
|
[remap evil-indent] #'ignore
|
|
|
|
[remap evil-shift-left] #'ignore
|
|
|
|
[remap evil-shift-right] #'ignore
|
|
|
|
[remap evil-invert-char] #'ignore))
|
|
|
|
|
2020-11-11 19:26:48 +01:00
|
|
|
(defun evil-collection-set-readonly-bindings (map-sym)
|
|
|
|
"Unmap insertion keys from normal state. Additionally q can `quit-window'.
|
|
|
|
This is particularly useful for read-only modes. Make sure it's
|
|
|
|
called before setting up other evil bindings so that it can be
|
|
|
|
overriden."
|
|
|
|
(evil-collection-inhibit-insert-state map-sym)
|
|
|
|
(evil-collection-define-key 'normal map-sym
|
|
|
|
"q" #'quit-window
|
|
|
|
"ZZ" #'quit-window
|
|
|
|
"ZQ" #'evil-quit))
|
|
|
|
|
2018-06-06 20:34:45 +02:00
|
|
|
(defun evil-collection--binding-lessp (a b)
|
|
|
|
"Comparison function used to sort bindings of the form (state key def)."
|
|
|
|
(let ((a-state (symbol-name (nth 0 a)))
|
|
|
|
(b-state (symbol-name (nth 0 b)))
|
|
|
|
(a-key (nth 1 a))
|
|
|
|
(b-key (nth 1 b)))
|
|
|
|
(if (not (string= a-state b-state))
|
|
|
|
(string-lessp a-state b-state)
|
|
|
|
(string-lessp a-key b-key))))
|
2018-06-05 20:10:15 +02:00
|
|
|
|
2019-07-30 03:12:58 +02:00
|
|
|
(annalist-define-view 'keybindings 'evil-collection-valid
|
|
|
|
(list (list 'keymap :sort #'annalist-string-<)
|
|
|
|
(list 'state :sort #'annalist-string-<))
|
|
|
|
:inherit 'valid)
|
|
|
|
|
|
|
|
(annalist-define-view 'keybindings 'evil-collection-active
|
|
|
|
(list (list 'keymap :sort #'annalist-string-<)
|
|
|
|
(list 'state :sort #'annalist-string-<))
|
|
|
|
:inherit 'active)
|
|
|
|
|
2018-06-13 03:57:16 +02:00
|
|
|
(defun evil-collection-describe-bindings (&optional arg)
|
|
|
|
"Print bindings made by Evil Collection to separate buffer.
|
|
|
|
|
|
|
|
With non-nil ARG, restrict to bindings corresponding to active
|
|
|
|
modes in the current buffer."
|
|
|
|
(interactive "P")
|
2019-07-30 03:12:58 +02:00
|
|
|
(annalist-describe 'evil-collection 'keybindings
|
|
|
|
(if arg
|
|
|
|
'evil-collection-active
|
|
|
|
'evil-collection-valid)))
|
2018-06-05 20:14:16 +02:00
|
|
|
|
2018-07-12 21:05:50 +02:00
|
|
|
(defun evil-collection--mode-file (mode file)
|
|
|
|
"Return path to FILE for MODE. Return nil if it doesn't exist."
|
|
|
|
(let ((path (expand-file-name
|
|
|
|
(format "modes/%s/%s" mode file) evil-collection-base-dir)))
|
|
|
|
(when (file-exists-p path)
|
2021-02-01 05:17:17 +01:00
|
|
|
path)))
|
2018-07-12 21:05:50 +02:00
|
|
|
|
|
|
|
(defun evil-collection-open-config-file (mode)
|
|
|
|
"Open configuration file corresponding to MODE."
|
|
|
|
(interactive
|
|
|
|
(list
|
|
|
|
(completing-read
|
|
|
|
"Mode: "
|
|
|
|
(cl-remove-if-not
|
|
|
|
(lambda (mode)
|
|
|
|
(evil-collection--mode-file mode (format "evil-collection-%s.el" mode)))
|
|
|
|
(directory-files
|
|
|
|
(expand-file-name "modes" evil-collection-base-dir)
|
|
|
|
nil "^[^.]")))))
|
|
|
|
(find-file (evil-collection--mode-file mode (format "evil-collection-%s.el" mode))))
|
|
|
|
|
|
|
|
(defun evil-collection-open-readme (mode)
|
|
|
|
"Open README.org corresponding to MODE."
|
|
|
|
(interactive
|
|
|
|
(list
|
|
|
|
(completing-read
|
|
|
|
"Mode: "
|
|
|
|
(cl-remove-if-not
|
|
|
|
(lambda (mode)
|
|
|
|
(evil-collection--mode-file mode "README.org"))
|
|
|
|
(directory-files
|
|
|
|
(expand-file-name "modes" evil-collection-base-dir)
|
|
|
|
nil "^[^.]")))))
|
|
|
|
(find-file (evil-collection--mode-file mode "README.org")))
|
|
|
|
|
2023-09-17 12:13:15 +02:00
|
|
|
(defun evil-collection--delay (condition form hook &optional append local name)
|
|
|
|
"Execute FORM when CONDITION becomes true, checking with HOOK.
|
|
|
|
NAME specifies the name of the entry added to HOOK. If APPEND is
|
|
|
|
non-nil, the entry is appended to the hook. If LOCAL is non-nil,
|
|
|
|
the buffer-local value of HOOK is modified.
|
|
|
|
|
|
|
|
This is a backport of `evil-delay' without the deprecation notice to deal with CI until migration can be done.
|
|
|
|
Ref: https://github.com/emacs-evil/evil-collection/issues/750"
|
|
|
|
(eval `(evil-with-delay ,condition (,hook ,append ,local ,name) ,form) t))
|
|
|
|
|
2022-04-14 05:51:50 +02:00
|
|
|
;;;###autoload
|
|
|
|
(cl-defun evil-collection-translate-minor-mode-key (states modes
|
|
|
|
&rest translations
|
|
|
|
&key destructive
|
|
|
|
&allow-other-keys)
|
|
|
|
"Translate keys in the keymap(s) corresponding to STATES and MODES.
|
2022-07-11 19:49:20 +02:00
|
|
|
|
|
|
|
Similar to `evil-collection-translate-key' but for minor modes.
|
2022-04-14 05:51:50 +02:00
|
|
|
STATES should be the name of an evil state, a list of states, or nil. MODES
|
|
|
|
should be a symbol corresponding to minor-mode to make the translations in or a
|
|
|
|
list of minor-mode symbols. TRANSLATIONS corresponds to a list of
|
|
|
|
key replacement pairs. For example, specifying \"a\" \"b\" will bind \"a\" to
|
|
|
|
\"b\"'s definition in the keymap. Specifying nil as a replacement will unbind a
|
|
|
|
key. If DESTRUCTIVE is nil, a backup of the keymap will be stored on the initial
|
|
|
|
invocation, and future invocations will always look up keys in the backup
|
|
|
|
keymap. When no TRANSLATIONS are given, this function will only create the
|
|
|
|
backup keymap without making any translations. On the other hand, if DESTRUCTIVE
|
|
|
|
is non-nil, the keymap will be destructively altered without creating a backup.
|
|
|
|
For example, calling this function multiple times with \"a\" \"b\" \"b\" \"a\"
|
|
|
|
would continue to swap and unswap the definitions of these keys. This means that
|
|
|
|
when DESTRUCTIVE is non-nil, all related swaps/cycles should be done in the same
|
|
|
|
invocation."
|
|
|
|
(declare (indent defun))
|
|
|
|
(unless (listp modes)
|
|
|
|
(setq modes (list modes)))
|
|
|
|
(unless (and (listp states)
|
|
|
|
(not (null states)))
|
|
|
|
(setq states (list states)))
|
|
|
|
(dolist (mode-symbol modes)
|
2022-04-14 16:15:50 +02:00
|
|
|
(let ((keymap-symbol (intern (format "%S-map" mode-symbol))))
|
|
|
|
(dolist (state states)
|
2023-09-17 12:13:15 +02:00
|
|
|
(let ((hook-name
|
|
|
|
(symbol-name
|
|
|
|
(cl-gensym
|
|
|
|
(format "evil-collection-translate-key-in-%s" keymap-symbol)))))
|
|
|
|
(evil-collection--delay `(and (boundp ',keymap-symbol)
|
|
|
|
(keymapp ,keymap-symbol))
|
|
|
|
`(evil-collection--translate-minor-mode-key
|
|
|
|
',state
|
|
|
|
',mode-symbol
|
|
|
|
',translations
|
|
|
|
,destructive)
|
|
|
|
'after-load-functions
|
2023-08-28 17:29:53 +02:00
|
|
|
t
|
|
|
|
nil
|
2023-09-17 12:13:15 +02:00
|
|
|
hook-name))))))
|
|
|
|
|
2022-04-14 05:51:50 +02:00
|
|
|
|
|
|
|
(defun evil-collection--translate-minor-mode-key (state
|
|
|
|
mode-symbol
|
|
|
|
translations
|
|
|
|
destructive)
|
|
|
|
"Helper function for `evil-collection-translate-minor-mode-key'.
|
|
|
|
In the minor mode keymap corresponding to STATE and MODE-SYMBOL, make the key
|
|
|
|
TRANSLATIONS. When DESTRUCTIVE is non-nil, make the TRANSLATIONS destructively
|
|
|
|
without creating/referencing a backup keymap."
|
|
|
|
(let* ((keymap-symbol (intern (format "%S-map" mode-symbol)))
|
|
|
|
(backup-keymap-symbol (intern (format "evil-collection-%s%s-backup-map"
|
|
|
|
mode-symbol
|
|
|
|
(if state
|
|
|
|
(format "-%s-state" state)
|
|
|
|
""))))
|
|
|
|
(keymap (symbol-value keymap-symbol))
|
|
|
|
(lookup-keymap (if (and (not destructive)
|
|
|
|
(boundp backup-keymap-symbol))
|
|
|
|
(symbol-value backup-keymap-symbol)
|
|
|
|
(copy-keymap
|
|
|
|
(if state
|
|
|
|
(evil-get-minor-mode-keymap state mode-symbol)
|
|
|
|
keymap))))
|
|
|
|
(maps (cl-loop for (key replacement) on translations by 'cddr
|
|
|
|
;; :destructive can be in TRANSLATIONS
|
|
|
|
unless (keywordp key)
|
|
|
|
collect key
|
|
|
|
and collect (when replacement
|
2023-04-12 02:44:29 +02:00
|
|
|
(evil-lookup-key lookup-keymap replacement)))))
|
2022-04-14 05:51:50 +02:00
|
|
|
(unless (or destructive
|
|
|
|
(boundp backup-keymap-symbol))
|
|
|
|
(set backup-keymap-symbol lookup-keymap))
|
|
|
|
(apply #'evil-define-minor-mode-key state mode-symbol maps)))
|
|
|
|
|
2017-12-18 04:26:31 +01:00
|
|
|
(defun evil-collection--translate-key (state keymap-symbol
|
|
|
|
translations
|
|
|
|
destructive)
|
|
|
|
"Helper function for `evil-collection-translate-key'.
|
|
|
|
In the keymap corresponding to STATE and KEYMAP-SYMBOL, make the key
|
|
|
|
TRANSLATIONS. When DESTRUCTIVE is non-nil, make the TRANSLATIONS destructively
|
|
|
|
without creating/referencing a backup keymap."
|
|
|
|
(let* ((backup-keymap-symbol (intern (format "evil-collection-%s%s-backup-map"
|
|
|
|
keymap-symbol
|
|
|
|
(if state
|
|
|
|
(format "-%s-state" state)
|
|
|
|
""))))
|
|
|
|
(keymap (symbol-value keymap-symbol))
|
|
|
|
(lookup-keymap (if (and (not destructive)
|
|
|
|
(boundp backup-keymap-symbol))
|
|
|
|
(symbol-value backup-keymap-symbol)
|
|
|
|
(copy-keymap
|
|
|
|
(if state
|
|
|
|
(evil-get-auxiliary-keymap keymap state t t)
|
|
|
|
keymap))))
|
|
|
|
(maps (cl-loop for (key replacement) on translations by 'cddr
|
|
|
|
;; :destructive can be in TRANSLATIONS
|
|
|
|
unless (keywordp key)
|
|
|
|
collect key
|
|
|
|
and collect (when replacement
|
2023-04-12 02:44:29 +02:00
|
|
|
(evil-lookup-key lookup-keymap replacement)))))
|
2017-12-18 04:26:31 +01:00
|
|
|
(unless (or destructive
|
|
|
|
(boundp backup-keymap-symbol))
|
|
|
|
(set backup-keymap-symbol lookup-keymap))
|
|
|
|
(apply #'evil-define-key* state keymap maps)))
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
(cl-defun evil-collection-translate-key (states keymaps
|
|
|
|
&rest translations
|
|
|
|
&key destructive
|
|
|
|
&allow-other-keys)
|
|
|
|
"Translate keys in the keymap(s) corresponding to STATES and KEYMAPS.
|
|
|
|
STATES should be the name of an evil state, a list of states, or nil. KEYMAPS
|
|
|
|
should be a symbol corresponding to the keymap to make the translations in or a
|
|
|
|
list of keymap symbols. Like `evil-define-key', when a keymap does not exist,
|
|
|
|
the keybindings will be deferred until the keymap is defined, so
|
2020-08-05 21:38:58 +02:00
|
|
|
`with-eval-after-load' is not necessary. TRANSLATIONS corresponds to a list of
|
2017-12-18 04:26:31 +01:00
|
|
|
key replacement pairs. For example, specifying \"a\" \"b\" will bind \"a\" to
|
|
|
|
\"b\"'s definition in the keymap. Specifying nil as a replacement will unbind a
|
|
|
|
key. If DESTRUCTIVE is nil, a backup of the keymap will be stored on the initial
|
|
|
|
invocation, and future invocations will always look up keys in the backup
|
|
|
|
keymap. When no TRANSLATIONS are given, this function will only create the
|
|
|
|
backup keymap without making any translations. On the other hand, if DESTRUCTIVE
|
|
|
|
is non-nil, the keymap will be destructively altered without creating a backup.
|
|
|
|
For example, calling this function multiple times with \"a\" \"b\" \"b\" \"a\"
|
|
|
|
would continue to swap and unswap the definitions of these keys. This means that
|
|
|
|
when DESTRUCTIVE is non-nil, all related swaps/cycles should be done in the same
|
|
|
|
invocation."
|
|
|
|
(declare (indent defun))
|
|
|
|
(unless (listp keymaps)
|
|
|
|
(setq keymaps (list keymaps)))
|
|
|
|
(unless (and (listp states)
|
|
|
|
(not (null states)))
|
|
|
|
(setq states (list states)))
|
|
|
|
(dolist (keymap-symbol keymaps)
|
|
|
|
(dolist (state states)
|
2023-09-17 12:13:15 +02:00
|
|
|
(let ((hook-name
|
|
|
|
(symbol-name
|
|
|
|
(cl-gensym
|
|
|
|
(format "evil-collection-translate-key-in-%s" keymap-symbol)))))
|
|
|
|
(evil-collection--delay `(and (boundp ',keymap-symbol)
|
|
|
|
(keymapp ,keymap-symbol))
|
|
|
|
`(evil-collection--translate-key
|
|
|
|
',state
|
|
|
|
',keymap-symbol
|
|
|
|
',translations
|
|
|
|
,destructive)
|
|
|
|
'after-load-functions
|
|
|
|
t
|
|
|
|
nil
|
|
|
|
hook-name)))))
|
|
|
|
|
2017-12-18 04:26:31 +01:00
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
(defmacro evil-collection-swap-key (states keymaps &rest args)
|
|
|
|
"Wrapper around `evil-collection-translate-key' for swapping keys.
|
|
|
|
STATES, KEYMAPS, and ARGS are passed to `evil-collection-translate-key'. ARGS
|
|
|
|
should consist of key swaps (e.g. \"a\" \"b\" is equivalent to \"a\" \"b\" \"b\"
|
|
|
|
\"a\" with `evil-collection-translate-key') and optionally keyword arguments for
|
|
|
|
`evil-collection-translate-key'."
|
|
|
|
(declare (indent defun))
|
|
|
|
(setq args (cl-loop for (key replacement) on args by 'cddr
|
|
|
|
collect key and collect replacement
|
|
|
|
and unless (keywordp key)
|
|
|
|
collect replacement and collect key))
|
|
|
|
`(evil-collection-translate-key ,states ,keymaps ,@args))
|
|
|
|
|
2022-04-14 05:51:50 +02:00
|
|
|
;;;###autoload
|
|
|
|
(defmacro evil-collection-swap-minor-mode-key (states modes &rest args)
|
|
|
|
"Wrapper around `evil-collection-translate-minor-mode-key' for swapping keys.
|
|
|
|
STATES, MODES, and ARGS are passed to
|
|
|
|
`evil-collection-translate-minor-mode-key'. ARGS should consist of key swaps
|
2023-08-28 17:29:53 +02:00
|
|
|
\(e.g. \"a\" \"b\" is equivalent to \"a\" \"b\" \"b\" \"a\"
|
2022-04-14 05:51:50 +02:00
|
|
|
with `evil-collection-translate-minor-mode-key') and optionally keyword
|
|
|
|
arguments for `evil-collection-translate-minor-mode-key'."
|
|
|
|
(declare (indent defun))
|
|
|
|
(setq args (cl-loop for (key replacement) on args by 'cddr
|
|
|
|
collect key and collect replacement
|
|
|
|
and unless (keywordp key)
|
|
|
|
collect replacement and collect key))
|
|
|
|
`(evil-collection-translate-minor-mode-key ,states ,modes ,@args))
|
|
|
|
|
2019-09-23 16:37:08 +02:00
|
|
|
;;;###autoload
|
|
|
|
(defun evil-collection-require (mode &optional noerror)
|
|
|
|
"Require the evil-collection-MODE file, but do not activate it.
|
|
|
|
|
|
|
|
MODE should be a symbol. This requires the evil-collection-MODE
|
|
|
|
feature without needing to manipulate `load-path'. NOERROR is
|
|
|
|
forwarded to `require'."
|
|
|
|
(let* ((mode-name (symbol-name mode))
|
|
|
|
(feature (intern (format "evil-collection-%s" mode-name)))
|
|
|
|
(file (expand-file-name
|
|
|
|
(format "modes/%s/evil-collection-%s" mode-name mode-name)
|
|
|
|
evil-collection-base-dir)))
|
|
|
|
(require feature file noerror)))
|
|
|
|
|
2019-09-29 13:59:13 +02:00
|
|
|
(declare-function evil-collection-unimpaired-setup "evil-collection-unimpaired")
|
|
|
|
|
2017-11-14 17:54:02 +01:00
|
|
|
;;;###autoload
|
2018-04-14 23:17:40 +02:00
|
|
|
(defun evil-collection-init (&optional modes)
|
2017-11-06 15:12:40 +01:00
|
|
|
"Register the Evil bindings for all modes in `evil-collection-mode-list'.
|
2017-11-05 17:05:46 +01:00
|
|
|
|
2017-11-06 15:12:40 +01:00
|
|
|
Alternatively, you may register select bindings manually, for
|
|
|
|
instance:
|
|
|
|
|
2022-06-01 00:34:08 +02:00
|
|
|
(with-eval-after-load \='calendar
|
2018-04-14 23:17:40 +02:00
|
|
|
(evil-collection-calendar-setup))
|
|
|
|
|
|
|
|
If MODES is specified (as either one mode or a list of modes), use those modes
|
|
|
|
instead of the modes in `evil-collection-mode-list'."
|
2017-11-05 17:05:46 +01:00
|
|
|
(interactive)
|
2018-04-14 23:17:40 +02:00
|
|
|
(if modes
|
|
|
|
(or (listp modes) (setq modes (list modes)))
|
|
|
|
(setq modes evil-collection-mode-list))
|
|
|
|
(dolist (mode modes)
|
2017-11-06 15:12:40 +01:00
|
|
|
(let ((m mode)
|
|
|
|
(reqs (list mode)))
|
|
|
|
(when (listp mode)
|
|
|
|
(setq m (car mode)
|
|
|
|
reqs (cdr mode)))
|
|
|
|
(dolist (req reqs)
|
|
|
|
(with-eval-after-load req
|
2022-06-06 07:53:34 +02:00
|
|
|
;; (message (format "Loaded %S..." req))
|
2019-09-23 16:37:08 +02:00
|
|
|
(evil-collection-require m)
|
2017-12-18 04:26:31 +01:00
|
|
|
(funcall (intern (concat "evil-collection-" (symbol-name m)
|
|
|
|
"-setup")))
|
|
|
|
(let ((mode-keymaps
|
|
|
|
(ignore-errors
|
|
|
|
(symbol-value
|
|
|
|
(intern (format "evil-collection-%s-maps" m))))))
|
2022-04-14 23:42:59 +02:00
|
|
|
(when (or evil-collection-always-run-setup-hook-after-load
|
|
|
|
(not (memq m evil-collection--modes-with-delayed-setup)))
|
|
|
|
(run-hook-with-args 'evil-collection-setup-hook
|
|
|
|
m mode-keymaps)))))))
|
2019-06-18 03:36:54 +02:00
|
|
|
(when evil-collection-want-unimpaired-p
|
2019-09-23 16:43:11 +02:00
|
|
|
(evil-collection-require 'unimpaired)
|
|
|
|
(evil-collection-unimpaired-setup)))
|
2017-11-05 17:05:46 +01:00
|
|
|
|
2022-06-06 07:53:34 +02:00
|
|
|
(defun evil-collection-setup (&optional modes)
|
|
|
|
"Register the Evil bindings for all modes in `evil-collection-mode-list'.
|
|
|
|
|
|
|
|
----------------------EXPERIMENTAL------------------------------------------
|
|
|
|
|
|
|
|
This is a special wrapper over `evil-collection-init' that respects
|
|
|
|
configuration from `evil-collection-config'. This function is experimental,
|
2022-06-06 17:12:57 +02:00
|
|
|
so don't use if you don't want breakages or API changes.
|
2022-06-06 07:53:34 +02:00
|
|
|
|
|
|
|
If MODES is specified (as either one mode or a list of modes), use those modes
|
|
|
|
instead of the modes in `evil-collection-mode-list'.
|
|
|
|
|
|
|
|
----------------------EXPERIMENTAL------------------------------------------"
|
|
|
|
(if modes
|
|
|
|
(or (listp modes) (setq modes (list modes)))
|
|
|
|
(setq modes evil-collection-mode-list))
|
|
|
|
(let ((configs evil-collection-config)
|
|
|
|
(deferred-modes)
|
|
|
|
(delays))
|
|
|
|
(dolist (config configs)
|
|
|
|
(let ((defer (plist-get (cdr config) :defer)))
|
|
|
|
(when defer
|
|
|
|
(push (car config) deferred-modes)
|
|
|
|
(push defer delays))))
|
|
|
|
(let ((filtered-modes
|
|
|
|
(cl-remove-if
|
|
|
|
(lambda (mode)
|
|
|
|
(let ((filterp nil)
|
|
|
|
(modes (if (consp mode) mode (list mode))))
|
|
|
|
(dolist (m modes)
|
|
|
|
(let ((x (memq m deferred-modes)))
|
|
|
|
(when x
|
|
|
|
(setf filterp t)
|
|
|
|
;; `evil-collection-config' format is slightly different
|
|
|
|
;; than `evil-collection-mode-list', so use the mode
|
|
|
|
;; entry from the mode list instead.
|
|
|
|
(setf (car x) mode))))
|
|
|
|
filterp))
|
|
|
|
modes)))
|
|
|
|
(evil-collection-init filtered-modes))
|
|
|
|
(message (format "Deferring: %S" deferred-modes))
|
|
|
|
(dotimes (i (length deferred-modes))
|
|
|
|
(let ((mode (nth i deferred-modes))
|
|
|
|
(delay (nth i delays)))
|
|
|
|
;; (message (format "Delaying %S..."
|
|
|
|
;; (if (consp mode) (car mode) mode)))
|
|
|
|
(run-with-idle-timer
|
|
|
|
(if (numberp delay) delay 3) nil
|
|
|
|
(apply-partially 'evil-collection-init (list mode)))))))
|
|
|
|
|
2018-02-15 13:08:41 +01:00
|
|
|
(defvar evil-collection-delete-operators '(evil-delete
|
|
|
|
evil-cp-delete
|
2018-02-19 10:36:26 +01:00
|
|
|
evil-sp-delete
|
2018-02-15 13:08:41 +01:00
|
|
|
lispyville-delete)
|
|
|
|
"List of delete operators.")
|
|
|
|
|
2018-02-23 18:31:31 +01:00
|
|
|
(defvar evil-collection-yank-operators '(evil-yank
|
|
|
|
evil-cp-yank
|
|
|
|
evil-sp-yank
|
|
|
|
lispyville-yank)
|
|
|
|
"List of yank operators.")
|
|
|
|
|
2018-06-29 19:55:03 +02:00
|
|
|
;;* Search
|
|
|
|
|
|
|
|
(defun evil-collection-evil-search-enabled ()
|
|
|
|
(eq evil-search-module 'evil-search))
|
|
|
|
|
|
|
|
(defvar evil-collection-evil-search-forward
|
|
|
|
'(menu-item "" nil :filter (lambda (&optional _)
|
|
|
|
(if (eq evil-search-module 'evil-search)
|
|
|
|
#'evil-ex-search-forward
|
|
|
|
#'evil-search-forward))))
|
|
|
|
|
|
|
|
(defvar evil-collection-evil-search-backward
|
|
|
|
'(menu-item "" nil :filter (lambda (&optional _)
|
|
|
|
(if (eq evil-search-module 'evil-search)
|
|
|
|
#'evil-ex-search-backward
|
|
|
|
#'evil-search-backward))))
|
|
|
|
|
|
|
|
(defvar evil-collection-evil-search-next
|
|
|
|
'(menu-item "" nil :filter (lambda (&optional _)
|
|
|
|
(if (eq evil-search-module 'evil-search)
|
|
|
|
#'evil-ex-search-next
|
|
|
|
#'evil-search-next))))
|
|
|
|
|
|
|
|
(defvar evil-collection-evil-search-previous
|
|
|
|
'(menu-item "" nil :filter (lambda (&optional _)
|
|
|
|
(if (eq evil-search-module 'evil-search)
|
|
|
|
#'evil-ex-search-previous
|
|
|
|
#'evil-search-previous))))
|
|
|
|
|
2017-11-05 17:05:46 +01:00
|
|
|
(provide 'evil-collection)
|
|
|
|
;;; evil-collection.el ends here
|