DRY way of remapping a key in all relevant modes
Hi, I've been using Vim with extensive remappings designed for the Colemak keyboard layout (http://colemak.com/pub/vim/colemak.vim). I'm trying to recreate the Vim mappings in Emacs with Evil. What's a good way of remapping a key in all relevant contexts? For example, I want "i" mapped to evil-forward-char in normal, visual, visual block, dired, etc. modes. I want to avoid this: (define-key evil-normal-state-map "i" 'evil-forward-char) (define-key evil-visual-state-map "i" 'evil-forward-char) (define-key whatever-corresponds-to-dired-map "i" 'evil-forward-char) I tried to write some Elisp to do this, but it doesn't work (Wrong type argument): (defun remap-all (char action states) (if states (progn (define-key (car states) char action) (remap-all char action (cdr states))))) (setq states '(evil-normal-state-map evil-visual-state-map)) (remap-all "i" 'evil-forward-char states) Thanks, Patrick
On Sat, Sep 22 2012 (10:22), Patrick Brinich-Langlois <[email protected]> wrote: [14 lines snipped]
I tried to write some Elisp to do this, but it doesn't work (Wrong type argument):
(defun remap-all (char action states) (if states (progn (define-key (car states) char action) (remap-all char action (cdr states))))) (setq states '(evil-normal-state-map evil-visual-state-map)) (remap-all "i" 'evil-forward-char states)
The problem is that you pass a list of symbols (e.g. (list 'evil-normal-state-map ...)) instead of a list of keymaps. Use (list evil-normal-state-map ...) to build such a list. Here's another approach, as recursion is not a fine choice for elisp: (defun set-in-all-evil-states (key def &optional maps) (unless maps (setq maps (list evil-normal-state-map evil-visual-state-map evil-insert-state-map evil-emacs-state-map))) (while maps (define-key (pop maps) key def))) ;; usage (set-in-all-evil-states "i" 'evil-forward-char) ;; or (set-in-all-evil-states "i" 'evil-forward-char (list evil-normal-state-map evil-visual-state-map)) HTH, Michael
Here's another approach, as recursion is not a fine choice for elisp:
(defun set-in-all-evil-states (key def &optional maps) (unless maps (setq maps (list evil-normal-state-map evil-visual-state-map evil-insert-state-map evil-emacs-state-map))) (while maps (define-key (pop maps) key def)))
;; usage
(set-in-all-evil-states "i" 'evil-forward-char)
;; or
(set-in-all-evil-states "i" 'evil-forward-char (list evil-normal-state-map evil-visual-state-map))
HTH, Michael
Thanks, Michael! That does help. It doesn't affect the bindings in Dired, though. Do I have to define those bindings specifically? For example, (evil-define-key 'normal dired-mode-map "i" 'evil-forward-char) Or is there a better way? Patrick
OK, I understand now that if my normal/insert/etc. remappings affected the Dired bindings, they would override the default Dired bindings, since most of them lack modifier keys. So maybe I'll just use the default Dired bindings.
On Sun, Sep 23 2012 (01:47), Patrick Brinich-Langlois <[email protected]> wrote:
Thanks, Michael! That does help. It doesn't affect the bindings in Dired, though. Do I have to define those bindings specifically? For example,
(evil-define-key 'normal dired-mode-map "i" 'evil-forward-char)
Or is there a better way?
Well you can certainly pack it into the function (I made also some other adjustments): (defun set-in-all-evil-states (key def &optional maps additional) (let ((maps (or maps (list evil-normal-state-map evil-visual-state-map evil-insert-state-map evil-emacs-state-map)))) (dolist (map maps) (define-key map key def)) (when additional (dolist (pair additional) (let ((state (first pair)) (map (second pair))) (evil-define-key state map key def)))))) although the interface gets quite messy as you have to encode the states you want to bind: (set-in-all-evil-states "i" 'evil-forward-char nil (list (list 'normal dired-mode-map) (list 'insert dired-mode-map))) You could admit symbols for the maps as well for a more concise one: (set-in-all-evil-states "i" 'evil-forward-char nil '((normal dired-mode-map) (insert dired-mode-map))) (defun set-in-all-evil-states (key def &optional maps additional) (let ((maps (or maps (list evil-normal-state-map evil-visual-state-map evil-insert-state-map evil-emacs-state-map)))) (dolist (map maps) (define-key map key def)) (when additional (dolist (pair additional) (let ((state (first pair)) (map (second pair))) (evil-define-key state (if (symbolp map) (symbol-value map) map) key def)))))) Of course you can tinker any further with it. Have fun, Michael
I want "i" mapped to evil-forward-char in normal, visual, visual block, dired, etc. modes. I want to avoid this:
If you want the key binding in normal and visual, you can add it to the evil-motion-state-map, which is active in both of those two. In terms of how to integrate it with Dired's own key bindings, I wrote up a guide on that kind of thing a few weeks ago: http://emacswiki.org/emacs/Evil#toc7 On Sat, Sep 22, 2012 at 4:22 AM, Patrick Brinich-Langlois < [email protected]> wrote:
Hi,
I've been using Vim with extensive remappings designed for the Colemak keyboard layout (http://colemak.com/pub/vim/colemak.vim). I'm trying to recreate the Vim mappings in Emacs with Evil. What's a good way of remapping a key in all relevant contexts? For example, I want "i" mapped to evil-forward-char in normal, visual, visual block, dired, etc. modes. I want to avoid this:
(define-key evil-normal-state-map "i" 'evil-forward-char) (define-key evil-visual-state-map "i" 'evil-forward-char) (define-key whatever-corresponds-to-dired-map "i" 'evil-forward-char)
I tried to write some Elisp to do this, but it doesn't work (Wrong type argument):
(defun remap-all (char action states) (if states (progn (define-key (car states) char action) (remap-all char action (cdr states))))) (setq states '(evil-normal-state-map evil-visual-state-map)) (remap-all "i" 'evil-forward-char states)
Thanks, Patrick
_______________________________________________ implementations-list mailing list [email protected] https://lists.ourproject.org/cgi-bin/mailman/listinfo/implementations-list
participants (3)
-
Barry OReilly -
Michael Markert -
Patrick Brinich-Langlois