Wrangling JavaScript with Vim

I’ve created a few posts on here about writing JavaScript with Vim, this is because it’s what I do all day (and night) long, I’ve refined my editor to make writing this slightly questionable language as easy as possible. I’ve now hit a point, once again, where I feel like I should share my tooling for everyone else to take advantage of. You can find everything I’m going to talk about in my dotfiles under the Vim directory if you’re curious.

Plugin management

I’ve gone through a few different systems since starting to use Vim, I’ve finally settled on one that’ll be tough to beat: vim-plug. A good plugin manager is essential to any good Vim configuration, in my opinion. It allows me to easily add, remove and update plugins as well as keep them in sync across machines. The parallel processing and optional deferred loading are excellent features.

My configuration is modularised by having bootstrap.vim load all files in my modules directory, one of these is plugins.vim which configures vim-plug and then loads the individual configuration files for each plugin from modules/plugins. This allows my actual plugin list to remain clean and concise. I recommend following a similar pattern to keep your configuration clean.

The point of this section being: Make sure you have a good plugin manager and a nice place to list your plugins as well as their configuration. It’ll help keep things clean. Feel free to copy my system exactly, in fact, I encourage it. Fork my dotfiles if you so wish.

Essential plugins

I’m going to list a fairly exhaustive list of every plugin I use that can help with JavaScript development. There’s going to be a lot here, but I’ll try to justify each one as best as I can. Adding all of them will have no impact on the performance of your editor (unless you’re on a Raspberry Pi for example) and vim-plug will fetch / update them incredibly quickly. I actually use a lot more than this, but these are some of the most relevant.

Project specific configuration

I use embear/vim-localvimrc to provide project specific functionality such as executing tests or running the build. Because this is something that isn’t universal, having a .lvimrc to hand is extremely useful. I have the following binding defined at the moment so I can just hit “<localleader>tt” (which is “|tt” right now for me) to test this file, it doesn’t matter if I’m in the source or test file, it just works.

This is relying on vim-dispatch to make the whole thing asynchronous. It actually executes in a tmux split and pulls the results into my Vim quickfix list when done.

I also have my path set to some greedy globs and suffixesadd set to contain .js. This allows me to press gf (open file under cursor) on the following require statement, and it will actually take me to the source (if it exists)!

And here’s the configuration I’m currently using for that particular bit of magic.


I use UltiSnips to manage my snippets, which is a fantastic tool. The key to snippets, however, is to not have too many. That is why I only have three at the time of writing. It’s pretty obvious what they’re for, the most used being fn. Having a few for your most common patterns is a good idea, but delete them if you find you’re not using them, keep your snippets clean.


Concealing is a neat (and relatively new) feature in Vim that allows you to mask a set of characters as a single character. It just so happens that vim-javascript has some excellent conceal configuration that’s easy to use and very effective. Here’s what I currently use, it’s pretty self explanatory.

This is all well and good, but it got me thinking, what if I could just press the @ key and have it expand to “this” but still show an @ through conceal? Essentially creating a cute little language on top of JavaScript within Vim that’s arguably easier to write and read.

Expanding and concealing

This is where my vim-syntax-expand plugin comes in. Here’s a quick demo to give you an idea of what I mean if my previous paragraph was not clear.

I can write concealed characters and see concealed characters, but it actually writes the real JavaScript to the file. It’s caused some people to be slightly confused when looking at my screen, but normal JavaScript is only a set conceallevel=0 away. And yes, it’s intelligent enough to not expand in comments or strings, so you can still type @ or # when required.

The < to “return” mapping uses a special rule that will only work if you’re at the beginning of a line, so you can still type “<=”. Here’s my full configuration, which is also featured in the repository README.md.

I’ve been using it for around and week so far and it feels great. I guess I’m just yearning for a more concise functional language. I type fn, hit “<C-j>” and I get a lambda symbol and a block to write in. Then I can return true by typing “< true”.

This is the sort of thing Vim is amazing at, removing the cruft between you and your text, so you can edit without thinking and concentrate on the problem at hand. Yes it takes practice to use efficiently, but so does every good tool.

This is Shia LaBeouf responding to your “should I give Vim a go?” thoughts.

  • dale


    for your article. it s really helpful. one question from noobie how your actual plugins within plugged forlder end up in modules/plugin folder. why you need to keep them in source control would not that will be anyway install once you start new fresh copy of vim from plugins.vim and kept in default folder of vim-plugged i.e plugged folder.

  • Pingback: Equipping Vim for JavaScript | Oliver Caldwell's blog()

  • Neil McLaughlin

    Really helpful post – thanks for writing up your thoughts.

    Looking at your current dot files it looks like you stopped using syntastic when moving to nvim (based on the fact that it was removed from neovim/.config/nvim/plugins.vim). Have I understood that right and what was your reasoning?



  • JavaMatrix

    The youtube link is dead. Thanks for the article, looking into learning JS and vim at the same time.

  • Mayur Pande

    How comes you refer to javascript as a questionable language? As I currently just stopped learning php to learn js, as people said that was a questionable language. Seems I am going around in circles!

  • Thanks for helping me get gf working in JavaScript! But why not just do:

    set path+=*

    It seems like this works just as well for me, and it doesn’t matter what project I’m in (It doesn’t have to have a src/main directory).