Created
August 6, 2014 00:31
-
-
Save dustinfarris/0ed0cf0c2f4e94917e33 to your computer and use it in GitHub Desktop.
python indentation with 2 spaces for hanging indents (put in .vim/indent)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
" Python indent file | |
" Language: Python | |
" Maintainer: Eric Mc Sween <em@tomcom.de> | |
" Original Author: David Bustos <bustos@caltech.edu> | |
" Last Change: 2004 Jun 07 | |
" Only load this indent file when no other was loaded. | |
if exists("b:did_indent") | |
finish | |
endif | |
let b:did_indent = 1 | |
setlocal expandtab | |
setlocal nolisp | |
setlocal autoindent | |
setlocal indentexpr=GetPythonIndent(v:lnum) | |
setlocal indentkeys=!^F,o,O,<:>,0),0],0},=elif,=except | |
let s:maxoff = 50 | |
" Find backwards the closest open parenthesis/bracket/brace. | |
function! s:SearchParensPair() | |
let line = line('.') | |
let col = col('.') | |
" Skip strings and comments and don't look too far | |
let skip = "line('.') < " . (line - s:maxoff) . " ? dummy :" . | |
\ 'synIDattr(synID(line("."), col("."), 0), "name") =~? ' . | |
\ '"string\\|comment"' | |
" Search for parentheses | |
call cursor(line, col) | |
let parlnum = searchpair('(', '', ')', 'bW', skip) | |
let parcol = col('.') | |
" Search for brackets | |
call cursor(line, col) | |
let par2lnum = searchpair('\[', '', '\]', 'bW', skip) | |
let par2col = col('.') | |
" Search for braces | |
call cursor(line, col) | |
let par3lnum = searchpair('{', '', '}', 'bW', skip) | |
let par3col = col('.') | |
" Get the closest match | |
if par2lnum > parlnum || (par2lnum == parlnum && par2col > parcol) | |
let parlnum = par2lnum | |
let parcol = par2col | |
endif | |
if par3lnum > parlnum || (par3lnum == parlnum && par3col > parcol) | |
let parlnum = par3lnum | |
let parcol = par3col | |
endif | |
" Put the cursor on the match | |
if parlnum > 0 | |
call cursor(parlnum, parcol) | |
endif | |
return parlnum | |
endfunction | |
" Find the start of a multi-line statement | |
function! s:StatementStart(lnum) | |
let lnum = a:lnum | |
while 1 | |
if getline(lnum - 1) =~ '\\$' | |
let lnum = lnum - 1 | |
else | |
call cursor(lnum, 1) | |
let maybe_lnum = s:SearchParensPair() | |
if maybe_lnum < 1 | |
return lnum | |
else | |
let lnum = maybe_lnum | |
endif | |
endif | |
endwhile | |
endfunction | |
" Find the block starter that matches the current line | |
function! s:BlockStarter(lnum, block_start_re) | |
let lnum = a:lnum | |
let maxindent = 10000 " whatever | |
while lnum > 1 | |
let lnum = prevnonblank(lnum - 1) | |
if indent(lnum) < maxindent | |
if getline(lnum) =~ a:block_start_re | |
return lnum | |
else | |
let maxindent = indent(lnum) | |
" It's not worth going further if we reached the top level | |
if maxindent == 0 | |
return -1 | |
endif | |
endif | |
endif | |
endwhile | |
return -1 | |
endfunction | |
function! GetPythonIndent(lnum) | |
" First line has indent 0 | |
if a:lnum == 1 | |
return 0 | |
endif | |
" If we can find an open parenthesis/bracket/brace, line up with it. | |
call cursor(a:lnum, 1) | |
let parlnum = s:SearchParensPair() | |
if parlnum > 0 | |
let parcol = col('.') | |
let closing_paren = match(getline(a:lnum), '^\s*[])}]') != -1 | |
if match(getline(parlnum), '[([{]\s*$', parcol - 1) != -1 | |
if closing_paren | |
return indent(parlnum) | |
else | |
" Dividing by two - DUSTIN | |
return indent(parlnum) + (&shiftwidth / 2) | |
endif | |
else | |
if closing_paren | |
return parcol - 1 | |
else | |
return parcol | |
endif | |
endif | |
endif | |
" Examine this line | |
let thisline = getline(a:lnum) | |
let thisindent = indent(a:lnum) | |
" If the line starts with 'elif' or 'else', line up with 'if' or 'elif' | |
if thisline =~ '^\s*\(elif\|else\)\>' | |
let bslnum = s:BlockStarter(a:lnum, '^\s*\(if\|elif\)\>') | |
if bslnum > 0 | |
return indent(bslnum) | |
else | |
return -1 | |
endif | |
endif | |
" If the line starts with 'except' or 'finally', line up with 'try' | |
" or 'except' | |
if thisline =~ '^\s*\(except\|finally\)\>' | |
let bslnum = s:BlockStarter(a:lnum, '^\s*\(try\|except\)\>') | |
if bslnum > 0 | |
return indent(bslnum) | |
else | |
return -1 | |
endif | |
endif | |
" Examine previous line | |
let plnum = a:lnum - 1 | |
let pline = getline(plnum) | |
let sslnum = s:StatementStart(plnum) | |
" If the previous line is blank, keep the same indentation | |
if pline =~ '^\s*$' | |
return -1 | |
endif | |
" If this line is explicitly joined, try to find an indentation that looks | |
" good. | |
if pline =~ '\\$' | |
let compound_statement = '^\s*\(if\|while\|for\s.*\sin\|except\)\s*' | |
let maybe_indent = matchend(getline(sslnum), compound_statement) | |
if maybe_indent != -1 | |
return maybe_indent | |
else | |
return indent(sslnum) + &sw * 2 | |
endif | |
endif | |
" If the previous line ended with a colon, indent relative to | |
" statement start. | |
if pline =~ ':\s*$' | |
return indent(sslnum) + &sw | |
endif | |
" If the previous line was a stop-execution statement or a pass | |
if getline(sslnum) =~ '^\s*\(break\|continue\|raise\|return\|pass\)\>' | |
" See if the user has already dedented | |
if indent(a:lnum) > indent(sslnum) - &sw | |
" If not, recommend one dedent | |
return indent(sslnum) - &sw | |
endif | |
" Otherwise, trust the user | |
return -1 | |
endif | |
" In all other cases, line up with the start of the previous statement. | |
return indent(sslnum) | |
endfunction |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment