Indenting Python with VIM
Vim’s default configuration for Python sucks! If you have used Vim to write Python code, you probably know this very well. It does not align to parentheses and braces.
dict(foo=bar<return> _ <= directly insert a 'tab'{'hello': 'world',<return> _ <= Same thing!
It doesn’t add indentation after Python keyword
if True:<return> _ <= Come on! I don’t want to hit 'tab' every time I open a block!
Not even mentioning insanities like: insert tabs instead of spaces, or tab width is 8 spaces. One can say it is a matter of taste; but it is generally accepted that Python code should have a 4 spaces indentation, as stated by PEP 8.
Making Vim PEP-8 friendly
Sane defaults
First I would like to point out something when writing a Vim configuration file.
Generally don’t use the autocmd
command to add hooks to a specific filename’s extension. AutoCmd ... *.py
...
might look like a good way of executing commands when opening a
Python file; it’s not. Because all Python filenames do not necessarily
end with .py
; some executable scripts might not have extension for
example.
autocmd FileType python
is better. But there is an even better way:
ftplugin.
For instance, instead of the following in your vimrc
AutoCmd BufNewFile,BufRead *.py \ setlocal tabstop=4 \ setlocal softtabstop=4 \ setlocal shiftwidth=4 \ setlocal textwidth=80 \ setlocal smarttab \ setlocal expandtab
Create the directory ~/.vim/ftplugin
; create a file named
~/.vim/ftplugin/python.vim
containing:
setlocal tabstop=4 setlocal softtabstop=4 setlocal shiftwidth=4 setlocal textwidth=80 setlocal smarttab setlocal expandtab
Now every files detected as Python files by Vim get the previous commands
executed. Even those with filenames which do not end with .py
.
Sexy edition
Now let’s tackle the edition problem. The solution lies in this
script written by Eric Mc Sween. Download it and drop it in the
~/.vim/indent
directory. You might have to rename the script to
python.vim
. Restart Vim and rejoice! This script intends to make
Vim behave the right way when editing, and is largely successful. Editing Python
code is now a real pleasure.
It aligns the cursor to parentheses and braces. It indents just after if, for, while and so forth. Most problems with the default Vim indentation are solved.
An additional tip about comments
The way comments are indented is still tedious; even when using the indent
script.
def function(foo, bar): if foo: # Some useful comment if bar: print 'foo bar' else: # Another useful comment print 'foo'
This looks more reasonable.
def function(foo, bar): if foo: # Some useful comment if bar: print 'foo bar' else: # Another useful comment print 'foo'
To get this working properly, edit the indentation script
~/.vim/indent/python.vim
. And replace
setlocal indentkeys=!^F,o,O,<:>,0),0],0},=elif,=except
with
setlocal indentkeys=!^F,o,O,<:>,0),0],0},=elif,=except,0#
With this modification, when pressing the # key, comments are indented
correctly.
Update, Clay Gerrard noted that the solution previously
described here doesn’t work on Vim 7. To get it to work, remove the
set smartindent
from your Vim configuration file, or better add
set nosmartindent
in your
~/.vim/ftplugin/python.vim
.
A final note
Make sure filetype plugin and indentation are enabled. It is deactivated by
default on many operating systems. Ubuntu and Debian deactivate indentation and
OpenBSD deactivates both! To make sure everything is activated type
:filetype plugin indent on
.
Don’t forget to put the following line in your vimrc
to make
sure file type plugin and indentation are enabled when you start Vim.
filetype plugin indent on
Update: the link to Eric’s script was broken, it is OK now. Many Thanks to Robert for pointing this out!