+*** [[https://github.com/noctuid/general.el][general]]
+
+#+begin_src emacs-lisp
+(use-package general
+ :demand t
+ :config
+ (general-evil-setup t)
+ (general-override-mode)
+
+ (general-create-definer
+ amin--leader-keys
+ :keymaps 'override
+ :states '(emacs normal visual motion insert)
+ :non-normal-prefix "M-m"
+ :prefix "SPC"))
+#+end_src
+
+*** [[https://github.com/emacs-evil/evil][evil]]
+
+#+begin_src emacs-lisp
+(use-package evil
+ :demand t
+ ;; :hook (org-src-mode . evil-motion-state)
+ :config
+ (evil-mode 1)
+ (general-swap-key nil '(normal motion) ";" ":")
+
+ (setq evil-want-visual-char-semi-exclusive t
+ evil-cross-lines t)
+
+ ;; custom mode state mappings
+ (dolist (mspair '((ebdb-mode . emacs)
+ (helpful-mode . motion)
+ (view-mode . motion)))
+ (evil-set-initial-state (car mspair) (cdr mspair)))
+
+ ;; fix tab and indentation in src blocks inside org-mode buffer
+ ;; also see https://git.sr.ht/~bandali/dotfiles/commit/0e2ffd584aafdd4cf256bcdf2473f01c3aaaed55
+ (unbind-key "TAB" evil-motion-state-map)
+
+ (unbind-key "C-d" evil-insert-state-map)
+ (unbind-key "C-v" evil-insert-state-map)
+ (unbind-key "C-y" evil-insert-state-map)
+ (unbind-key "C-a" evil-insert-state-map)
+ (unbind-key "C-e" evil-insert-state-map)
+ (unbind-key "C-p" evil-insert-state-map)
+ (unbind-key "C-n" evil-insert-state-map)
+ (unbind-key "C-k" evil-insert-state-map)
+ (bind-keys
+ :map evil-insert-state-map
+ ("C-k" . kill-line)
+ ("C-S-k" . evil-insert-digraph)
+ :map evil-motion-state-map
+ ([down-mouse-1] . nil)))
+#+end_src
+
+#+begin_src emacs-lisp
+(use-package evil-escape
+ :after evil
+ :init
+ (setq evil-escape-excluded-states '(normal visual multiedit emacs motion)
+ evil-escape-excluded-major-modes '(neotree-mode)
+ evil-escape-key-sequence "jk"
+ evil-escape-delay 0.25)
+ ;; :general
+ ;; (:states '(insert replace visual operator)
+ ;; "C-g" #'evil-escape)
+ :config
+ (evil-escape-mode 1)
+ ;; no `evil-escape' in minibuffer
+ (push #'minibufferp evil-escape-inhibit-functions))
+#+end_src
+
+#+begin_src emacs-lisp
+(use-package evil-nerd-commenter
+ :after evil
+ :general
+ (nmap
+ "gc" 'evilnc-comment-operator
+ "gy" 'evilnc-copy-and-comment-lines))
+#+end_src
+
+#+begin_src emacs-lisp
+(use-package evil-surround
+ :after evil
+ :general
+ (omap
+ "s" 'evil-surround-edit
+ "S" 'evil-Surround-edit)
+ (vmap
+ "S" 'evil-surround-region
+ "gS" 'evil-Surround-region))
+#+end_src
+
+#+begin_src emacs-lisp
+(amin--leader-keys
+ "/" '(:ignore t :wk "search")
+
+ "a" '(:ignore t :wk "apps")
+ "a i" 'ielm
+
+ "b" '(:ignore t :wk "buffers")
+ "b k" 'kill-this-buffer
+ "b s" 'save-buffer
+
+ "e" '(:ignore t :wk "eval")
+ "e b" 'eval-buffer
+ "e r" 'eval-region
+
+ "f" '(:ignore t :wk "files")
+
+ "F" '(:ignore t :wk "frames")
+ "F m" 'make-frame-command
+ "F d" 'delete-frame
+ "F D" 'delete-other-frames
+
+ "h" '(:ignore t :wk "help(ful)")
+ "h c" 'describe-char
+ "h f" 'describe-function
+ "h F" 'describe-face
+ "h H" 'view-hello-file
+ "h i" 'info
+ "h k" 'describe-key
+ "h l" 'view-lossage
+ "h v" 'describe-variable
+
+ "o" 'other-window
+
+ "w" '(:ignore t :wk "window")
+ "w o" 'other-window
+ "w 0" 'delete-window
+ "w 1" 'delete-other-windows
+ "w 2" 'split-window-below
+ "w 3" 'split-window-right
+ "w u" 'winner-undo
+ "w r" 'winner-redo
+
+ "q" '(:ignore t :wk "quit")
+ "q q" 'save-buffers-kill-terminal)
+#+end_src
+