Vim is fairly extensible. Unlike Emacs or Eclipse, it’s just an editor, not a platform. It is, however, very featureful, and includes its own slightly eccentric domain language as well as bindings into a few others. Note: this isn’t a HOWTO, it’s just a few things to consider before jumping in.
1. Vim Script
Here is a neat lineage: the Unix line editor
ed evolved into the more advanced
ex which was used as the basis for the command mode in
vi and extended into the roughly Turing-complete mini-language of Vim. And development continues; in his latest release, Bram Moolenaar has added native support for floating point numbers.
Vim Script supports many regular programming concepts: loops, lists, dictionaries, exceptions, etc. But the language is odd. Here’s some code showing the hoops one must jump through to map a bit of functionality to a key:
function! s:doSomething() " stuff endfunction command DoSomething :call <SID>doSomething() nmap k :DoSomething
- A trailing
s:in the function definition and the
<SID>in the command declaration are a thin but tenable form of namespace management. They’ll expand to a unique name at read time so that similarly named functions in other files are not clobbered.
functioncould be replaced equivalently with
func, etc. This follows for all Vim commands. As long as a token can uniquely complete into a keyword, it is valid.
As in many other languages, statements can be wrapped using a
\ character. Unlike in those languages, in Vim Script it must appear at the beginning of the succeeding line:
if some_exceedingly_long_expression || \ a_second_expression echo 'Success' endif
2. Alternative plugin languages
It isn’t widely known that Vim has interfaces into several popular scripting languages: Python, Ruby, Perl, Scheme, and Tcl. These are more powerful than Vim Script but have certain drawbacks in use.
- Debugging is difficult. Foreign code is interpreted by what is essentially one giant eval. If you misplace a close parenthesis or an
endkeyword, you will have to track it down yourself.
- Integration with Vim is slight. The calling interface is in a table below. The bindings just tunnel most editor interactions through
Vim::command(or equivalent) as string arguments.
- Many Vim installations don’t include external language support by default. It’s an easy fix for a user running a
rpm-based Linux distribution, but will require a recompile on Windows, something a Windows user is not wont to do. OS X is hit-or-miss.
Point (3) is particularly unfortunate if you’re making an extension you intend to distribute. I wrote perhaps the largest Ruby-based plugin for Vim available; the majority of people who contact me about it are only looking for installation help.
This is what it looks like to interact with Vim from Ruby:
# Setting options inside the editor is pretty # straightforward. VIM::set_option "noinsertmode" VIM::set_option "hlsearch" # ...unless you want to set an option local to a buffer. # There's no API call for this, so we must go up one # layer of abstraction: VIM::command "setlocal nowrap" VIM::command "setlocal spell" VIM::command "setlocal foldcolumn=0"
If we’re going to do an odd call in multiple places, it makes sense to add some glue to confine code acrobatics:
def VIM::has_syntax? # All return values from `evaluate` are strings, and # "0" evaluates to true in ruby. VIM::evaluate('has("syntax")') != "0" end
See below the partial interfaces for a few languages. Obviously there’s room for improvement in the API:
For some strange reason, the Scheme interface also offers
(beep), and the Tcl interface,
Interesting sidenote: these extension languages have access to window handles within Vim, allowing deterministic window management. Vim Script doesn’t seem to support this, so using an alternative language seems to offer a superset of functionality.
3. Choosing a language
This can be summarized like so:
- Great integrated
- Lots of other plugins you can crib from.
- The language is awkward.
Other (Perl, Python, Ruby, Tcl, Scheme)
- Strong languages.
- Experience carries over into other pursuits.
- Debugging is hard.
- Interface to Vim is slight.
- May require the user to install language libraries.
- Syntax highlighting in a
.vimfile is easily confused.
- Neglected by both plugin writers and Vim developers.
Using Vim Script means giving up the good stuff: closures, object-orientation, higher-order functions, reflection, and metaprogramming. So despite the extra work, selecting an alternative language is recommended for non-trivial extensions. Perhaps support within Vim will improve as more plugin writers follow this route.
Thanks to Jesse Funaro and Chris Gaal for their comments and suggestions.