Movatterモバイル変換


[0]ホーム

URL:


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

Sign up
Appearance settings

Commitd113cff

Browse files
authored
Merge pull requestpython-mode#715 from fmv1992/develop
improved folding in various cases
2 parentsf7ccee5 +e3f714b commitd113cff

File tree

2 files changed

+105
-17
lines changed

2 files changed

+105
-17
lines changed

‎autoload/pymode/folding.vim

Lines changed: 104 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,25 @@
11
" Python-mode folding functions
22

3+
" Notice that folding is based on single line so complex regular expressions
4+
" that take previous line into consideration are not fit for the job.
35

6+
" Regex definitions for correct folding
47
lets:def_regex=g:pymode_folding_regex
58
lets:blank_regex='^\s*$'
6-
lets:decorator_regex='^\s*@'
7-
lets:doc_begin_regex='^\s*\%("""\|''''''\)'
9+
" Spyder, a very popular IDE for python has a template which includes
10+
" '@author:' ; thus the regex below.
11+
lets:decorator_regex='^\s*@\(author:\)\@!'
12+
lets:doc_begin_regex='^\s*[uU]\=\%("""\|''''''\)'
813
lets:doc_end_regex='\%("""\|''''''\)\s*$'
9-
lets:doc_line_regex='^\s*\("""\|''''''\).\+\1\s*$'
14+
" This one is needed for the while loop to count for opening and closing
15+
" docstrings.
16+
lets:doc_general_regex='\%("""\|''''''\)'
17+
lets:doc_line_regex='^\s*[uU]\=\("""\|''''''\).\+\1\s*$'
1018
lets:symbol=matchstr(&fillchars,'fold:\zs.')" handles multibyte characters
1119
ifs:symbol==''
1220
lets:symbol=''
1321
endif
22+
" ''''''''
1423

1524

1625
fun!pymode#folding#text()" {{{
@@ -33,24 +42,29 @@ fun! pymode#folding#text() " {{{
3342
letline=substitute(line,'\t', onetab,'g')
3443

3544
letline=strpart(line,0, windowwidth-2-len(foldedlinecount))
36-
letline=substitute(line,'\%("""\|''''''\)','','')
45+
letline=substitute(line,'[uU]\=\%("""\|''''''\)','','')
3746
let fillcharcount= windowwidth-len(line)-len(foldedlinecount)+1
3847
returnline .'' .repeat(s:symbol, fillcharcount) .'' . foldedlinecount
3948
endfunction"}}}
4049

41-
4250
fun!pymode#folding#expr(lnum)"{{{
4351

4452
letline=getline(a:lnum)
4553
letindent=indent(a:lnum)
4654
let prev_line=getline(a:lnum-1)
55+
let next_line=getline(a:lnum+1)
4756

57+
" Decorators {{{
4858
ifline=~s:decorator_regex
4959
return">".(indent / &shiftwidth+1)
50-
endif
60+
endif"}}}
5161

62+
" Definition {{{
5263
ifline=~s:def_regex
53-
" single line def
64+
" If indent of this line is greater or equal than line below
65+
" and previous non blank line does not end with : (that is, is not a
66+
" definition)
67+
" Keep the same indentation
5468
ifindent(a:lnum)>=indent(a:lnum+1)&&getline(prevnonblank(a:lnum))!~':\s*$'
5569
return'='
5670
endif
@@ -71,16 +85,35 @@ fun! pymode#folding#expr(lnum) "{{{
7185
else
7286
return">".(indent / &shiftwidth+1)
7387
endif
74-
endif
88+
endif"}}}
7589

76-
ifline=~s:doc_begin_regex&&line!~s:doc_line_regex&& prev_line=~s:def_regex
77-
return">".(indent / &shiftwidth+1)
90+
" Docstrings {{{
91+
92+
" TODO: A while loop now counts the number of open and closed folding in
93+
" order to determine if it is a closing or opening folding.
94+
" It is working but looks like it is an overkill.
95+
96+
" Notice that an effect of this is that other docstring matches will not
97+
" be one liners.
98+
ifline=~s:doc_line_regex
99+
return"="
78100
endif
79101

80-
ifline=~s:doc_end_regex&&line!~s:doc_line_regex
81-
return"<".(indent / &shiftwidth+1)
102+
ifline=~s:doc_begin_regex
103+
" echom 'just entering'
104+
ifs:Is_opening_folding(a:lnum)
105+
" echom 'entering at line ' . a:lnum
106+
return">".(indent / &shiftwidth+1)
107+
endif
82108
endif
109+
ifline=~s:doc_end_regex
110+
if!s:Is_opening_folding(a:lnum)
111+
" echom 'leaving at line ' . a:lnum
112+
return"<".(indent / &shiftwidth+1)
113+
endif
114+
endif"}}}
83115

116+
" Nested Definitions {{{
84117
" Handle nested defs but only for files shorter than
85118
" g:pymode_folding_nest_limit lines due to performance concerns
86119
ifline('$') <g:pymode_folding_nest_limit&&indent(prevnonblank(a:lnum))
@@ -125,18 +158,25 @@ fun! pymode#folding#expr(lnum) "{{{
125158
finally
126159
callsetpos('.', curpos)
127160
endtry
128-
endif
161+
endif" }}}
129162

163+
" Blank Line {{{
130164
ifline=~s:blank_regex
131165
if prev_line=~s:blank_regex
132-
ifindent(a:lnum+1)==0&&getline(a:lnum+1)!~s:blank_regex
133-
return0
166+
ifindent(a:lnum+1)==0&& next_line!~s:blank_regex&& next_line!~s:doc_general_regex
167+
ifs:Is_opening_folding(a:lnum)
168+
" echom a:lnum
169+
return"="
170+
else
171+
" echom "not " . a:lnum
172+
return0
173+
endif
134174
endif
135175
return-1
136176
else
137177
return'='
138178
endif
139-
endif
179+
endif" }}}
140180

141181
return'='
142182

@@ -174,4 +214,52 @@ fun! s:BlockEnd(lnum) "{{{
174214
returnsearchpos('\v^\s{,'.indent('.').'}\S','nW')[0]-1
175215
endfunction"}}}
176216

217+
function!s:Is_opening_folding(lnum)"{{{
218+
" Helper function to see if docstring is opening or closing
219+
let number_of_folding=0" To be analized if odd/even to inform if it is opening or closing.
220+
let has_open_docstring=0" To inform is already has an open docstring.
221+
let extra_docstrings=0" To help skipping ''' and""" which are not docstrings
222+
223+
" The idea of this part of the function is to identify real docstrings and
224+
" not just triple quotes (that could be a regular string).
225+
"
226+
" Iterater over all lines from the start until current line (inclusive)
227+
foriinrange(1,a:lnum)
228+
let i_line=getline(i)
229+
230+
if i_line=~s:doc_line_regex
231+
" echom "case 00 on line " . i
232+
continue
233+
endif
234+
235+
if i_line=~s:doc_begin_regex&& ! has_open_docstring
236+
" echom "case 01 on line " . i
237+
" This causes the loop to continue if there is a triple quote which
238+
" is not a docstring.
239+
if extra_docstrings >0
240+
let extra_docstrings= extra_docstrings-1
241+
continue
242+
else
243+
let has_open_docstring=1
244+
let number_of_folding= number_of_folding+1
245+
endif
246+
" If it is an end doc and has an open docstring.
247+
elseif i_line=~s:doc_end_regex&& has_open_docstring
248+
" echom "case 02 on line " . i
249+
let has_open_docstring=0
250+
let number_of_folding= number_of_folding+1
251+
252+
elseif i_line=~s:doc_general_regex
253+
" echom "extra docstrings on line " . i
254+
let extra_docstrings= extra_docstrings+1
255+
endif
256+
endfor
257+
258+
iffmod(number_of_folding,2)==1"If odd then it is an opening
259+
return1
260+
else
261+
return0
262+
endif
263+
endfunction"}}}
264+
177265
" vim:fdm=marker:fdl=0

‎plugin/pymode.vim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ call pymode#default("g:pymode_folding", 1)
3939
" Maximum file length to check for nested class/def statements
4040
callpymode#default("g:pymode_folding_nest_limit",1000)
4141
" Change for folding customization (by example enable fold for 'if', 'for')
42-
callpymode#default("g:pymode_folding_regex",'^\s*\%(class\|def\|async\s\+def\)\w\+')
42+
callpymode#default("g:pymode_folding_regex",'^\s*\%(class\|def\|async\s\+def\).\+\(:\s\+\w\)\@!')
4343

4444
" Enable/disable python motion operators
4545
callpymode#default("g:pymode_motion",1)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp