-
Notifications
You must be signed in to change notification settings - Fork 0
/
python_fold.vim
executable file
·122 lines (101 loc) · 2.91 KB
/
python_fold.vim
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
" Vim folding file
" Language: Python
" Author: Jorrit Wiersma (foldexpr), Max Ischenko (foldtext), Robert
" Ames (line counts)
" Last Change: 2005 Jul 14
" Version: 2.3
" Bug fix: Drexler Christopher, Tom Schumm, Geoff Gerrietts
setlocal foldmethod=expr
setlocal foldexpr=GetPythonFold(v:lnum)
setlocal foldtext=PythonFoldText()
function! PythonFoldText()
let line = getline(v:foldstart)
let nnum = nextnonblank(v:foldstart + 1)
let nextline = getline(nnum)
if nextline =~ '^\s\+"""$'
let line = line . getline(nnum + 1)
elseif nextline =~ '^\s\+"""'
let line = line . ' ' . matchstr(nextline, '"""\zs.\{-}\ze\("""\)\?$')
elseif nextline =~ '^\s\+"[^"]\+"$'
let line = line . ' ' . matchstr(nextline, '"\zs.*\ze"')
elseif nextline =~ '^\s\+pass\s*$'
let line = line . ' pass'
endif
let size = 1 + v:foldend - v:foldstart
if size < 10
let size = " " . size
endif
if size < 100
let size = " " . size
endif
if size < 1000
let size = " " . size
endif
return size . " lines: " . line
endfunction
function! GetPythonFold(lnum)
" Determine folding level in Python source
"
let line = getline(a:lnum)
let ind = indent(a:lnum)
" Ignore blank lines
if line =~ '^\s*$'
return "="
endif
" Ignore triple quoted strings
if line =~ "(\"\"\"|''')"
return "="
endif
" Ignore continuation lines
if line =~ '\\$'
return '='
endif
" Support markers
if line =~ '{{{'
return "a1"
elseif line =~ '}}}'
return "s1"
endif
" Classes and functions get their own folds
if line =~ '^\s*\(class\|def\)\s'
return ">" . (ind / &sw + 1)
endif
let pnum = prevnonblank(a:lnum - 1)
if pnum == 0
" Hit start of file
return 0
endif
" If the previous line has foldlevel zero, and we haven't increased
" it, we should have foldlevel zero also
if foldlevel(pnum) == 0
return 0
endif
" The end of a fold is determined through a difference in indentation
" between this line and the next.
" So first look for next line
let nnum = nextnonblank(a:lnum + 1)
if nnum == 0
return "="
endif
" First I check for some common cases where this algorithm would
" otherwise fail. (This is all a hack)
let nline = getline(nnum)
if nline =~ '^\s*\(except\|else\|elif\)'
return "="
endif
" Python programmers love their readable code, so they're usually
" going to have blank lines at the ends of functions or classes
" If the next line isn't blank, we probably don't need to end a fold
if nnum == a:lnum + 1
return "="
endif
" If next line has less indentation we end a fold.
" This ends folds that aren't there a lot of the time, and this sometimes
" confuses vim. Luckily only rarely.
let nind = indent(nnum)
if nind < ind
return "<" . (nind / &sw + 1)
endif
" If none of the above apply, keep the indentation
return "="
endfunction