forked from aniani/vim
		
	
		
			
	
	
		
			207 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			VimL
		
	
	
	
	
	
		
		
			
		
	
	
			207 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			VimL
		
	
	
	
	
	
|   | " Vim indent file | ||
|  | " Language:     Erlang | ||
|  | " Maintainer:   Csaba Hoch <csaba.hoch@gmail.com> | ||
|  | " Contributor:  Edwin Fine <efine145_nospam01 at usa dot net> | ||
|  | " Last Change:  2008 Mar 12 | ||
|  | 
 | ||
|  | " Only load this indent file when no other was loaded. | ||
|  | if exists("b:did_indent") | ||
|  |   finish | ||
|  | endif | ||
|  | let b:did_indent = 1 | ||
|  | 
 | ||
|  | setlocal indentexpr=ErlangIndent() | ||
|  | setlocal indentkeys+==after,=end,=catch,=),=],=} | ||
|  | 
 | ||
|  | " Only define the functions once. | ||
|  | if exists("*ErlangIndent") | ||
|  |    finish | ||
|  | endif | ||
|  | 
 | ||
|  | " The function go through the whole line, analyses it and sets the indentation | ||
|  | " (ind variable). | ||
|  | " l: the number of the line to be examined. | ||
|  | function s:ErlangIndentAtferLine(l) | ||
|  |     let i = 0 " the index of the current character in the line | ||
|  |     let length = strlen(a:l) " the length of the line | ||
|  |     let ind = 0 " how much should be the difference between the indentation of | ||
|  |                 " the current line and the indentation of the next line? | ||
|  |                 " e.g. +1: the indentation of the next line should be equal to | ||
|  |                 " the indentation of the current line plus one shiftwidth | ||
|  |     let lastFun = 0 " the last token was a 'fun' | ||
|  |     let lastReceive = 0 " the last token was a 'receive'; needed for 'after' | ||
|  |     let lastHashMark = 0 " the last token was a 'hashmark' | ||
|  | 
 | ||
|  |     while 0<= i && i < length | ||
|  | 
 | ||
|  |         " m: the next value of the i | ||
|  |         if a:l[i] == '%' | ||
|  |             break | ||
|  |         elseif a:l[i] == '"' | ||
|  |             let m = matchend(a:l,'"\%([^"\\]\|\\.\)*"',i) | ||
|  |             let lastReceive = 0 | ||
|  |         elseif a:l[i] == "'" | ||
|  |             let m = matchend(a:l,"'[^']*'",i) | ||
|  |             let lastReceive = 0 | ||
|  |         elseif a:l[i] =~# "[a-z]" | ||
|  |             let m = matchend(a:l,".[[:alnum:]_]*",i) | ||
|  |             if lastFun | ||
|  |                 let ind = ind - 1 | ||
|  |                 let lastFun = 0 | ||
|  |                 let lastReceive = 0 | ||
|  |             elseif a:l[(i):(m-1)] =~# '^\%(case\|if\|try\)$' | ||
|  |                 let ind = ind + 1 | ||
|  |             elseif a:l[(i):(m-1)] =~# '^receive$' | ||
|  |                 let ind = ind + 1 | ||
|  |                 let lastReceive = 1 | ||
|  |             elseif a:l[(i):(m-1)] =~# '^begin$' | ||
|  |                 let ind = ind + 2 | ||
|  |                 let lastReceive = 0 | ||
|  |             elseif a:l[(i):(m-1)] =~# '^end$' | ||
|  |                 let ind = ind - 2 | ||
|  |                 let lastReceive = 0 | ||
|  |             elseif a:l[(i):(m-1)] =~# '^after$' | ||
|  |                 if lastReceive == 0 | ||
|  |                     let ind = ind - 1 | ||
|  |                 else | ||
|  |                     let ind = ind + 0 | ||
|  |                 end | ||
|  |                 let lastReceive = 0 | ||
|  |             elseif a:l[(i):(m-1)] =~# '^fun$' | ||
|  |                 let ind = ind + 1 | ||
|  |                 let lastFun = 1 | ||
|  |                 let lastReceive = 0 | ||
|  |             endif | ||
|  |         elseif a:l[i] =~# "[A-Z_]" | ||
|  |             let m = matchend(a:l,".[[:alnum:]_]*",i) | ||
|  |             let lastReceive = 0 | ||
|  |         elseif a:l[i] == '$' | ||
|  |             let m = i+2 | ||
|  |             let lastReceive = 0 | ||
|  |         elseif a:l[i] == "." && (i+1>=length || a:l[i+1]!~ "[0-9]") | ||
|  |             let m = i+1 | ||
|  |             if lastHashMark | ||
|  |                 let lastHashMark = 0 | ||
|  |             else | ||
|  |                 let ind = ind - 1 | ||
|  |             end | ||
|  |             let lastReceive = 0 | ||
|  |         elseif a:l[i] == '-' && (i+1<length && a:l[i+1]=='>') | ||
|  |             let m = i+2 | ||
|  |             let ind = ind + 1 | ||
|  |             let lastReceive = 0 | ||
|  |         elseif a:l[i] == ';' | ||
|  |             let m = i+1 | ||
|  |             let ind = ind - 1 | ||
|  |             let lastReceive = 0 | ||
|  |         elseif a:l[i] == '#' | ||
|  |             let m = i+1 | ||
|  |             let lastHashMark = 1 | ||
|  |         elseif a:l[i] =~# '[({[]' | ||
|  |             let m = i+1 | ||
|  |             let ind = ind + 1 | ||
|  |             let lastFun = 0 | ||
|  |             let lastReceive = 0 | ||
|  |             let lastHashMark = 0 | ||
|  |         elseif a:l[i] =~# '[)}\]]' | ||
|  |             let m = i+1 | ||
|  |             let ind = ind - 1 | ||
|  |             let lastReceive = 0 | ||
|  |         else | ||
|  |             let m = i+1 | ||
|  |         endif | ||
|  | 
 | ||
|  |         let i = m | ||
|  | 
 | ||
|  |     endwhile | ||
|  | 
 | ||
|  |     return ind | ||
|  | 
 | ||
|  | endfunction | ||
|  | 
 | ||
|  | function s:FindPrevNonBlankNonComment(lnum) | ||
|  |     let lnum = prevnonblank(a:lnum) | ||
|  |     let line = getline(lnum) | ||
|  |     " continue to search above if the current line begins with a '%' | ||
|  |     while line =~# '^\s*%.*$' | ||
|  |         let lnum = prevnonblank(lnum - 1) | ||
|  |         if 0 == lnum | ||
|  |             return 0 | ||
|  |         endif | ||
|  |         let line = getline(lnum) | ||
|  |     endwhile | ||
|  |     return lnum | ||
|  | endfunction | ||
|  | 
 | ||
|  | function ErlangIndent() | ||
|  | 
 | ||
|  |     " Find a non-blank line above the current line. | ||
|  |     let lnum = prevnonblank(v:lnum - 1) | ||
|  | 
 | ||
|  |     " Hit the start of the file, use zero indent. | ||
|  |     if lnum == 0 | ||
|  |         return 0 | ||
|  |     endif | ||
|  | 
 | ||
|  |     let prevline = getline(lnum) | ||
|  |     let currline = getline(v:lnum) | ||
|  | 
 | ||
|  |     let ind = indent(lnum) + &sw * s:ErlangIndentAtferLine(prevline) | ||
|  | 
 | ||
|  |     " special cases: | ||
|  |     if prevline =~# '^\s*\%(after\|end\)\>' | ||
|  |         let ind = ind + 2*&sw | ||
|  |     endif | ||
|  |     if currline =~# '^\s*end\>' | ||
|  |         let ind = ind - 2*&sw | ||
|  |     endif | ||
|  |     if currline =~# '^\s*after\>' | ||
|  |         let plnum = s:FindPrevNonBlankNonComment(v:lnum-1) | ||
|  |         if getline(plnum) =~# '^[^%]*\<receive\>\s*\%(%.*\)\=$' | ||
|  |             let ind = ind - 1*&sw | ||
|  |             " If the 'receive' is not in the same line as the 'after' | ||
|  |         else | ||
|  |             let ind = ind - 2*&sw | ||
|  |         endif | ||
|  |     endif | ||
|  |     if prevline =~# '^\s*[)}\]]' | ||
|  |         let ind = ind + 1*&sw | ||
|  |     endif | ||
|  |     if currline =~# '^\s*[)}\]]' | ||
|  |         let ind = ind - 1*&sw | ||
|  |     endif | ||
|  |     if prevline =~# '^\s*\%(catch\)\s*\%(%\|$\)' | ||
|  |         let ind = ind + 1*&sw | ||
|  |     endif | ||
|  |     if currline =~# '^\s*\%(catch\)\s*\%(%\|$\)' | ||
|  |         let ind = ind - 1*&sw | ||
|  |     endif | ||
|  | 
 | ||
|  |     if ind<0 | ||
|  |         let ind = 0 | ||
|  |     endif | ||
|  |     return ind | ||
|  | 
 | ||
|  | endfunction | ||
|  | 
 | ||
|  | " TODO: | ||
|  | "  | ||
|  | " f() -> | ||
|  | "     x("foo | ||
|  | "         bar") | ||
|  | "         , | ||
|  | "         bad_indent. | ||
|  | " | ||
|  | " fun | ||
|  | "     init/0, | ||
|  | "     bad_indent | ||
|  | " | ||
|  | "     #rec | ||
|  | "     .field, | ||
|  | " bad_indent | ||
|  | " | ||
|  | " case X of | ||
|  | "     1 when A; B -> | ||
|  | "     bad_indent | ||
|  | 
 |