Skip to content

Simple helper for god-mode to add leader key functionality

License

Notifications You must be signed in to change notification settings

Havner/leader-key

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Summary

Simple helper to add leader key functionality (e.g. for god-mode)

The idea is to replicate a vim/evil leader key concept, but be independant of any other mode. This has been developed and tested together with god-mode but should work without it or even without any modal mode. It works together with which-key, but the dependency is optional.

With the configuration below we can do shortcuts like:

SPC x q       ;; quits emacs
SPC p p       ;; opens projectile project list
SPC <left>    ;; moves to the left window
SPC m         ;; opens magit
SPC SPC       ;; starts selection
SPC x SPC     ;; starts rectangle selection
SPC q c       ;; (vdiff)-close-fold, only when major vdiff-mode active
SPC q c       ;; (rust-mode)-rust-compile, only when major rust-mode active

leader key example

Configuration

Mandatory configuration

To configure (an example with god-mode):

(require 'which-key)                     ;; optional
(require 'leader-key)                    ;; only in case of no auto-loads

Define the main/root leader key that will trigger the leader map (make sure the key is not bound to anything in situations we want it to trigger, in this case when god-mode is active):

(setq leader-key-root-key "SPC")         ;; redundant, "SPC" is default
(with-eval-after-load 'god-mode
  (define-key god-local-mode-map (kbd leader-key-root-key) nil))

Configure the predicament that must be true for the leader-key to be triggered. Otherwise the key should fall back to its default function. In case of god-mode the below is a usable choice (activate when god-mode is active or the buffer is read only):

(defun +leader-key-pred ()
  (or buffer-read-only
      god-local-mode))
(setq leader-key-pred #'+leader-key-pred)

Turn on the global minor mode:

(leader-key-mode t)

Problematic modes

There are some major-modes that don't play well with leader, e.g. modes that are marked as read only yet we need the leader key to do its original job. One of such modes is vterm-mode. To handle such cases add this mode to exceptions:

(add-to-list 'leader-key-exempt-major-modes 'vterm-mode t)

There might also be some major-modes that can have our leader key already mapped to something else and it conflicts with the leader-key in leader minor map. In such a case there is a helper function that will add our leader key directly to such a map. The second parameter for (leader-key-do-map) is optional, it will basically do (eval-after-load 2ND-PARAM) for that expression so we don't need to handle the loading order.

(leader-key-do-map 'custom-mode-map 'cus-edit)
(leader-key-do-map 'magit-blame-read-only-mode-map 'magit-blame)

Alternative configuration

An alternative configuration without any modal mode, where the leader key is always active with a M-SPC shortcut:

(global-set-key (kbd "M-SPC") nil)       ;; so it doesn't conflict
(setq leader-key-root-key "M-SPC")
(setq leader-key-pred #'(lambda () t))   ;; always active
(leader-key-mode t)

Building leader map

There is no default for the map that will be triggered with leader-key, we need to build it ourselves. We can add whole submaps or just specific functions. Examples below:

(with-eval-after-load 'projectile
  (leader-key-define-key "p" projectile-command-map "projectile"))
(with-eval-after-load 'flycheck
  (leader-key-define-key "f" flycheck-command-map "flycheck"))

(leader-key-define-key "m" #'magit-status)
(leader-key-define-key "g" #'magit-file-dispatch)

(leader-key-define-key "<left>" #'window-jump-left)
(leader-key-define-key "<right>" #'window-jump-right)
(leader-key-define-key "<up>" #'window-jump-up)
(leader-key-define-key "<down>" #'window-jump-down)
(leader-key-define-key "0" #'+switch-window-then-delete-window-and-balance "delete-window")
(leader-key-define-key "1" #'switch-window-then-maximize "maximize")
(leader-key-define-key "2" #'+switch-window-then-split-below-switch-and-balance "split-below")
(leader-key-define-key "3" #'+switch-window-then-split-right-switch-and-balance "split-right")

(leader-key-define-key "SPC" #'set-mark-command)

(leader-key-describe-key "x" "emacs")       ;; optional, for which-key
(leader-key-define-key "x SPC" #'rectangle-mark-mode)
(leader-key-define-key "x ;" #'eval-expression)
(leader-key-define-key "x e" #'eval-last-sexp)
(leader-key-define-key "x p" #'paradox-list-packages)
(leader-key-define-key "x q" #'save-buffers-kill-terminal)
(leader-key-define-key "x s" #'save-some-buffers)
(leader-key-define-key "x w" #'write-file)
(leader-key-define-key "x x" #'execute-extended-command)

Major mode submaps

We can also have a sub map assigned that will be different dependent on the currently active major mode. This requires key and specific map assignment.

(setq leader-key-major-mode-key "q")        ;; redundant, "q" is default

The first parameter for (leader-key-major-mode-map) defines the major mode map where our leader will be active (basically the major mode map assigned to major mode), the second parameter is the map we want to have assigned under leader key (might be provided externally, some packages provide usable maps, might be built manually), the third parameter is optional, it basically does (eval-after-load 3RD-PARAM) so we don't need to bother with loading order.

(leader-key-major-mode-map 'vdiff-mode-map 'vdiff-mode-prefix-map 'vdiff)

(setq rust-mode-map (make-sparse-keymap))   ;; optional, to clean up unusable default
(defvar rust-command-map
  (let ((map (make-sparse-keymap)))
    (define-key map (kbd "d") #'rust-dbg-wrap-or-unwrap)
    (define-key map (kbd "c") #'rust-compile)
    (define-key map (kbd "k") #'rust-check)
    (define-key map (kbd "t") #'rust-test)
    (define-key map (kbd "r") #'rust-run)
    (define-key map (kbd "l") #'rust-run-clippy)
    (define-key map (kbd "f") #'rust-format-buffer)
    (define-key map (kbd "n") #'rust-goto-format-problem)
    map))
(leader-key-major-mode-map 'rust-mode-map 'rust-command-map 'rust-mode)

About

Simple helper for god-mode to add leader key functionality

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published