1. Frank Fischer
  2. evil
  3. Issues
Issue #4 resolved

`evil-define-key' like `vimpulse-define-key'

Michael Markert
created an issue

In vimpulse I could define a key for a mode that is not already loaded.

Now I have to use `evil-define-key' on a real keymap, i.e. the keymap must already be defined and thus the file loaded.

This leaves me with either use a mode-hook use eval-after-load.

Both are not really satisfying.

Comments (7)

  1. Vegard Øye

    In Vimpulse, the function for assigning a state binding to a mode is:

    (vimpulse-define-key MODE STATE KEY DEF)

    In Evil, the equivalent function is:

    (evil-define-key STATE KEYMAP KEY DEF)

    The main difference is that the MODE argument has been replaced by a KEYMAP argument. The reason for this change is that not all keymaps have modes. The Vimpulse function cannot handle modeless keymaps, while the Evil function can.

    I can see that repeatedly using eval-after-load/require/mode hooks can get frustrating, though, and the ideal may be a MODE-OR-KEYMAP argument. Then one could pass either a mode symbol or a keymap to the function, and both would work. Unfortunately, this is only partially implementable.

    To see why, consider that Vimpulse gets its mode information from minor-mode-map-alist, which is an association list of modes and keymaps. Evil, on the other hand, uses the output of (current-active-maps), which is a plain list of keymaps without any mode information (but which includes some keymaps that are not listed in minor-mode-map-alist). Evil's approach is more complete, but it lacks the necessary information to look up mode symbols.

    One could solve this by running through (current-active-maps) first (looking up keymaps), and then through minor-mode-map-alist (looking up mode symbols), but this would mess up the keymap order: if two keymaps bind the same key, then the "first" keymap should win. The "first" keymap is the keymap which is listed first in the output of (current-active-maps), usually because it occurs first in minor-mode-map-alist. Running through both in sequence would give all the keymap bindings precedence over the mode bindings, or the other way around. (One could check if each keymap from (current-active-maps) has an entry in minor-mode-map-alist, but it would likely have a huge penalty cost. Maybe one could solve this by "merging" the two as one is running through them ... but I imagine that could break very easily.)

    All things considered, I think the safest approach would be to create a macro wrapper for evil-define-key. If the macro receives an unbound keymap variable, it will try to re-evaluate it in the after-load-functions hook, i.e., whenever a new file is loaded. Once the variable points to a keymap, the binding is made, and the re-evaluation is stopped.

  2. Log in to comment