How I Use Vim
Over the past few months I've heard several comments and misconceptions about Vim, largely surrounding supposed missing features that make the editor a non-viable tool to work effectively as a developer. Things like code completion, go-to-definition, syntax highlighting for various languages, file navigation, etc. So I thought I would put together a post that tries to debunk some of those myths and showcase how you can have an incredibly powerful workflow using this classic text editor.
Before we get started let's start off by answering a very basic question; why do I use Vim? There are a multitude of IDEs out there, VS Code being the gold standard these days, all of them incredibly feature-rich right out of the box. So... why??
There are a few things that I look for in my developer workflow:
- I need to have an excellent editing experience; code completion, moving text around quickly, indentation, etc.
- I need to have great syntax highlighting support for whatever languages I may be working on on any given day.
- I need to be able to find files, terms, function, and type definitions easily and frictionless.
- I need to be able to do these things better than in other environments. Otherwise, why even bother?
- I need to be able to tinker with my environment to my heart's content.
The last point here is really at the core of why I choose to stick with Vim year after year. Out of the box, Vim comes with a powerful set of core features to work with and manipulate text, but that's basically it. It's a text editor. Everything else you have to build on top of it. And I absolutely love that. So let's cover each of the points above to showcase how quickly and easily you can make Vim an incredibly powerful code editor. One that you can tweak and customize to seemingly no end.
File search and navigation
I consider this to be the price of admission for any code editor. If you can't get this right it is effectively useless. So how can Vim, a basic terminal text editor, not just provide this basic capability but actually excel at it?
There are two plug-ins I leverage here dozens of times a minute; Netrw for file tree navigation and FZF for file name and codebase-wide term searches. Here's an example of each.
Netrw, the "built-in" file tree
There are a number of file tree solutions out there, but my needs here are pretty basic. I need to quickly be able to see the files in the current director I'm working in, and I need to be able to easily step out of that directory and navigate "sibling" directories. Netrw is technically a plug-in, but comes bundled with Vim. Here's what that looks like in my set up.
I can quickly see the directory for the file I'm currently working with, navigate around, etc. I can also quickly rename files and folders, jump to the root of the project, and more.
FZF, the incredibly power fuzzy finder
If you're already a Vim user you've likely come across dozens of posts about FZF. If you're not, you're about to be amazed at this ridiculously powerful tool. What can it do? Well, the possibilities seem rather endless, but I use it for a few key tasks:
- Find a specific file in my repository
- Search for a specific term in all files in my repository
- Search for the term under my cursor in all files in my repository
- Effortlessly filter down the results to find what I need
Let's take a look at each one of these cases with examples, and incorporate the last bullet point. First up is finding a specific file in my repository. I've mapped ff
(my mapping for "find files") to open up FZF and show me all files in my repository.
There's a few things happening here. First, a file list opens up showing me every file in my repo (respecting custom ignore rules that I've set). I can navigate that list with my keyboard and choose to open any one of them (or multiple!). If I need to search for a specific file I can just type what I'm looking for. That term will be a fuzzy search. If I'd like to search for an exact match I type '
before my term, and if I'd like to omit a term I type !
before the term. Quite easy, incredibly fast. As you can see, I also get a live preview of the selected file above. All of this, including the layout, is highly configurable.
But what if I need to search for a specific term, or a term that my cursor is currently over?
Again, a few key things are happening here. First I put my cursor over the word "ThemeProvider" and press fw
(my mapping for "find word"). This does a repo-wide search for this term and shows me all files that contain that word. After that, I can use '
before my term to filter down matches that also contain an exact term, and if I'd like to omit a term I type !
to filter down my list further. Finally, I press fs
(my mapping for "find search") to search for the word "props".
As you can see, with just a few keystrokes I can get anywhere instantly. This entire flow is also highly configurable to suit your needs, and it is something I like to tinker with from time to time. FZF is incredibly fast and supports a number of search tools. It also supports a vast array of configurations and is an awesome plug-in to play with.
Syntax highlighting support
Syntax highlighting is another feature that's considered part of the price of admission for code editors. I was surprised to see that so many of the folks I talk to about Vim have this idea that Vim is this ugly, unstyled mess that makes it impossible to read code in. The truth is that Vim can support syntax highlighting for effectively any programming language. Paired with a good color scheme it can be a dream. At work I frequently work with JavaScript, HTML, JSX, CSS, Scala, Java, Python, GraphQL, markdown, JSON, SQL, and more. At home I also mess with vimscript, bash... All of these are easily supported.
One of the more popular syntax highlighting plugins out there is vim-polyglot, but there are many more out there. I'm currently loving the Nord color scheme.
Code completion and navigation
Up until this point we've really only just paid the price of admission; opening a codebase and navigating it in a sane, consistent, and predictable way. But a huge piece of writing code in our editors is powerful tooling around code completion and navigation. We can't keep every method name and location in our heads, so we use our editors to assist us. Rumor has it a lot of folks think this is an impossibility in Vim.
Again, there are a number of solutions here, from the very basic to the feature-rich. I've chosen to use a plugin called Conquer of Completion. It is a code completion plugin that comes with support for LSPs (Language Service Providers). So, if you work with JavaScript, Scala, or whatever other language, you can install the language servers for those and get "plug and play" code navigation, code completion, and more.
In this example we see pop-ups with TypeScript warnings, go-to-definition, and code completion with method descriptions. For this I'm using the coc-tsserver
language server for coc-nvim
.
Wrapping up
In conclusion, what I've shown here is really less than the tip of the iceberg. Vim is nearly infinitely configurable and can be adjusted to work for any environment. But it does take time to tune things to the way you want them. If you'd like to take a look at my dotfiles, please do!
Some plug-ins I use often:
- ALE for code linting
- Vimwiki for personal notes
- nvim-metals for Scala development
- delimitMate for auto closing of brackets, etc
- coc-git for git status support in-file
You can take a look at my dotfiles on GitHub and see what other nifty tricks I've added.