X-Git-Url: https://git.madduck.net/etc/vim.git/blobdiff_plain/10228215c76da4004b5ac4b60cfdf94682ea6e22..7dfebca4ed468be64afffd8107e7a87f35d8ef5b:/indent/python.vim diff --git a/indent/python.vim b/indent/python.vim index 6bf45a8..befc60a 100644 --- a/indent/python.vim +++ b/indent/python.vim @@ -145,20 +145,26 @@ endfunction " Find possible indent(s) of the block starter that matches the current line. function! s:find_start_of_block(lnum, types, multiple) let r = [] + let types = copy(a:types) let re = '\V\^\s\*\('.join(a:types, '\|').'\)\>' let lnum = a:lnum let last_indent = indent(lnum) + 1 while lnum > 0 && last_indent > 0 let indent = indent(lnum) if indent < last_indent - if getline(lnum) =~# re - if !a:multiple - return [indent] + for type in types + let re = '\v^\s*'.type.'>' + if getline(lnum) =~# re + if !a:multiple + return [indent] + endif + if index(r, indent) == -1 + let r += [indent] + endif + " Remove any handled type, e.g. 'if'. + call remove(types, index(types, type)) endif - if !len(r) || index(r, indent) == -1 - let r += [indent] - endif - endif + endfor let last_indent = indent(lnum) endif let lnum = prevnonblank(lnum - 1) @@ -239,14 +245,15 @@ function! s:indent_like_block(lnum) if len(indents) == 1 return indents[0] endif + " Multiple valid indents, e.g. for 'else' with both try and if. let indent = indent(a:lnum) - for possible_indent in indents - if indent == possible_indent - return indent - endif - endfor - return -2 + if index(indents, indent) != -1 + " The indent is valid, keep it. + return indent + endif + " Fallback to the first/nearest one. + return indents[0] endfor endfor return -2 @@ -342,12 +349,25 @@ function! GetPythonPEPIndent(lnum) return 0 endif + let line = getline(a:lnum) + let prevline = getline(a:lnum-1) + " Multilinestrings: continous, docstring or starting. - if s:is_python_string(a:lnum, 1) - \ && s:is_python_string(a:lnum-1, len(getline(a:lnum-1))) - " Keep existing indent. - if match(getline(a:lnum), '\v^\s*\S') != -1 - return -1 + if s:is_python_string(a:lnum-1, len(prevline)) + \ && (s:is_python_string(a:lnum, 1) + \ || match(line, '^\%("""\|''''''\)') != -1) + + " Indent closing quotes as the line with the opening ones. + let match_quotes = match(line, '^\s*\zs\%("""\|''''''\)') + if match_quotes != -1 + " closing multiline string + let quotes = line[match_quotes:match_quotes+2] + let pairpos = searchpairpos(quotes, '', quotes, 'b') + if pairpos[0] != 0 + return indent(pairpos[0]) + else + " TODO: test to cover this! + endif endif if s:is_python_string(a:lnum-1) @@ -355,21 +375,35 @@ function! GetPythonPEPIndent(lnum) return indent(a:lnum-1) endif - if match(getline(a:lnum-1), '^\s*\%("""\|''''''\)') != -1 + if match(prevline, '^\s*\%("""\|''''''\)') != -1 " docstring. return indent(a:lnum-1) endif let indent_multi = get(b:, 'python_pep8_indent_multiline_string', \ get(g:, 'python_pep8_indent_multiline_string', 0)) + if match(prevline, '\v%("""|'''''')$') != -1 + " Opening multiline string, started in previous line. + if (&autoindent && indent(a:lnum) == indent(a:lnum-1)) + \ || match(line, '\v^\s+$') != -1 + " with empty line or to split up 'foo("""bar' into + " 'foo("""' and 'bar'. + if indent_multi == -2 + return indent(a:lnum-1) + s:sw() + endif + return indent_multi + endif + endif + + " Keep existing indent. + if match(line, '\v^\s*\S') != -1 + return -1 + endif + if indent_multi != -2 return indent_multi endif - if match(getline(a:lnum-1), '\v%("""|'''''')$') != -1 - " Opening multiline string, started in previous line. - return indent(a:lnum-1) + s:sw() - endif return s:indent_like_opening_paren(a:lnum) endif