Working with Vim and IPython
Note: the text below is not for the fainthearted. Setting up Vim to communicate with IPython is currently not very straightforward. The situation will improve soon.
When I write Python code I tend to use IPython quite a bit to test and experiment. Currently this means quite a bit of reloading and writing test code in the IPython shell. I’ve always been a little jealous of the Emacs folks for being able to communicate with the Python shell with ease. Vim has a different philosophy. We use the editor to edit stuff and the shell to run it. With that in mind, one can set up Vim to talk to IPython.
There are several steps for this:
- Ensure that Vim is compiled with +python
- Get the code that enables communication with IPython
- Write code to send code from Vim to the server
1. Ensure that vim is compiled with +python
Open your favorite version of Vim and do1 | :version |
In there look for “+python”. If it is not there, you need to somehow get a version that has “+python”. It is also important to check which version of Python your Vim was compiled against. For this, execute the following command in vim:
1 | :python import sys; print sys.version |
2. Getting the code for communicating with IPython
Matt Foster has written a plugin for Textmate called ipythontm-bundle. This Textmate bundle uses the ipy_textmateserver.py to create a Twisted server to which stuff is sent for evaluation from Vim.
This file is can be downloaded from the textmate-server branch of IPython. For Vim we only need this file. Why only this file will be explained at the end of this post. Once the file is downloaded put it in your IPython/Extensions directory. For me this directory is:
1 | /opt/local/Library/Frameworks/Python.framework/Versions/Current/lib/python2.6/site-packages/IPython/Extensions |
3. The Vim side of life
At the moment, Vim has no idea that there will be a server running. Therefore, we have to write a plugin. The following (very very simple) code server as said plugin.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | import vim import socket def runner(content): s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) try: # make sure to chage the directory here s.connect("/YOUR/HOME/DIR/.ipython/IPYS") s.send(content) s.close() except: print "Error: could not connect to iPython server." # --- Functions for running code in iPython --------------------------------- # def run_current_line(): runner(vim.current.line) def run_selection(): runner("\n".join(vim.current.range)) def run_buffer(): runner("\n".join(vim.current.buffer)) # --- Clean up function def remove_sockets(): import os import sys os.remove("/Users/petrov/.ipython/IPYS") |
Essentially, the server will create a UNIX socket. By default the socket is:
1 | $HOME/.ipython/IPYS |
It is possible to rename the socket or use different ones for different Vim windows. For now, I wanted to get the basics going. The Python code above should go into
1 | $HOME/.vim/plugin |
4. Using the code
Now that the code is in place we can start using it. Start IPython and execute the following code:1 2 3 4 5 6 | import ipy_textmateserver # create the server s = ipy_textmateserver.TextMateServer() # start the server s.start() # to stop the server do: s.stop() |
1 | :map ,el :python run_current_line()<cr> |
Put the cursor on the line of code you want to eval and do: ,el.
This should send the line to IPython and you should see the results of execution in the shell.
The other two functions in on the plugin side can also be mapped to whatever you want.
Question and Answer
This is very complicated!
Yes, this is not the easiest thing in the world. But it let’s me work the way I want to work. In the future this will be packaged better
as a proper Vim plugin.
Why not use the client that comes with the ipythontm-bundle.
I did try to use that code. However, it seems that Vim and Textmate do things differently. The Vim client that comes with ipythontm-bundle
uses a Twisted reactor to send code to the server. This is great. However, once the reactor is stopped it can’t be restarted. Any attempts to do
so result in a blocked thread. When this happens from inside Vim, it kills the whole session. This sucks. My guess is that Textmate reloads the whole
client file. Vim doesn’t seem to do this. Therefore, I opted to use simple Python sockets.
Why not use ipy_vimserver.py?
I tried this as well. However, it uses socket code that doesn’t work on my machine. If you’re on Linux you should be able to use ipy_vimserver.py without
any problems.
This looks great! (Haven’t actually got around to trying it, since I need to recompile gvim…)
Anyway, for the home folder in the plugin, you can use os.path.expanduser(’~’), especially for the last line, where you use you own home directory :)
Comment by Johannes — Oct 5, 2009 2:35:22 AM | # - re
[…] Working with Vim and IPython — Experiment Room 4 When I write Python code I tend to use IPython quite a bit to test and experiment. Currently this means quite a bit of […]
Pingback by Links for 2009-10-04 [del.icio.us] | TuxWire : The Linux Blog — Oct 5, 2009 4:52:57 AM | # - re
if you need help recompiling gvim with the appropriate version of Python, see below:
Compiling VIM with Python 2.5 support on Windows XP showmedo.com/videotutorials/video?name=1850010&fromSeriesID=185
Comment by xxx — Oct 24, 2009 11:21:49 PM | # - re
when I try this on winxp, I get:
In [5]: Traceback (most recent call last): File “C:\Python25\Lib\threading.py”, line 460, in __bootstrap self.run() File “C:\Python25\Lib\site-packages\IPython\kernel\twistedutil.py”, line 45, in run reactor.run(installSignalHandlers=0) File “C:\Python25\Lib\site-packages\twisted\internet\base.py”, line 1128, in run self.mainLoop() File “C:\Python25\Lib\site-packages\twisted\internet\base.py”, line 1137, in mainLoop
self.runUntilCurrent()
— <exception caught here> —
File “C:\Python25\Lib\site-packages\twisted\internet\base.py”, line 729, in runUntilCurrent f(a, *kw) File “C:\Python25\lib\site-packages\IPython/Extensions\ipy_textmateserver.py”, line 100, in _sta rt_listening self.connection = reactor.listenUNIX(self.address, self.factory) File “C:\Python25\Lib\site-packages\twisted\internet\posixbase.py”, line 312, in listenUNIX assert unixEnabled, “UNIX support is not present” exceptions.AssertionError: UNIX support is not present
Comment by xxx — Oct 26, 2009 1:59:30 PM | # - re