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