blob: 930f5d13254303c1c4da14af7ee14e96f4eea4df [file] [log] [blame]
Bram Moolenaar3577c6f2008-06-24 21:16:56 +00001" Vim indent file
2" Language: Erlang
Bram Moolenaar6be7f872012-01-20 21:08:56 +01003" 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
Bram Moolenaar3577c6f2008-06-24 21:16:56 +00009
Bram Moolenaar6be7f872012-01-20 21:08:56 +010010" Only load this indent file when no other was loaded
Bram Moolenaar3577c6f2008-06-24 21:16:56 +000011if exists("b:did_indent")
Bram Moolenaar6be7f872012-01-20 21:08:56 +010012 finish
13else
14 let b:did_indent = 1
Bram Moolenaar3577c6f2008-06-24 21:16:56 +000015endif
Bram Moolenaar3577c6f2008-06-24 21:16:56 +000016
17setlocal indentexpr=ErlangIndent()
18setlocal indentkeys+==after,=end,=catch,=),=],=}
19
Bram Moolenaar6be7f872012-01-20 21:08:56 +010020" Only define the functions once
Bram Moolenaar3577c6f2008-06-24 21:16:56 +000021if exists("*ErlangIndent")
Bram Moolenaar6be7f872012-01-20 21:08:56 +010022 finish
Bram Moolenaar3577c6f2008-06-24 21:16:56 +000023endif
24
Bram Moolenaar6be7f872012-01-20 21:08:56 +010025" 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
30function 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
Bram Moolenaar3577c6f2008-06-24 21:16:56 +000033 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
Bram Moolenaar6be7f872012-01-20 21:08:56 +010037 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 '#'
Bram Moolenaar3577c6f2008-06-24 21:16:56 +000040
Bram Moolenaar6be7f872012-01-20 21:08:56 +010041 " Ignore comments
42 if a:line =~# '^\s*%'
43 return 0
44 endif
Bram Moolenaar3577c6f2008-06-24 21:16:56 +000045
Bram Moolenaar6be7f872012-01-20 21:08:56 +010046 " Partial function head where the guard is missing
47 if a:line =~# "\\(^\\l[[:alnum:]_]*\\)\\|\\(^'[^']\\+'\\)(" && a:line !~# '->'
48 return 2
49 endif
50
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
Bram Moolenaar3577c6f2008-06-24 21:16:56 +000057 " m: the next value of the i
Bram Moolenaar6be7f872012-01-20 21:08:56 +010058 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
Bram Moolenaar3577c6f2008-06-24 21:16:56 +000067 let ind = ind - 1
Bram Moolenaar6be7f872012-01-20 21:08:56 +010068 let last_fun = 0
69 let last_receive = 0
70 elseif a:line[(i):(m-1)] =~# '^\%(case\|if\|try\)$'
Bram Moolenaar3577c6f2008-06-24 21:16:56 +000071 let ind = ind + 1
Bram Moolenaar6be7f872012-01-20 21:08:56 +010072 elseif a:line[(i):(m-1)] =~# '^receive$'
Bram Moolenaar3577c6f2008-06-24 21:16:56 +000073 let ind = ind + 1
Bram Moolenaar6be7f872012-01-20 21:08:56 +010074 let last_receive = 1
75 elseif a:line[(i):(m-1)] =~# '^begin$'
Bram Moolenaar3577c6f2008-06-24 21:16:56 +000076 let ind = ind + 2
Bram Moolenaar6be7f872012-01-20 21:08:56 +010077 let last_receive = 0
78 elseif a:line[(i):(m-1)] =~# '^end$'
Bram Moolenaar3577c6f2008-06-24 21:16:56 +000079 let ind = ind - 2
Bram Moolenaar6be7f872012-01-20 21:08:56 +010080 let last_receive = 0
81 elseif a:line[(i):(m-1)] =~# '^after$'
82 if last_receive == 0
Bram Moolenaar3577c6f2008-06-24 21:16:56 +000083 let ind = ind - 1
84 else
85 let ind = ind + 0
Bram Moolenaar6be7f872012-01-20 21:08:56 +010086 endif
87 let last_receive = 0
88 elseif a:line[(i):(m-1)] =~# '^fun$'
Bram Moolenaar3577c6f2008-06-24 21:16:56 +000089 let ind = ind + 1
Bram Moolenaar6be7f872012-01-20 21:08:56 +010090 let last_fun = 1
91 let last_receive = 0
Bram Moolenaar3577c6f2008-06-24 21:16:56 +000092 endif
Bram Moolenaar6be7f872012-01-20 21:08:56 +010093 elseif a:line[i] =~# "[A-Z_]"
94 let m = matchend(a:line,".[[:alnum:]_]*",i)
95 let last_receive = 0
96 elseif a:line[i] == '$'
Bram Moolenaar3577c6f2008-06-24 21:16:56 +000097 let m = i+2
Bram Moolenaar6be7f872012-01-20 21:08:56 +010098 let last_receive = 0
99 elseif a:line[i] == "." && (i+1>=linelen || a:line[i+1]!~ "[0-9]")
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000100 let m = i+1
Bram Moolenaar6be7f872012-01-20 21:08:56 +0100101 if last_hash_sym
102 let last_hash_sym = 0
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000103 else
104 let ind = ind - 1
Bram Moolenaar6be7f872012-01-20 21:08:56 +0100105 endif
106 let last_receive = 0
107 elseif a:line[i] == '-' && (i+1<linelen && a:line[i+1]=='>')
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000108 let m = i+2
109 let ind = ind + 1
Bram Moolenaar6be7f872012-01-20 21:08:56 +0100110 let last_receive = 0
111 elseif a:line[i] == ';' && a:line[(i):(linelen)] !~# '.*->.*'
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000112 let m = i+1
113 let ind = ind - 1
Bram Moolenaar6be7f872012-01-20 21:08:56 +0100114 let last_receive = 0
115 elseif a:line[i] == '#'
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000116 let m = i+1
Bram Moolenaar6be7f872012-01-20 21:08:56 +0100117 let last_hash_sym = 1
118 elseif a:line[i] =~# '[({[]'
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000119 let m = i+1
120 let ind = ind + 1
Bram Moolenaar6be7f872012-01-20 21:08:56 +0100121 let last_fun = 0
122 let last_receive = 0
123 let last_hash_sym = 0
124 elseif a:line[i] =~# '[)}\]]'
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000125 let m = i+1
126 let ind = ind - 1
Bram Moolenaar6be7f872012-01-20 21:08:56 +0100127 let last_receive = 0
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000128 else
129 let m = i+1
130 endif
131
132 let i = m
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000133 endwhile
134
135 return ind
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000136endfunction
137
138function s:FindPrevNonBlankNonComment(lnum)
139 let lnum = prevnonblank(a:lnum)
140 let line = getline(lnum)
Bram Moolenaar6be7f872012-01-20 21:08:56 +0100141 " Continue to search above if the current line begins with a '%'
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000142 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
150endfunction
151
Bram Moolenaar6be7f872012-01-20 21:08:56 +0100152" 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
157function s:GetLineIndent(lnum)
158 return (indent(a:lnum) / &sw) * &sw
159endfunction
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000160
Bram Moolenaar6be7f872012-01-20 21:08:56 +0100161function ErlangIndent()
162 " Find a non-blank line above the current line
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000163 let lnum = prevnonblank(v:lnum - 1)
164
Bram Moolenaar6be7f872012-01-20 21:08:56 +0100165 " Hit the start of the file, use zero indent
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000166 if lnum == 0
167 return 0
168 endif
169
170 let prevline = getline(lnum)
171 let currline = getline(v:lnum)
172
Bram Moolenaar6be7f872012-01-20 21:08:56 +0100173 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
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000179
Bram Moolenaar6be7f872012-01-20 21:08:56 +0100180 " Special cases:
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000181 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*\%(%.*\)\=$'
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000190 " If the 'receive' is not in the same line as the 'after'
Bram Moolenaar6be7f872012-01-20 21:08:56 +0100191 let ind = ind - 1*&sw
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000192 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
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000213endfunction