From ff84d5e1c9cdb97858389807703410c4eb181847 Mon Sep 17 00:00:00 2001 From: Case Duckworth Date: Sat, 20 Feb 2021 15:33:45 -0600 Subject: Add acdw/bind and acdw/bind-after-map Small convenience macros to define key bindings. --- config.org | 179 +++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 109 insertions(+), 70 deletions(-) diff --git a/config.org b/config.org index b23420f..14cc597 100644 --- a/config.org +++ b/config.org @@ -192,7 +192,7 @@ Let's try settings from [[https://github.com/nex3/perspective-el#some-musings-on *** Switch to other window or buffer :crux: #+begin_src emacs-lisp :noweb-ref bindings - (define-key acdw/map (kbd "M-o") #'crux-other-window-or-switch-buffer) + (acdw/bind "M-o" #'crux-other-window-or-switch-buffer) #+end_src *** The *Help* window @@ -269,7 +269,7 @@ someday. #+end_src #+begin_src emacs-lisp :noweb-ref bindings - (define-key acdw/leader (kbd "C-x") #'scratch) + (acdw/bind "C-x" #'scratch :map acdw/leader) #+end_src *** Kill buffers better @@ -294,7 +294,7 @@ someday. #+end_src #+begin_src emacs-lisp :noweb-ref bindings - (define-key acdw/map (kbd "C-x k") #'kill-a-buffer) + (acdw/bind "C-x k" #'kill-a-buffer) #+end_src *** Kill old buffers after a while @@ -953,19 +953,15 @@ Let's have =prescient= and =selectrum= work together. #+end_src #+begin_src emacs-lisp :noweb-ref bindings - (with-eval-after-load 'icomplete - (define-key icomplete-minibuffer-map (kbd "") - #'icomplete-forward-completions) - (define-key icomplete-minibuffer-map (kbd "C-n") - #'icomplete-forward-completions) - (define-key icomplete-minibuffer-map (kbd "") - #'icomplete-backward-completions) - (define-key icomplete-minibuffer-map (kbd "C-p") - #'icomplete-backward-completions)) + (acdw/bind-after-map 'icomplete icomplete-minibuffer-map + (("" #'icomplete-forward-completions) + ("C-n" #'icomplete-forward-completions) + ("" #'icomplete-backward-completions) + ("C-p" #'icomplete-backward-completions))) - (with-eval-after-load 'icomplete-vertical - (define-key icomplete-minibuffer-map (kbd "C-v") - #'icomplete-vertical-toggle)) + (acdw/bind "C-v" #'icomplete-vertical-toggle + :after 'icomplete-vertical + :map icomplete-minibuffer-map) #+end_src #+begin_src emacs-lisp :noweb-ref modes @@ -997,39 +993,39 @@ Consult has a lot of great bindings that work well with Emacs's default completion system. These all come from the [[https://github.com/minad/consult#configuration][example configuration]]. #+begin_src emacs-lisp :noweb-ref bindings - (with-eval-after-load 'consult + (acdw/bind-after-map 'consult acdw/map ;; C-c bindings (`mode-specific-map') - (define-key acdw/map (kbd "C-c h") #'consult-history) - (define-key acdw/map (kbd "C-c m") #'consult-mode-command) - ;; C-x bindings (`ctl-x-map') - (define-key acdw/map (kbd "C-x M-:") #'consult-complex-command) - (define-key acdw/map (kbd "C-x b") #'consult-buffer) - (define-key acdw/map (kbd "C-x 4 b") #'consult-buffer-other-window) - (define-key acdw/map (kbd "C-x 5 b") #'consult-buffer-other-frame) - (define-key acdw/map (kbd "C-x r x") #'consult-register) - (define-key acdw/map (kbd "C-x r b") #'consult-bookmark) - ;; M-g bindings (`goto-map') - (define-key acdw/map (kbd "M-g g") #'consult-line) - (define-key acdw/map (kbd "M-g M-g") #'consult-line) - (define-key acdw/map (kbd "M-g o") #'consult-outline) - (define-key acdw/map (kbd "M-g m") #'consult-mark) - (define-key acdw/map (kbd "M-g k") #'consult-global-mark) - (define-key acdw/map (kbd "M-g i") #'consult-imenu) - (define-key acdw/map (kbd "M-g e") #'consult-error) - ;; M-s bindings (`search-map') - (define-key acdw/map (kbd "M-s g") #'consult-grep) ; alts: + (("C-c h" #'consult-history) + ("C-c m" #'consult-mode-command) + ;; C-x bindings (`ctl-x-map') + ("C-x M-:" #'consult-complex-command) + ("C-x b" #'consult-buffer) + ("C-x 4 b" #'consult-buffer-other-window) + ("C-x 5 b" #'consult-buffer-other-frame) + ("C-x r x" #'consult-register) + ("C-x r b" #'consult-bookmark) + ;; M-g bindings (`goto-map') + ("M-g g" #'consult-line) + ("M-g M-g" #'consult-line) + ("M-g o" #'consult-outline) + ("M-g m" #'consult-mark) + ("M-g k" #'consult-global-mark) + ("M-g i" #'consult-imenu) + ("M-g e" #'consult-error) + ;; M-s bindings (`search-map') + ("M-s g" #'consult-grep) ; alts: ; consult-git-grep, ; consult-ripgrep - (define-key acdw/map (kbd "M-s f") #'consult-find) ; alts: + ("M-s f" #'consult-find) ; alts: ; consult-locate - (define-key acdw/map (kbd "M-s l") #'consult-line) - (define-key acdw/map (kbd "M-s m") #'consult-multi-occur) - (define-key acdw/map (kbd "M-s k") #'consult-keep-lines) - (define-key acdw/map (kbd "M-s u") #'consult-focus-lines) - ;; Other bindings - (define-key acdw/map (kbd "M-y") #'consult-yank-pop) - (define-key acdw/map (kbd " a") #'consult-apropos) - (define-key acdw/map (kbd "C-h a") #'consult-apropos)) + ("M-s l" #'consult-line) + ("M-s m" #'consult-multi-occur) + ("M-s k" #'consult-keep-lines) + ("M-s u" #'consult-focus-lines) + ;; Other bindings + ("M-y" #'consult-yank-pop) + (" a" #'consult-apropos) + ("C-h a" #'consult-apropos))) #+end_src #+begin_src emacs-lisp :noweb-ref settings @@ -1084,7 +1080,7 @@ Before I install any completion framework, I want a good default for completing. =hippie-expand= fills that niche. #+begin_src emacs-lisp :noweb-ref bindings - (define-key acdw/map (kbd "M-/") #'hippie-expand) + (acdw/bind "M-/" #'hippie-expand) #+end_src ** Bindings @@ -1113,6 +1109,49 @@ on as I please. (blackout 'acdw/mode) #+end_src +*** =acdw/bind= macro + +Since defining keys can be a chore, I've written this macro to make it just a +/little/ bit easier. It's /not/ as comprehensive as =bind-key=, but it's just a +little sugar on top of =define-key= et al. + +#+begin_src emacs-lisp :noweb-ref functions + (defmacro acdw/bind (key def &rest args) + "A simple key-binding macro that takes care of the annoying stuff. + + If KEY is a vector, it's passed directly to `define-key', + otherwise it wraps it in `kbd'. It does NOT quote any + definitions, because I like to keep those explicit in the + definitions. + + The following keywords are recognized: + + :after PACKAGE-OR-FEATURE .. wrap key definition in `with-eval-after-load' + :map KEYMAP .. define key in KEYMAP instead of `acdw/map'" + (let* ((after (plist-get args :after)) + (map (or (plist-get args :map) 'acdw/map)) + (key (if (vectorp key) key `(kbd ,key))) + (def-key `(define-key ,map ,key ,def))) + (if after + `(with-eval-after-load ,after + ,def-key) + def-key))) + + (defmacro acdw/bind-after-map (feature keymap bindings) + "Wrap multiple calls to `acdw/bind' in a `with-eval-after-load' form. + + FEATURE is the argument to `with-eval-after-load'. KEYMAP is + passed to the `:map' argument of `acdw/bind', if it's non-nil." + (declare (indent 2)) + (let (bind-list) + (dolist (bind bindings bind-list) + (if keymap + (push `(acdw/bind ,@bind :map ,keymap) bind-list) + (push `(acdw/bind ,@bind) bind-list))) + `(with-eval-after-load ,feature + ,@bind-list))) +#+end_src + **** Turn off acdw/mode in the minibuffer #+begin_src emacs-lisp :noweb-ref acdw-mode @@ -1464,7 +1503,7 @@ that I /literally/ never use. So I'm going to bind it to =find-file= ... since that's the only time I accidentally call it, anyway. #+begin_src emacs-lisp :noweb-ref bindings - (define-key acdw/map (kbd "C-x f") #'find-file) + (acdw/bind "C-x f" #'find-file) #+end_src *** Auto-fill vs. Visual-line @@ -1621,7 +1660,7 @@ see also #+end_src #+begin_src emacs-lisp :noweb-ref bindings - (define-key acdw/map (kbd "C-=") #'er/expand-region) + (acdw/bind "C-=" #'er/expand-region) #+end_src *** Pulse the modified region with goggles @@ -1649,8 +1688,8 @@ see also #+end_src #+begin_src emacs-lisp :noweb-ref bindings - (define-key acdw/map (kbd "C-/") #'undo-fu-only-undo) - (define-key acdw/map (kbd "C-?") #'undo-fu-only-redo) + (acdw/bind "C-/" #'undo-fu-only-undo) + (acdw/bind "C-?" #'undo-fu-only-redo) #+end_src *** Undo Fu session @@ -1719,13 +1758,13 @@ I've switched =query-replace= and =query-replace-regexp= with their anzu versions, because of the regex thing. #+begin_src emacs-lisp :noweb-ref bindings - (define-key acdw/map [remap query-replace] #'anzu-query-replace-regexp) - (define-key acdw/map [remap query-replace-regexp] #'anzu-query-replace) - - (define-key isearch-mode-map [remap isearch-query-replace] - #'anzu-isearch-query-replace) - (define-key isearch-mode-map [remap isearch-query-replace-regexp] - #'anzu-isearch-query-replace-regexp) + (acdw/bind-after-map 'anzu nil + (([remap query-replace] #'anzu-query-replace-regexp) + ([remap query-replace-regexp] #'anzu-query-replace) + ([remap isearch-query-replace] #'anzu-isearch-query-replace + :map isearch-mode-map) + ([remap isearch-query-replace-regexp] #'anzu-isearch-query-replace-regexp + :map isearch-mode-map))) #+end_src ** Commenting :crux: @@ -1739,7 +1778,7 @@ already commented. That's it. #+end_src #+begin_src emacs-lisp :noweb-ref bindings - (define-key acdw/map (kbd "M-;") #'comment-or-uncomment-region) + (acdw/bind "M-;" #'comment-or-uncomment-region) #+end_src * Writing @@ -1772,7 +1811,7 @@ I just found out that =M-== counts the words in a region. That's great, but I often want to count the words in the whole buffer. #+begin_src emacs-lisp :noweb-ref bindings - (define-key acdw/map (kbd "M-=") #'count-words) + (acdw/bind "M-=" #'count-words) #+end_src ** Spell checking @@ -1813,8 +1852,9 @@ Display corrections with =completing-read=. #+end_src #+begin_src emacs-lisp :noweb-ref bindings - (with-eval-after-load 'flyspell - (define-key flyspell-mode-map (kbd "C-;") #'flyspell-correct-wrapper)) + (acdw/bind "C-;" #'flyspell-correct-wrapper + :after 'flyspell + :map flyspell-mode-map) #+end_src * Reading @@ -2108,7 +2148,7 @@ move up a directory with a keybinding, I'll change =-a= to =-A=. #+end_src #+begin_src emacs-lisp :noweb-ref bindings - (define-key acdw/map (kbd "C-x C-j") #'dired-jump) + (acdw/bind "C-x C-j" #'dired-jump) #+end_src *** Expand subtrees :package: @@ -2121,8 +2161,7 @@ enables me to open them in the same buffer, fancily indented. #+end_src #+begin_src emacs-lisp :noweb-ref bindings - (with-eval-after-load 'dired - (define-key dired-mode-map "i" #'dired-subtree-toggle)) + (acdw/bind "i" #'dired-subtree-toggle :after 'dired :map dired-mode-map) #+end_src *** Collapse singleton directories :package: @@ -2147,7 +2186,7 @@ that one item is. #+end_src #+begin_src emacs-lisp :noweb-ref bindings - (define-key acdw/leader "g" #'magit-status) + (acdw/bind "g" #'magit-status :map acdw/leader) #+end_src **** Use =~/.authinfo= for passwords @@ -2298,7 +2337,7 @@ See [[https://github.com/redguardtoo/mastering-emacs-in-one-year-guide/blob/mast #+end_src #+begin_src emacs-lisp :noweb-ref bindings - (define-key acdw/leader "f" #'elfeed) + (acdw/bind "f" #'elfeed :map acdw/leader) #+end_src **** Elfeed feeds @@ -2499,11 +2538,11 @@ others. #+end_src #+begin_src emacs-lisp :noweb-ref bindings - (with-eval-after-load 'elpher - (define-key elpher-mode-map "n" #'elpher-next-link) - (define-key elpher-mode-map "p" #'elpher-prev-link) - (define-key elpher-mode-map "o" #'elpher-follow-current-link) - (define-key elpher-mode-map "G" #'elpher-go-current)) + (acdw/bind-after-map 'elpher elpher-mode-map + (("n" #'elpher-next-link) + ("p" #'elpher-prev-link) + ("o" #'elpher-follow-current-link) + ("G" #'elpher-go-current))) #+end_src #+begin_src emacs-lisp :noweb-ref hooks -- cgit 1.4.1-21-gabe81