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

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 906eff5

Browse files
committed
Make folding nested defs much faster
1 parent d113fe0 commit 906eff5

File tree

2 files changed

+52
-15
lines changed

2 files changed

+52
-15
lines changed

autoload/pymode/folding.vim

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -58,18 +58,43 @@ 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) + 1, last_block_end])
88+
if a:lnum == fold_end
89+
return 's1'
90+
else
91+
return '='
92+
endif
7093
endif
7194
endif
72-
endif
95+
finally
96+
call setpos('.', curpos)
97+
endtry
7398
endif
7499

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

92117
endfunction "}}}
93118

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

95132
" 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
8000 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