Navigate ES6 projects with Vim using ctags
Navigating a large JavaScript codebase using Vim can be a little annoying. The module system does not impose any relation between file names and their contents. That makes it impossible to know where a function or class is defined just by its name. You can always reach to the top of the file and look for the import
statement, but you still have to deal with the many different ways of resolving files in JavaScript projects: you might be using Babel resolvers or Webpack aliases; or maybe you are importing something reexported from an index.js
file.
In the end, you’ll find yourself making project-wide searches by name. The problem is, that can lead to too many unrelated matches (you’ll find the definition, but also every usage of the function).
Enter ctags
What is ctags
?
Ctags is a programming tool that generates an index (or tag) file of names found in source and header files of various programming languages. […] These tags allow definitions to be quickly and easily located by a text editor or other utility.
Generating a tags file
There are many variants of the original ctags
program. I use exuberant-ctags
, but depending on your editor and programming language, you may choose a different one.
Installing exuberant-ctags
In OS X, use homebrew:
brew install ctags-exuberant
Configure ctags for JavaScript
The default JavaScript support doesn’t work well with the modern syntax. You’ll need to tell ctags
how to parse all the new ways of declaring things (const
, let
, method shorthand, …). You can use the expressions defined in this repo:
Follow the instructions and update the global configuration file in your home directory: ~/.ctags
.
You might want to configure some default file exclusions to prevent ctags
from processing common directories. You can do that adding a list of exclusions to ~/.ctags
:
--exclude=.git
--exclude=log
--exclude=tmp
Generate the tags file
Now you can finally generate a tags file for your project, running the following command in the project root:
ctags -R
You can further customize the way the tags file is generated defining a local .ctags
file for your project. For example, if you don’t need to navigate to your project’s dependencies source code, you can exclude node_modules
:
--exclude=node_modules
Use tags within Vim
Vim supports tags files out of the box. You can use the command :tag {name}
to move to the file where {name}
is defined, or press ctrl-]
to use the keyword under the cursor as the tag name.
To learn more about all the available configuration options and commands related to tags, run:
:help tags
Plugins
I use two plugins to improve the experience of working with tags files in Vim.
The first one, vim-gutentags, keeps your tags files up to date while you are working. It updates the tag definitions as you save your work, so you don’t need to run ctags -R
in the console.
The second one is fzf.vim. Fzf is “a general-purpose command-line fuzzy finder”, so it has nothing to do with tags files in particular, but the Vim plugin includes specific commands for doing fuzzy search of tags. (You can use other plugins like ctrlp.vim or unite.vim if you don’t like fzf or you already use them for other purposes).
Using a setup like this, you can navigate large (modern) JavaScripts codebases from within Vim. But remember: Vim is not an IDE. You’ll find some edge cases where the tags file doesn’t work as expected, and you’ll end up doing a project-wide text search, just the one thing you were trying to avoid. That’s a price I’m willing to pay for using such a beautiful editor. I hope you feel the same as me :D