I spent this week using Vim. Yes, me, the Emacs fan-boy using Vim. Why you ask? Because it was better than using Zend Studio. See, we are working on a PHP project at work, and the general slowness of Zend and its primitive key bindings left me wanting for more. I tried Emacs, but I ran into a few indentation problems. Also, I knew that I wouldn’t be writing as much new code as correcting mistakes in old code, so I thought that Vim would be the best for that job. And it was; I quickly got back into Vim mode in spite of not using it for much more than configuration files editing. This made me think about Vim and Emacs as editors and of course, which one is the better one? The short answer: neither is better than the other. They both got great features in common that other editors lack such as file recovery. There are some points however where I have a preference for one or the other. This is what this post is going to be about, a bunch of features where I think one of the two has a advantage.
Editing (Vim)
Vim is king when it comes to editing code. There is no contest whatsoever. Take any general- or specific-purpose text editor, pit it against Vim and Vim will come out as the winner. I like modal editing, it gives you a whole lot more commands to work around with your text. As you may have heard if you are no a vi/vim user, the commands such as deleting, changing (deleting and going back in insert mode) and yanking (copying) can be mixed with the very powerful movement commands. You want to delete text until the second closing parenthese? d2t). That’s it. The 2t) command brings the cursor over the character preceding the second parenthese after the current position of the cursor. To delete the text between these two positions, you just prepend ‘d’. Emacs doesn’t have this kind of power. You need to go in mark-mode (where you select text), and use either the movement commands or do a search on ‘)’, hit C-s to go to the next match and then C-w to kill the mark. This works, of course, but it’s a bit more work. Vim also does an operation on an entire line if you press on the operator key twice: dd deletes the current line. The way to do that in Emacs is C-a C-k C-k (or just one C-k if you set kill-whole-line to T). No matter what other modeless editors try to do, I don’t think they can match the editing power of Vim, period.
Edit: A helpful commenter mentioned the zap-to-char command, which is mapped to M-z, so my example that Emacs can’t delete up until a particular character doesn’t work anymore. However, if we change the operation from deleting to upcasing or downcasing up until a particular character, Vim works the exact same way (with the gU and gu commands.) Emacs doesn’t have such a built-in command, so you will need to select the text and then use M-x upcase-region.
Key bindings (Vim)
I love the Vim keybindings. The non-reliance on the modifier keys such as Ctrl and Alt is appreciated by my wrists. I don’t have carpal tunnel, however, after long Emacs editing sessions I sometimes feel a lot of pain in my wrists. Vim is also better when I use a french canadian keyboard. As an example, in Emacs to indent a region, the keyboard shortcut in C-M-\. On a US keyboard, this isn’t so bad, however on a french keyboard, writing a backslash is done by pressing AltCar (the Alt key to the right of your space bar) and the ` key as located on a US keyboard. This key sequence is so awkward that most of the time, I just use M-x indent-region instead. With Vim, I select the region with V (visual line) and press = to reindent. No pain there. Vim also just has a whole lot more keybindings than Emacs. In a column called My save-excursion, Steve Yegge, a die-hard Emacs user, writes a Lisp function to count the number of characters in the current buffer. He also counts word by simply dividing the number of characters by 5. Commenters are quick to point out that he could’ve selected the entire buffer and ran the wc Unix program on that selection (the complete sequence is C-x h M-| wc <RET>). Surprisingly, I don’t think I saw any Vim user say that he could’ve used g CTRL-G had he been using Vim. If you want to see some unusual Vim commands, look at all the g and z commands.
Selection mode (Vim)
In Vim, selecting text is called visual mode, in Emacs it’s setting the mark. I prefer Vim here too for the same reasons as editing. One of Vim’s visual mode is the visual block mode. It allows you to define a rectangle and edit on that section. Emacs has something similar, however you need to visualize the rectangle: the entire lines are selection (except the first and last) and you need to remember that when you are going to use a rectangle editing command (which are all different from the normal mark commands by the way, another source of annoyance) the section that’s going to be worked on is the wide as much as from the beginning of the mark up until the end of the mark. It’s kind of hard to explain, but Vim makes the whole thing easier by showing you just the rectangle you are about to edit. And in Vim, the keys do not change; d will delete the rectangle as it deletes a normal selection. In Emacs, deleting a normal selection is C-w, but deleting in rectangle mode is C-x r d. I often forget the rectangle editing commands in Emacs.
Syntax highlighting (Vim)
There’s only one word to win this for Vim: inkpot. Inkpot is the sexiest color scheme ever, it puts to shame all other vim and Emacs color schemes. Vim also seems to color more elements than Emacs, so that’s another point in its favor.
Hey, funny story, while I was looking for a screenshot of inkpot, Firefox froze up and for some reason froze openbox, my window manager, too. I hadn’t saved this post (which I am writing in Vim), but Vim’s recovery system worked flawlessly. I wasn’t even worried.
Auto indenting (Emacs)
Maybe it’s because Emacs has a more powerful and expressive extension language, but Emacs has less problems with auto indenting than Vim. Here are two examples:
# Emacs indenting Python code
foo(10,
"hello")
# Vim indenting the same Python code
foo(10,
"hello")
# Emacs indenting Ruby code
a = {
'one' => a.sort { |a, b|
a.length b.length
},
}
# Vim indenting the same Ruby code
a = {
'one' => a.sort { |a, b|
a.length b.length
},
}
In pretty much any language I used, the Emacs indenting was always better than Vim’s. Emacs has also a command that I find myself using all the time called M-x align. Basically, you select a bunch of assignment lines, you call align and all the equal signs will be aligned. It also works with dictionaries/hashes. Aligning code makes it easier to read, and it’s nice that I don’t need to do that by myself.
Command line (Emacs)
When I talk about the command line, I refer to the minibuffer in Emacs (accessible with M-x) and when you do a :, / or ? in Vim. Emacs has a few advantages here. Although both do tab completion, Emacs’ minibuffer works with dabbrev-mode, so you can type the beginning of a word then M-/ and Emacs will complete the word. If there are multiple matches, pressing on M-/ again will cycle to the next match. Vim cannot do that, using CTRL-P and CTRL-N will go up and down the history of commands. Another thing I prefer about Emacs is that when you use C-x C-f to open a file, the current working directory appears, so you know exactly where you are; Vim doesn’t do that. The iswitchb-mode in Emacs shows all the buffer names when you press C-x b, and when you start typing, iswitchb will match that string anywhere in all buffer names and remove those that don’t match. This is a very powerful and very useful way of changing buffers. This makes it easier, in my opinion, to work with multiple files in Emacs.
Extension language (Emacs)
Emacs is configured in Lisp, Vim is configured in VimScript. Lisp is just more powerful than VimScript and it is also more present in the system: I can do C-h f to view the documentation on a Lisp function, I can do C-h v to view the documentation on a Lisp variable. I can use any buffer to input Lisp code and C-x C-e will evaluate it. When I was looking for a way to wrap text in rcirc, an IRC client for Emacs, at the width of the narrowest window, I needed to write a function to find the smallest width. Here’s that function:
(defun narrowest-window-width ()
(apply #'min (mapcar #'window-width (windows-list))))
Easy, isn’t it? And I was able to find about window-list and window-width by using the afore-mentionned built-in help system for Lisp. When I look at the available modes and applications for Emacs, such as Gnus, ERC, rcirc, tetris, I can’t help but think that the Emacs folks chose the best possible language to extend Emacs. Vim supports many other languages besides VimScript, such as Python, Perl, Ruby, TCL, mzscheme, but I don’t think we’re likely to see popular extensions in those, because since they rely on a scripting extension that might not be available, portability is lost. Maybe a future version of Vim will officially support a second scripting language that will be included in the default distribution.
Documentation (tie)
Both editors have a tremendous amount of documentation that is browseable directly from the editor. I know I said earlier that I would list only the features where one editor had an advantage, but good documentation is often ignored in the open source world, and it’s important to mention that both editor are top-notch in this area.
Integration with other tools (Emacs)
Emacs has been integrated with virutally every tool in a programmer’s toolbox: debuggers, make, compilers, interpreters, manual pages, grep, version control systems, shells, you name it, there’s an Emacs mode to interact with that. The reason Vim gives to explain this lacking can be found in the *design-not* section of the documentation (:help design-not):
- Vim is not a shell or an Operating System. You will not be able to run a
shell inside Vim or use it to control a debugger. This should work the
other way around: Use Vim as a component from a shell or in an IDE.
A satirical way to say this: “Unlike Emacs, Vim does not attempt to include
everything but the kitchen sink, but some people say that you can clean one
with it. ;-)”
In spite of this goal, it appears that Vim users want more and more. The Clewn project integrates gdb with vim, Vim-Shell makes it possible to run shells and other programs in Vim’s split windows. Most languages have syntax and indent files, but people are now uploading plugins to http://vim.sf.net to make the manipulation of certain type of files (C files, Python files) easier. To an Emacs user, this sounds like they are trying to replicate the features found in Emacs’s programming modes. In version 7, new features have been added to VimScript (:h new-vim-script) such as lists, dictionaries and function references to make the extension language more powerful. A more powerful extension language means more advanced plugins. I expect that Vim will soon have programming support that rivals Emacs’ most powerful modes.
Folding (Vim)
Vim does folding out of the box, Emacs has something really basic called narrow-mode. Vim’s folding is much more like what we’ve come to expect from an editor that what Emacs offers. Vim also has the advantage of having multiple folding methods (manual, indent-based, marker-based, etc.) and has a bunch of z commands to open and close folds.
Self-contained (Vim)
Starting with version 7, Vim has its own built-in spell checker. This is a good thing, because you don’t have to rely on an external tool to do the spell checking. The *develop-spell* documentation section describes more technical reasons why a built-in spell checker was a better idea for Vim. Emacs integrates with existing spelling programs. On Unix systems, it’s not so bad to install ispell or aspell, but I’m not sure how easy it is to get them working on Windows systems. With Vim, I know I can have spell checking anywhere without having to install a separate, non-related package. Bonus points for the cute squiggly lines under the misspelled words. And as with anything in Vim, there is a flurry of commands to go to the next/previous misspelled word, add it to the dictionary, correct it, etc.
Version 7 also has a command called :vimgrep which works like :grep, but which doesn’t depend on an external grep command. This means that on Windows, where you are unlikely to have grep installed, you can still use that functionality. Again, Emacs’ M-x grep command relies on an externally installed grep program.
Having these commands built into the editor means that your workflow remains the same regardless of the platform you are working on. If you rely on external tools on one platform, then you move to another, your workflow is affected because the same commands cannot be used because the external programs they rely on are unavailable. A side effect of having more features built-in as opposed to being third-party additions is that pretty much everyone will use them, and bugs are much more likely to be found and fixed. It also reduces the number of files you need to carry around to have a comfortable environment. My elisp/ directory is 8 MB and I need it all to feel comfortable. With Vim, I just need my .vimrc file, the inkpot color scheme and the french spelling files. Beyond that, everything I need is already in Vim.
Completion (Vim)
In version 7, Vim introduced omni-completion, which is a bit like IntelliSense. Emacs has an external mode called CEDET that supposedly does something like that, but I was never able to install it, so I don’t know how well it works. OmniComplete is great however. If you type CTRL-P or CTRL-N and there is more than one match, a colorful menu is displayed in which you can select the appropriate completion. See this page for some screenshots of the C++ completion. Completion scripts for other languages are expected to be released, keep an eye out at www.vim.org for them.
February 24, 2007 at 6:11 pm
You’re kidding, right?
Alt-2 Alt-z )February 24, 2007 at 6:39 pm
Oops, I never knew about this zap command. Good to know!
February 24, 2007 at 7:22 pm
As far as indenting goes, I will agree that the indent script which comes with Vim is rather lacking. There is one that I use from vim.org (http://www.vim.org/scripts/script.php?script_id=974) which does a much better job of autoindenting python code.
One of the most common mistakes with Vim when it comes to indenting is the use of ’smartindent’, ‘autoindent’, and ‘cindent’. In general, those shouldn’t be enabled and one should use “:filetype indent on” instead. Granted, there are certain instances where Vim may not have an indent script and use of the indent options are better but those have been far and few between in my experience.
There’s also an alignment script for Vim (http://www.vim.org/scripts/script.php?script_id=294) which I’ve heard works quite well but don’t personally have experience with it since I’m not a fan of aligning code like that.
February 24, 2007 at 7:39 pm
Thanks for the tip on Align. I’ll try to install it. It looks like exactly what I want.
February 24, 2007 at 8:37 pm
Regarding the completion: I myself am *very* happy with hippie-expand in Emacs. Just paste the following into your ~/.emacs:
(require ‘hippie-exp)
(setq hippie-expand-try-functions-list
‘(try-expand-dabbrev
try-expand-dabbrev-all-buffers
try-expand-dabbrev-from-kill
try-complete-file-name-partially
try-complete-file-name
try-complete-lisp-symbol-partially
try-complete-lisp-symbol
try-expand-whole-kill))
also, I tend to use C-SPC for this instead of set-mark-command:
(global-set-key (kbd “C-SPC”) ‘hippie-expand)
Another great auto-completion feature in emacs (this time for the minibuffer (esp. when switching buffers or choosing files) is ido:
(require ‘ido)
(ido-mode t)
now if that really leaves anything to desire in comparison with vim’s OmniCompletion, I missed out there.
February 25, 2007 at 1:12 am
Folding: Emacs has it as outline minor mode (I contributed a tiny patch for cperl-mode to make better use of folding). Emacs 22 has added (at least, I don’t remember it in Emacs 21) foldout mode to make it even easier.
Emacs also has rect-mark.el which I think will do what you want with rectangular editing. I don’t know since I haven’t used that feature in vim.
February 25, 2007 at 7:12 am
Strange how something as trivial as the syntax highlight for a particular language can make you try another editor. Emacs was my first love and I used it for 6 years – all through university and into my first job. Then I had to write some MIPS assembly code and it sucked bad. Now, 6 years on, I remember as little about emacs as I knew about vim back then.
February 25, 2007 at 7:29 am
For someone who calls himself a “Emacs fan-boy” it seems you have no idea what you’re talking about. Maybe this is just the definition of “fan-boy”.
February 25, 2007 at 9:04 am
afoo:
> now if that really leaves anything to desire in comparison with vim’s OmniCompletion, I missed out there.
Sorry, but you completely misunderstood what Omnicompletion is. I recommend reading the doc and then come back and tell us if Emacs really can do that ;)
February 25, 2007 at 4:51 pm
You might be interested in “A Tale of Five Editors”, which compares ed, vi, emacs, Sam, and wily: see http://www.faqs.org/docs/artu/ch13s02.html (be sure to read the following page as well by clicking on “Next” at the bottom.
February 26, 2007 at 2:12 am
Thank you for the tip on inkpot. It opened a new universe for me. : )
February 26, 2007 at 6:28 pm
Just out of curiosity, were you using the bundled PHP syntax or the newer syntax on vim.org? (http://www.vim.org/scripts/script.php?script_id=1571)
February 28, 2007 at 12:33 pm
My Vim indents the Ruby code you posted perfectly with autoindent, smartindent and cindent on (although I’ll have to test out jamessan’s suggestion too now). It does indent the Python code funny, though; I don’t code Python regularly, so I haven’t noticed.
I don’t agree with you when you say that Vim seems to color more elements than Emacs. I always envy the Emacs users I see coding, because their files are so much more colorful than mine :( By reading the documentation on syntax highlighting it seems like “minor groups” are colored the same as “preferred groups” by default, so some :highlighting should be able to remedy that.
February 28, 2007 at 2:40 pm
Spug: Are you using the default Vim Ruby indent file or a newer version? Mine is: $Id: ruby.vim,v 1.5 2006/04/25 22:09:06 vimboss Exp $
For the number of colors, it might be the themes I use, but Vim definitely seems to color more stuff:
Emacs editing my .emacs
Vim editing my .emacs
March 1, 2007 at 9:08 am
I use the same indent file as you.
Yeah, I get the same result on my .emacs file, actually. Ruby and Java and probably other programming languages, though, seem more colorful in Emacs. Both of them editing a simple Java program I’m writing as an assignment:
Emacs editing a .java file
Vim editing a .java file
Comments and variable/method/class names are all in Norwegian, but it should be pretty obvious that classes, method definitions and variables are basically what Emacs colors and Vim doesn’t, though (while Vim on the other hand colors integers?), but only in declarations (both the class Integer and method calls are white in both, as you can see). The difference isn’t that big, though.
March 2, 2007 at 2:13 am
Vim’s command line will cycle to the next match when you press tab again.
March 6, 2007 at 6:12 pm
Why not Viper? In Emacs 22 beta it is very good.
And perhaps, maybe a small perhaps, you would also be interested in nXhtml for mixing XHTML and PHP in Emacs:
http://ourcomments.org/Emacs/nXhtml/doc/nxhtml.html
March 6, 2007 at 6:46 pm
LeoB: viper is a vi emulation mode, not a vim emulation mode, so a lot of interesting keybindings are absent. What’s more, viper occasionally breaks certain modes, python-mode for instance where backspace doesn’t go back to the previous indentation level if the preceding characters are spaces.
I’ve bookmarked that nxml, I’ll check it out.