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:
python << EOF
def _my_function(some_arg=None):
import vim
print len(vim.current.buffer)
EOF
command -nargs=* MyCommand :python _my_function(<f-args>)
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):
:py import vim :py vim.current.line = '123' Traceback (most recent call last): File "<string>", line 1, in <module> TypeError: bad argument type for built-in operation
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:
:ruby VIM::Buffer.current.line = '123' TypeError: can't modify frozen string
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.
A nice writeup. Refering to some of the problems you have had, to insert the text "foo bar" on line 3 of the current file use:
Not at all obvious, but it kind of makes sense if you are used to Python slicing.
I run Vim on Linux and I haven't had any problems updating vim.current.line. I wonder if this is a bug in MacVim?
Feb. 23, 2009, 11:26 p.m.
Thank you :-) I always forget that you can also modify a list using slicing. The funny thing is, that vim.current.line seems to mostly work in MacVIM but not in the terminal version provided by MacPort :-/
Feb. 24, 2009, 10:05 a.m.