250 lines
6.7 KiB
VimL
250 lines
6.7 KiB
VimL
" Vim folding file
|
|
" Language: Python
|
|
" Author: Jorrit Wiersma (foldexpr), Max Ischenko (foldtext), Robert,
|
|
" Ames (line counts), Jean-Pierre Chauvel (bugfixes and improvements)
|
|
" Last Change: 2008 Apr 20
|
|
" Version: 2.9.c
|
|
" Bugfixes: Jean-Pierre Chauvel
|
|
|
|
|
|
if exists("b:did_ftplugin")
|
|
finish
|
|
endif
|
|
let b:did_ftplugin = 1
|
|
|
|
if !exists("g:ifold_mode")
|
|
let g:ifold_mode = 1
|
|
endif
|
|
|
|
" map <buffer> f :call ToggleFold()<CR>
|
|
|
|
set tabstop=4
|
|
set softtabstop=4
|
|
set shiftwidth=4
|
|
set expandtab
|
|
set autoindent
|
|
set foldcolumn=1
|
|
|
|
let w:nestinglevel = 0
|
|
let w:signature = 0
|
|
let w:is_folded = 1
|
|
|
|
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)
|
|
let line = getline(a:lnum - 1)
|
|
|
|
" Classes and functions get their own folds
|
|
if line =~ '^\s*\(class\|def\)\s'
|
|
" Verify if the next line is a class or function definition
|
|
" as well
|
|
let imm_nnum = a:lnum + 1
|
|
let nnum = nextnonblank(imm_nnum)
|
|
if nnum - imm_nnum < 2
|
|
let nind = indent(nnum)
|
|
let pind = indent(a:lnum - 1)
|
|
if pind >= nind
|
|
let nline = getline(nnum)
|
|
let w:nestinglevel = nind
|
|
return "<" . ((w:nestinglevel + &sw) / &sw)
|
|
endif
|
|
endif
|
|
let w:nestinglevel = indent(a:lnum - 1)
|
|
return ">" . ((w:nestinglevel + &sw) / &sw)
|
|
endif
|
|
|
|
" If next line has less or equal indentation than the first one,
|
|
" we end a fold.
|
|
let nind = indent(nextnonblank(a:lnum + 1))
|
|
if nind <= w:nestinglevel
|
|
let w:nestinglevel = nind
|
|
return "<" . ((w:nestinglevel + &sw) / &sw)
|
|
else
|
|
let ind = indent(a:lnum)
|
|
if ind == (w:nestinglevel + &sw)
|
|
if nind < ind
|
|
let w:nestinglevel = nind
|
|
return "<" . ((w:nestinglevel + &sw) / &sw)
|
|
endif
|
|
endif
|
|
endif
|
|
|
|
" If none of the above apply, keep the indentation
|
|
return "="
|
|
endfunction
|
|
|
|
function! GetPythonFoldBest(lnum)
|
|
" Determine folding level in Python source
|
|
"
|
|
let line = getline(a:lnum - 1)
|
|
|
|
" Handle Support markers
|
|
if line =~ '{{{'
|
|
return "a1"
|
|
elseif line =~ '}}}'
|
|
return "s1"
|
|
endif
|
|
|
|
" Classes and functions get their own folds
|
|
if line =~ '^\s*\(class\|def\)\s'
|
|
" Verify if the next line is a class or function definition
|
|
" as well
|
|
let imm_nnum = a:lnum + 1
|
|
let nnum = nextnonblank(imm_nnum)
|
|
let nind = indent(nnum)
|
|
let pind = indent(a:lnum - 1)
|
|
if pind >= nind
|
|
let nline = getline(nnum)
|
|
let w:nestinglevel = nind
|
|
return "<" . ((w:nestinglevel + &sw) / &sw)
|
|
endif
|
|
let w:nestinglevel = indent(a:lnum - 1)
|
|
return ">" . ((w:nestinglevel + &sw) / &sw)
|
|
endif
|
|
|
|
" If next line has less or equal indentation than the first one,
|
|
" we end a fold.
|
|
let nnonblank = nextnonblank(a:lnum + 1)
|
|
let nextline = getline(nnonblank)
|
|
if (nextline !~ '^#\+.*')
|
|
let nind = indent(nnonblank)
|
|
if nind <= w:nestinglevel
|
|
let w:nestinglevel = nind
|
|
return "<" . ((w:nestinglevel + &sw) / &sw)
|
|
else
|
|
let ind = indent(a:lnum)
|
|
if ind == (w:nestinglevel + &sw)
|
|
if nind < ind
|
|
let w:nestinglevel = nind
|
|
return "<" . ((w:nestinglevel + &sw) / &sw)
|
|
endif
|
|
endif
|
|
endif
|
|
endif
|
|
|
|
" If none of the above apply, keep the indentation
|
|
return "="
|
|
endfunction
|
|
|
|
function! GetPythonFoldExperimental(lnum)
|
|
" Determine folding level in Python source
|
|
"
|
|
let line = getline(a:lnum - 1)
|
|
|
|
" Handle suport markers
|
|
if line =~ '{{{'
|
|
return "a1"
|
|
elseif line =~ '}}}'
|
|
return "s1"
|
|
endif
|
|
|
|
" Classes and functions get their own folds
|
|
if line =~ '^\s*\(class\|def\)\s'
|
|
" Verify if the next line is a class or function definition
|
|
" as well
|
|
let imm_nnum = a:lnum + 1
|
|
let nnum = nextnonblank(imm_nnum)
|
|
let nind = indent(nnum)
|
|
let pind = indent(a:lnum - 1)
|
|
if pind >= nind
|
|
let nline = getline(nnum)
|
|
let w:nestinglevel = nind
|
|
return "<" . ((w:nestinglevel + &sw) / &sw)
|
|
endif
|
|
let w:signature = 1
|
|
let w:nestinglevel = indent(a:lnum - 1)
|
|
endif
|
|
|
|
if line =~ '^.*:' && w:signature
|
|
let w:signature = 0
|
|
return ">" . ((w:nestinglevel + &sw) / &sw)
|
|
endif
|
|
|
|
" If next line has less or equal indentation than the first one,
|
|
" we end a fold.
|
|
let nnonblank = nextnonblank(a:lnum + 1)
|
|
let nextline = getline(nnonblank)
|
|
if (nextline !~ '^#\+.*')
|
|
let nind = indent(nnonblank)
|
|
if nind <= w:nestinglevel
|
|
let w:nestinglevel = nind
|
|
return "<" . ((w:nestinglevel + &sw) / &sw)
|
|
else
|
|
let ind = indent(a:lnum)
|
|
if ind == (w:nestinglevel + &sw)
|
|
if nind < ind
|
|
let w:nestinglevel = nind
|
|
return "<" . ((w:nestinglevel + &sw) / &sw)
|
|
endif
|
|
endif
|
|
endif
|
|
endif
|
|
|
|
" If none of the above apply, keep the indentation
|
|
return "="
|
|
endfunction
|
|
|
|
function! ToggleFold()
|
|
let w:nestinglevel = 0
|
|
let w:signature = 0
|
|
if w:is_folded
|
|
set foldexpr=0
|
|
let w:is_folded = 0
|
|
else
|
|
call ReFold()
|
|
" Open the fold we are in
|
|
exec 'norm! zO'
|
|
let w:is_folded = 1
|
|
endif
|
|
endfunction
|
|
|
|
" In case folding breaks down
|
|
function! ReFold()
|
|
set foldmethod=expr
|
|
set foldexpr=0
|
|
set foldmethod=expr
|
|
if g:ifold_mode == 0
|
|
set foldexpr=GetPythonFold(v:lnum)
|
|
else
|
|
if g:ifold_mode == 1
|
|
set foldexpr=GetPythonFoldBest(v:lnum)
|
|
else
|
|
if g:ifold_mode == 2
|
|
set foldexpr=GetPythonFoldExperimental(v:lnum)
|
|
endif
|
|
endif
|
|
endif
|
|
|
|
if g:ifold_mode
|
|
set foldtext=PythonFoldText()
|
|
else
|
|
set foldtext='Folded\ code'
|
|
endif
|
|
echo
|
|
endfunction
|
|
|
|
call ReFold()
|