Developer

Extending Vim with Python

If you're a user of the text editor Vim, chances are you are already impressed with the number and power of its inbuilt features. If you've ever tried to add your own functionality to the editor but been turned off by its arcane Vimscript language, then you'll be pleased to know that Vim now supports internal Python scripting.

If you're a user of the text editor Vim, chances are you are already impressed with the number and power of its inbuilt features. If you've ever tried to add your own functionality to the editor but been turned off by its arcane Vimscript language, then you'll be pleased to know that Vim now supports internal Python scripting.

The following commands only work if your version of Vim has been compiled with the -python flag set, pre-built versions of Vim later than version 7.0 have this flag set by default, older versions may not. You can check if your Vim program has Python support by typing the following command:

:python print "hi"

If the status bar displays hi, then you're in business.

You can use the Python command whenever you need a little Python right away, but as you might have noticed from the previous example, its standard output goes to the status line, not to the document.

To do more complicated Python code, you'll want to start embedding your code into functions. There are a few different ways to do this, either you can embed a Python block in a Vimscript function or use a map or a macro to call a Python function. We'll show you the first.

We'll be writing a function that uses the urllib and BeautifulSoup libraries to download a Web page and insert it into the current window. If you're unfamiliar with using BeautifulSoup, you may want to look back over our guide to Web parsing in Python.

Open up a new text file, and call it pyextend.vim — we'll be writing our functions in here, and then sourcing this file in our editor to interpret it. Once you're comfortable with your code, you could include the code in your .vimrc (or _vimrc, in Windows) file so that it is always interpreted whenever you start a Vim or gVim session.

In pyextend.vim type the following:

function! GetHTML()
python 

There's a lot going on there, so we'll go through it line by line.

function! GetHTML()

This first line defines a function in Vimscript called GetHTML, which takes no arguments. Function names must start with capital letters in Vim. The ! symbol after function tells Vim to overwrite any existing function called GetHTML.

python

This line says that until Vim sees a line containing just "EOF" we'll be writing Python code, rather than Vimscript.

import vim, BeautifulSoup, urllib

Here we import the three modules we'll be using: the vim module gives us access to the Vim window and its contents, BeautifulSoup is the library we use to parse the HTML and urllib is the library we use to download the Web page.

handle = urllib.urlopen(vim.current.line)

Creates a variable, called handle, and sets it to the file handle of opening a connection to the Web page. The address of the Web page is taken as the contents of the current line in the Vim window.

soup = BeautifulSoup.BeautifulSoup(handle.read())

Reads from the file handle and creates a BeautifulSoup instance with its contents.

vim.current.buffer[:] = soup.prettify().split('\n')

vim.current.buffer is a list containing the lines in the file we are currently working on in Vim. By using the [:] slice we are replacing it's entire contents with the prettified HTML source of the Web page.

EOF

We put "EOF" on a line all by itself to tell Vim that we are finished with Python code;

endfunction

Then end the function.

Save the pyextend.vim file and open a new window (or, type :new in Vim to open a new split). Then source the new function by typing :source pyextend.vim — if there are errors check your indentation, Python code is still sensitive to indentation when embedded.

You can test this new function by typing in the address of any Web site (don't forget the http:// prefix) — then in command mode, with your cursor on the line of the address, type :call GetHTML(). Your buffer should be replaced with the source of the page.

If your address was http://www.builderau.com.au/ then it should look something like this:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
 <head>
  <title>
   By developers, for developers - Builder AU
  </title>

There is a lot more you can do by extending Vim with Python scripting. If you want to explore, have a browse through the Vim module documentation.

Editor's Picks

Free Newsletters, In your Inbox