165 lines
5.0 KiB
Org Mode
165 lines
5.0 KiB
Org Mode
|
#+title: Emacs — Keybinding Managers
|
|||
|
#+setupfile: ../headers
|
|||
|
#+property: header-args:emacs-lisp :mkdirp yes :lexical t :exports code
|
|||
|
#+property: header-args:emacs-lisp+ :tangle ~/.config/emacs/lisp/keybinding-managemers.el
|
|||
|
#+property: header-args:emacs-lisp+ :mkdirp yes :noweb no-export
|
|||
|
|
|||
|
* Keybinding Managers
|
|||
|
** Which-key
|
|||
|
Which key is, I think, one of my favorite quality of life package.
|
|||
|
When you begin a keybind, Emacs will show you all keybinds you can
|
|||
|
follow the first one with in order to form a full keychord. Very
|
|||
|
useful when you have a lot of keybinds and don’t remember exactly what
|
|||
|
is what.
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(use-package which-key
|
|||
|
:straight (:build t)
|
|||
|
:defer t
|
|||
|
:init (which-key-mode)
|
|||
|
:diminish which-key-mode
|
|||
|
:config
|
|||
|
(setq which-key-idle-delay 1))
|
|||
|
#+end_src
|
|||
|
|
|||
|
** General
|
|||
|
General is an awesome package for managing keybindings. Not only is it
|
|||
|
oriented towards keychords by default (which I love), but it also
|
|||
|
provides some integration with evil so that we can declare keybindings
|
|||
|
for certain states only! This is a perfect replacement for ~define-key~,
|
|||
|
~evil-define-key~, and any other function for defining keychords. And it
|
|||
|
is also possible to declare a prefix for my keybindings! By default,
|
|||
|
all keybinds will be prefixed with ~SPC~ and keybinds related to a
|
|||
|
specific mode (often major modes) will be prefixed by a comma ~,~ (and
|
|||
|
by ~C-SPC~ and ~M-m~ respectively when in ~insert-mode~ or ~emacs-mode~). You
|
|||
|
can still feel some influence from my Spacemacs years here.
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(use-package general
|
|||
|
:straight (:build t)
|
|||
|
:init
|
|||
|
(general-auto-unbind-keys)
|
|||
|
:config
|
|||
|
(general-create-definer phundrak/undefine
|
|||
|
:keymaps 'override
|
|||
|
:states '(normal emacs))
|
|||
|
(general-create-definer phundrak/evil
|
|||
|
:states '(normal))
|
|||
|
(general-create-definer phundrak/leader-key
|
|||
|
:states '(normal insert visual emacs)
|
|||
|
:keymaps 'override
|
|||
|
:prefix "SPC"
|
|||
|
:global-prefix "C-SPC")
|
|||
|
(general-create-definer phundrak/major-leader-key
|
|||
|
:states '(normal insert visual emacs)
|
|||
|
:keymaps 'override
|
|||
|
:prefix ","
|
|||
|
:global-prefix "M-m"))
|
|||
|
#+end_src
|
|||
|
|
|||
|
** Evil
|
|||
|
Evil emulates most of vim’s keybinds, because let’s be honest here,
|
|||
|
they are much more comfortable than Emacs’.
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(use-package evil
|
|||
|
:straight (:build t)
|
|||
|
:after (general)
|
|||
|
:init
|
|||
|
(setq evil-want-integration t
|
|||
|
evil-want-keybinding nil
|
|||
|
evil-want-C-u-scroll t
|
|||
|
evil-want-C-i-jump nil)
|
|||
|
(require 'evil-vars)
|
|||
|
:config
|
|||
|
<<evil-undefine-keys>>
|
|||
|
<<evil-bepo>>
|
|||
|
(evil-mode 1)
|
|||
|
(setq evil-want-fine-undo t) ; more granular undo with evil
|
|||
|
(evil-set-initial-state 'messages-buffer-mode 'normal)
|
|||
|
(evil-set-initial-state 'dashboard-mode 'normal))
|
|||
|
#+end_src
|
|||
|
|
|||
|
I want to undefine some default keybinds of Evil because it does not
|
|||
|
match my workflow. Namely, I use the space key and the comma as
|
|||
|
leaders for my keybinds, and I’m way too used to Emacs’ ~C-t~, ~C-a~, ~C-e~,
|
|||
|
and ~C-y~.
|
|||
|
#+name: evil-undefine-keys
|
|||
|
#+begin_src emacs-lisp :tangle no
|
|||
|
(evil-global-set-key 'motion "t" 'evil-next-visual-line)
|
|||
|
(evil-global-set-key 'motion "s" 'evil-previous-visual-line)
|
|||
|
|
|||
|
(general-define-key
|
|||
|
:keymaps 'evil-motion-state-map
|
|||
|
"SPC" nil
|
|||
|
"," nil)
|
|||
|
(general-define-key
|
|||
|
:keymaps 'evil-insert-state-map
|
|||
|
"C-t" nil)
|
|||
|
(general-define-key
|
|||
|
:keymaps 'evil-insert-state-map
|
|||
|
"U" nil
|
|||
|
"C-a" nil
|
|||
|
"C-y" nil
|
|||
|
"C-e" nil)
|
|||
|
#+end_src
|
|||
|
|
|||
|
Something else that really bugs me is I use the bépo layout, which is
|
|||
|
not at all like the qwerty layout. For instance, ~hjkl~ becomes ~ctsr~.
|
|||
|
Thus, I need some bépo-specific changes.
|
|||
|
#+name: evil-bepo
|
|||
|
#+begin_src emacs-lisp :tangle no
|
|||
|
(dolist (key '("c" "C" "t" "T" "s" "S" "r" "R" "h" "H" "j" "J" "k" "K" "l" "L"))
|
|||
|
(general-define-key :states 'normal key nil))
|
|||
|
|
|||
|
(general-define-key
|
|||
|
:states 'motion
|
|||
|
"h" 'evil-replace
|
|||
|
"H" 'evil-replace-state
|
|||
|
"j" 'evil-find-char-to
|
|||
|
"J" 'evil-find-char-to-backward
|
|||
|
"k" 'evil-substitute
|
|||
|
"K" 'evil-smart-doc-lookup
|
|||
|
"l" 'evil-change
|
|||
|
"L" 'evil-change-line
|
|||
|
|
|||
|
"c" 'evil-backward-char
|
|||
|
"C" 'evil-window-top
|
|||
|
"t" 'evil-next-visual-line
|
|||
|
"T" 'evil-join
|
|||
|
"s" 'evil-previous-visual-line
|
|||
|
"S" 'evil-lookup
|
|||
|
"r" 'evil-forward-char
|
|||
|
"R" 'evil-window-bottom)
|
|||
|
#+end_src
|
|||
|
|
|||
|
This package enables and integrates Evil into a lot of different
|
|||
|
modes, such as org-mode, dired, mu4e, etc. Again, I need some
|
|||
|
additional code compared to most people due to the bépo layout.
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(use-package evil-collection
|
|||
|
:after evil
|
|||
|
:straight (:build t)
|
|||
|
:config
|
|||
|
;; bépo conversion
|
|||
|
(defun my/bépo-rotate-evil-collection (_mode mode-keymaps &rest _rest)
|
|||
|
(evil-collection-translate-key 'normal mode-keymaps
|
|||
|
;; bépo ctsr is qwerty hjkl
|
|||
|
"c" "h"
|
|||
|
"t" "j"
|
|||
|
"s" "k"
|
|||
|
"r" "l"
|
|||
|
;; add back ctsr
|
|||
|
"h" "c"
|
|||
|
"j" "t"
|
|||
|
"k" "s"
|
|||
|
"l" "r"))
|
|||
|
(add-hook 'evil-collection-setup-hook #'my/bépo-rotate-evil-collection)
|
|||
|
(evil-collection-init))
|
|||
|
#+end_src
|
|||
|
|
|||
|
** Hydra
|
|||
|
[[https://github.com/abo-abo/hydra][Hydra]] is a simple menu creator for keybindings.
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(use-package hydra
|
|||
|
:straight (:build t)
|
|||
|
:defer t)
|
|||
|
#+end_src
|