-
-
Save alexforsale/94c9a5f28b988476f675963e8c4d0c42 to your computer and use it in GitHub Desktop.
Spacemacs-like menus using general.el
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| * Spacemacs-like menus using general.el | |
| ** Global keybindings | |
| First, we define a global prefix key: | |
| #+begin_src emacs-lisp | |
| (general-create-definer global-definer | |
| :keymaps 'override | |
| :states '(insert emacs normal hybrid motion visual operator) | |
| :prefix "SPC" | |
| :non-normal-prefix "S-SPC") | |
| #+end_src | |
| Bind top level, global commands like so: | |
| #+begin_src emacs-lisp | |
| (global-definer | |
| "!" 'shell-command | |
| ":" 'eval-expression) | |
| #+end_src | |
| ** Nested menus | |
| To ease the creation of nested menus, we define a macro: | |
| #+begin_src emacs-lisp | |
| (defmacro +general-global-menu! (name infix-key &rest body) | |
| "Create a definer named +general-global-NAME wrapping global-definer. | |
| Create prefix map: +general-global-NAME. Prefix bindings in BODY with INFIX-KEY." | |
| (declare (indent 2)) | |
| `(progn | |
| (general-create-definer ,(intern (concat "+general-global-" name)) | |
| :wrapping global-definer | |
| :prefix-map (quote ,(intern (concat "+general-global-" name "-map"))) | |
| :infix ,infix-key | |
| :wk-full-keys nil | |
| "" '(:ignore t :which-key ,name)) | |
| (,(intern (concat "+general-global-" name)) | |
| ,@body))) | |
| #+end_src | |
| This macro defines top-level nested menus. e.g. a menu for "buffer" bindings: | |
| #+begin_src emacs-lisp | |
| (+general-global-menu! "buffer" "b" | |
| "d" 'kill-current-buffer | |
| "o" '((lambda () (interactive) (switch-to-buffer nil)) | |
| :which-key "other-buffer") | |
| "p" 'previous-buffer | |
| "r" 'rename-buffer | |
| "M" '((lambda () (interactive) (switch-to-buffer "*Messages*")) | |
| :which-key "messages-buffer") | |
| "n" 'next-buffer | |
| "s" '((lambda () (interactive) (switch-to-buffer "*scratch*")) | |
| :which-key "scratch-buffer") | |
| "TAB" '((lambda () (interactive) (switch-to-buffer nil)) | |
| :which-key "other-buffer")) | |
| #+end_src | |
| You can specify per-package keybindings with the =:general= use-package keyword. | |
| For example, here's a minimal helm configuration that binds =SPC bb= to =helm-mini=: | |
| #+begin_src emacs-lisp | |
| (use-package helm | |
| :init (require 'helm-config) | |
| :defer 1 | |
| :config | |
| (helm-mode) | |
| :general | |
| (+general-global-buffer | |
| "b" 'helm-mini)) | |
| #+end_src | |
| ** Contextual (mode specific) leader key | |
| We define a global-leader definer to access major-mode specific bindings: | |
| #+begin_src emacs-lisp | |
| (general-create-definer global-leader | |
| :keymaps 'override | |
| :states '(emacs normal hybrid motion visual operator) | |
| :prefix "SPC m" | |
| "" '(:ignore t :which-key (lambda (arg) `(,(cadr (split-string (car arg) " ")) . ,(replace-regexp-in-string "-mode$" "" (symbol-name major-mode)))))) | |
| #+end_src | |
| Again, we use the =:general= keyword to bind mode-specific bindings. | |
| For example, with the following, we can =eval-buffer= when in =emacs-lisp-mode= or =lisp-interaction-mode= | |
| by pressing =SPC m e b=: | |
| #+begin_src emacs-lisp | |
| (use-package elisp-mode | |
| ;;this is a built in package, so we don't want to try and install it | |
| :ensure nil | |
| :general | |
| (global-leader | |
| ;;specify the major modes these should apply to: | |
| :major-modes | |
| '(emacs-lisp-mode lisp-interaction-mode t) | |
| ;;and the keymaps: | |
| :keymaps | |
| '(emacs-lisp-mode-map lisp-interaction-mode-map) | |
| "e" '(:ignore t :which-key "eval") | |
| "eb" 'eval-buffer | |
| "ed" 'eval-defun | |
| "ee" 'eval-expression | |
| "ep" 'pp-eval-last-sexp | |
| "es" 'eval-last-sexp | |
| "i" 'elisp-index-search)) | |
| #+end_src | |
| * Conclusion | |
| Hope this helps. | |
| ~ Nicholas Vollmer |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment