blob: 3e847b9575fff79d36d7be950c793c1ca1680526 [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 Moolenaar15146672011-10-20 22:22:38 +02004" Version: 1.58
5" Last Change: 2011 Sep 27
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()
Bram Moolenaar9964e462007-05-05 17:54:07 +000016setlocal indentkeys=!^F,o,O,0(,0)
17setlocal indentkeys+==~begin,=~end\ ,=~end\ ,=~is,=~select,=~when
Bram Moolenaar51156d52006-01-26 22:17:47 +000018setlocal indentkeys+==~if,=~then,=~elsif,=~else
Bram Moolenaar9964e462007-05-05 17:54:07 +000019setlocal indentkeys+==~case,=~loop,=~for,=~generate,=~record,=~units,=~process,=~block,=~function,=~component,=~procedure
20setlocal indentkeys+==~architecture,=~configuration,=~entity,=~package
Bram Moolenaar51156d52006-01-26 22:17:47 +000021
Bram Moolenaar51156d52006-01-26 22:17:47 +000022" constants
23" not a comment
24let s:NC = '\%(--.*\)\@<!'
25" end of string
26let s:ES = '\s*\%(--.*\)\=$'
27" no "end" keyword in front
28let s:NE = '\%(\<end\s\+\)\@<!'
29
Bram Moolenaar9964e462007-05-05 17:54:07 +000030" option to disable alignment of generic/port mappings
Bram Moolenaara7241f52008-06-24 20:39:31 +000031if !exists("g:vhdl_indent_genportmap")
32 let g:vhdl_indent_genportmap = 1
Bram Moolenaar9964e462007-05-05 17:54:07 +000033endif
34
35" option to disable alignment of right-hand side assignment "<=" statements
Bram Moolenaara7241f52008-06-24 20:39:31 +000036if !exists("g:vhdl_indent_rhsassign")
37 let g:vhdl_indent_rhsassign = 1
Bram Moolenaar9964e462007-05-05 17:54:07 +000038endif
39
Bram Moolenaar51156d52006-01-26 22:17:47 +000040" only define indent function once
41if exists("*GetVHDLindent")
42 finish
43endif
44
45function GetVHDLindent()
46 " store current line & string
47 let curn = v:lnum
48 let curs = getline(curn)
49
50 " find previous line that is not a comment
51 let prevn = prevnonblank(curn - 1)
52 let prevs = getline(prevn)
53 while prevn > 0 && prevs =~ '^\s*--'
54 let prevn = prevnonblank(prevn - 1)
55 let prevs = getline(prevn)
56 endwhile
Bram Moolenaara7241f52008-06-24 20:39:31 +000057 let prevs_noi = substitute(prevs, '^\s*', '', '')
Bram Moolenaar51156d52006-01-26 22:17:47 +000058
59 " default indent starts as previous non-comment line's indent
60 let ind = prevn > 0 ? indent(prevn) : 0
61 " backup default
62 let ind2 = ind
63
Bram Moolenaar280f1262006-01-30 00:14:18 +000064 " indent: special; kill string so it would not affect other filters
65 " keywords: "report" + string
66 " where: anywhere in current or previous line
67 let s0 = s:NC.'\<report\>\s*".*"'
68 if curs =~? s0
69 let curs = ""
70 endif
71 if prevs =~? s0
72 let prevs = ""
73 endif
74
Bram Moolenaar51156d52006-01-26 22:17:47 +000075 " indent: previous line's comment position, otherwise follow next non-comment line if possible
76 " keyword: "--"
77 " where: start of current line
78 if curs =~ '^\s*--'
79 let pn = curn - 1
80 let ps = getline(pn)
Bram Moolenaara7241f52008-06-24 20:39:31 +000081 if curs =~ '^\s*--\s' && ps =~ '--'
82 return indent(pn) + stridx(substitute(ps, '^\s*', '', ''), '--')
Bram Moolenaar51156d52006-01-26 22:17:47 +000083 else
84 " find nextnonblank line that is not a comment
85 let nn = nextnonblank(curn + 1)
86 let ns = getline(nn)
87 while nn > 0 && ns =~ '^\s*--'
88 let nn = nextnonblank(nn + 1)
89 let ns = getline(nn)
90 endwhile
91 let n = indent(nn)
92 return n != -1 ? n : ind
93 endif
94 endif
95
96 " ****************************************************************************************
97 " indent: align generic variables & port names
Bram Moolenaar15146672011-10-20 22:22:38 +020098 " keywords: "procedure" + name, "generic", "map", "port" + "(", provided current line is part of mapping
Bram Moolenaar51156d52006-01-26 22:17:47 +000099 " where: anywhere in previous 2 lines
100 " find following previous non-comment line
101 let pn = prevnonblank(prevn - 1)
102 let ps = getline(pn)
103 while pn > 0 && ps =~ '^\s*--'
104 let pn = prevnonblank(pn - 1)
105 let ps = getline(pn)
106 endwhile
Bram Moolenaar15146672011-10-20 22:22:38 +0200107 if (curs =~ '^\s*)' || curs =~? '^\s*\%(\<\%(procedure\|generic\|map\|port\)\>.*\)\@<!\w\+\s*\w*\s*\%(=>\s*\S\+\|:[^=]\@=\s*\%(\%(in\|out\|inout\|buffer\|linkage\)\>\|\w\+\s\+:=\)\)') && (prevs =~? s:NC.'\<\%(procedure\s\+\S\+\|generic\|map\|port\)\s*(\%(\s*\w\)\=' || (ps =~? s:NC.'\<\%(procedure\|generic\|map\|port\)'.s:ES && prevs =~ '^\s*('))
Bram Moolenaar51156d52006-01-26 22:17:47 +0000108 " align closing ")" with opening "("
109 if curs =~ '^\s*)'
Bram Moolenaara7241f52008-06-24 20:39:31 +0000110 return ind2 + stridx(prevs_noi, '(')
Bram Moolenaar51156d52006-01-26 22:17:47 +0000111 endif
Bram Moolenaara7241f52008-06-24 20:39:31 +0000112 let m = matchend(prevs_noi, '(\s*\ze\w')
Bram Moolenaar51156d52006-01-26 22:17:47 +0000113 if m != -1
Bram Moolenaara7241f52008-06-24 20:39:31 +0000114 return ind2 + m
Bram Moolenaar51156d52006-01-26 22:17:47 +0000115 else
Bram Moolenaara7241f52008-06-24 20:39:31 +0000116 if g:vhdl_indent_genportmap
117 return ind2 + stridx(prevs_noi, '(') + &sw
Bram Moolenaar9964e462007-05-05 17:54:07 +0000118 else
119 return ind2 + &sw
120 endif
Bram Moolenaar51156d52006-01-26 22:17:47 +0000121 endif
122 endif
123
124 " indent: align conditional/select statement
Bram Moolenaar280f1262006-01-30 00:14:18 +0000125 " keywords: variable + "<=" without ";" ending
126 " where: start of previous line
127 if prevs =~? '^\s*\S\+\s*<=[^;]*'.s:ES
Bram Moolenaara7241f52008-06-24 20:39:31 +0000128 if g:vhdl_indent_rhsassign
129 return ind2 + matchend(prevs_noi, '<=\s*\ze.')
Bram Moolenaar9964e462007-05-05 17:54:07 +0000130 else
131 return ind2 + &sw
132 endif
Bram Moolenaar51156d52006-01-26 22:17:47 +0000133 endif
134
135 " indent: backtrace previous non-comment lines for next smaller or equal size indent
136 " keywords: "end" + "record", "units"
137 " where: start of previous line
138 " keyword: ")"
139 " where: start of previous line
140 " keyword: without "<=" + ";" ending
141 " where: anywhere in previous line
142 " keyword: "=>" + ")" ending, provided current line does not begin with ")"
143 " where: anywhere in previous line
144 " _note_: indent allowed to leave this filter
145 let m = 0
146 if prevs =~? '^\s*end\s\+\%(record\|units\)\>'
147 let m = 3
148 elseif prevs =~ '^\s*)'
149 let m = 1
150 elseif prevs =~ s:NC.'\%(<=.*\)\@<!;'.s:ES || (curs !~ '^\s*)' && prevs =~ s:NC.'=>.*'.s:NC.')'.s:ES)
151 let m = 2
152 endif
153
154 if m > 0
155 let pn = prevnonblank(prevn - 1)
156 let ps = getline(pn)
157 while pn > 0
158 let t = indent(pn)
Bram Moolenaarb2c03502010-07-02 20:20:09 +0200159 if ps !~ '^\s*--' && (t < ind || (t == ind && m == 3))
Bram Moolenaar51156d52006-01-26 22:17:47 +0000160 " make sure one of these is true
Bram Moolenaar280f1262006-01-30 00:14:18 +0000161 " keywords: variable + "<=" without ";" ending
162 " where: start of previous non-comment line
Bram Moolenaar15146672011-10-20 22:22:38 +0200163 " keywords: "procedure", "generic", "map", "port"
Bram Moolenaar51156d52006-01-26 22:17:47 +0000164 " where: anywhere in previous non-comment line
165 " keyword: "("
166 " where: start of previous non-comment line
Bram Moolenaar280f1262006-01-30 00:14:18 +0000167 if m < 3 && ps !~? '^\s*\S\+\s*<=[^;]*'.s:ES
Bram Moolenaar15146672011-10-20 22:22:38 +0200168 if ps =~? s:NC.'\<\%(procedure\|generic\|map\|port\)\>' || ps =~ '^\s*('
Bram Moolenaar51156d52006-01-26 22:17:47 +0000169 let ind = t
170 endif
171 break
172 endif
173 let ind = t
174 if m > 1
175 " find following previous non-comment line
176 let ppn = prevnonblank(pn - 1)
177 let pps = getline(ppn)
178 while ppn > 0 && pps =~ '^\s*--'
179 let ppn = prevnonblank(ppn - 1)
180 let pps = getline(ppn)
181 endwhile
182 " indent: follow
183 " keyword: "select"
184 " where: end of following previous non-comment line
185 " keyword: "type"
186 " where: start of following previous non-comment line
187 if m == 2
188 let s1 = s:NC.'\<select'.s:ES
189 if ps !~? s1 && pps =~? s1
190 let ind = indent(ppn)
191 endif
192 elseif m == 3
193 let s1 = '^\s*type\>'
194 if ps !~? s1 && pps =~? s1
195 let ind = indent(ppn)
196 endif
197 endif
198 endif
199 break
200 endif
201 let pn = prevnonblank(pn - 1)
202 let ps = getline(pn)
203 endwhile
204 endif
205
206 " indent: follow indent of previous opening statement, otherwise -sw
207 " keyword: "begin"
208 " where: anywhere in current line
209 if curs =~? s:NC.'\<begin\>'
Bram Moolenaar51156d52006-01-26 22:17:47 +0000210 " find previous opening statement of
211 " keywords: "architecture", "block", "entity", "function", "generate", "procedure", "process"
212 let s2 = s:NC.s:NE.'\<\%(architecture\|block\|entity\|function\|generate\|procedure\|process\)\>'
Bram Moolenaar15146672011-10-20 22:22:38 +0200213
214 let pn = prevnonblank(curn - 1)
215 let ps = getline(pn)
216 while pn > 0 && (ps =~ '^\s*--' || ps !~? s2)
217 let pn = prevnonblank(pn - 1)
218 let ps = getline(pn)
219
220 if (ps =~? s:NC.'\<begin\>')
221 return indent(pn) - &sw
222 endif
223 endwhile
224
225 if (pn == 0)
226 return ind - &sw
227 else
228 return indent(pn)
Bram Moolenaar51156d52006-01-26 22:17:47 +0000229 endif
Bram Moolenaar51156d52006-01-26 22:17:47 +0000230 endif
231
232 " indent: +sw if previous line is previous opening statement
233 " keywords: "record", "units"
234 " where: anywhere in current line
235 if curs =~? s:NC.s:NE.'\<\%(record\|units\)\>'
236 " find previous opening statement of
237 " keyword: "type"
238 let s3 = s:NC.s:NE.'\<type\>'
239 if curs !~? s3.'.*'.s:NC.'\<\%(record\|units\)\>.*'.s:ES && prevs =~? s3
240 let ind = ind + &sw
241 endif
242 return ind
243 endif
244
245 " ****************************************************************************************
246 " indent: 0
247 " keywords: "architecture", "configuration", "entity", "library", "package"
248 " where: start of current line
249 if curs =~? '^\s*\%(architecture\|configuration\|entity\|library\|package\)\>'
250 return 0
251 endif
252
Bram Moolenaar280f1262006-01-30 00:14:18 +0000253 " indent: maintain indent of previous opening statement
Bram Moolenaar51156d52006-01-26 22:17:47 +0000254 " keyword: "is"
255 " where: start of current line
256 " find previous opening statement of
257 " keywords: "architecture", "block", "configuration", "entity", "function", "package", "procedure", "process", "type"
258 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 +0000259 return ind2
Bram Moolenaar51156d52006-01-26 22:17:47 +0000260 endif
261
Bram Moolenaar280f1262006-01-30 00:14:18 +0000262 " indent: maintain indent of previous opening statement
Bram Moolenaar51156d52006-01-26 22:17:47 +0000263 " keyword: "then"
264 " where: start of current line
265 " find previous opening statement of
266 " keywords: "elsif", "if"
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000267 if curs =~? '^\s*\<then\>' && prevs =~? s:NC.'\%(\<elsif\>\|'.s:NE.'\<if\>\)'
Bram Moolenaar280f1262006-01-30 00:14:18 +0000268 return ind2
Bram Moolenaar51156d52006-01-26 22:17:47 +0000269 endif
270
Bram Moolenaar280f1262006-01-30 00:14:18 +0000271 " indent: maintain indent of previous opening statement
Bram Moolenaar51156d52006-01-26 22:17:47 +0000272 " keyword: "generate"
273 " where: start of current line
274 " find previous opening statement of
275 " keywords: "for", "if"
Bram Moolenaar9964e462007-05-05 17:54:07 +0000276 if curs =~? '^\s*\<generate\>' && prevs =~? s:NC.s:NE.'\%(\%(\<wait\s\+\)\@<!\<for\|\<if\)\>'
Bram Moolenaar280f1262006-01-30 00:14:18 +0000277 return ind2
Bram Moolenaar51156d52006-01-26 22:17:47 +0000278 endif
279
280 " indent: +sw
Bram Moolenaar9964e462007-05-05 17:54:07 +0000281 " keywords: "block", "process"
282 " removed: "begin", "case", "elsif", "if", "loop", "record", "units", "while"
Bram Moolenaar51156d52006-01-26 22:17:47 +0000283 " where: anywhere in previous line
Bram Moolenaar9964e462007-05-05 17:54:07 +0000284 if prevs =~? s:NC.s:NE.'\<\%(block\|process\)\>'
Bram Moolenaar51156d52006-01-26 22:17:47 +0000285 return ind + &sw
286 endif
287
288 " indent: +sw
Bram Moolenaar9964e462007-05-05 17:54:07 +0000289 " keywords: "architecture", "configuration", "entity", "package"
290 " removed: "component", "for", "when", "with"
Bram Moolenaar51156d52006-01-26 22:17:47 +0000291 " where: start of previous line
Bram Moolenaar9964e462007-05-05 17:54:07 +0000292 if prevs =~? '^\s*\%(architecture\|configuration\|entity\|package\)\>'
Bram Moolenaar51156d52006-01-26 22:17:47 +0000293 return ind + &sw
294 endif
295
296 " indent: +sw
Bram Moolenaar9964e462007-05-05 17:54:07 +0000297 " keyword: "select"
298 " removed: "generate", "is", "=>"
Bram Moolenaar51156d52006-01-26 22:17:47 +0000299 " where: end of previous line
Bram Moolenaar9964e462007-05-05 17:54:07 +0000300 if prevs =~? s:NC.'\<select'.s:ES
Bram Moolenaar51156d52006-01-26 22:17:47 +0000301 return ind + &sw
302 endif
303
304 " indent: +sw
Bram Moolenaar9964e462007-05-05 17:54:07 +0000305 " keyword: "begin", "loop", "record", "units"
306 " where: anywhere in previous line
307 " keyword: "component", "else", "for"
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000308 " where: start of previous line
Bram Moolenaar9964e462007-05-05 17:54:07 +0000309 " keyword: "generate", "is", "then", "=>"
Bram Moolenaar51156d52006-01-26 22:17:47 +0000310 " where: end of previous line
311 " _note_: indent allowed to leave this filter
Bram Moolenaar9964e462007-05-05 17:54:07 +0000312 if prevs =~? s:NC.'\%(\<begin\>\|'.s:NE.'\<\%(loop\|record\|units\)\>\)' || prevs =~? '^\s*\%(component\|else\|for\)\>' || prevs =~? s:NC.'\%('.s:NE.'\<generate\|\<\%(is\|then\)\|=>\)'.s:ES
Bram Moolenaar51156d52006-01-26 22:17:47 +0000313 let ind = ind + &sw
314 endif
315
316 " ****************************************************************************************
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000317 " indent: -sw
Bram Moolenaar9964e462007-05-05 17:54:07 +0000318 " keywords: "when", provided previous line does not begin with "when", does not end with "is"
Bram Moolenaar51156d52006-01-26 22:17:47 +0000319 " where: start of current line
320 let s4 = '^\s*when\>'
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000321 if curs =~? s4
Bram Moolenaar9964e462007-05-05 17:54:07 +0000322 if prevs =~? s:NC.'\<is'.s:ES
323 return ind
324 elseif prevs !~? s4
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000325 return ind - &sw
326 else
327 return ind2
328 endif
Bram Moolenaar51156d52006-01-26 22:17:47 +0000329 endif
330
331 " indent: -sw
Bram Moolenaar9964e462007-05-05 17:54:07 +0000332 " keywords: "else", "elsif", "end" + "block", "for", "function", "generate", "if", "loop", "procedure", "process", "record", "units"
Bram Moolenaar51156d52006-01-26 22:17:47 +0000333 " where: start of current line
Bram Moolenaar15146672011-10-20 22:22:38 +0200334 let s5 = 'block\|for\|function\|generate\|if\|loop\|procedure\|process\|record\|units'
335 if curs =~? '^\s*\%(else\|elsif\|end\s\+\%('.s5.'\)\)\>'
336 if prevs =~? '^\s*\%(elsif\|'.s5.'\)'
337 return ind
338 else
339 return ind - &sw
340 endif
Bram Moolenaar51156d52006-01-26 22:17:47 +0000341 endif
342
Bram Moolenaar280f1262006-01-30 00:14:18 +0000343 " indent: backtrace previous non-comment lines
344 " keyword: "end" + "case", "component"
Bram Moolenaar51156d52006-01-26 22:17:47 +0000345 " where: start of current line
Bram Moolenaar280f1262006-01-30 00:14:18 +0000346 let m = 0
Bram Moolenaar51156d52006-01-26 22:17:47 +0000347 if curs =~? '^\s*end\s\+case\>'
Bram Moolenaar280f1262006-01-30 00:14:18 +0000348 let m = 1
349 elseif curs =~? '^\s*end\s\+component\>'
350 let m = 2
351 endif
352
353 if m > 0
Bram Moolenaar51156d52006-01-26 22:17:47 +0000354 " find following previous non-comment line
355 let pn = prevn
356 let ps = getline(pn)
357 while pn > 0
358 if ps !~ '^\s*--'
Bram Moolenaar280f1262006-01-30 00:14:18 +0000359 "indent: -2sw
360 "keywords: "end" + "case"
361 "where: start of previous non-comment line
362 "indent: -sw
363 "keywords: "when"
364 "where: start of previous non-comment line
365 "indent: follow
366 "keywords: "case"
367 "where: start of previous non-comment line
368 if m == 1
369 if ps =~? '^\s*end\s\+case\>'
370 return indent(pn) - 2 * &sw
371 elseif ps =~? '^\s*when\>'
372 return indent(pn) - &sw
373 elseif ps =~? '^\s*case\>'
374 return indent(pn)
375 endif
376 "indent: follow
377 "keyword: "component"
Bram Moolenaar9964e462007-05-05 17:54:07 +0000378 "where: start of previous non-comment line
Bram Moolenaar280f1262006-01-30 00:14:18 +0000379 elseif m == 2
Bram Moolenaar9964e462007-05-05 17:54:07 +0000380 if ps =~? '^\s*component\>'
Bram Moolenaar280f1262006-01-30 00:14:18 +0000381 return indent(pn)
382 endif
Bram Moolenaar51156d52006-01-26 22:17:47 +0000383 endif
384 endif
385 let pn = prevnonblank(pn - 1)
386 let ps = getline(pn)
387 endwhile
Bram Moolenaar280f1262006-01-30 00:14:18 +0000388 return ind - &sw
Bram Moolenaar51156d52006-01-26 22:17:47 +0000389 endif
390
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000391 " indent: -sw
392 " keyword: ")"
393 " where: start of current line
394 if curs =~ '^\s*)'
395 return ind - &sw
396 endif
397
Bram Moolenaar51156d52006-01-26 22:17:47 +0000398 " indent: 0
399 " keywords: "end" + "architecture", "configuration", "entity", "package"
400 " where: start of current line
401 if curs =~? '^\s*end\s\+\%(architecture\|configuration\|entity\|package\)\>'
402 return 0
403 endif
404
405 " indent: -sw
Bram Moolenaar9028b102010-07-11 16:58:51 +0200406 " keywords: "end" + identifier, ";"
Bram Moolenaar51156d52006-01-26 22:17:47 +0000407 " where: start of current line
Bram Moolenaar9964e462007-05-05 17:54:07 +0000408 "if curs =~? '^\s*end\s\+\w\+\>'
Bram Moolenaar9028b102010-07-11 16:58:51 +0200409 if curs =~? '^\s*end\%(\s\|;'.s:ES.'\)'
Bram Moolenaar51156d52006-01-26 22:17:47 +0000410 return ind - &sw
411 endif
412
413 " ****************************************************************************************
Bram Moolenaar280f1262006-01-30 00:14:18 +0000414 " indent: maintain indent of previous opening statement
Bram Moolenaar15146672011-10-20 22:22:38 +0200415 " keywords: without "procedure", "generic", "map", "port" + ":" but not ":=" + "in", "out", "inout", "buffer", "linkage", variable & ":="
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000416 " where: start of current line
Bram Moolenaar15146672011-10-20 22:22:38 +0200417 if curs =~? '^\s*\%(\<\%(procedure\|generic\|map\|port\)\>.*\)\@<!\w\+\s*\w*\s*:[^=]\@=\s*\%(\%(in\|out\|inout\|buffer\|linkage\)\>\|\w\+\s\+:=\)'
Bram Moolenaar51156d52006-01-26 22:17:47 +0000418 return ind2
419 endif
420
421 " return leftover filtered indent
422 return ind
423endfunction