On Thu, Aug 11, 2011 at 01:56:05AM +0200, Michael Markert wrote:
Hi,
I'm using this function to exit insert state with jk
You found a point where the evil already has an answer ;) The following code should work (I removed the lambda-trick because you need 'evil-define-command' so this is easier). #+begin_src emacs-lisp (define-key evil-insert-state-map "j" #'cofi/maybe-exit) (evil-define-command cofi/maybe-exit () :repeat change (interactive) (let ((modified (buffer-modified-p))) (insert "j") (let ((evt (read-event (format "Insert %c to exit insert state" ?k) nil 0.5))) (cond ((null evt) (message "")) ((and (integerp evt) (char-equal evt ?k)) (delete-char -1) (set-buffer-modified-p modified) (push 'escape unread-command-events)) (t (setq unread-command-events (append unread-command-events (list evt)))))))) #+end_src emacs-lisp The only difference is the keyword ':repeat change' and instead of switching back to normal mode the 'escape event resend (given that this event still exits insert-mode, otherwise you need more work). Let me explain how this works. Evil knows two different ways of recording changes. The first simpler way is to record the key-strokes, which is the default for (almost) all commands. This is usually what you want and this approach handles some cases like automatic identation very well. But your function is ... evil. Its behaviour depends on time and therefore the function is not recordable as key-strokes. Even if the switch back to normal-state would work, it would be impossible to repeat the two characters "jk" in some word, because when repeated those two commands would always follow very quickly and therefore exit insert-state, no matter how big the pause between the two original key-strokes has been. The same problem arises, e.g., for some auto-completion packages which popup possible completions after some time. For these situations Evil has a second way to record repeation, namely by buffer changes. Instead of recording the key-sequences the buffer changes itself are recorded (and the key-strokes are dropped). The keyword ':repeat change' makes Evil repeat your function by change instead of by key-strokes. This means when "jk" is repeated the function cofi/maybe-exit is never called again. Instead the buffer change itself is replayed, which is either the insertion of "jk" or the insertion and deletion of "j". Furthermore, if "jk" is used to exit insert-state, the extra event 'escape is appended to the repeat-information (i.e., the whole repeat-information for the insertion consists of the command to start insert-state, some keys that are inserted literally, some buffer changes caused by "jk" and finally a key-stroke sequence [escape]) which is the same as pressing escape. I hope this helps. Frank