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