@@ -38,6 +38,15 @@ if !exists('g:python_pep8_indent_hang_closing')
3838 let g: python_pep8_indent_hang_closing = 0
3939endif
4040
41+ " TODO: check required patch for timeout argument, likely lower than 7.3.429 though.
42+ if ! exists (' g:python_pep8_indent_searchpair_timeout' )
43+ if has (' patch-8.0.1483' )
44+ let g: python_pep8_indent_searchpair_timeout = 150
45+ else
46+ let g: python_pep8_indent_searchpair_timeout = 0
47+ endif
48+ endif
49+
4150let s: block_rules = {
4251 \ ' ^\s*elif\>' : [' if' , ' elif' ],
4352 \ ' ^\s*except\>' : [' try' , ' except' ],
5766endif
5867let s: stop_statement = ' ^\s*\(break\|continue\|raise\|return\|pass\)\>'
5968
60- " Skip strings and comments. Return 1 for chars to skip.
61- " jedi* refers to syntax definitions from jedi-vim for call signatures, which
62- " are inserted temporarily into the buffer.
63- let s: skip_special_chars = ' synIDattr(synID(line("."), col("."), 0), "name") ' .
64- \ ' =~? "\\vstring|comment|^pythonbytes%(contents)=$|jedi\\S"'
65-
6669let s: skip_after_opening_paren = ' synIDattr(synID(line("."), col("."), 0), "name") ' .
6770 \ ' =~? "\\vcomment|jedi\\S"'
6871
69- " Also ignore anything concealed.
70- " Wrapper around synconcealed for older Vim (7.3.429, used on Travis CI).
71- function ! s: is_concealed (line , col )
72- let concealed = synconcealed (a: line , a: col )
73- return len (concealed) && concealed[0 ]
74- endfunction
75- if has (' conceal' )
76- let s: skip_special_chars .= ' || s:is_concealed(line("."), col("."))'
77- endif
72+ if ! get (g: , ' python_pep8_indent_skip_concealed' , 0 ) || ! has (' conceal' )
73+ " Skip strings and comments. Return 1 for chars to skip.
74+ " jedi* refers to syntax definitions from jedi-vim for call signatures, which
75+ " are inserted temporarily into the buffer.
76+ function ! s: _skip_special_chars (line , col )
77+ return synIDattr (synID (a: line , a: col , 0 ), ' name' )
78+ \ = ~? " \\ vstring|comment|^pythonbytes%(contents)=$|jedi\\ S"
79+ endfunction
80+ else
81+ " Also ignore anything concealed.
82+ " TODO: doc; likely only necessary with jedi-vim, where a better version is
83+ " planned (https://github.com/Vimjas/vim-python-pep8-indent/pull/98).
84+
85+ " Wrapper around synconcealed for older Vim (7.3.429, used on Travis CI).
86+ function ! s: is_concealed (line , col )
87+ let concealed = synconcealed (a: line , a: col )
88+ return len (concealed) && concealed[0 ]
89+ endfunction
7890
91+ function ! s: _skip_special_chars (line , col )
92+ return synIDattr (synID (a: line , a: col , 0 ), ' name' )
93+ \ = ~? " \\ vstring|comment|^pythonbytes%(contents)=$|jedi\\ S"
94+ \ || s: is_concealed (a: line , a: col )
95+ endfunction
96+ endif
7997
8098" Use 'shiftwidth()' instead of '&sw'.
8199" (Since Vim patch 7.3.629, 'shiftwidth' can be set to 0 to follow 'tabstop').
@@ -99,10 +117,12 @@ function! s:find_opening_paren(lnum, col)
99117 call cursor (a: lnum , a: col )
100118
101119 let nearest = [0 , 0 ]
120+ let timeout = g: python_pep8_indent_searchpair_timeout
121+ let skip_special_chars = ' s:_skip_special_chars(line("."), col("."))'
102122 for [p , maxoff] in items (s: paren_pairs )
103123 let stopline = max ([0 , line (' .' ) - maxoff, nearest[0 ]])
104124 let next = searchpairpos (
105- \ ' \V' .p [0 ], ' ' , ' \V' .p [1 ], ' bnW' , s: skip_special_chars , stopline)
125+ \ ' \V' .p [0 ], ' ' , ' \V' .p [1 ], ' bnW' , skip_special_chars, stopline, timeout )
106126 if next [0 ] && (next [0 ] > nearest[0 ] || (next [0 ] == nearest[0 ] && next [1 ] > nearest[1 ]))
107127 let nearest = next
108128 endif
@@ -257,24 +277,23 @@ function! s:indent_like_previous_line(lnum)
257277 let base = indent (start )
258278 let current = indent (a: lnum )
259279
260- " Jump to last character in previous line.
261- call cursor (lnum, len (text) )
262- let ignore_last_char = eval ( s: skip_special_chars )
280+ " Ignore last character in previous line?
281+ let lastcol = len (text)
282+ let col = lastcol
263283
264284 " Search for final colon that is not inside something to be ignored.
265285 while 1
266- let curpos = getpos (' .' )[2 ]
267- if curpos == 1 | break | endif
268- if eval (s: skip_special_chars ) || text[curpos- 1 ] = ~# ' \s'
269- normal ! h
286+ if col == 1 | break | endif
287+ if text[col - 1 ] = ~# ' \s' || s: _skip_special_chars (lnum, col )
288+ let col = col - 1
270289 continue
271- elseif text[curpos - 1 ] == # ' :'
290+ elseif text[col - 1 ] == # ' :'
272291 return base + s: sw ()
273292 endif
274293 break
275294 endwhile
276295
277- if text = ~# ' \\$' && ! ignore_last_char
296+ if text = ~# ' \\$' && ! s: _skip_special_chars (lnum, lastcol)
278297 " If this line is the continuation of a control statement
279298 " indent further to distinguish the continuation line
280299 " from the next logical line.
@@ -356,11 +375,12 @@ function! GetPythonPEPIndent(lnum)
356375 if match_quotes != -1
357376 " closing multiline string
358377 let quotes = line [match_quotes: (match_quotes+ 2 )]
359- let pairpos = searchpairpos (quotes, ' ' , quotes, ' b' )
378+ call cursor (a: lnum , 1 )
379+ let pairpos = searchpairpos (quotes, ' ' , quotes, ' bW' , ' ' , 0 , g: python_pep8_indent_searchpair_timeout )
360380 if pairpos[0 ] != 0
361381 return indent (pairpos[0 ])
362382 else
363- " TODO: test to cover this!
383+ return -1
364384 endif
365385 endif
366386
0 commit comments