Menu

call vim from inside a python script

As I mentioned in my last post, I’ve been re-working a script to add tasks to a task manager. I’m using The Hit List again, because I’ve decided to move myself away from gmail and google tasks.
At any rate, I want to be able to add tasks to THL from the CLI, something I’ve been doing with google tasks for a while. The quickest way for me to do this is with a script that combines python and applescript. I decided too that I want to be able to edit tasks with Vim, which I’m using more and more lately.1
It’s easy to call vim, or any other editor, from within a python script. There are just one or two tricks that are helpful.

The flow for an edit function needs to open vim with a named temporary file in the buffer, allow the user to write what needs to be written, save and close vim, and then capture that input. In my case, I want the capture to return a dictionary of key:value pairs to use with my task script. The easiest way I can think to do this is to use yaml as the file format. Thus, this script needs pyyaml installed.

Following good python practice, import the needed modules with standard and third party modules on separate lines:

1
2
3
4

#! /usr/bin/env pythonimporttempfile,subprocessimportyaml

tempfile is part of Python’s standard library, and provides simple support for spinning up temporary files that are automatically flushed by the script. That means, of course, that your task won’t be stored permanently on disk as a file. It also means the file needs to be read before it’s flushed. We do this with a while block:

This code creates a temporary file object with the suffix ‘.task’. temp.name passes the name of the temp file to vim, which is called by subprocess.call(). Note that call expects a list as input, which includes the command and any arguments passed to it. At this point, vim will open and we can write whatever we want as per usual, saving and exiting vim as per usual. Upon exiting vim, and before the while block ends, we assign the contents of the temp file to text.

In my case, text is a series of key:value pairs in yaml form. To get a dictionary, we simply load text as yaml:

params=yaml.load(text)

Now we have a Python dictionary of key:value pairs that can be used by other functions in the script.

I want these yaml files to be consistent, so I’m using a vim plugin that will serve templates based on filetype. After installing the plugin, I put a file named taskedit in ~/.vim/templates like this:

title:context:tags:note:#cursor:112del

So, when the script opens a new vim buffer, it’ll be pre-populated with this template, with the cursor waiting after title for input. Nifty. Those keys will be the keys of my parameter dictionary as well.

This week macromates announced that Textmate2 is being open-sourced. I’ve been an avid Textmate user for about 4 years. I wonder what that bodes for the future of the application, and whether it will mark a further stalling of development. Textmate 1.5 still works on Lion, but I’m wondering how long that will be true as the OSX ecosystem continues to evolve. In the meantime, I’m giving SublimeText2 a closer look, and getting more familiar with Vim. ↩