blob: e510f3c8f394aed5c744f0d1f0c8cb7385f6006e [file] [log] [blame]
Bram Moolenaar280f1262006-01-30 00:14:18 +00001" VHDL indent ('93 syntax)
Bram Moolenaar51156d52006-01-26 22:17:47 +00002" Language: VHDL
3" Maintainer: Gerald Lai <laigera+vim?gmail.com>
Bram Moolenaarb8a7b562006-02-01 21:47:16 +00004" Version: 1.3
5" Last Change: 2006 Jan 31
Bram Moolenaar280f1262006-01-30 00:14:18 +00006" URL: http://www.vim.org/scripts/script.php?script_id=1450
Bram Moolenaar51156d52006-01-26 22:17:47 +00007
8" only load this indent file when no other was loaded
9if exists("b:did_indent")
10 finish
11endif
12let b:did_indent = 1
13
14" setup indent options for local VHDL buffer
15setlocal indentexpr=GetVHDLindent()
16setlocal indentkeys=!^F,o,O,e,0(,0)
17setlocal indentkeys+==~if,=~then,=~elsif,=~else
18setlocal indentkeys+==~begin,=~is,=~select,=~--
19
20" move around
21" keywords: "architecture", "block", "configuration", "component", "entity", "function", "package", "procedure", "process", "record", "units"
22let b:vhdl_explore = '\%(architecture\|block\|configuration\|component\|entity\|function\|package\|procedure\|process\|record\|units\)'
23nnoremap <silent><buffer>[[ :cal search('\%(\<end\s\+\)\@<!\<'.b:vhdl_explore.'\>\c','bW')<CR>
24nnoremap <silent><buffer>]] :cal search('\%(\<end\s\+\)\@<!\<'.b:vhdl_explore.'\>\c','W')<CR>
25nnoremap <silent><buffer>[] :cal search('\<end\s\+'.b:vhdl_explore.'\>\c','bW')<CR>
26nnoremap <silent><buffer>][ :cal search('\<end\s\+'.b:vhdl_explore.'\>\c','W')<CR>
27
28" constants
29" not a comment
30let s:NC = '\%(--.*\)\@<!'
31" end of string
32let s:ES = '\s*\%(--.*\)\=$'
33" no "end" keyword in front
34let s:NE = '\%(\<end\s\+\)\@<!'
35
36" for matchit plugin
37if exists("loaded_matchit")
38 let b:match_ignorecase = 1
39 let b:match_words =
40 \ s:NE.'\<if\>:\<elsif\>:\<else\>:\<end\s\+if\>,'.
41 \ s:NE.'\<case\>:\<when\>:\<end\s\+case\>,'.
42 \ s:NE.'\<loop\>:\<end\s\+loop\>,'.
43 \ s:NE.'\<for\>:\<end\s\+for\>,'.
44 \ s:NE.'\<generate\>:\<end\s\+generate\>,'.
45 \ s:NE.'\<record\>:\<end\s\+record\>,'.
46 \ s:NE.'\<units\>:\<end\s\+units\>,'.
47 \ s:NE.'\<process\>:\<end\s\+process\>,'.
48 \ s:NE.'\<block\>:\<end\s\+block\>,'.
49 \ s:NE.'\<function\>:\<end\s\+function\>,'.
50 \ s:NE.'\<entity\>:\<end\s\+entity\>,'.
51 \ s:NE.'\<component\>:\<end\s\+component\>,'.
52 \ s:NE.'\<architecture\>:\<end\s\+architecture\>,'.
53 \ s:NE.'\<package\>:\<end\s\+package\>,'.
54 \ s:NE.'\<procedure\>:\<end\s\+procedure\>,'.
55 \ s:NE.'\<configuration\>:\<end\s\+configuration\>'
56endif
57
58" only define indent function once
59if exists("*GetVHDLindent")
60 finish
61endif
62
63function GetVHDLindent()
64 " store current line & string
65 let curn = v:lnum
66 let curs = getline(curn)
67
68 " find previous line that is not a comment
69 let prevn = prevnonblank(curn - 1)
70 let prevs = getline(prevn)
71 while prevn > 0 && prevs =~ '^\s*--'
72 let prevn = prevnonblank(prevn - 1)
73 let prevs = getline(prevn)
74 endwhile
75
76 " default indent starts as previous non-comment line's indent
77 let ind = prevn > 0 ? indent(prevn) : 0
78 " backup default
79 let ind2 = ind
80
Bram Moolenaar280f1262006-01-30 00:14:18 +000081 " indent: special; kill string so it would not affect other filters
82 " keywords: "report" + string
83 " where: anywhere in current or previous line
84 let s0 = s:NC.'\<report\>\s*".*"'
85 if curs =~? s0
86 let curs = ""
87 endif
88 if prevs =~? s0
89 let prevs = ""
90 endif
91
Bram Moolenaar51156d52006-01-26 22:17:47 +000092 " indent: previous line's comment position, otherwise follow next non-comment line if possible
93 " keyword: "--"
94 " where: start of current line
95 if curs =~ '^\s*--'
96 let pn = curn - 1
97 let ps = getline(pn)
98 if ps =~ '--'
99 return stridx(ps, '--')
100 else
101 " find nextnonblank line that is not a comment
102 let nn = nextnonblank(curn + 1)
103 let ns = getline(nn)
104 while nn > 0 && ns =~ '^\s*--'
105 let nn = nextnonblank(nn + 1)
106 let ns = getline(nn)
107 endwhile
108 let n = indent(nn)
109 return n != -1 ? n : ind
110 endif
111 endif
112
113 " ****************************************************************************************
114 " indent: align generic variables & port names
115 " keywords: "generic", "map", "port" + "(", provided current line is part of mapping
116 " where: anywhere in previous 2 lines
117 " find following previous non-comment line
118 let pn = prevnonblank(prevn - 1)
119 let ps = getline(pn)
120 while pn > 0 && ps =~ '^\s*--'
121 let pn = prevnonblank(pn - 1)
122 let ps = getline(pn)
123 endwhile
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000124 if (curs =~ '^\s*)' || curs =~? '^\s*\%(\<\%(generic\|map\|port\)\>.*\)\@<!\S\+\s*\%(=>\s*\S\+\|:[^=]\@=\s*\%(\%(in\|out\|inout\|buffer\|linkage\)\>\|\w\+\s\+:=\)\)') && (prevs =~? s:NC.'\<\%(generic\|map\|port\)\s*(\%(\s*\w\)\=' || (ps =~? s:NC.'\<\%(generic\|map\|port\)'.s:ES && prevs =~ '^\s*('))
Bram Moolenaar51156d52006-01-26 22:17:47 +0000125 " align closing ")" with opening "("
126 if curs =~ '^\s*)'
127 return stridx(prevs, '(')
128 endif
129 let m = matchend(prevs, '(\s*\ze\w')
130 if m != -1
131 return m
132 else
133 return stridx(prevs, '(') + &sw
134 endif
135 endif
136
137 " indent: align conditional/select statement
Bram Moolenaar280f1262006-01-30 00:14:18 +0000138 " keywords: variable + "<=" without ";" ending
139 " where: start of previous line
140 if prevs =~? '^\s*\S\+\s*<=[^;]*'.s:ES
Bram Moolenaar51156d52006-01-26 22:17:47 +0000141 return matchend(prevs, '<=\s*\ze.')
142 endif
143
144 " indent: backtrace previous non-comment lines for next smaller or equal size indent
145 " keywords: "end" + "record", "units"
146 " where: start of previous line
147 " keyword: ")"
148 " where: start of previous line
149 " keyword: without "<=" + ";" ending
150 " where: anywhere in previous line
151 " keyword: "=>" + ")" ending, provided current line does not begin with ")"
152 " where: anywhere in previous line
153 " _note_: indent allowed to leave this filter
154 let m = 0
155 if prevs =~? '^\s*end\s\+\%(record\|units\)\>'
156 let m = 3
157 elseif prevs =~ '^\s*)'
158 let m = 1
159 elseif prevs =~ s:NC.'\%(<=.*\)\@<!;'.s:ES || (curs !~ '^\s*)' && prevs =~ s:NC.'=>.*'.s:NC.')'.s:ES)
160 let m = 2
161 endif
162
163 if m > 0
164 let pn = prevnonblank(prevn - 1)
165 let ps = getline(pn)
166 while pn > 0
167 let t = indent(pn)
168 if ps !~ '^\s*--' && t < ind
169 " make sure one of these is true
Bram Moolenaar280f1262006-01-30 00:14:18 +0000170 " keywords: variable + "<=" without ";" ending
171 " where: start of previous non-comment line
Bram Moolenaar51156d52006-01-26 22:17:47 +0000172 " keywords: "generic", "map", "port"
173 " where: anywhere in previous non-comment line
174 " keyword: "("
175 " where: start of previous non-comment line
Bram Moolenaar280f1262006-01-30 00:14:18 +0000176 if m < 3 && ps !~? '^\s*\S\+\s*<=[^;]*'.s:ES
Bram Moolenaar51156d52006-01-26 22:17:47 +0000177 if ps =~? s:NC.'\<\%(generic\|map\|port\)\>' || ps =~ '^\s*('
178 let ind = t
179 endif
180 break
181 endif
182 let ind = t
183 if m > 1
184 " find following previous non-comment line
185 let ppn = prevnonblank(pn - 1)
186 let pps = getline(ppn)
187 while ppn > 0 && pps =~ '^\s*--'
188 let ppn = prevnonblank(ppn - 1)
189 let pps = getline(ppn)
190 endwhile
191 " indent: follow
192 " keyword: "select"
193 " where: end of following previous non-comment line
194 " keyword: "type"
195 " where: start of following previous non-comment line
196 if m == 2
197 let s1 = s:NC.'\<select'.s:ES
198 if ps !~? s1 && pps =~? s1
199 let ind = indent(ppn)
200 endif
201 elseif m == 3
202 let s1 = '^\s*type\>'
203 if ps !~? s1 && pps =~? s1
204 let ind = indent(ppn)
205 endif
206 endif
207 endif
208 break
209 endif
210 let pn = prevnonblank(pn - 1)
211 let ps = getline(pn)
212 endwhile
213 endif
214
215 " indent: follow indent of previous opening statement, otherwise -sw
216 " keyword: "begin"
217 " where: anywhere in current line
218 if curs =~? s:NC.'\<begin\>'
219 let ind = ind - &sw
220 " find previous opening statement of
221 " keywords: "architecture", "block", "entity", "function", "generate", "procedure", "process"
222 let s2 = s:NC.s:NE.'\<\%(architecture\|block\|entity\|function\|generate\|procedure\|process\)\>'
223 if curs !~? s2.'.*'.s:NC.'\<begin\>.*'.s:ES && prevs =~? s2
224 let ind = ind + &sw
225 endif
226 return ind
227 endif
228
229 " indent: +sw if previous line is previous opening statement
230 " keywords: "record", "units"
231 " where: anywhere in current line
232 if curs =~? s:NC.s:NE.'\<\%(record\|units\)\>'
233 " find previous opening statement of
234 " keyword: "type"
235 let s3 = s:NC.s:NE.'\<type\>'
236 if curs !~? s3.'.*'.s:NC.'\<\%(record\|units\)\>.*'.s:ES && prevs =~? s3
237 let ind = ind + &sw
238 endif
239 return ind
240 endif
241
242 " ****************************************************************************************
243 " indent: 0
244 " keywords: "architecture", "configuration", "entity", "library", "package"
245 " where: start of current line
246 if curs =~? '^\s*\%(architecture\|configuration\|entity\|library\|package\)\>'
247 return 0
248 endif
249
Bram Moolenaar280f1262006-01-30 00:14:18 +0000250 " indent: maintain indent of previous opening statement
Bram Moolenaar51156d52006-01-26 22:17:47 +0000251 " keyword: "is"
252 " where: start of current line
253 " find previous opening statement of
254 " keywords: "architecture", "block", "configuration", "entity", "function", "package", "procedure", "process", "type"
255 if curs =~? '^\s*\<is\>' && prevs =~? s:NC.s:NE.'\<\%(architecture\|block\|configuration\|entity\|function\|package\|procedure\|process\|type\)\>'
Bram Moolenaar280f1262006-01-30 00:14:18 +0000256 return ind2
Bram Moolenaar51156d52006-01-26 22:17:47 +0000257 endif
258
Bram Moolenaar280f1262006-01-30 00:14:18 +0000259 " indent: maintain indent of previous opening statement
Bram Moolenaar51156d52006-01-26 22:17:47 +0000260 " keyword: "then"
261 " where: start of current line
262 " find previous opening statement of
263 " keywords: "elsif", "if"
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000264 if curs =~? '^\s*\<then\>' && prevs =~? s:NC.'\%(\<elsif\>\|'.s:NE.'\<if\>\)'
Bram Moolenaar280f1262006-01-30 00:14:18 +0000265 return ind2
Bram Moolenaar51156d52006-01-26 22:17:47 +0000266 endif
267
Bram Moolenaar280f1262006-01-30 00:14:18 +0000268 " indent: maintain indent of previous opening statement
Bram Moolenaar51156d52006-01-26 22:17:47 +0000269 " keyword: "generate"
270 " where: start of current line
271 " find previous opening statement of
272 " keywords: "for", "if"
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000273 if curs =~? '^\s*\<generate\>' && prevs =~? s:NC.s:NE.'\%(\%(\<wait\s\+\)\@<!\<for\>\|\<if\>\)'
Bram Moolenaar280f1262006-01-30 00:14:18 +0000274 return ind2
Bram Moolenaar51156d52006-01-26 22:17:47 +0000275 endif
276
277 " indent: +sw
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000278 " keywords: "begin", "block", "loop", "process", "record", "units"
279 " removed: "case", "elsif", "if", "while"
Bram Moolenaar51156d52006-01-26 22:17:47 +0000280 " where: anywhere in previous line
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000281 if prevs =~? s:NC.'\%(\<begin\>\|'.s:NE.'\<\%(block\|loop\|process\|record\|units\)\>\)'
Bram Moolenaar51156d52006-01-26 22:17:47 +0000282 return ind + &sw
283 endif
284
285 " indent: +sw
Bram Moolenaar280f1262006-01-30 00:14:18 +0000286 " keywords: "architecture", "component", "configuration", "entity", "for", "package"
287 " removed: "when", "with"
Bram Moolenaar51156d52006-01-26 22:17:47 +0000288 " where: start of previous line
Bram Moolenaar280f1262006-01-30 00:14:18 +0000289 if prevs =~? '^\s*\%(architecture\|component\|configuration\|entity\|for\|package\)\>'
Bram Moolenaar51156d52006-01-26 22:17:47 +0000290 return ind + &sw
291 endif
292
293 " indent: +sw
294 " keyword: "generate", "is", "select", "=>"
295 " where: end of previous line
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000296 if prevs =~? s:NC.'\%(\%('.s:NE.'\<generate\|\<is\|\<select\)\|=>\)'.s:ES
Bram Moolenaar51156d52006-01-26 22:17:47 +0000297 return ind + &sw
298 endif
299
300 " indent: +sw
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000301 " keyword: "else"
302 " where: start of previous line
303 " keyword: "then"
Bram Moolenaar51156d52006-01-26 22:17:47 +0000304 " where: end of previous line
305 " _note_: indent allowed to leave this filter
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000306 if prevs =~? '^\s*else\>' || prevs =~? s:NC.'\<then'.s:ES
Bram Moolenaar51156d52006-01-26 22:17:47 +0000307 let ind = ind + &sw
308 endif
309
310 " ****************************************************************************************
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000311 " indent: -sw
312 " keywords: "when", provided previous line does not begin with "when"
Bram Moolenaar51156d52006-01-26 22:17:47 +0000313 " where: start of current line
314 let s4 = '^\s*when\>'
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000315 if curs =~? s4
316 if prevs !~? s4
317 return ind - &sw
318 else
319 return ind2
320 endif
Bram Moolenaar51156d52006-01-26 22:17:47 +0000321 endif
322
323 " indent: -sw
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000324 " keywords: "else", "elsif", provided previous line does not contain "then"
Bram Moolenaar51156d52006-01-26 22:17:47 +0000325 " where: start of current line
326 if curs =~? '^\s*\%(else\|elsif\)\>'
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000327 if prevs !~? s:NC.'\<then\>'
328 return ind - &sw
329 else
330 return ind2
331 endif
Bram Moolenaar51156d52006-01-26 22:17:47 +0000332 endif
333
334 " indent: -sw
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000335 " keywords: "end" + "if", provided previous line does not begin with "else", not contain "then"
Bram Moolenaar51156d52006-01-26 22:17:47 +0000336 " where: start of current line
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000337 if curs =~? '^\s*end\s\+if\>'
338 if prevs !~? '^\s*else\>' && prevs !~? s:NC.'\<then\>'
339 return ind - &sw
340 else
341 return ind2
342 endif
343 endif
344
345 " indent: -sw
346 " keywords: "end" + "function", "procedure", provided previous line does not contain "begin"
Bram Moolenaar51156d52006-01-26 22:17:47 +0000347 " where: start of current line
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000348 if curs =~? '^\s*end\s\+\%(function\|procedure\)\>'
349 if prevs !~? s:NC.'\<begin\>'
350 return ind - &sw
351 else
352 return ind2
353 endif
354 endif
355
356 " indent: -sw
357 " keywords: "end" + "block", "for", "generate", "loop", "process", "record", "units"
358 " where: start of current line
359 if curs =~? '^\s*end\s\+\%(block\|for\|generate\|loop\|process\|record\|units\)\>'
Bram Moolenaar51156d52006-01-26 22:17:47 +0000360 return ind - &sw
361 endif
362
Bram Moolenaar280f1262006-01-30 00:14:18 +0000363 " indent: backtrace previous non-comment lines
364 " keyword: "end" + "case", "component"
Bram Moolenaar51156d52006-01-26 22:17:47 +0000365 " where: start of current line
Bram Moolenaar280f1262006-01-30 00:14:18 +0000366 let m = 0
Bram Moolenaar51156d52006-01-26 22:17:47 +0000367 if curs =~? '^\s*end\s\+case\>'
Bram Moolenaar280f1262006-01-30 00:14:18 +0000368 let m = 1
369 elseif curs =~? '^\s*end\s\+component\>'
370 let m = 2
371 endif
372
373 if m > 0
Bram Moolenaar51156d52006-01-26 22:17:47 +0000374 " find following previous non-comment line
375 let pn = prevn
376 let ps = getline(pn)
377 while pn > 0
378 if ps !~ '^\s*--'
Bram Moolenaar280f1262006-01-30 00:14:18 +0000379 "indent: -2sw
380 "keywords: "end" + "case"
381 "where: start of previous non-comment line
382 "indent: -sw
383 "keywords: "when"
384 "where: start of previous non-comment line
385 "indent: follow
386 "keywords: "case"
387 "where: start of previous non-comment line
388 if m == 1
389 if ps =~? '^\s*end\s\+case\>'
390 return indent(pn) - 2 * &sw
391 elseif ps =~? '^\s*when\>'
392 return indent(pn) - &sw
393 elseif ps =~? '^\s*case\>'
394 return indent(pn)
395 endif
396 "indent: follow
397 "keyword: "component"
398 "where: anywhere in previous non-comment line
399 elseif m == 2
400 if ps =~? s:NC.s:NE.'\<component\>'
401 return indent(pn)
402 endif
Bram Moolenaar51156d52006-01-26 22:17:47 +0000403 endif
404 endif
405 let pn = prevnonblank(pn - 1)
406 let ps = getline(pn)
407 endwhile
Bram Moolenaar280f1262006-01-30 00:14:18 +0000408 return ind - &sw
Bram Moolenaar51156d52006-01-26 22:17:47 +0000409 endif
410
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000411 " indent: -sw
412 " keyword: ")"
413 " where: start of current line
414 if curs =~ '^\s*)'
415 return ind - &sw
416 endif
417
Bram Moolenaar51156d52006-01-26 22:17:47 +0000418 " indent: 0
419 " keywords: "end" + "architecture", "configuration", "entity", "package"
420 " where: start of current line
421 if curs =~? '^\s*end\s\+\%(architecture\|configuration\|entity\|package\)\>'
422 return 0
423 endif
424
425 " indent: -sw
426 " keywords: "end" + identifier
427 " where: start of current line
428 if curs =~? '^\s*end\s\+\w\+\>'
429 return ind - &sw
430 endif
431
432 " ****************************************************************************************
Bram Moolenaar280f1262006-01-30 00:14:18 +0000433 " indent: maintain indent of previous opening statement
Bram Moolenaar51156d52006-01-26 22:17:47 +0000434 " keywords: without "generic", "map", "port" + ":" but not ":=" + "in", "out", "inout", "buffer", "linkage", variable & ":="
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000435 " where: start of current line
436 if curs =~? '^\s*\%(\<\%(generic\|map\|port\)\>.*\)\@<!\S\+\s*:[^=]\@=\s*\%(\%(in\|out\|inout\|buffer\|linkage\)\>\|\w\+\s\+:=\)'
Bram Moolenaar51156d52006-01-26 22:17:47 +0000437 return ind2
438 endif
439
440 " return leftover filtered indent
441 return ind
442endfunction