Rethink map! macro; replace :local=>:L, :defer=>:map* (addresses #19)

This commit is contained in:
Henrik Lissner 2017-01-02 20:59:28 -05:00
parent 5536ab887d
commit e1000fcfc5
8 changed files with 174 additions and 143 deletions

View file

@ -195,6 +195,7 @@ Examples:
;; Register keywords for proper indentation (see `map!')
(put ':prefix 'lisp-indent-function 'defun)
(put ':map 'lisp-indent-function 'defun)
(put ':map* 'lisp-indent-function 'defun)
(put ':after 'lisp-indent-function 'defun)
(put ':when 'lisp-indent-function 'defun)
(put ':unless 'lisp-indent-function 'defun)
@ -207,6 +208,11 @@ Examples:
plist key flags. It was designed to make binding multiple keys more concise,
like in vim.
Yes, it tries to do too much. Yes, I only did it to make the \"frontend\" config
that little bit more concise. Yes, I could simply have used the above functions.
But it takes a little insanity to custom write your own emacs.d, so what else
were you expecting?
States
:n normal
:v visual
@ -215,17 +221,20 @@ States
:o operator
:m motion
:r replace
:L local
These can be combined (order doesn't matter), e.g. :nvi will apply to
normal, visual and insert mode. The state resets after the following
key=>def pair.
Capitalize the state flag to make it a local binding.
If omitted, the keybind will be defined globally.
Flags
:unset [KEY] ; unset key
:nodefer ; don't use `evil-delay' for future keybinds
(:map [KEYMAP] [...]) ; apply all inner keybinds to KEYMAP
(:map [KEYMAP] [...]) ; apply inner keybinds to KEYMAP
(:map* [KEYMAP] [...]) ; apply inner keybinds to KEYMAP (deferred)
(:prefix [PREFIX] [...]) ; assign prefix to all inner keybindings
(:after [FEATURE] [...]) ; apply keybinds when [FEATURE] loads
@ -242,8 +251,7 @@ Example
(:when IS-MAC
:n \"M-s\" 'some-fn
:i \"M-o\" (lambda (interactive) (message \"Hi\"))))"
(let ((i 0)
(keymaps (if (boundp 'keymaps) keymaps))
(let ((keymaps (if (boundp 'keymaps) keymaps))
(state-map '(("n" . normal)
("v" . visual)
("i" . insert)
@ -252,15 +260,18 @@ Example
("m" . motion)
("r" . replace)))
(prefix (if (boundp 'prefix) prefix))
(nodefer (if (boundp 'nodefer) nodefer))
key def states forms)
(defer (if (boundp 'defer) defer))
local key def states forms)
(while rest
(setq key (pop rest))
(push
(reverse
(cond ((listp key) ; it's a sub exp
(cond
;; it's a sub expr
((listp key)
`(,(macroexpand `(map! ,@key))))
;; it's a flag
((keywordp key)
(when (memq key '(:leader :localleader))
(push (cond ((eq key :leader)
@ -272,7 +283,7 @@ Example
(pcase key
(:prefix (setq prefix (concat prefix (kbd (pop rest)))) nil)
(:map (setq keymaps (-list (pop rest))) nil)
(:nodefer (setq nodefer t) nil)
(:map* (setq defer t keymaps (-list (pop rest))) nil)
(:unset `(,(macroexpand `(map! ,(kbd (pop rest)) nil))))
(:after (prog1 `((after! ,(pop rest) ,(macroexpand `(map! ,@rest)))) (setq rest '())))
(:when (prog1 `((if ,(pop rest) ,(macroexpand `(map! ,@rest)))) (setq rest '())))
@ -281,10 +292,18 @@ Example
(mapc (lambda (letter)
(cond ((assoc letter state-map)
(push (cdr (assoc letter state-map)) states))
((string= letter "L")
(setq local t))
(t (user-error "Invalid mode prefix %s in key %s" letter key))))
(split-string (substring (symbol-name key) 1) "" t))
(unless states
(user-error "Unrecognized keyword %s" key)) nil)))
(user-error "Unrecognized keyword %s" key))
(when (assoc "L" states)
(cond ((= (length states) 1)
(user-error "local keybinding for %s must accompany another state" key))
((> (length keymaps) 0)
(user-error "local keybinding for %s cannot accompany a keymap" key))))
nil)))
;; It's a key-def pair
((or (stringp key)
@ -301,7 +320,7 @@ Example
(let (out-forms)
(cond ((and keymaps states)
(mapc (lambda (keymap)
(push `(,(if nodefer 'evil-define-key* 'evil-define-key)
(push `(,(if defer 'evil-define-key 'evil-define-key*)
',states ,keymap ,key ,def)
out-forms))
keymaps))
@ -309,16 +328,21 @@ Example
(mapc (lambda (keymap) (push `(define-key ,keymap ,key ,def) out-forms))
keymaps))
(states
(mapc (lambda (state) (push `(define-key (evil-state-property ',state :keymap t) ,key ,def)
(mapc (lambda (state)
(push `(define-key
(evil-state-property ',state ,(if local :local-keymap :keymap) t)
,key ,def)
out-forms))
states))
(t (push `(global-set-key ,key ,def) out-forms)))
(setq states '())
(t (push `(,(if local 'local-set-key 'global-set-key)
,key ,def)
out-forms)))
(setq states '()
local nil)
out-forms))
(t (user-error "Invalid key %s" key))))
forms)
(setq i (1+ i)))
forms))
`(progn ,@(apply #'nconc (delete nil (delete (list nil) (reverse forms))))))))
(defmacro def-repeat! (command next-func prev-func)

View file

@ -320,8 +320,8 @@
:i "<C-tab>" 'indent-for-tab-command
:i "<A-tab>" (λ! (insert "\t"))
;; No dumb-tab for lisp
(:map lisp-mode-map :i [remap doom/dumb-indent] 'indent-for-tab-command)
(:map emacs-lisp-mode-map :i [remap doom/dumb-indent] 'indent-for-tab-command)
(:map* lisp-mode-map :i [remap doom/dumb-indent] 'indent-for-tab-command)
(:map* emacs-lisp-mode-map :i [remap doom/dumb-indent] 'indent-for-tab-command)
;; Highjacks space/backspace to:
;; a) eat spaces on either side of the cursor, if present ( | ) -> (|)
;; b) allow backspace to delete space-indented blocks intelligently
@ -348,11 +348,11 @@
:i "A-w" 'evil-forward-word-begin
:i "A-e" 'evil-forward-word-end
;; Textmate-esque insert-line before/after
:i "<M-return>" 'evil-open-below
:i "<S-M-return>" 'evil-open-above
:i [M-return] 'evil-open-below
:i [S-M-return] 'evil-open-above
;; insert lines in-place)
:n "<M-return>" (λ! (save-excursion (evil-insert-newline-below)))
:n "<S-M-return>" (λ! (save-excursion (evil-insert-newline-above)))
:n [M-return] (λ! (save-excursion (evil-insert-newline-below)))
:n [S-M-return] (λ! (save-excursion (evil-insert-newline-above)))
;; Make ESC quit all the things
(:map (minibuffer-local-map
minibuffer-local-ns-map
@ -378,20 +378,19 @@
"h" nil
"g" nil)))
;; Fix certain keys in the terminal
(unless window-system
(map! :map key-translation-map
"TAB" [tab]))
;; Fix certain keys in the terminal
(:unless window-system "TAB" [tab])
;; Common unicode characters
(map! :map key-translation-map
"A-o" (kbd "ø")
"A-O" (kbd "Ø")
"A--" (kbd "")
"A-_" (kbd "")
"A-8" (kbd "")
"A-*" (kbd "°")
"A-p" (kbd "π"))
:i "A-o" (kbd "ø")
:i "A-O" (kbd "Ø")
:i "A--" (kbd "")
:i "A-_" (kbd "")
:i "A-8" (kbd "")
:i "A-*" (kbd "°")
:i "A-p" (kbd "π"))
(provide 'core-editor)
;;; core-editor.el ends here

View file

@ -23,7 +23,14 @@
:config
(defvar helm-global-prompt " ")
(map! :map helm-map
(map! "M-x" 'helm-M-x
"A-x" 'helm-M-x
"M-X" 'helm-apropos
"A-X" 'helm-apropos
"A-X" 'helm-apropos
"M-o" 'helm-find-files
(:map helm-map
"C-S-n" 'helm-next-source
"C-S-p" 'helm-previous-source
"C-u" 'helm-delete-minibuffer-contents
@ -36,9 +43,10 @@
"<escape>" 'helm-keyboard-quit
"ESC" 'helm-keyboard-quit
[escape] 'helm-keyboard-quit
"<tab>" 'helm-execute-persistent-action
:map helm-generic-files-map
:e "ESC" 'helm-keyboard-quit)
"<tab>" 'helm-execute-persistent-action)
(:map* helm-generic-files-map
:e "ESC" 'helm-keyboard-quit))
;;; Popup setup
(def-popup! "\\` ?\\*[hH]elm.*?\\*\\'" :align below :size 14 :select t :regexp t)

View file

@ -64,24 +64,23 @@
;; overridden when the neotree buffer is spawned). So we bind them in a hook.
(add-hook 'neo-after-create-hook 'doom|neotree-init-keymap)
(defun doom|neotree-init-keymap (&rest _)
(map! :map evil-motion-state-local-map
"\\\\" 'evil-window-prev
"ESC ESC" 'neotree-hide
"q" 'neotree-hide
[return] 'neotree-enter
"RET" 'neotree-enter
"<return>" 'neotree-enter
"J" 'neotree-select-next-sibling-node
"K" 'neotree-select-previous-sibling-node
"H" 'neotree-select-up-node
"L" 'neotree-select-down-node
"v" 'neotree-enter-vertical-split
"s" 'neotree-enter-horizontal-split
"c" 'neotree-create-node
"d" 'neotree-delete-node
"C-r" 'neotree-refresh
"r" 'neotree-rename-node
"R" 'neotree-change-root)))
(map! :Lm "\\\\" 'evil-window-prev
:Lm "ESC ESC" 'neotree-hide
:Lm "q" 'neotree-hide
:Lm [return] 'neotree-enter
:Lm "RET" 'neotree-enter
:Lm "<return>" 'neotree-enter
:Lm "J" 'neotree-select-next-sibling-node
:Lm "K" 'neotree-select-previous-sibling-node
:Lm "H" 'neotree-select-up-node
:Lm "L" 'neotree-select-down-node
:Lm "v" 'neotree-enter-vertical-split
:Lm "s" 'neotree-enter-horizontal-split
:Lm "c" 'neotree-create-node
:Lm "d" 'neotree-delete-node
:Lm "C-r" 'neotree-refresh
:Lm "r" 'neotree-rename-node
:Lm "R" 'neotree-change-root)))
(use-package projectile
:config

View file

@ -9,6 +9,11 @@
(sp-with-modes '(css-mode scss-mode less-css-mode stylus-mode)
(sp-local-pair "/*" "*/" :post-handlers '(("[d-3]||\n[i]" "RET") ("| " "SPC"))))
(map! (:map* (css-mode-map scss-mode-map less-css-mode-map)
:n "M-R" 'doom/web-refresh-browser)
(:map* (css-mode-map scss-mode-map less-css-mode-map)
:localleader :nv ";" 'doom/append-semicolon))
(use-package css-mode
:mode "\\.css$"
:init
@ -51,9 +56,6 @@
(push '("scss" "css") projectile-other-file-alist)
(setq scss-compile-at-save nil))
(map! :map (css-mode-map sass-mode-map scss-mode-map)
:n "M-R" 'doom/web-refresh-browser
(:localleader :nv ";" 'doom/append-semicolon))
(provide 'module-css)
;;; module-css.el ends here

View file

@ -3,9 +3,6 @@
(associate! emacs-lisp-mode :match "\\(/Cask\\|\\.\\(el\\|gz\\)\\)$")
(add-hook! emacs-lisp-mode '(eldoc-mode highlight-numbers-mode))
;; Real go-to-definition for elisp
(map! :map emacs-lisp-mode-map :m "gd" 'doom/elisp-find-function-at-pt)
(add-hook 'emacs-lisp-mode-hook 'doom/elisp-init)
(defun doom/elisp-init ()
(def-company-backend! emacs-lisp-mode (elisp yasnippet))
@ -25,6 +22,9 @@
(delq (assq 'emacs-lisp-mode editorconfig-indentation-alist)
editorconfig-indentation-alist))
;; Real go-to-definition for elisp
(map! :map emacs-lisp-mode-map :m "gd" 'doom/elisp-find-function-at-pt)
(remove-hook 'emacs-lisp-mode-hook 'doom/elisp-init))
(add-hook 'emacs-lisp-mode-hook 'doom/elisp-hook)

View file

@ -233,8 +233,7 @@
"Q" 'doom/org-agenda-quit)))
(defun doom|org-keybinds ()
(map! :nodefer
(:map org-mode-map
(map! (:map org-mode-map
"RET" nil
"C-j" nil
"C-k" nil

View file

@ -11,8 +11,7 @@
'(call-interactively 'counsel-find-file)
)))))
(map! :nodefer
[f9] 'what-face
(map! [f9] 'what-face
;; Essential
(:when (featurep 'helm)
"M-x" 'helm-M-x
@ -282,9 +281,10 @@
:nv "<C-tab>" 'aya-create
;; yasnippet
(:after yasnippet
(:map yas-minor-mode-map
:i [tab] 'yas-expand
:v [tab] 'doom/yas-insert-snippet)
:v [tab] 'doom/yas-insert-snippet))
;; company-mode and vim-like omni-complete
:i "C-SPC" 'doom/company-complete