Python with a modular IDE (Vim)

Tags: python vim

On Thursday, May 9th, 2008 the Utah Python User Group decided to settle the debate that has plagued us developers since the beginning of time: If you were a programming language, what editor would you use?


I was tasked with showing Eclipse with the PyDev plugin in all its glory–but we all know–real men / developers don’t use IDE’s, so we are going to talk about using Python and Vim together, reaching a state of Zen that the Dalai LLama would be jealous of and establishing more Feng Shui than Martha Stewart’s Kitchen.


Freely jump between your code and python class libraries


There are 2 ways to add your ability to jump between python class libraries, the first is to setup vim to know where the Python libs are so you can use ‘gf’ to get to them (gf is goto file). You can do this by adding this snippet to your .vimrc:


python << EOF
import os
import sys
import vim
for p in sys.path:
if os.path.isdir(p):
vim.command(r"set path+=%s" % (p.replace(" ", r"\ ")))
EOF

With that snippet you will be able to go to your import statements and hit ‘gf’ on one of them and it’ll jump you to that file.


Continuing accessibility of the Python class libraries we are going to want to use ctags to generate an index of all the code for vim to reference:


$ ctags -R -f ~/.vim/tags/python.ctags /usr/lib/python2.5/


and then in your .vimrc


set tags+=$HOME/.vim/tags/python.ctags


This will give you the ability to use CTRL+] to jump to the method/property under your cursor in the system libraries and CTRL+T to jump back to your source code.


I also have 2 tweaks in my .vimrc so you can use CTRL+LeftArrow and CTRL+RightArrow to move between the files with more natural key bindings.


map <silent><C-Left> <C-T>
map <silent><C-Right> <C-]>


You can also see all the tags you’ve been to with “:tags”


Code Completion


To enable code completion support for Python in Vim you should be able to add the following line to your .vimrc:


autocmd FileType python set omnifunc=pythoncomplete#Complete


but this relies on the fact that your distro compiled python support into vim (which they should!).


Then all you have to do to use your code completion is hit the unnatural, wrist breaking, keystrokes CTRL+X, CTRL+O. I’ve re-bound the code completion to CTRL+Space since we are making vim an IDE! Add this command to your .vimrc to get the better keybinding:


inoremap <Nul> <C-x><C-o>


Documentation


No IDE is complete without the ability to access the class libraries documentation! You’ll need to grab this vim plugin. This gives you the ability to type :Pydoc os.path or use the keystrokes <Leader>pw and <Leader>pW to search for the item under the cursor. (Vim’s default <Leader> is “\”).


Syntax Checking


Vim already has built in syntax highlighting for python but I have a small tweak to vim to give you notifications of small syntax errors like forgetting a colon after a for loop. Create a file called ~/.vim/syntax/python.vim and add the following into it:

syn match pythonError "^\s*def\s\+\w\+(.*)\s*$" display
syn match pythonError "^\s*class\s\+\w\+(.*)\s*$" display
syn match pythonError "^\s*for\s.*[^:]$” display
syn match pythonError “^\s*except\s*$” display
syn match pythonError “^\s*finally\s*$” display
syn match pythonError “^\s*try\s*$” display
syn match pythonError “^\s*else\s*$” display
syn match pythonError “^\s*else\s*[^:].*” display
syn match pythonError “^\s*if\s.*[^\:]$” display
syn match pythonError “^\s*except\s.*[^\:]$” display
syn match pythonError “[;]$” display
syn keyword pythonError         do

Now that you have the basics covered, lets get more complicated checking added. Add these 2 lines to your .vimrc so you can type :make and get a list of syntax errors:


autocmd BufRead *.py set makeprg=python\ -c\ \"import\ py_compile,sys;\ sys.stderr=sys.stdout;\ py_compile.compile(r'%')\"
autocmd BufRead *.py set efm=%C\ %.%#,%A\ \ File\ \"%f\"\\,\ line\ %l%.%#,%Z%[%^\ ]%\\@=%m


You will have the ability to to type :cn and :cp to move around the error list. You can also type :clist to see all the errors, and finally, sometimes you will want to check the syntax of small chunks of code, so we’ll add the ability to execute visually selected lines of code, add this snippet to your .vimrc:


python << EOL
import vim
def EvaluateCurrentRange():
eval(compile('\n'.join(vim.current.range),'','exec'),globals())
EOL
map <C-h> :py EvaluateCurrentRange()


Now you will be able to visually select a method/class and execute it by hitting “Ctrl+h”.


Browsing the source


Moving around the source code is an important feature in most IDE’s with their project explorers, so to get that type of functionality in vim we grab the Tag Listplugin. This will give you the ability to view all opened buffers easily and jump to certain method calls in those buffers.


The other must-have feature of an IDE when browsing code is being able to open up multiple files in tabs. To do this you type :tabnew to open up a file in a new tab and than :tabn and :tabp to move around the tabs. Add these to lines to your .vimrc to be able to move between the tabs with ALT+LeftArrow and ALT+RightArrow:



map <silent><A-Right> :tabnext<CR>
map <silent><A-Left> :tabprevious<CR>


Debugging


To add debugging support into vim, we use the pdb module. Add this to your ~/.vim/ftplugin/python.vim to have the ability to quickly add break points and clear them out when you are done debugging:


python << EOF
def SetBreakpoint():
import re
nLine = int( vim.eval( 'line(".")'))

strLine = vim.current.line
strWhite = re.search( '^(\s*)', strLine).group(1)

vim.current.buffer.append(
"%(space)spdb.set_trace() %(mark)s Breakpoint %(mark)s" %
{'space':strWhite, 'mark': '#' * 30}, nLine - 1)

for strLine in vim.current.buffer:
if strLine == "import pdb":
break
else:
vim.current.buffer.append( 'import pdb', 0)
vim.command( 'normal j1')

vim.command( 'map <f7> :py SetBreakpoint()<cr>')

def RemoveBreakpoints():
import re

nCurrentLine = int( vim.eval( 'line(".")'))

nLines = []
nLine = 1
for strLine in vim.current.buffer:
if strLine == ‘import pdb’ or strLine.lstrip()[:15] == ‘pdb.set_trace()’:
nLines.append( nLine)
nLine += 1

nLines.reverse()

for nLine in nLines:
vim.command( ‘normal %dG’ % nLine)
vim.command( ‘normal dd’)
if nLine < nCurrentLine:
nCurrentLine -= 1

vim.command( ‘normal %dG’ % nCurrentLine)

vim.command( ‘map <s-f7> :py RemoveBreakpoints()<cr>’)
EOF

With that code you can now hit F7 and Shift-F7 to add/remove breakpoints. Then you just launch your application with !python % (percent being the current file, you can declare your main file here if its different).


Another tweak I use is to have my vim inside screen with a horizontal split, that way I can see the python interpreter and debug while still having vim there so I can easily fix my code.


Snippets


A great time saver with standard IDE’s is code snippets, so you can type a few key strokes and get a lot of code out of it. An example of this would be a django model, instead of typing out the complete declaration you could type ‘mmo<tab><tab>’ and have a skeleton of your model done for you. To do this in vim we grab the Snippets EMU plugin.


Check out a great screencast of snippetsEmu in action here


Emacs


Here is a great post on how to do the same with Emacs.

Comments
2010-03-05 20:06:55 - Adena Bandel

Definitely agree with what you stated. Your explanation was certainly the easiest to understand. I tell you, I usually get irked when folks discuss issues that they plainly do not know about. You managed to hit the nail right on the head and explained out everything without complication. Maybe, people can take a signal. Will likely be back to get more. Thanks

2010-03-06 00:19:00 - Peter

Great Post. I would love to read more in future. keep up the good work. Yearly hosting http://www.intelweb.biz

2010-03-06 13:42:51 - Whitesmoke Review

Great post thanks, all the best. I really enjoy reading this blog, it has a great position on my favourites bar! Whitesmoke Review

2010-03-06 14:55:14 - Calculating Percentages

Wicked post, I totally agree. How long have you been blogging for now, I really like the look of your site. Cheers, Calculating Percentages

2010-03-06 15:12:50 - How to Remove Scars

Great post, I totally agree. How long have you been blogging for now, I really like the design of your site. Cheers, How to Remove Scars

2010-03-07 04:28:35 - nj scrap metal

I was searching for information on this topic and many blogs came up. I also really like the layout of the site is this a free theme or a premium one? If free I would like to know where to get it so I could utilize it on one of my sites. It is so hard to find a free theme that is professional looking. tj

2010-03-07 21:06:32 - The values are going to be fetched thru the form.

There is an old saying 'A debt should not out last the person who created it'. So add up all you current debts to one figure and this is our starting point. From here, depending on individual circumstances we might add in educations cost of children, funeral costs and medical expenses. The last but not the least point to take into account is the future income requirements to the family. This last point is very important as many families struggle to survive after the death of the main income generator into the family.

2010-03-08 04:54:13 - ghd hair straighteners discount

Great post I must say.. Simple but yet interesting and engaging.. Keep up the good work!