#+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-managers.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-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