8000 Make folding nested defs much faster · python-mode/python-mode@95911d1 · GitHub
[go: up one dir, main page]

Skip to content

Commit 95911d1

Browse files
committed
Make folding nested defs much faster
1 parent d113fe0 commit 95911d1

File tree

2 files changed

+50
-15
lines changed

2 files changed

+50
-15
lines changed

autoload/pymode/folding.vim

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -58,18 +58,41 @@ fun! pymode#folding#expr(lnum) "{{{
5858
endif
5959

6060
" Handle nested defs
61-
let last_def = pymode#motion#BlockStart(a:lnum, s:def_regex)
62-
if getline(last_def) =~ s:def_regex
63-
let last_def_end = pymode#motion#BlockEnd(last_def)
64-
if last_def_end < line('$')
65-
let nested = getline(pymode#motion#BlockStart(last_def - 1)) =~ s:def_regex
66-
if nested && getline(nextnonblank(a:lnum)) !~ s:def_regex
67-
let fold_end = min([prevnonblank(last_def_end - 1) + 2, last_def_end])
68-
if a:lnum == fold_end
69-
return 's1'
61+
if indent(prevnonblank(a:lnum))
62+
let curpos = getcurpos()
63+
try
64+
let last_block = s:BlockStart(a:lnum)
65+
let last_block_indent = indent(last_block)
66+
67+
" Check if last class/def is not indented and therefore can't be
68+
" nested and make sure it is a class/def block instead of a zero
69+
" indented regular statement
70+
if last_block_indent && getline(last_block) =~ s:def_regex
71+
" Note: This relies on the cursor position being set by s:BlockStart
72+
let next_def = searchpos('^\s*def \w', 'nW')[0]
73+
let next_def_indent = next_def ? indent(next_def) : -1
74+
let last_block_end = s:BlockEnd(last_block)
75+
76+
" If the next def has the same or greater indent than the
77+
" previous def, it is either nested at the same level or
78+
" nested one level deeper, and in either case will have its
79+
" own fold. If the class/def containing the current line is on
80+
" the first line it can't be nested, and if the this block
81+
" ends on the last line, it contains no trailing code that
82+
" should not be folded. Otherwise, we know the current line
83+
" is at the end of a nested def.
84+
if next_def_indent < last_block_indent && last_block > 1 && last_block_end < line('$')
85+
86+
" Include up to one blank line in the fold
87+
let fold_end = min([prevnonblank(last_block_end - 1) + 2, last_block_end])
88+
if a:lnum == fold_end
89+
return 's1'
90+
endif
7091
endif
7192
endif
72-
endif
93+
finally
94+
call setpos('.', curpos)
95+
endtry
7396
endif
7497

7598
if line =~ s:blank_regex
@@ -91,5 +114,17 @@ fun! pymode#folding#expr(lnum) "{{{
91114

92115
endfunction "}}}
93116

117+
fun! s:BlockStart(lnum) "{{{
118+
" Note: Make sure to reset cursor position after using this function.
119+
call cursor(a:lnum, 0)
120+
let max_indent = max([indent(prevnonblank(a:lnum)) - &shiftwidth, 0])
121+
return searchpos('\v^(\s{,'.max_indent.'}(def |class |\@)\w|[^ \t#])', 'bcnW')[0]
122+
endfunction "}}}
123+
124+
fun! s:BlockEnd(lnum) "{{{
125+
" Note: Make sure to reset cursor position after using this function.
126+
call cursor(a:lnum, 0)
127+
return searchpos('\v^\s{,'.indent('.').'}\S', 'nW')[0] - 1
128+
endfunction "}}}
94129

95130
" vim: fdm=marker:fdl=0

autoload/pymode/motion.vim

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,15 @@ endfunction "}}}
3232
fun! pymode#motion#select(pattern, inner) "{{{
3333
let cnt = v:count1 - 1
3434
let orig = getpos('.')[1:2]
35-
let snum = pymode#motion#BlockStart(orig[0], a:pattern)
35+
let snum = s:BlockStart(orig[0], a:pattern)
3636
if getline(snum) !~ a:pattern
3737
return 0
3838
endif
39-
let enum = pymode#motion#BlockEnd(snum, indent(snum))
39+
let enum = s:BlockEnd(snum, indent(snum))
4040
while cnt
4141
let lnum = search(a:pattern, 'nW')
4242
if lnum
43-
let enum = pymode#motion#BlockEnd(lnum, indent(lnum))
43+
let enum = s:BlockEnd(lnum, indent(lnum))
4444
call cursor(enum, 1)
4545
endif
4646
let cnt = cnt - 1
@@ -58,7 +58,7 @@ fun! pymode#motion#select(pattern, inner) "{{{
5858
endfunction "}}}
5959

6060

61-
fun! pymode#motion#BlockStart(lnum, ...) "{{{
61+
fun! s:BlockStart(lnum, ...) "{{{
6262
let pattern = a:0 ? a:1 : '^\s*\(@\|class\s.*:\|def\s\)'
6363
let lnum = a:lnum + 1
6464
let indent = 100
@@ -82,7 +82,7 @@ fun! pymode#motion#BlockStart(lnum, ...) "{{{
8282
endfunction "}}}
8383

8484

85-
fun! pymode#motion#BlockEnd(lnum, ...) "{{{
85+
fun! s:BlockEnd(lnum, ...) "{{{
8686
let indent = a:0 ? a:1 : indent(a:lnum)
8787
let lnum = a:lnum
8888
while lnum

0 commit comments

Comments
 (0)
0