I've been programming for a living, for the better part of the last two decades - and in my experience as a programmer, the editor I used really mattered. A large part of my life passes working inside it - and the more I "invest" in learning it, the faster I code.

In what follows, I will try to explain why learning VIM has proven very beneficial to me. You can also read this and this to see why VI/VIM can vastly improve your efficiency in editing files.

(Caveat: I am not a VIM expert - even though I've worked with VIM for decades, I am only using a small part of its functionality, and only rarely do I write a function inside my .vimrc. Mostly I just stand on the shoulders of giants. I only wrote this post because I keep seeing people "wow"-ed by the things I do within VIM - and wanted to share the marvelous things this gem of an editor can do. To any real VIM experts out there: I'd be grateful if you could review my setup and tell me the things I am doing wrong...).

Working remotely

In my work, I increasingly find myself doing things remotely - i.e. working over network links. By using VIM, I have a significant advantage: I can edit anything I want over e.g. SSH connections, with minimal bandwidth/latency requirements. To that end, whatever machine I am working on, I will always install an SSH server (even under Windows) - and I can then edit stuff remotely, using VIM. To really understand the efficiency of this, try using any GUI over a slow VPN connection (e.g. using VNC or RemoteDesktop) - you will soon begin to appreciate a fast, console-based editor.

Programmable editors - VIM plugins

Almost all professional editors are "tweakable" - e.g. they allow you to configure keyboard shortcuts. But that's not what I mean with "programmable editor"; I am referring to editors that allow you to actually code (and therefore customize) significant parts of their behaviour; only a handful fit this description.

If a large community of coders is using this customization facility for their professional endeavours... then there is a good chance that the things they build will apply to you, too. For VIM, there are almost 4000 custom VIM scripts, tailored to their creators' specific needs. Let's look at some of these, and how I am using them.

Auto-completion / language-aware navigation

Some people still think that if you use a "spartan" editor like VIM, you lose all the auto-completion magic and language-aware navigation that modern IDEs offer. That is simply not true:

Some of the things I can do when I work with C or C++ code.

Executive summary for C/C++ coders:

Add clang complete to your installed VIM plugins, and install libclang in your machine. If your build process has "exotic" macros defined or needs "special" include flags, just add them in a .clang_complete file (which this VIM plugin reads).

If you want to exclude stuff you don't navigate with tags,
and/or want to minimize the size of your tags database, you can exclude folders - e.g. to exclude Boost...

# cd /usr/include
# ctags -R --exclude=boost/\* .

Your own C/C++ code must automatically update its tags database, so use a rule like this in your Makefile:

tags:
ctags -R --c++-kinds=+p --fields=+iaS --extra=+q .

...and you can then tell your VIM to always use the "constant" tags, alongside any other ctags database you use (e.g. the one that your Makefile updates during your builds):

$ cat .vimrc
...
set tags+=/usr/include/tags
...

Notice how we therefore re-use tags databases amongst all the projects we work on in this machine. This can be applied to more than just /usr/include; you can create individual tags databases for each library or code folder of your own, and only pay the price of creating the tags when something changes in them.

Learn to use Makefiles - and build your code with a simple ":make". VIM will guide you to whatever compilation errors you have; just use ":cn" and ":cp" to navigate amongst compilation errors.

Automating repetitive tasks

In the video, you saw me using NERDTree - a "file manager" plugin from within VIM. But, to toggle that window, you need to escape into command mode, and type ':NERDTreeToggle'. Isn't that too much typing?

Indeed it is, so you map it to something you can easily use via your .vimrc:

This tells VIM that in both command mode and insert mode, when you hit F10, you want the NERDTree file manager to appear/disappear.

Similarly, when I search for something (/whatever), I want the search results to be highlighted (in yellow) - but after finding what I want, I no longer want to see the highlights - so I map "Ctrl-L" to clear them up:

A function is defined, called ReadMan. It reads the current word under the cursor, and then invokes a series of commands that create a new window and read the relevant manpage inside it. This function is then mapped to 'K'.

The power that comes from this kind of customizing can provide immense productivity gains. Imagine reading outputs of custom commands you build yourself, and then have VIM act on their results - storing variables, calling functions, whatever.

Update: mgedmin from Reddit was kind enough to suggest some improvements in ReadMan, and to also point out that as an example it is fine, but functionality-wise it is no longer necessary - VIM already includes this functionality via :runtime ftplugin/man.vim followed by :Man whatever.

Identical customized environment everywhere you work

You might argue: "this customization you just did - the 'F10' invoking NERDTree, the 'Ctrl-L' clearing search highlights, etc - you are the only VIM user doing it, so when you go to another machine, you have a problem, no?"

Actually, I don't; whenever I work with a new machine, I just do this:

VIM (like other programmable editors) allows you to configure it via a text-based configuration file (.vimrc). By placing this file under source-control in a public repository (mine is in GitHub) I can consistently reproduce my own, customized editing environment, tailored to my needs - in ALL machines I work on.

Plugin maintenance

So I packaged a bunch of plugins in my GitHub account. But these are live, evolving creatures. Their authors may have fixed bugs since I copied them - am I stuck in whatever version I originally copied?

No - thanks to Pathogen. Did you notice the Git submodule commands executed above? They use Git to fetch the latest versions of whatever plugins I am using (git submodule update). I am always up-to-date!

Coding is not just about editing code

Even if you love your IDE, and you think it does all you ever wanted - you will soon find out that you need to edit things that are *not* code; configuration files, READMEs, notes, mails, commit messages, etc. How will you edit them? You will spawn your takes-10-seconds-to-launch IDE just to edit an .ini file? Or /etc/apache/httpd.conf?

The point I am trying to make here, is that by investing in learning and customizing an editor like VIM, I can then put that power to use regardless of where I am and what I am editing. I have that power with me, "everywhere I go" - i.e. no matter what files I am working on.

"Power... Unlimited power!"

Let's say you discover for the first time a REPL-enabled language. REPL means 'Read'-'Evaluate'-'Print'-'Loop'. It refers to all these dynamically-typed languages that offer an interpreter (LISP, Python, Ruby, etc) - an environment that reads individual statements that you write, then evaluates them, and then prints the results.

Cool, it works... How nice, to have an interpreter! You suddenly realize how easily one can tinker with these dynamic languages. No edit-compile-run cycle. Fast. Easy.

But... you miss your editor. You want to be able to write the code in it, using all the customized power you have gathered there over the years - and then somehow "magically" transport functions (not complete files!) across to the interpreter. How can you do that? How can you incrementally build your code base, testing each function as you go along?

You may be lucky enough, to be working with languages/tools that already offer this[1]. Usually, however, this is not the case. You could ask the company that builds your favourite IDE for this feature, but the time and money it will take to implement prohibit it. Instead, you combine the power of the tools you already have, by being a programmer that is not limited to a single company's IDE - here's how:

The screen tool allows one to create standalone command line sessions. It also allows creation of "windows" inside them, e.g. have VIM run in one window, and Python run in another.

More importantly, screen allows you to copy text into a screen session, via the "screen -S sessionName -p windowName -X stuff" command. You can therefore 'paste' anything you want inside a screen "window".

If we can somehow automatically "gather" the text of a function, we can send it across to another screen window by just spawning "screen ... -X stuff ...".

Why don't we add this gathering stage as a VIM function? And then have it send the data across to the "window" running the python interpreter?

The algorithm is quite simple: When the user hits the "magic key combo" we need to identify the function or class that our cursor is in, and send it across. For Python, this is easy:

we have to search for a def or class definition at the beginning of a line. And that's what we do - we use VIM's language to describe searching backwards from the cursor position, looking for the ^def\|^class regular expression - and store the line we find as s:beginLineNumber.

If we don't find it, we just use 1 (i.e. we will copy from the begining of the file).

We do the same thing to find the next class/function beginning, and mark that as s:endLineNumber.

If we don't find it, we just use the last line (i.e. we will copy until the end of the file)

We now yank (i.e. "copy") all the lines from s:beginLineNumber to s:endLineNumber into register "r

And spawn "screen" with the '-X stuff' parameter - to paste the text in the Python interpreter (Or use the SLIME plugin which I slightly customized to automatically target the Python window).

That's all. It's not bullet-proof, but it only took 20min to write and test, since I could already base my efforts on the VIM slime plugin. And most importantly, I will have this in my arsenal from now on, for any REPL-enabled language - where I will just have to modify the "find the function borders" algorithm.

I hope that you can now see how it pays to have a programmable editor... Whatever functionality you want, you can easily implement it inside it - especially if you adhere to the UNIX mentality, i.e. you use tools that do one thing and do it well. In this case, the screen tool allowed us to paste data in another window by a simple spawning - which we easily do inside VIM, by calling system.

Executive summary

Be a man, use a programmable editor like VIM! :‑)

If you code for a living, it will more than make up for your investment - it will make you far more productive that any single IDE can ever hope to.

Acknowledgments: Far too many to mention. Plugins, ideas, SLIMEy things, etc, are all gifts from the Gods. I must, however, express my gratitude to the man that showed me the path: Hartmut Brandt, a FreeBSD committer who I was lucky enough to work with, 17 years ago. Hartmut introduced me to the wonderful things that VIM can do. Wherever you are, harti: I remain forever grateful :‑)

[1] Gasp! An Emacs link in a VIM article! Where's my helmet? :‑) Joking aside, I think that both VIM *and* Emacs are amazing - and that any aspiring programmer stands to gain much by learning at least one of them.

The comments on this website require the use of JavaScript. Perhaps your browser isn't
JavaScript capable or the script is not being run for another reason. If you're
interested in reading the comments or leaving a comment behind please try again with a
different browser or from a different connection.