1. Frank Fischer
  2. evil
  3. Issues
Issue #350 invalid

Entering Evil Normal State by Default Anywhere

Alexander Shukaev
created an issue

Evil provides the following function:

(evil-define-command evil-window-new (count file)
  "Splits the current window horizontally
and opens a new buffer or edits a certain FILE."
  :repeat nil
  (interactive "P<f>")
  (split-window (selected-window) count)
  (if file
      (evil-edit file)
    (let ((buffer (generate-new-buffer "*new*")))
      (set-window-buffer (selected-window) buffer)
      (with-current-buffer buffer
        (evil-normal-state)))))

In my opinion, the last line reveals a huge flaw.

First of all, recently I've been writing a tiling window manager for Emacs. Of course when I create new windows there, I create buffers as well with the same generate-new-buffer function.

And of course as suggested by the evil-window-new function presented above, one has to call (with-current-buffer buffer (evil-normal-state)) so that Evil does not break here and works properly in this newly created buffer.

That's incredibly annoying for 2 main reasons:

  1. now, for instance, my tiling window manager has to depend on the Evil package just to make this little hack for those who wish to use Evil with my tiling window manager; Obviously this also applies to all the other Emacs 3rd party packages that manipulate buffers somehow;
  2. you have already probably noticed that such buffers as Emacs Help and friends do not work with Evil properly too.

The reason for that is the same simply because in case of Emacs Help buffer you could no longer inject this hackish call:

(with-current-buffer buffer (evil-normal-state))

Evil should have more seamless and natural integration with the whole Emacs environment. And my proposal to you is to include the following snippets in Evil:

(defadvice generate-new-buffer
  (after evil-normal-state (name) activate)
  (with-current-buffer ad-return-value (evil-normal-state)))

(defadvice other-buffer
  (after evil-normal-state (&optional buffer visible-ok frame) activate)
  (with-current-buffer ad-return-value (evil-normal-state)))

(defadvice get-buffer-create
  (after evil-normal-state (buffer-or-name) activate)
  (with-current-buffer ad-return-value (evil-normal-state)))

(add-hook
 'temp-buffer-show-hook
 (lambda ()
   (with-current-buffer (current-buffer) (evil-normal-state))))

I've tested this and it works like a charm. After that you can remove this hackish (with-current-buffer buffer (evil-normal-state)) from all of your functions, and enjoy Evil in any buffer that gets opened in Emacs by default.

Looking forward to your feedback!