3

I'm trying to transfer over from vim to Emacs. I'm using evil to emulate vim modal editing. In vim, I've remapped jk to get me out of insert mode and back into normal mode using inoremap jk <esc>. At the moment, I'm using

(key-chord-define evil-insert-state-map "jk" 'evil-normal-state)
(key-chord-define evil-replace-state-map "jk" 'evil-normal-state)

to do this in Emacs.

However, when I'm in insert mode and want to type, say, jump, I end up with just mp, and j u is undefined appears under the mode bar.

Is there any way to fix this behaviour? Preferably, the solution would even allow me to type jk by typing j, waiting, and then typing k (like in vim).


UPDATE

To clarify, I was only using key-chord as a temporary solution to get me into normal mode; I am very willing to accept any solution that fixes the problem, regardless of whether it involves key-chord.

  • This shouldn't happen in the first place with key-chord. – wasamasa Jan 31 '16 at 10:19
  • (key-chord-define evil-insert-state-map "jk" 'evil-normal-state) let's you escape from insert mode. – ReneFroger Feb 3 '16 at 9:38
3

FWIW, I cannot reproduce the condition as reported above. It would be helpful if you could share a minimal configuration that can reproduce this error of yours.

An alternative way of solving this is writing a command bound to the initial key of the escape sequence that waits with a timeout for another event to occur. If this event happens in a timely manner and matches the final key of the escape sequence, execute the command to exit insert state. If the timeout is met, but the final key is wrong, insert the initial key and the different one. If the timeout is missed, insert the first key.

(defun my-jk ()
  (interactive)
  (let* ((initial-key ?j)
         (final-key ?k)
         (timeout 0.5)
         (event (read-event nil nil timeout)))
    (if event
        ;; timeout met
        (if (and (characterp event) (= event final-key))
            (evil-normal-state)
          (insert initial-key)
          (push event unread-command-events))
      ;; timeout exceeded
      (insert initial-key))))

(define-key evil-insert-state-map (kbd "j") 'my-jk)

Another implementation of the above with slightly different semantics can be found in cofi's config.

  • The file you like to is far from trivial. Can you add a line reference so we can quickly jump to the section you mention? – PythonNut Feb 3 '16 at 5:29
4

You have, in effect, defined j as a prefix key, which means that any key you press after it is looked up in the keymap associated with j. Since u is undefined after j you get the behavior you see.

A key cannot be bound to two different commands. In particular, it cannot be bound to both self-insert-command (or equivalent), which inserts a character, and bound to a keymap (acts as a prefix key).

What you can do instead is to bind j to a command that reads a character and does something different depending on what that character is: If it is k then do evil-normal-state. If it is any other character than k then it inserts that character.

Something like this (but you would bind the key in some Evil mode, no doubt, not globally):

(defun my-j ()
  "Read a char.  If `k' then invoke `evil-normal-state'.  Else insert it."
  (interactive)
  (let ((ch  (read-char-exclusive)))
    (if (eq ?k ch)
        (message "Invoke EVIL-NORMAL-STATE HERE") ;; (evil-normal-state)
      (insert "j" (string ch)))))

(global-set-key "j" 'my-j)
  • This can be done significantly better by taking a timeout into account, see this question for a code example. – wasamasa Jan 31 '16 at 10:20
  • Also, the first part of the explanation does not apply as this is not regular define-key, but key-chord-define... – wasamasa Jan 31 '16 at 10:21
  • @wasamasa; could you put this into an answer? – digitalis_ Feb 1 '16 at 18:13
  • Neither of these answer the question as is, so I won't until it changes to reflect that you're no longer interested in using key-chord to escape from Evil's insert state. – wasamasa Feb 1 '16 at 23:32
  • @wasamasa; I've updated the question accordingly. – digitalis_ Feb 2 '16 at 16:47
0

(key-chord-define evil-insert-state-map "jk" 'evil-normal-state) let's you escape from insert mode.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.