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