summaryrefslogtreecommitdiff
path: root/.config/emacs/modules/mm-keybindings.el
blob: dc49261c61d5f3127fa2d1173bce221a6717cc64 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
;;; mm-keybindings.el --- Emacs keybindings  -*- lexical-binding: t; -*-

(require 'editing)

;; The following keys are either unbound and are free to populate, or are
;; bound to functions I don’t care for:
;; ‘C-i’, ‘C-j’, ‘C-o’, ‘C-{’, ‘C-}’, ‘C-|’, ‘C-/’, ‘C-\;’, ‘C-:’

^L
;;; Helper Macros

(defmacro mm-keymap-set (keymap &rest definitions)
  (declare (indent 1))
  (unless (cl-evenp (length definitions))
    (user-error "Expected an even-number of elements in DEFINITIONS."))
  `(cl-loop for (from to) on (list ,@definitions) by #'cddr
            do (keymap-set ,keymap from to)))

(defmacro mm-keymap-set-repeating (keymap &rest definitions)
  (declare (indent 1))
  (unless (cl-evenp (length definitions))
    (user-error "Expected an even-number of elements in DEFINITIONS."))
  (let ((keymap-gen (gensym "mm-keybindings--repeat-map-")))
    `(progn
       (defvar-keymap ,keymap-gen)
       (cl-loop for (from to) on (list ,@definitions) by #'cddr
                do (progn
                     (keymap-set ,keymap-gen from to)
                     (put to 'repeat-map ',keymap-gen))))))

(defmacro mm-keymap-remap (keymap &rest commands)
  "Define command remappings for a given KEYMAP.
COMMANDS is a sequence of unquoted commands.  For each pair of COMMANDS
the first command is remapped to the second command."
  (declare (indent 1))
  (unless (cl-evenp (length commands))
    (user-error "Expected an even-number of elements in COMMANDS."))
  (macroexp-progn
   (cl-loop for (from to) in (seq-partition commands 2)
            collect `(keymap-set
                      ,keymap
                      ,(concat "<remap> <" (symbol-name from) ">")
                      #',to))))

^L
;;; Support QMK Hyper

(defun mm-qmk-hyper-as-hyper (args)
  (let ((chord (cadr args)))
    (when (string-prefix-p "H-" chord)
      (setf (cadr args) (concat "C-M-s" (substring chord 1)))))
  args)

;; Both ‘keymap-global-set’ and ‘keymap-local-set’ call ‘keymap-set’
;; internally, so this advice covers all cases
(advice-add #'keymap-set :filter-args #'mm-qmk-hyper-as-hyper)

^L
;;; Disable ESC as Meta

(keymap-global-set "<escape>" #'ignore)

^L
;;; Enable Repeat Bindings

(use-package repeat
  :init
  (repeat-mode))

^L
;;; Remap Existing Bindings

(mm-keymap-remap global-map
  backward-delete-char-untabify backward-delete-char
  kill-ring-save                e/kill-ring-save-dwim

  capitalize-word capitalize-dwim
  downcase-word   downcase-dwim
  upcase-word     upcase-dwim

  mark-word e/mark-entire-word
  mark-sexp e/mark-entire-sexp

  transpose-chars e/transpose-previous-chars
  transpose-lines e/transpose-current-and-next-lines

  delete-indentation e/join-current-and-next-line)

(with-eval-after-load 'cc-vars
  (setopt c-backspace-function #'backward-delete-char))

^L
;;; Remove Unwanted Bindings

(keymap-global-unset "C-x C-c" :remove) ; ‘capitalize-region’
(keymap-global-unset "C-x C-l" :remove) ; ‘downcase-region’
(keymap-global-unset "C-x C-u" :remove) ; ‘upcase-region’

^L
;;; Bind Commands Globally

(mm-keymap-set global-map
  "<next>"    #'e/scroll-up
  "<prior>"   #'e/scroll-down
  "C-<next>"  #'forward-page
  "C-<prior>" #'backward-page

  "C-." #'repeat
  "C-/" #'e/mark-line-dwim

  "C-c d"   #'duplicate-dwim
  "C-c t a" #'e/align-regexp
  "C-c t f" #'fill-paragraph
  "C-c t s" #'sort-lines)

(mm-keymap-set-repeating global-map
  "j" #'e/join-current-and-next-line
  "J" #'join-line)

(with-eval-after-load 'increment
  (mm-keymap-set-repeating global-map
    "d" #'decrement-number-at-point
    "i" #'increment-number-at-point))

^L
;;; Display Available Keybindings

(use-package which-key
  :hook after-init
  :custom
  (which-key-dont-use-unicode nil)
  (which-key-ellipsis "…")
  (wihch-key-idle-delay .5))

(provide 'mm-keybindings)