From 1f4c47575357c55d90ac9f122b7bc2b647ff52f3 Mon Sep 17 00:00:00 2001 From: Hynek Schlawack Date: Tue, 26 Jun 2012 14:07:20 +0200 Subject: [PATCH] Initial import --- README.rst | 37 ++++++++++ python.vim | 194 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 231 insertions(+) create mode 100644 README.rst create mode 100644 python.vim diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..ebcf4d4 --- /dev/null +++ b/README.rst @@ -0,0 +1,37 @@ +vim-python-pep8-indent +====================== + +This small script that goes directly into `~/.vim/indent/` modifies vim_’s +indentation behavior to comply with PEP8_: :: + + foobar(foo, + bar) + +and :: + + foobar( + foo, + bar + ) + +It was *not* originally written by me. I have found the script in vim’s `script +repo`_, however the indentation was off by one character in the first case. + +I fixed it with the help of `Steve Losh`_ and am putting it out here so you +don’t have to patch the original. The original patch is still available here_. + +While my Vimscript_ skills are still feeble, I intend to maintain it for now. +So feel free to report bugs, I’ll try to address them as good as possible if +they fit into the scope of this project. + +Unfortunately, I wasn’t able to reach any of the original authors/maintainers: +**David Bustos** and **Eric Mc Sween**. I’d like to thank them here for their +work and release it hereby to the *Public Domain*. If anyone – who has a say in +this – objects, please let me know. + +.. _vim: http://www.vim.org/ +.. _PEP8: http://www.python.org/dev/peps/pep-0008/ +.. _`script repo`: http://www.vim.org/scripts/script.php?script_id=974 +.. _`Steve Losh`: http://stevelosh.com/ +.. _here: https://gist.github.com/2965846 +.. _`Vimscript`: http://learnvimscriptthehardway.stevelosh.com/ diff --git a/python.vim b/python.vim new file mode 100644 index 0000000..82f0d7c --- /dev/null +++ b/python.vim @@ -0,0 +1,194 @@ +" PEP8 compatible Python indent file +" Language: Python +" Maintainer: Hynek Schlawack +" Prev Maintainer: Eric Mc Sween (address invalid) +" Original Author: David Bustos (address invalid) +" Last Change: 2012-06-21 +" License: Public Domain + +" 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 + return indent(parlnum) + &shiftwidth + endif + else + return parcol + 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 -- 2.39.5