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.
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.
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 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):
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
The DetectIndent plugin is another alternative.
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
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