comparison runtime/indent/erlang.vim @ 48:67300faee616 v7-3-618

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