Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
68 lines (61 sloc) 3.85 KB
;;; Bind keys from some prefixes in different ones, making them more convenient. -*- lexical-binding: t -*-
;; Conventions for the C-c prefix:
;; * Letter (upper or lower case): reserved for the user.
;; * Control character, digit, :, ;, {, }, <, >: major mode.
;; * Other punctuation: minor mode (or sometimes major mode).
(with-eval-after-load 'evil
(require 'conf/utils/keys) ; Used: map-bindings-between-keymaps.
(require 'conf/utils/lists) ; Used: list-to-vector.
(require 'conf/utils/events) ; Used: event-with-modifier, event-without-modifier, event-inverted-modifier.
(require 'cl-lib) ; Used: cl-set-difference.
(defun my-make-key-more-convenient (key)
"Make the key vector KEY more convenient to hit after a prefix starting with a non-modified keypress.
Do that by inverting the state of Control on some events (all C-letter except C-h (help), C-m (RET), C-i (TAB))."
(let ((first-event-of-key (car (vector-to-list key)))
;; Invert Control on all C-letters except C-h (help), C-m (RET), C-i (TAB), C-g (quit).
(control-inverted-events (cl-set-difference (number-sequence ?a ?z)
'(?h ?m ?i ?g))))
(cond
;; If KEY starts with C-`char' or `char', with `char' in `control-inverted-events',
;; invert Control state on all events in KEY that are in `control-inverted-events'.
((or (memq first-event-of-key control-inverted-events)
(memq (event-inverted-modifier 'control first-event-of-key) control-inverted-events))
(list-to-vector
(mapcar (lambda (event)
(if (or (memq event control-inverted-events)
(memq (event-inverted-modifier 'control event) control-inverted-events))
(event-inverted-modifier 'control event)
event))
key)))
;; Otherwise, do nothing.
(t key))))
;; Make "e" a prefix for "C-x" commands, and "C-e" the former "e" (end of word).
(defun rebind-C-x-to-e ()
"Bind all \"C-x\" bindings in the \"e\" prefix (in `evil-motion-state-map'), with the `my-make-key-more-convenient' transformation."
(interactive)
(bind-key "e" nil evil-motion-state-map)
(map-key-sequences-in-keymap (key-binding (kbd "C-x"))
(lambda (key binding)
(define-key evil-motion-state-map
(concat-keys (kbd "e") (my-make-key-more-convenient key))
binding))))
(bind-key "C-e" #'evil-forward-word-end evil-motion-state-map)
(add-hook 'emacs-startup-hook #'rebind-C-x-to-e)
;; Make "SPC" a prefix for "C-c" commands.
(defun rebind-C-c-to-SPC ()
"Bind all \"C-c\" bindings in the \"SPC\" prefix (in the current major mode's map), with the `my-make-key-more-convenient' transformation.
Omit \"C-c [a-zA-Z]\" bindings, since they are not major-mode bindings, but user's custom ones."
(interactive)
(bind-key "SPC" nil evil-motion-state-map)
(bind-key "SPC" nil evil-motion-state-local-map)
(map-key-sequences-in-keymap (key-binding (kbd "C-c"))
(lambda (key binding)
;; Ignore the binding if KEY starts with a character from [a-zA-Z].
(unless (memq (car (vector-to-list key))
(append (number-sequence ?a ?z) (number-sequence ?A ?Z)))
(define-key evil-motion-state-local-map
(concat-keys (kbd "SPC") (my-make-key-more-convenient key))
binding)))))
(add-hook 'after-change-major-mode-hook #'rebind-C-c-to-SPC t)
(add-hook 'emacs-startup-hook #'rebind-C-c-to-SPC))
(provide 'conf/evil-specific/convenient-prefix-keys)