I do not understand why you would prefer to have some binding that would switch to normal-state
instead of just staying in insert-state
, and in that case you can simply bind the normal-state-commands
to the key-combo's in insert-state
. However, if you insist on having the inconvenient behavior of also switching to normal state (and move your finger to M
instead of ESC
), then in response to the answer by @wasamama (and your comment there), I would say that creating a workaround isn't that hard. You could create a binding for every key-combo starting with M
in insert mode, to a function which runs the command that is bound in the evil-normal-state-map
, e.g.:
(defun my-evil-normal-from-insert ()
(interactive)
(let ((normal-key (substring (key-description (this-command-keys)) 2)))
(evil-normal-state)
(funcall (alist-get (string-to-char normal-key) (cdr evil-motion-state-map)))))
If you don't want to exit from insert-state, then you could comment out evil-normal-state
and have the arguably more convenient behavior.
However, many normal-state
bindings (like those of j,k,h,l
) are actually defined in the evil-motion-state-map
, so if you only require such commands, then you could simply replace the map in the function above.
If you would like to 'remap' all keys after M
with commands that can be bound in either the evil-motion-state-map
or the evil-normal-state-map
then you could use the following function:
(defun my-evil-normal-from-insert ()
(interactive)
(let ((maps (list evil-motion-state-map evil-normal-state-map))
(normal-key (substring (key-description (this-command-keys)) 2))
(continue t))
(while (and maps continue)
(when-let (command (alist-get (string-to-char normal-key) (cdar maps)))
;; (evil-normal-state)
(funcall command)
(setq continue nil))
(setq maps (cdr maps)))))
Then you can define the bindings for the insert-state keys that you need individually, or you could create a loop to bind most/all of them.
Here follows an example for such a loop, where I have not checked if all created bindings make sense:
(let* ((letters "qwertyuiopasdfghjklzxcvbnm")
(capitals (upcase letters))
(others "1234567890-=[];',./!@#$%^&*()_+{}|:<>?")
(c-list (split-string (concat letters capitals others) "")))
(dolist (l c-list)
(evil-global-set-key 'insert (kbd (concat "M-" l)) #'my-evil-normal-from-insert)))
You could extend the loop if you would like to bind even more options.
I am almost sure that there must be more elegant ways to achieve this. However, I think this example already shows how 'hackable' Emacs is, by showing how often Emacs can still do things, despite those things 'being hard-coded' not to work in a certain way.