Turn Vim into Powerful JavaScript Editor

After trying NetBeans, AptanaStudio, Emacs, KomodoEdit, and Jedit, I’ve finally settled on Vim (again) for my JavaScript/HTML/CSS editing needs. AptanaStudio is ok by default, but extending it wasn’t very fun. NetBeans simply doesn’t do what I need. KomodoEdit has no code re-indentation (code formatting) feature which is a big fail in my opinion. Jedit was just ugly, and the default feature set left a lot to be desired. There are tons of plugins for it, but I just didn’t have the time to try them all out.

Vim doesn’t have too many features related to editing JavaScript code out of the box. Indentation is horrendous, error-checking is non-existent, and it’s generally a pain in the arse. However, Vim is very extensible, and with a few cool plugins, you can turn it into a powerful JavaScript editor within a few minutes (plus the time you waste reading this post, of course). Here’s a list of plugins that transform Vim into one of the coolest JavaScript editors i’ve used.

NERDTree

NERDTree is definitely a must when it comes to quickly finding your way around the file system. Latest version as of this writing is 4.1.0. Once you have it installed as per the documentation on the plugin page, you might also want to create key bindings for it. Add the following to the .vimrc file (on Linux, it’s usually located in your home directory).

"Map NERDTree to \p
nmap <silent> <Leader>p :NERDTreeToggle<CR>

Now you can activate NERDTree using the \p shortcut.

Indentation

Before the following works you have to enable some Vim features:

"Filetype
set filetype=on
filetype plugin on
filetype indent on

Then you can set up the global settings for indentation. Add the following to your .vimrc. This sets tabs to 4-character width, and indents your files using spaces rather than tabs. It also sets the right margin to 79 characters (the textwidth or tw parameter) and enables automatic wrapping (don’t worry, we’ll override these per file type).

set ai
set ts=4
set sts=4
set et
set sw=4
set textwidth=79

Now you have to set up the overrides per file type. Remember that whatever file type you don’t override will use the settings of the last file type that was loaded into the editor. So you should override the settings for any file type that you use.

" HTML (tab width 2 chr, no wrapping)
autocmd FileType html set sw=2
autocmd FileType html set ts=2
autocmd FileType html set sts=2
autocmd FileType html set textwidth=0
" Python (tab width 4 chr, wrap at 79th char)
autocmd FileType python set sw=4
autocmd FileType python set ts=4
autocmd FileType python set sts=4
autocmd FileType python set textwidth=79
" CSS (tab width 2 chr, wrap at 79th char)
autocmd FileType css set sw=2
autocmd FileType css set ts=2
autocmd FileType css set sts=2
autocmd FileType css set textwidth=79
" JavaScript (tab width 4 chr, wrap at 79th)
autocmd FileType javascript set sw=4
autocmd FileType javascript set ts=4
autocmd FileType javascript set sts=4
autocmd FileType javascript set textwidth=79

The reason some of the settings are the same as default is that you have to reset the settings after opening a file that overrides the defaults with non-default settings. For example, if I didn’t use the same default settings for JavaScript file, I would have 2-character tabs in JavaScript after editing a CSS file. (If you know of a better way to do this, please drop me a line).

UPDATE: I’ve discovered shortly after posting this that you can use setlocal instead of set to avoid permanently overriding the defaults. So here are the latest settings for indentation:

" HTML (tab width 2 chr, no wrapping)
autocmd FileType html set sw=2
autocmd FileType html set ts=2
autocmd FileType html set sts=2
autocmd FileType html set textwidth=0
" XHTML (tab width 2 chr, no wrapping)
autocmd FileType xhtml set sw=2
autocmd FileType xhtml set ts=2
autocmd FileType xhtml set sts=2
autocmd FileType xhtml set textwidth=0
" CSS (tab width 2 chr, wrap at 79th char)
autocmd FileType css set sw=2
autocmd FileType css set ts=2
autocmd FileType css set sts=2

As you can see, I’ve also added the xhtml FileType, as Vim differentiates between plain HTML and XHTML.

Autocompletion

To enable auto-completion for the file types we use, you can set up OmniCompletion:

autocmd FileType python set omnifunc=pythoncomplete#Complete
autocmd FileType javascript set omnifunc=javascriptcomplete#CompleteJS
autocmd FileType html set omnifunc=htmlcomplete#CompleteTags
autocmd FileType css set omnifunc=csscomplete#CompleteCSS

This sets up OmniCompletion for Python, JavaScript, HTML, and CSS. The shortcuts for completion are:

  • Ctrl+X, Ctrl+O: OmniComplete
  • Ctrl+X, Ctrl+P: Complete keyword (any keyword in the file)
  • Ctrl+X, Ctrl+L: Complete the line (based on the lines in the file)

There are more shortcuts (albeit only the first one is actually OmniComplete), but these are the ones I use the most.

JavaScript-specific indentation

By default, Vim uses C indentation for JavaScript. Although this sort-of works, it’s far from ideal. That’s why we have IndentAnything plugin, and JavaScript indentation plugin that builds on it to enable correct indentation in JavaScript. Simply install them as per instructions on the respective pages, and you’re done.

UPDATE: After a while working with this plugin, I’ve discovered some edge cases that cause the plugin to fail or not yield very nice results as per my own sense of taste. I’ve found an alternative plugin that sort-of takes care of some of these edge cases. Neither is perfect, so you might want to give both a try before deciding.

JavaScript beautifier

Formatting code means readability. Readability is… Ok, enough of the corny intro. jsbeautify plugin helps you beautify your code. Once you’ve installed it as per instructions, you can fire it by pressing \ff combo. It works either on selected text or the entire file.

JSLint integration

Having JSLint integrated into your editor is not only a good idea, it’s absolutely necessary, in my opinion. I’ve helped a guy hunt down extra comma that made his code fail in Internet Explorer, and believe me, it’s hard to find those errors when you firmly believe the code is correct. That’s why having JSLint insult you to death with its error messages is a good thing. And there’s a plugin that does that. Install the jslint plugin as per instructions, and also install a JavaScript interpreter like Rhino (package available on Ubuntu Maverick), Spidermonkey, or node.js.

I must warn you that this plugin is very slow. However, it wasn’t any faster in Aptana Studio, so I’m guessing it’s good enough. The JavaScript editing may become a bit less responsive from time to time.

The way it works is it underlines with wavy red line (in graphical mode) the errors in your code. You can see the error message in command mode. Again, it’s slow, so you may have to wait a second or two before the underline disappears after you modify the code.

UPDATE: A reader mentioned an alternative plugin for JSLint integration. If the plugin discussed above is too painfully slow, you might try that one instead. The alternative will only do the check when the buffer is saved, so it will give you better editing performance.

Enabling line numbering

To display line numbers on the left margin, add this to the .vimrc:

"Show line number
set number

Highlighting the current line and cursor

With the following lines the current line in your editor will be highlighted:

"Higlight current line only in insert mode
autocmd InsertLeave * set nocursorline
autocmd InsertEnter * set cursorline

"Highlight cursor
highlight CursorLine ctermbg=8 cterm=NONE

Search as you type

Called ‘incremental search’ in Vim, it’s a great feature. The editor will start searching as soon as you start typing the keyword.

"Incremental search
set incsearch

If things don’t work

If something doesn’t work, try adding this to your .vimrc:

set nocompatible

Stuff not included in this guide

Some things you might have wanted are deliberately omitted. For example, I don’t use advanced auto-completion that takes into account the source code or the JavaScript frameworks included in your project. I’ve also omitted SCM integration and things like maximizing the window on start, etc. I leave these things as an exercise for the reader.

All in all, I hope this has helped you get a better experience editing JavaScript in Vim. Happy hacking!