Getting to VIM's Python interface

Scripting is usually one of the selling points for those types of text editors
that are specifically targeted at power-users. But most of the time you have
to learn a whole new scripting language to really be able to use it. Imagine
my surprise when I noticed that VIM besides having it’s own scripting
language also let’s you also write plugin in Perl, Python, Ruby and TCL. This
way you don’t really have to learn a new language for scripting VIM, although
you might still want to look into it because there are a few problems.

Since I like Python quite a bit, the rest of this post will be mostly focused
on the Python interface.

To be able to script in other languages, VIM has to be specifically compiled
with support for the language of your choice. Being a bit lazy here I simply
got myself a nice Python-enabled VIM with MacVIM. Using MacPorts you can also get the something similar for the shell with this :

$ sudo port install vim +python

Once you have that, you get a small set of new commands:

python

pyfile

The first lets you execute Python code directly while the latter will load a
given Python file.

If you want to write a plugin, you will most likely also like to take a look
at the vim module the interface offers, which let’s you access things like
the current buffer or the current line (vim.current.line). You can also
get down to the current cursor position with vim.current.window.cursor.

Using the new commands mentioned above you can easily define for instance a
function within a VIM plugin and then bind a command to it::

The documentation of all that is actually quite good, so I will just defer to
the official instructions. I just want to note a
few observations, though.

First of all, the Python interface seems not to offer you all the things you
can do in the native language for writing plugins. For instance: buffers don’t
implement everything you’d normally expect from list objects in Python and
therefor there is for instance no such thing as buffer.insert. This means
that you can’t really create a new lines within a buffer as easily as with the
native append(line_num, text) function.

The Python interface has a buffer.append method but it only lets you
append content to the end of the buffer instead of allowing append/insert
operations at an arbitrary line number. In practice I simple resorted to
something like this for creating new lines after a given line-number:

line_num = 123
cmd = '%ds/$/\r/' % (line_num, )
vim.command(cmd)

Another problem I ran into was something that I couldn’t yet solve. For some
reason, I can’t actually modify a buffer (either the current or any other line
inside a buffer):

The interesting thing about this is that it only happens when I’m using the
terminal version of VIM. In MacVIM everything works just fine. And this isn’t
really limited to the Python interface. I also tried the Ruby one and got
this:

But there it only happens when I’m operating for instance on unsaved buffers.
If someone has a solution for this, please let me know :-) For now I had
to rewrite a small plugin I just wrote today in order to get it to work
everywhere.