Jakub Arnold's Blog


Evil Mode: How I Switched From VIM to Emacs

I’ve been a long time VIM user. I use it every day for all of my work and side projects, writing blog posts, writing other content, sometimes even for writing emails if the text is long enough. VIM is like my home and I’m deeply in love with it.

The problem is that VIM is a horrible IDE. It’s an amazing and super productive editor, but it really sucks at doing IDE-like things. Now you might be thinking I’m a noob who needs to click on good looking buttons in RubyMine to get things done. No, that’s not what I mean by IDE … let me explain.

Most of my work in the past years has been either Ruby or JavaScript. Those are dynamic languages with close to none IDE support. You don’t usually run a REPL and eval your Rails app, but instead write a test, write some code, hit a button to run the test, and occasionally reload the browser.

Most of the work is heavy editing of large amounts of source code, which is what VIM excels at. Running the tests is easy as well, since you can just bind it to a key with a single line of vimscript

nnoremap <leader>t :!rspec %<cr>

This is all nice, but what if you want to use a language which has a REPL? What if you want to display errors inline every time you save a file?

I can actually answer both of these right now. There were numerous attempts to bring something REPL-like to VIM, but usually the outcome is unusable. Most people I know don’t even bother with this and use tmux. Which is fine if this is the only problem you’re trying to solve, but there’s more. Let’s go to problem #2.

If you’ve been using VIM for a while, you probably immediately thought Doesn’t syntastic already display errors inline?. Yes it does, but it’s doing so in a synchronous way. Which means if you’re using a checker which is slower than half a second, you will have a bad time. This is especially true for ghc-mod, which takes up to 5 seconds on my machine. There are alternatives that make this faster, but this is still talking about a fast dev machine. When I’m working on my tiny 11" Lenovo, it’s just impossible to have Syntastic turned on.

Evil Mode

I’ve been using Emacs on and off for about 2-3 years now. But there was always the feeling of being slow compared to VIM. Especially once you get really fast at navigating in VIM, it’s hard to use anything else.

Then one night I decided to give Evil Mode. Every other editor supports some sort of VIM emulation, but every single one of them I tried fell short. But not Emacs. I am completely blown away by the level of integration Evil Mode has. There are even ports of the most popular VIM plugins into Evil Mode, such as Tim Pope’s vim-surround.

Almost everything works out of the box, and even more, it works really well with the built-in Emacs key-bindings. You can search, record macros, jump around like you would in VIM, but you get the full power of Emacs at your hand as well. This means you can be in the middle of typing something and immediately press C-c C-l while still in insert mode to load your file into the REPL. (Yes you still have to save the file, but that can be done while in insert mode as well.)

There are things that I love about Emacs that I was missing in VIM, and there are things about VIM that I was missing in Emacs, but Evil Mode does such a great job at bringing the two together. It’s hard to describe this feeling in words. I can only imagine that the developers behind it are very skilled VIM users.

Disadvantages

While most things work really nice with the default Emacs keymap, there is one VIM feature that I had to disable, and that is q. The reason for this is that q is being used at many places in Emacs to close things, and sometimes it so happens that Evil Mode is turned on in that window at the same time, which results in recording a macro instead of closing the window.

Here’s my complete list of customizations.

(define-key evil-normal-state-map (kbd ",f") 'projectile-find-file)
(define-key evil-normal-state-map (kbd ",,") 'evil-buffer)
(define-key evil-normal-state-map (kbd "q") nil)

(define-key evil-insert-state-map (kbd "C-e") nil)
(define-key evil-insert-state-map (kbd "C-d") nil)
(define-key evil-insert-state-map (kbd "C-k") nil)
(define-key evil-insert-state-map (kbd "C-g") 'evil-normal-state)
(define-key evil-visual-state-map (kbd "C-c") 'evil-normal-state)

(define-key evil-motion-state-map (kbd "C-e") nil)
(define-key evil-visual-state-map (kbd "C-c") 'evil-exit-visual-state)

Most of these are just minor inconveniences, though I really do appreciate the level of customization available in Evil Mode. If anything misbehaves, it’s easy to just C-h k and press the key, to see which function gets invoked. After that it’s just a matter of looking at the source code, or simply overriding the key in the specific mode.

Customizability (is that even a word?) is one of the reasons why I’m starting to like Emacs more and more. Even though I’m not a big Lisp fan, I still prefer it to vimscript any day of the week. Most of the Elisp code out there is very readable and well commented, so it’s not that hard to dig into the source of the package you’re using and try to figure some things out. Having more customization options is also a disadvantage to some extent, since Emacs packages are usually more complex than the VIM counterparts and it takes more time to setup things.

I don’t think I’ll ever give up VIM entirely, mostly because I’ve invested many years into perfecting my Ruby workflow. That being said, I don’t mind switching to Emacs for other languages, where the support is much better to begin with, and the price to pay in terms of differences between evil mode and VIM is quite small. Maybe one day I will be able to write Ruby in Emacs as well.

Related
Emacs