While working with python files written by others with varying indentation levels (some using 3 spaces and others using 4 spaces, and some mixing tabs and spaces), it gets tiresome to determine the right settings and change them manually.
Solution using Vindect
There is a python script called vindect that is designed specifically for detecting indentation of Python files in Vim. The script is able to set the below settings appropriate to the current file based on the current usage of spaces and tabs:
- shiftwidth
- tabstop
- softtabstop
- smarttab
- expandtab
The script requires a Python enabled Vim to run. It is invoked using the below command:
py vindect.detect(preferred='space')
The above command can be invoked manually at anytime on the ex command-line, but it is more convenient if it is invoked automatically, whenever a Python file is opened using a simple setup shown below.
The script comes with below instructions to setup, however look further for an Alternative Setup that should work better.
Setup
- place this file in ~/.vim/
- in .vimrc add:
let mysyntaxfile = "~/.vim/mysyntax.vim" if has("python") py import sys,os; sys.path.append(os.path.expanduser("~/.vim/")) py import vindect "if you want different defaults: py vindect.setDefaults(...) endif
- in ~/.vim/mysyntax.vim:
if has("python") au Syntax python py vindect.detect() au Syntax cpp py vindect.detect() au Syntax c py vindect.detect() au Syntax java py vindect.detect(preferred='space') "...etc... endif
Alternative Setup
- Place the python file in your .vim or vimfiles directory.
- Rename it as vindect.py (remove the version number in the filename).
- Create an after/ftplugin/python.vim file with the below contents (change vimfiles to .vim accordingly):
if !exists('s:configured_vindect') if has("python") py import sys,os; sys.path.append(os.path.expanduser("~/vimfiles/")) try py import vindect let s:configured_vindect = 1 catch let s:configured_vindect = 0 endtry "if you want different defaults: py vindect.setDefaults(...) else let s:configured_vindect = 0 endif endif if s:configured_vindect py vindect.detect(preferred='space') endif
Other Solutions
DetectIndent
There is a vim script called DetectIndent that is meant to do exactly this, but it didn't work well for some of the python files I tried (some being set to shiftwidth of 1). YMMV.
Comments
Thanks for the tip. I think we need to explain a little more what happens. While many of our old tips are full of mystery, we're trying to spell out what each new tip actually does. The lead paragraph does a good job, but there needs to be a section which lists the actual effect. Perhaps something like "for example, if you edit a Python file which uses two spaces for each indent, vindent.detect() will change the following Vim settings ...". What does happen if tabs and spaces are used? Also, can we spell out "change vimfiles to .vim accordingly". The DetectIndent info should probably be removed from the lead and added in a separate section (which will probably grow), perhaps "Other solutions".
JohnBeckett 01:04, 21 March 2009 (UTC)
I have now explained it a little more. Thanks for taking the time to make the above comment.
I think it is possible to avoid hardcoded path to vindect.py by using :exec command along with expand('<sfile>') and filenamemodify(), but I haven't tried it.
Haridsv 02:24, 21 March 2009 (UTC)