@@ -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
92117endfunction " }}}
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
0 commit comments