201 lines
4.9 KiB
VimL
201 lines
4.9 KiB
VimL
" Vim ftplugin file
|
|
" Language: Erlang
|
|
" Maintainer: Oscar Hellström <oscar@oscarh.net>
|
|
" URL: http://personal.oscarh.net
|
|
" Version: 2006-06-23
|
|
" ------------------------------------------------------------------------------
|
|
" Usage: {{{1
|
|
"
|
|
" To disable folding put
|
|
" let g:erlangFold=0
|
|
" in your vimrc
|
|
"
|
|
" Folding will make only one fold for a complete function, even though it has
|
|
" more than one function head and body
|
|
" To change this behaviour put
|
|
" let g:erlangFoldSplitFunction=1
|
|
" in your vimrc file
|
|
"
|
|
" }}}
|
|
" ------------------------------------------------------------------------------
|
|
" Plugin init {{{1
|
|
"if exists("b:did_ftplugin")
|
|
" finish
|
|
"endif
|
|
|
|
" Don't load any other
|
|
let b:did_ftplugin=1
|
|
|
|
if exists('s:doneFunctionDefinitions')
|
|
call s:SetErlangOptions()
|
|
finish
|
|
endif
|
|
|
|
let s:doneFunctionDefinitions=1
|
|
" }}}
|
|
|
|
" Local settings {{{1
|
|
" Run Erlang make instead of GNU Make
|
|
function s:SetErlangOptions()
|
|
if version >= 700
|
|
setlocal omnifunc=erlangcomplete#Complete
|
|
endif
|
|
|
|
" {{{2 Settings for folding
|
|
if (!exists("g:erlangFold")) || g:erlangFold
|
|
setlocal foldmethod=expr
|
|
setlocal foldexpr=GetErlangFold(v:lnum)
|
|
setlocal foldtext=ErlangFoldText()
|
|
"setlocal fml=2
|
|
endif
|
|
endfunction
|
|
|
|
|
|
" Define folding functions {{{1
|
|
if !exists("*GetErlangFold")
|
|
" Folding params {{{2
|
|
" FIXME: Could these be shared between scripts?
|
|
let s:ErlangFunEnd = '^[^%]*\.\s*\(%.*\)\?$'
|
|
let s:ErlangFunHead = '^\a\w*(.*)\(\s+when\s+.*\)\?\s\+->\s*$'
|
|
let s:ErlangBeginHead = '^\a\w*(.*$'
|
|
let s:ErlangEndHead = '^\s\+[a-zA-Z-_{}\[\], ]\+)\(\s+when\s+.*\)\?\s\+->\s\(%.*\)\?*$'
|
|
let s:ErlangBlankLine = '^\s*\(%.*\)\?$'
|
|
|
|
" Auxiliary fold functions {{{2
|
|
function s:GetNextNonBlank(lnum)
|
|
let lnum = nextnonblank(a:lnum + 1)
|
|
let line = getline(lnum)
|
|
while line =~ s:ErlangBlankLine && 0 != lnum
|
|
let lnum = nextnonblank(lnum + 1)
|
|
let line = getline(lnum)
|
|
endwhile
|
|
return lnum
|
|
endfunction
|
|
|
|
function s:GetFunName(str)
|
|
return matchstr(a:str, '^\a\w*(\@=')
|
|
endfunction
|
|
|
|
function s:GetFunArgs(str, lnum)
|
|
let str = a:str
|
|
let lnum = a:lnum
|
|
while str !~ '->\s*\(%.*\)\?$'
|
|
let lnum = s:GetNextNonBlank(lnum)
|
|
if 0 == lnum " EOF
|
|
return ""
|
|
endif
|
|
let str .= getline(lnum)
|
|
endwhile
|
|
return matchstr(str,
|
|
\ '\(^(\s*\)\@<=.*\(\s*)\(\s\+when\s\+.*\)\?\s\+->\s*\(%.*\)\?$\)\@=')
|
|
endfunction
|
|
|
|
function s:CountFunArgs(arguments)
|
|
let pos = 0
|
|
let ac = 0 " arg count
|
|
let arguments = a:arguments
|
|
|
|
" Change list / tuples into just one A(rgument)
|
|
let erlangTuple = '{\([A-Za-z_,|=\-\[\]]\|\s\)*}'
|
|
let erlangList = '\[\([A-Za-z_,|=\-{}]\|\s\)*\]'
|
|
|
|
" FIXME: Use searchpair?
|
|
while arguments =~ erlangTuple
|
|
let arguments = substitute(arguments, erlangTuple, "A", "g")
|
|
endwhile
|
|
" FIXME: Use searchpair?
|
|
while arguments =~ erlangList
|
|
let arguments = substitute(arguments, erlangList, "A", "g")
|
|
endwhile
|
|
|
|
let len = strlen(arguments)
|
|
while pos < len && pos > -1
|
|
let ac += 1
|
|
let pos = matchend(arguments, ',\s*', pos)
|
|
endwhile
|
|
return ac
|
|
endfunction
|
|
|
|
" Main fold function {{{2
|
|
function GetErlangFold(lnum)
|
|
let lnum = a:lnum
|
|
let line = getline(lnum)
|
|
|
|
" Function head gives fold level 1 {{{3
|
|
if line=~ s:ErlangBeginHead
|
|
while line !~ s:ErlangEndHead
|
|
if 0 == lnum " EOF / BOF
|
|
retun '='
|
|
endif
|
|
if line =~ s:ErlangFunEnd
|
|
return '='
|
|
endif
|
|
endif
|
|
let lnum = s:GetNextNonBlank(lnum)
|
|
let line = getline(lnum)
|
|
endwhile
|
|
" check if prev line was really end of function
|
|
let lnum = s:GetPrevNonBlank(a:lnum)
|
|
if exists("g:erlangFoldSplitFunction") && g:erlangFoldSplitFunction
|
|
if getline(lnum) !~ s:ErlangFunEnd
|
|
return '='
|
|
endif
|
|
endif
|
|
return '1>'
|
|
endif
|
|
|
|
" End of function (only on . not ;) gives fold level 0 {{{3
|
|
if line =~ s:ErlangFunEnd
|
|
return '<1'
|
|
endif
|
|
|
|
" Check if line below is a new function head {{{3
|
|
" Only used if we want to split folds for different function heads
|
|
" Ignores blank lines
|
|
if exists("g:erlangFoldSplitFunction") && g:erlangFoldSplitFunction
|
|
let lnum = s:GetNextNonBlank(lnum)
|
|
|
|
if 0 == lnum " EOF
|
|
return '<1'
|
|
endif
|
|
|
|
let line = getline(lnum)
|
|
|
|
" End of prev function head (new function here), ending fold level 1
|
|
if line =~ s:ErlangFunHead || line =~ s:ErlangBeginHead
|
|
return '<1'
|
|
endif
|
|
endif
|
|
|
|
" Otherwise use fold from previous line
|
|
return '='
|
|
endfunction
|
|
|
|
" Erlang fold description (foldtext function) {{{2
|
|
function ErlangFoldText()
|
|
let foldlen = v:foldend - v:foldstart
|
|
if 1 < foldlen
|
|
let lines = "lines"
|
|
else
|
|
let lines = "line"
|
|
endif
|
|
let line = getline(v:foldstart)
|
|
let name = s:GetFunName(line)
|
|
let arguments = s:GetFunArgs(strpart(line, strlen(name)), v:foldstart)
|
|
let argcount = s:CountFunArgs(arguments)
|
|
let retval = v:folddashes . " " . name . "/" . argcount
|
|
let retval .= " (" . foldlen . " " . lines . ")"
|
|
return retval
|
|
endfunction " }}}
|
|
endif " }}}
|
|
|
|
call s:SetErlangOptions()
|
|
|
|
" Skeletons {{{1
|
|
function GenServer()
|
|
echo foo
|
|
endfunction
|
|
" }}}
|
|
|
|
" vim: set foldmethod=marker:
|