Set indent parameters for Python files
Talk0this wiki
created May 13, 2006 · complexity intermediate · author Davide Alberani · version 6.0
You may need to maintain source files that use different indentation styles. For example, some files may use four spaces for each indent, while others use three spaces, or use tabs, or use a mixture of tabs and spaces.
This tip presents alternative procedures to automatically detect and set the indent options so Vim adapts to the style of the program you are working on. The procedures are oriented towards working on Python programs but may be useful for other languages.
Contents |
IndentConsistencyCop
The IndentConsistencyCop plugin warns if inconsistent indentation is used in a buffer and also offers to correct the buffer's indent settings (shiftwidth, softtabstop, etc) if they do not match the indent type used in the buffer. This plugin is not limited to Python files. Checks can be triggered manually or (with the IndentConsistencyCopAutoCmds add-on plugin) automatically for certain filetypes.
Indent Finder
The Indent Finder plugin sets the correct indentation for each file that you edit. It uses a Python script that determines what indent style was used, then adjusts your settings so that new modifications use the same style.
Vindect
Vindect is a Python script to detect the indent options required for editing a Python program. In Vim, output from the :version command should include "+python".
The following options are set based upon usage in the current file, and your preferences: shiftwidth, tabstop, softtabstop, smarttab, expandtab.
Rename the downloaded file to vindect.py. The file includes setup instructions using the deprecated mysyntaxfile variable. Following is a better procedure that should be used instead.
The following commands need to be executed once per Vim session (done below):
" First need to set the Python path so vindect.py is found. :py import vindect :py vindect.setDefaults(...) " optional to set different defaults
This command detects and sets the indent options when a new file is opened (done below):
:py vindect.detect(preferred='space')
The following setup performs all the required steps whenever a Python file is opened.
- Place vindent.py in your .vim (Unix based systems) or vimfiles (Windows) directory.
- Create an after/ftplugin/python.vim file with the following contents. On Windows systems, change .vim to vimfiles.
if !exists('s:configured_vindect')
if has('python')
py import sys,os; sys.path.append(os.path.expanduser('~/.vim/'))
try
py import vindect
let s:configured_vindect = 1
catch
let s:configured_vindect = 0
endtry
" to set different defaults: py vindect.setDefaults(...)
else
let s:configured_vindect = 0
endif
endif
if s:configured_vindect
py vindect.detect(preferred='space')
endif
DetectIndent
The DetectIndent plugin is another alternative.
Vim script
The following script can only choose between two sets of fixed options. One set is used if tabs are detected; otherwise another set is used (for space indents).
You could put the following in your vimrc and use a mapping to call PyIndentAutoCfg() when wanted, or define an auto command to call that function when a Python file is opened.
" Set options if using spaces for indents (default).
function PySpacesCfg()
set expandtab
set tabstop=8
set softtabstop=4
set shiftwidth=4
endfunction
" Set options if using tabs for indents.
function PyTabsCfg()
set noexpandtab
set tabstop=4
set softtabstop=4
set shiftwidth=4
endfunction
" Return 1 if using tabs for indents, or 0 otherwise.
function PyIsTabIndent()
let lnum = 1
let got_cols = 0 " 1 if previous lines ended with columns
while lnum <= 100
let line = getline(lnum)
let lnum = lnum + 1
if got_cols == 1
if line =~ "^\t\t" " two tabs to prevent false positives
return 1
endif
endif
if line =~ ":\s*$"
let got_cols = 1
else
let got_cols = 0
endif
endwhile
return 0
endfunction
" Check current buffer and configure for tab or space indents.
function PyIndentAutoCfg()
if PyIsTabIndent()
call PyTabsCfg()
else
call PySpacesCfg()
endif
endfunction
Comments
Re configuration of vindent: It may be possible to avoid a hard coded path to vindect.py by using :exec with expand('<sfile>') and filenamemodify().
Re the Vim script: The following version of PyIsTabIndent() handles more languages:
function! PyIsTabIndent()
let lnum = 1
while lnum <= 100
let line = getline(lnum)
let lnum = lnum + 1
if line =~ '^\t\t\(if\|while\|do\|for\|public\|private\|char\|int\|float\|double\|call\)\>'
return 1
endif
endwhile
return 0
endfunction