Vim: What Works and What Doesn't

A good hacker needs a good set of tools and Vim is, at the very least, a good tool. After five years of using Vim, I'd like to share a few tips.

Note: Please remember that this article is as much for me as it is for any other reader. Therefore, this is really a working draft and I will update it as I see fit. So, if you like what you read here and you want to make sure that it doesn't disappear then archive it for yourself. Here's one way: wget -E -H -k -K -p http://<site>/<document>.

Note: Unix and Linux are used interchangeably in this post. I personally use Linux.

Vim is not a Very Good IDE

Despite Numerous claims, Vim is not a very good IDE. Vim is not an IDE and it never has tried to be. It has a plugin language, VimL, that authors have used to try to create just about every IDE feature that you can think of with varying degrees of success. This approach is fundamentally flawed because Vim has only a finite amount of flexibility in the interfaces that it's capable of presenting. Basically, it has windows that are filled with text and, in some cases, popup menus. It also has support for key mappings and a handful of 'events' (autocommands). You can get pretty far with this but you're never going to have the full set of interface capabilities available to an IDE. Here are some conrete examples of interface limitations:

  • There is no autocommand that fires when a directory changes. Because of this, if you want to create a file navigator it won't update with the current files when the user changes the current directory. It has to be updated explicitly.
  • There is not a good way to achieve dedicated panels or icons for IDE style interfaces (code navigation, debuggers, etc) within VIM. This is because any panel that you have will just be another window to Vim. The solution for this is usually just to have a dedicated or semi dedicated window which comes up on the left or the right side of the editor when some command is called. This is a workable solution but it's certainly not the same as having a full fledged configurable IDE UI with an iconified, customized interface utilizing different fonts, colorschemes, font sizes, menus, sub layouts, etc. There are a huge number of graphical capabilities that are available to the core developers of an IDE that Vim was never built for. Trying to add these kinds of things to vim core is nearly impossible. I'll explain why shortly.
  • In many cases, Vim's autocmds are lacking and where they are you have to resort to using something like VimCursorMovedI which is a noticeably not great solution (takes a while to update). See above where I mentioned changing current directory.
  • VimL is pretty slow and so is syntax highlighting. In my experience plugins that create top notch syntax highlighting for filetypes cause the editor to lag on large files.

The above limitations are basically inherent within Vim. This is because both the graphical version of Vim as well as the terminal version are married to ncurses and so are also married inherently to the set of capabilities available to a terminal. Within Vim's source code the authors utilized a bridge design pattern to adapt the later graphical interfaces to behave the same way as ncurses. Because of this, all of those extra libraries really behave just like ncurses under the hood. Of course, if you were very brave then you could try to change this but is it really worth changing? Vim's code base is massive, ~600,000 lines and the primary holders of state within (by far) are global variables. Even when variables are scoped to functions in many cases they have single letter names and the functions are literally thousands of lines long. On top of that, the code for Vim doesn't even conform to C89 standards which is especially annoying for function definitions and makes everything even harder to read. Hopefully, you're starting to see that for most situations modifying Vim core is not really a viable long term solution. Certainly, where it was feasible authors have already made every effort to do so.

I have a lot more that I could say on this topic but hopefully for the typical reader the above will serve as sufficient evidence that Vim really will never be able to compete with an IDE at being an IDE and that way lies madness. If what you want is an IDE then go get one of those. But I don't think you should want one in the first place. If you're interested then read on...

Vim Is Better Than Your Favorite IDE

Like I said above, Vim has never tried to be an IDE. Vim adheres to the Linux toolkit philosophy. This means every tool has one job and does it well. This is really just the same as the Single Responsibility Principle. However, in Linux this principle is typically used at the process level so that each process defines a responsibility rather than each "class" or "module". So, there is nothing wrong with an IDE but they integrate at the module level rather than at the process level (multiple components in a single program in the former and multiple programs working together to complete a single task in the latter). What this means is that by analogy Vim is not your IDE, Linux is. Vim is the text editor that has been provided which works alongside all of the other tools available on Linux. And Vim integrates very well this way! There are a lot of commands that support this workflow within Vim. For example, the following are all ways that you can integrate with other processes within Vim:

  • The filter command :[range]! cmd can be used to pipe [range] lines into an external command and replace them with the results of that command. You could use this for a lot of things. For example :%!xxd for editing binary files.
  • set grepprg to integrate an external search program
  • set makeprg interfaces with an external make program for doing builds
  • The system() function (:help functions)
  • :r !cmd to read in the results of another command
  • :r file to read in the output of a file (could be a device)
  • vim - on the command line causes Vim to edit the content of its standard input.
  • normal mode command !{motion}{filter} or [count]!!{filter} or {Visual}!filter all cause lines to be filtered through an external program
  • :! just execute an outside command and show the results
  • :redir to redirect the output of ex to a file or a register.
  • :python and friends to feed code to external language interpreters.

This is really just scratching the surface of what Vim has to offer in this area and really this is all just sugar on top of a core philosophy: everything is a file in Linux anyway so any editor that edits text effectively will work well in the Linux "IDE".

When we look at Vim as if the OS itself is the IDE we only need to look at Vim's ability to edit text and its ability to interface with other tools that do their jobs well at the process level. It turns out that Vim is very good at this - superior.

Nearly all of VimL's functionality is centered around making this as easy and flexible as possible. In fact, VimL is really just an extension to the set of ex commands available which are for, wait for it, editing text. Because of this all VimL commands are available to you in realtime in the editor by pressing : and typing them like you would any "other" command. Try this hat on :for i in [1,2,3] | echo "hello ".i | endfor.

What's more ex commands are just text too and so you can even edit those with Vim. Try pressing : and then CTRL-f. You're now editing your ex command with Vim and you can even edit your ex command with more ex commands (which includes VimL language features).

In bash, you can even press CTRL-x_CTRL-e and open up a Vim window to edit your current line. ZZ that file and it will send the command back to bash and execute it there in the shell right where it should be.

Ex command syntax is very terse which makes it very easy to write ex commands very quickly and edit text on the fly. Ex is so terse that it's actually incredibly easy to take some text and convert that text into an ex script. E.g. want to rm a list of files? Use block selection (CTRL-v) hop to the end of the file with G press I to go to insert mode for the block and type :!rm. You now have a viable list of ex commands to remove all of those files. At this point you can simple :so % and obliterate them all.

It's easy to see why ex command syntax is generally very terse: it's meant to be hacked out on the fly. It's also very easy to see why you wouldn't want to program a huge effort with ex commands: it would be insanely error prone and it is, every single time.

There's a lot more I could say about all of the ways that Vim is capable of integrating really well with other processes/programs and maybe I will some other time but all of that is available online somewhere anyway if you look. The point is that if you adopt this philosophy: stay away from trying to make Vim an IDE and let Linux be your IDE instead then you will have a lot easier time and will ultimately be a lot more productive.

Vim is not for the Faint of Heart

Linux really isn't either and when you throw Git into the mix (you should) and the other plethora of tools you probably should be using the whole thing is a mess. You need to stick with it for a while before it will really do much for you. If you need to use another editor while you're learning that's totally fine. If you decide that it's not worth it to you and you go with something else that's okay too. There is no predefined toolset for a good hacker. You just have to figure out what works for you. Vim is one good tool but it's not the only one and text editing is just one small part of a much larger endeavor. Don't be an idiot and tote your favorite tool around claiming it makes you a god. It's just a tool.

Plugins are Good, Use Them

While there are a lot of tools out there that try to make Vim into an IDE there are a lot also that just try to make it a better editor. Stay away from tools that try to make Vim an IDE and lean towards the tools that try to make it easy to integrate at the process level without doing too much legwork with the UI. I use plugins like matchit, unimpaired, syntax highlighting plugins, sleuth, Ack, tabular, Ultisnips and other plugins along the same lines. I stay away from plugins like vimshell, ctrl-p, fugitive and anything else that tries to do a lot of UI legwork. I try hard not to change Vim's core philosophy - it bites me every time.

Now, I have to reconcile some of Vim's actual weaknesses here. You might have noticed that earlier I said that VimL would not be a good language for a large endeavor and yet I'm still advocating using plugins. How does that work?

Well, Vim has a need to be able to expand its core editing functionality - to do its job better. Vim has support for passing off code to other interpreters like python and many plugins like Ultisnips make use of this. This is a good way to go. Whatever you do, however, if you decide to write a Vim plugin you're going to have a good amount of code that you have to write in VimL and the experience is never pleasant. This is a real weakness in Vim and one that will likely never be fully remedied. However, you'll find that VimL does not fight with you nearly as hard when you're not trying to do something that Vim was never intended to do and after a while you get used to the quirks. Since you have the option of working in another language in all but the top levels of your plugin the situtation really isn't all that bad.

There are a few specific cases where some kind of UI integration doesn't fit into Vim's core philosphy but it's really needed. One of these instances is file navigation. Because of something mentioned earlier Vim will not be able to keep any file explorer up to date with the current directory without a lot of ineffective workarounds. You just have to accept this. It's not really a huge deal it's just kind of unfortunate. I also use Tagbar which is less than ideal in terms of UI and will always trail behind the UI of a "real" IDE. I don't care. I usually know where my code is anyway. This sucks but I'm not going to lie to you and tell you Vim can compete in this area because it can't. It's just not a large concern for me and Vim is great at most of the things that do concern me.

Portability Won't Work

A lot of people like the portability of Vim and so they try to avoid plugins and custom configurations at all costs. This is a really bad idea in my opinion - you miss out on a lot of really good functionality that has been created since the core of the editor stagnated. I manage this situation by keeping a git repository containing submodules of my plugins on bitbucket. It has a .vimrc file in there also and so all I have to do to get myself up and running on a new machine is type in four or five commands and I'm all systems go. git submodule update --init will do most of the work. I use powerline so I have to download some custom fonts and I also usually install the color palette for the solarized colorscheme on my terminal. Obviously I don't do all of this for every machine that I ssh into but if I'm going to be doing a decent amount of work on a machine then I will. There are other very good options also. One of them is sshfs which will allow you to work on a remote machine with your home editor - fully configured. Another good option is to setup your write command to automatically rsync with another server. Vim also has an scp mode which will allow you to edit files over scp (doesn't work as well as the other two solutions in my experience). The best solution is to just keep your code centralized and automate deployments. Whatever solution you go with I don't recommend developing in a bare bones environment.

Use The Mouse

It's pretty easy to use the mouse with Vim but a lot of people don't know how or think it's dirty. Just set mouse=a in your .vimrc. You don't want to use the mouse all the time obviously because that would defeat the purpose of using Vim. There are things that just work better with the mouse though. I primarily use the mouse when I am reading and navigating exclusively because it is truly superior there. The keyboard is superior for editing though. Don't be afraid of the mouse. Just consider whether you're undercutting yourself by using it. You should be doing this with everything in your workflow not just the mouse.

Conclusion

The most important part of Vim is really the philosophy. Once you understand how Vim is supposed to work the rest of the answers will come.