Vim has been my editor of choice from day one, and I have been using the same setup for years. I pimped up my Vim to match what’s possible in October 2019. Here are my thoughts about coding editors and a breakdown of my setup.
My first stab at programming was writing shell scripts for fun. I started by watching a video course on the topic. I would not know the name nor the publisher of this course anymore. All I can say is that the resolution of the videos would not meet the requirements of our 4k era where everything is fun and games. But I can still vividly remember that the lecturer, an elderly gentleman, had a soothing voice and used Vim over PuTTY to write his scripts.
This was in 2008, right about the same time when StackOverflow was launched. My baby steps in the world of programming therefore coincided with the world’s most popular programming QA forum. Just like everybody else, I too found it difficult to exit the editor. I had to figure out the answer to one of the most asked StackOverflow questions all by myself.
So, there I was, stuck in a cryptic command line editor thinking to myself: “What a crappy piece of software!”
After getting over the initial hurdles by completing vimtutor,
I was
nonetheless hooked. The killer feature of Vim for years was the fact I could run
my scripts and silly apps from the editor itself without recourse to the
terminal. You do this by typing in normal mode:
:!bash ./script.sh # Or what have you
That was it for me. That was the one feature that I liked the most. Then there are the Vim keymappings that are not easy to explain in words. Your fingers know them best.
When I’m at a developer cocktail party or just straight-up boozing at the office, the subject of editors comes up every now and then. I’ve always disliked these discussions. I think xkcd explains it best:

The whole dispute over who uses what is just absurd and makes for studies in sociology under the topic cultural identification; I see the editor as the sword that I wield against my enemies time and entropy.
So, after a passage of a decade of the former and observing the increase in the latter, why do I still use Vim? And since a program dating back to early 1990s is bound to have some obsolete parts, how to work around them?
The good parts
1. The most versatile editor by a large margin
It does not matter if you want to manipulate a database dump or write a research paper, Vim can handle it. It does not matter if you are logged into a super computer over a remote connection or into your laptop, Vim will be available.
It has been just one of those life lessons for me that all other editors, applying fancy design patterns and implemented in modern programming language, just plain halt when I have something to say. And patience was never one of my virtues.
Despite being somewhat on the legacy side, Vim is still very performant and can adapt to an amazing variety of use cases — well, practically all I have encountered so far except one: Java.
2. Changes the way you think
Since Vim comes from the C era, it’s pretty Spartan and deliberately tries to be just an editor and not and IDE. You will not set up flaky abstractions like projects or workspaces, nor will there be a debugger or integration with a version control system.
More than that, Vim does not attempt to “understand the source code in a deep way,” like you would read in the sales pitch of an IDE. This is actually good, since it is you who has to understand the code. And for you to understand it without fancy tools, you have to pay attention to its design and be disciplined about the way you code. Necessity is the mother of invention.
Another shift in thinking has to do with fully embracing the UNIX idea of composing simple things together. This is one of those evergreen ideas in programming that pops up everywhere when you want to go to scale. For more in depth discussion, I recommend reading The art of UNIX programming by ESR or the interview of Joe Armstrong (father of Erlang) in Coders at Work.
For example, it is just natural to delegate the task of sorting a range of lines
to an external program like the UNIX command sort
:
:'<,'>!sort
Why is this better than a GUI? Because the user interface for modifying the details of sorting uses the least number of bytes. If I want to do a descending numerical sort based on column 2 of some CSV file, I just do:
:'<,'>!sort -t, -k2 -nr
No menus or input boxes were harmed during the execution of that command. In
general, the commands cut
, grep
and friends open up a whole new world of
idioms of modifying structured text, not only in your editor but on the command
line as well.
3. Keeps your workspace rodent-free
As I am writing this paragraph, I have my both thumbs on the space bar. They are almost touching each other. The rest of my fingers are over the letters A, S, D, F and H, J, K, L. In addition to being used to insert the actual characters in insert mode, all of these keys are used to perform core Vim tricks in normal mode. The palms of my hands are practically stationary no matter what I do.
I do not recall using the arrow keys in Vim. I almost never use any GUI menus of any kind and I haven’t used a mouse in a long long time. I do use the trackpad but it integrates seamlessly with my workflow. I guess I use it for scrolling for the most part.
If you suffer from tense shoulders and neck pains, take a look at your hands to see if they are too wide apart. A mouse may be necessary in a gaming context, but I think it’s harmful for programming for extended periods of time. Your shoulders will thank you after learning to code ergonomically with Vim.
The bad parts
1. Buffers and regular expressions
Vim sees the source code as buffers filled with bytes by design. If you want to rename something, you do a search-and-replace. To automate things, you write a macro or extend the editor with ad hoc regular-expression-ridden scripts. This approach cuts the mustard, but it would be far better if Vim would know how to parse source code and we could manipulate it as an Abstract Syntax Tree (AST). Check out the cool TypeScript AST Viewer to see how ASTs work in practice.
Imagine an editor where you could “Inspect” a given statement, much like you use Developer tools in a browser. You could also do modifications by visiting the nodes with some selector statement much like you manipulate the DOM in JavaScript. The same visitor pattern is also the central idea when transpiling JavaScript with BabelJS or refactoring an entire code base with codemods.
This should not even be so far-fetched given that we have the LLVM project with its framework of digesting just about anything that has a well-defined grammar.
The lack of parsing support in Vim is for me the biggest missed opportunity and leads to a lot of fragile VimScript code. Think syntax highlighting and indentation scripts as examples.
2. Configuration madness
There are just way too many settings in the editor and it takes effort to understand which ones are applied in which context. Modelines are evil, too. It is also way too easy for plugins to start conflicting with each other.
Then there are projects like Editorconfig and Prettier that are really cool but add an extra layer of complexity. Talk about entropy and fragmentation. There are now something like four different ways to set the linewidth. Sigh…
3. VimScript, Python, Lua, Ruby, Perl…
Perhaps in line with the anything-you-like approach to configuration, there is no one way to extend the editor either. Vim can be extended with its own scripting language VimScript. However, the editor also ships with support for Python, Lua, Ruby and Perl…
In my opinion, there’s no good reason for this. All these so-called scripting languages are effectively the same and suffer from fragmentation. Python 2, can you die, please?
I wish the editor had a single tightly sandboxed DSL with builtin support for ASTs and events. I don’t see any reason why Vim plugins should be able to do arbitrary side-effects either, so why not restrict the DSL to the pure subset of functional languages as well.
My Vim setup™

Enough with ranting and pipe dreams. Let me show you my setup. I use
MacVim for the most part, but I do my
Git commits with command line vim
. I am aware of
neovim but haven’t really checked it out.
If you are still rocking Vim 7, I would totally recommend version 8. It allows
you to install Vim plugins as separate
packages instead of clumping everything
into a single folder structure. I also like to store all my Vim files in
~/Config/vim
so I can track everything in Git. Actually, I keep all my
dotfiles in GitHub.
My setup looks roughly like this:
~/Config/vim
├── pack
│ ├── com.github
│ │ └── start
│ └── net.keksipurkki
│ └── start
└── vimrc
I use a dozen or so plugins from GitHub. These go under pack/com.github/start
.
Similarly, my own hacks go under pack/net.keksipurkki/start
.
Vimrc
My vimrc settings are mostly patching the editor to not beep, blink or clutter my laptop. Oh, and I love the Monego font, even though Hack and SF Mono are great monospace fonts too.
I typically load the whole codebase into Vim and navigate between files using
the :buffer
command that has some idea of fuzzy completion. I then “cd” around
the codebase when needed. There are probably better ways; I have never fully
learned to use plugins like NERDTree.
For me, the following custom commands are sufficient:
" Commands
command! GitRoot :execute 'lcd' systemlist('git rev-parse --show-toplevel')[0]
command! -nargs=* GitLoadEm :args `set -f ; printf \"\%s\\n\" \"$(git grep --cached -Il '' )\"`
command! TakeMeHere :lcd %:p:h
I typically start my Vim session with a :GitLoadEm
followed by :TakeMeHere
.
Finally, on the autocommand side I have a miscellaneous bunch of niceties:
" Jump to the line that was last edited
function! LastLine()
if line("'\"") > 1 && line("'\"") <= line("$") |
exe "normal! g`\"" |
endif
endfunction
" Turn off syntax highlighting if the file under edit is over 1 MB
function! SyntaxEscapeHatch()
if getfsize(expand("%")) > 1024 * 1024 | syntax off | endif
endfunction
" Sanitize indent settings globally
function! IndentReset()
setlocal autoindent
setlocal smartindent
setlocal nocindent
endfunction
autocmd BufReadPre * silent call SyntaxEscapeHatch()
autocmd BufReadPost * silent call LastLine()
autocmd BufReadPost * silent call IndentReset()
autocmd VimLeave * macaction terminate:
Language Server Protocol support
Intellisense completion has always been difficult in Vim. Everybody wishes to have it secretly and most live in denial. Fiddling with ctags and the like has never been worth the effort for me.
A bit mysteriously, Microsoft decided to standardize its Language server protocol (LSP) that was designed initially for implementing intellisense in VSCode, the coding editor that I would use if I wasn’t so wont to my ways. What is more, Vim 8 also has support for running tasks as background processes.
Adding one plus one, it’s now finally possible to have decent intellisense
completion in Vim by running an appropriate LSP server and have it talk to
Vim via background processes. Examples of LSP servers include clangd
for C,
tsserver
for TypeScript and sourcekit-lsp
for Swift. See the full list
here.
In my opinion, Vim should have native LSP client capabilities. It already has support for integrating with NetBeans. The two notable contenders for having LSP support today are CoC and ALE.
I use my own fork of CoC, as I wanted to run code analysis only after writing the buffer on disk and not immediately after exiting insert mode. I don’t really get why these plugins even try to lint code after each change. Ain’t nobody got CPU cycles for that!
The end result looks like this:
General purpose plugins
Finally, a couple of words about other plugins. My pick for the top 5 general purpose plugins would be
Vim Prettier and EditorConfig are what I use to format code and set formatting
options — I code JavaScript for a living. An .editorconfig
file should be
commited to version control per project and the config must be enforced across
the whole team.
Vim Airline pimps up the statusline and it is there mostly just for the bling. It’s however very useful to know when the buffer has syntax syntax errors or formatting issues, as the plugin plays well together with CoC.
Vim CSS colors works wonders when programming a front end. It simply highlights color codes in the appropriate color. Simple and to the point!
The delimiters plugin is my own creation. I wrote it once years ago and have
been using it ever since. It simply autocompletes block delimiters ({}, (), []
…) using an algorithm that I like. The plugin is probably too custom for
general use.
Closing remarks
As you can see, Vim is still live and well and it can still learn new tricks. I shall follow the advancements in the LSP business with great enthusiasm and will take my current setup for battle testing at work.
However, truth to be told, I would not recommend Vim anymore to new developers. From what I gather, VSCode is the favorite among my colleagues. But Vim will remain my editor of choice — it has seeped into the most primordial parts of my programming brain and prevents me from using any other editor. You know that the program has a hold of you once you start typing :wq accidentally all over the place. Btw, that’s how you exit the editor ;-).