Runtime files update
[MacVim.git] / runtime / indent / erlang.vim
blob236c2c25ea5231a7734617cd6ec316abf24b2a05
1 " Vim indent file
2 " Language:     Erlang
3 " Maintainer:   Csaba Hoch <csaba.hoch@gmail.com>
4 " Last Change:  2007 Dec 08
6 " Only load this indent file when no other was loaded.
7 if exists("b:did_indent")
8   finish
9 endif
10 let b:did_indent = 1
12 setlocal indentexpr=ErlangIndent()
13 setlocal indentkeys+==after,=end,=catch,=),=],=}
15 " Only define the functions once.
16 if exists("*ErlangIndent")
17    finish
18 endif
20 " The function go through the whole line, analyses it and sets the indentation
21 " (ind variable).
22 " l: the number of the line to be examined.
23 function s:ErlangIndentAtferLine(l)
24     let i = 0 " the index of the current character in the line
25     let length = strlen(a:l) " the length of the line
26     let ind = 0 " how much should be the difference between the indentation of
27                 " the current line and the indentation of the next line?
28                 " e.g. +1: the indentation of the next line should be equal to
29                 " the indentation of the current line plus one shiftwidth
30     let lastFun = 0 " the last token was a 'fun'
31     let lastReceive = 0 " the last token was a 'receive'; needed for 'after'
32     let lastHashMark = 0 " the last token was a 'hashmark'
34     while 0<= i && i < length
36         " m: the next value of the i
37         if a:l[i] == '%'
38             break
39         elseif a:l[i] == '"'
40             let m = matchend(a:l,'"\%([^"\\]\|\\.\)*"',i)
41             let lastReceive = 0
42         elseif a:l[i] == "'"
43             let m = matchend(a:l,"'[^']*'",i)
44             let lastReceive = 0
45         elseif a:l[i] =~ "[a-z]"
46             let m = matchend(a:l,".[[:alnum:]_]*",i)
47             if lastFun
48                 let ind = ind - 1
49                 let lastFun = 0
50                 let lastReceive = 0
51             elseif a:l[(i):(m-1)] =~ '^\%(case\|if\|try\)$'
52                 let ind = ind + 1
53             elseif a:l[(i):(m-1)] =~ '^receive$'
54                 let ind = ind + 1
55                 let lastReceive = 1
56             elseif a:l[(i):(m-1)] =~ '^begin$'
57                 let ind = ind + 2
58                 let lastReceive = 0
59             elseif a:l[(i):(m-1)] =~ '^end$'
60                 let ind = ind - 2
61                 let lastReceive = 0
62             elseif a:l[(i):(m-1)] =~ '^after$'
63                 if lastReceive == 0
64                     let ind = ind - 1
65                 else
66                     let ind = ind + 0
67                 end
68                 let lastReceive = 0
69             elseif a:l[(i):(m-1)] =~ '^fun$'
70                 let ind = ind + 1
71                 let lastFun = 1
72                 let lastReceive = 0
73             endif
74         elseif a:l[i] =~ "[A-Z_]"
75             let m = matchend(a:l,".[[:alnum:]_]*",i)
76             let lastReceive = 0
77         elseif a:l[i] == '$'
78             let m = i+2
79             let lastReceive = 0
80         elseif a:l[i] == "." && (i+1>=length || a:l[i+1]!~ "[0-9]")
81             let m = i+1
82             if lastHashMark
83                 let lastHashMark = 0
84             else
85                 let ind = ind - 1
86             end
87             let lastReceive = 0
88         elseif a:l[i] == '-' && (i+1<length && a:l[i+1]=='>')
89             let m = i+2
90             let ind = ind + 1
91             let lastReceive = 0
92         elseif a:l[i] == ';'
93             let m = i+1
94             let ind = ind - 1
95             let lastReceive = 0
96         elseif a:l[i] == '#'
97             let m = i+1
98             let lastHashMark = 1
99         elseif a:l[i] =~ '[({[]'
100             let m = i+1
101             let ind = ind + 1
102             let lastFun = 0
103             let lastReceive = 0
104             let lastHashMark = 0
105         elseif a:l[i] =~ '[)}\]]'
106             let m = i+1
107             let ind = ind - 1
108             let lastReceive = 0
109         else
110             let m = i+1
111         endif
113         let i = m
115     endwhile
117     return ind
119 endfunction
121 function s:FindPrevNonBlankNonComment(lnum)
122     let lnum = prevnonblank(a:lnum)
123     let line = getline(lnum)
124     " continue to search above if the current line begins with a '%'
125     while line =~ '^\s*%.*$'
126         let lnum = prevnonblank(lnum - 1)
127         if 0 == lnum
128             return 0
129         endif
130         let line = getline(lnum)
131     endwhile
132     return lnum
133 endfunction
135 function ErlangIndent()
137     " Find a non-blank line above the current line.
138     let lnum = prevnonblank(v:lnum - 1)
140     " Hit the start of the file, use zero indent.
141     if lnum == 0
142         return 0
143     endif
145     let prevline = getline(lnum)
146     let currline = getline(v:lnum)
148     let ind = indent(lnum) + &sw * s:ErlangIndentAtferLine(prevline)
150     " special cases:
151     if prevline =~ '^\s*\%(after\|end\)\>'
152         let ind = ind + 2*&sw
153     endif
154     if currline =~ '^\s*end\>'
155         let ind = ind - 2*&sw
156     endif
157     if currline =~ '^\s*after\>'
158         let plnum = s:FindPrevNonBlankNonComment(v:lnum-1)
159         if getline(plnum) =~ '^[^%]*\<receive\>\s*\%(%.*\)\=$'
160             let ind = ind - 1*&sw
161             " If the 'receive' is not in the same line as the 'after'
162         else
163             let ind = ind - 2*&sw
164         endif
165     endif
166     if prevline =~ '^\s*[)}\]]'
167         let ind = ind + 1*&sw
168     endif
169     if currline =~ '^\s*[)}\]]'
170         let ind = ind - 1*&sw
171     endif
172     if prevline =~ '^\s*\%(catch\)\s*\%(%\|$\)'
173         let ind = ind + 1*&sw
174     endif
175     if currline =~ '^\s*\%(catch\)\s*\%(%\|$\)'
176         let ind = ind - 1*&sw
177     endif
179     if ind<0
180         let ind = 0
181     endif
182     return ind
184 endfunction
186 " TODO:
188 " f() ->
189 "     x("foo
190 "         bar")
191 "         ,
192 "         bad_indent.
194 " fun
195 "     init/0,
196 "     bad_indent
198 "     #rec
199 "     .field,
200 " bad_indent