blob: 717857fe3d207e837a3a97d2ef7db9c9f6bf82e1 [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 Moolenaar9028b102010-07-11 16:58:51 +02004" Version: 1.56
5" Last Change: 2010 Jun 29
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
98 " keywords: "generic", "map", "port" + "(", provided current line is part of mapping
99 " 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 Moolenaarb8a7b562006-02-01 21:47:16 +0000107 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 +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 Moolenaar51156d52006-01-26 22:17:47 +0000163 " keywords: "generic", "map", "port"
164 " 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 Moolenaar51156d52006-01-26 22:17:47 +0000168 if ps =~? s:NC.'\<\%(generic\|map\|port\)\>' || ps =~ '^\s*('
169 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\>'
210 let ind = ind - &sw
211 " find previous opening statement of
212 " keywords: "architecture", "block", "entity", "function", "generate", "procedure", "process"
213 let s2 = s:NC.s:NE.'\<\%(architecture\|block\|entity\|function\|generate\|procedure\|process\)\>'
Bram Moolenaar9964e462007-05-05 17:54:07 +0000214 if (curs !~? s2.'.*'.s:NC.'\<begin\>.*'.s:ES && prevs =~? s2) || m == 1
Bram Moolenaar51156d52006-01-26 22:17:47 +0000215 let ind = ind + &sw
216 endif
217 return ind
218 endif
219
220 " indent: +sw if previous line is previous opening statement
221 " keywords: "record", "units"
222 " where: anywhere in current line
223 if curs =~? s:NC.s:NE.'\<\%(record\|units\)\>'
224 " find previous opening statement of
225 " keyword: "type"
226 let s3 = s:NC.s:NE.'\<type\>'
227 if curs !~? s3.'.*'.s:NC.'\<\%(record\|units\)\>.*'.s:ES && prevs =~? s3
228 let ind = ind + &sw
229 endif
230 return ind
231 endif
232
233 " ****************************************************************************************
234 " indent: 0
235 " keywords: "architecture", "configuration", "entity", "library", "package"
236 " where: start of current line
237 if curs =~? '^\s*\%(architecture\|configuration\|entity\|library\|package\)\>'
238 return 0
239 endif
240
Bram Moolenaar280f1262006-01-30 00:14:18 +0000241 " indent: maintain indent of previous opening statement
Bram Moolenaar51156d52006-01-26 22:17:47 +0000242 " keyword: "is"
243 " where: start of current line
244 " find previous opening statement of
245 " keywords: "architecture", "block", "configuration", "entity", "function", "package", "procedure", "process", "type"
246 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 +0000247 return ind2
Bram Moolenaar51156d52006-01-26 22:17:47 +0000248 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: "then"
252 " where: start of current line
253 " find previous opening statement of
254 " keywords: "elsif", "if"
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000255 if curs =~? '^\s*\<then\>' && prevs =~? s:NC.'\%(\<elsif\>\|'.s:NE.'\<if\>\)'
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: "generate"
261 " where: start of current line
262 " find previous opening statement of
263 " keywords: "for", "if"
Bram Moolenaar9964e462007-05-05 17:54:07 +0000264 if curs =~? '^\s*\<generate\>' && prevs =~? s:NC.s:NE.'\%(\%(\<wait\s\+\)\@<!\<for\|\<if\)\>'
Bram Moolenaar280f1262006-01-30 00:14:18 +0000265 return ind2
Bram Moolenaar51156d52006-01-26 22:17:47 +0000266 endif
267
268 " indent: +sw
Bram Moolenaar9964e462007-05-05 17:54:07 +0000269 " keywords: "block", "process"
270 " removed: "begin", "case", "elsif", "if", "loop", "record", "units", "while"
Bram Moolenaar51156d52006-01-26 22:17:47 +0000271 " where: anywhere in previous line
Bram Moolenaar9964e462007-05-05 17:54:07 +0000272 if prevs =~? s:NC.s:NE.'\<\%(block\|process\)\>'
Bram Moolenaar51156d52006-01-26 22:17:47 +0000273 return ind + &sw
274 endif
275
276 " indent: +sw
Bram Moolenaar9964e462007-05-05 17:54:07 +0000277 " keywords: "architecture", "configuration", "entity", "package"
278 " removed: "component", "for", "when", "with"
Bram Moolenaar51156d52006-01-26 22:17:47 +0000279 " where: start of previous line
Bram Moolenaar9964e462007-05-05 17:54:07 +0000280 if prevs =~? '^\s*\%(architecture\|configuration\|entity\|package\)\>'
Bram Moolenaar51156d52006-01-26 22:17:47 +0000281 return ind + &sw
282 endif
283
284 " indent: +sw
Bram Moolenaar9964e462007-05-05 17:54:07 +0000285 " keyword: "select"
286 " removed: "generate", "is", "=>"
Bram Moolenaar51156d52006-01-26 22:17:47 +0000287 " where: end of previous line
Bram Moolenaar9964e462007-05-05 17:54:07 +0000288 if prevs =~? s:NC.'\<select'.s:ES
Bram Moolenaar51156d52006-01-26 22:17:47 +0000289 return ind + &sw
290 endif
291
292 " indent: +sw
Bram Moolenaar9964e462007-05-05 17:54:07 +0000293 " keyword: "begin", "loop", "record", "units"
294 " where: anywhere in previous line
295 " keyword: "component", "else", "for"
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000296 " where: start of previous line
Bram Moolenaar9964e462007-05-05 17:54:07 +0000297 " keyword: "generate", "is", "then", "=>"
Bram Moolenaar51156d52006-01-26 22:17:47 +0000298 " where: end of previous line
299 " _note_: indent allowed to leave this filter
Bram Moolenaar9964e462007-05-05 17:54:07 +0000300 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 +0000301 let ind = ind + &sw
302 endif
303
304 " ****************************************************************************************
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000305 " indent: -sw
Bram Moolenaar9964e462007-05-05 17:54:07 +0000306 " keywords: "when", provided previous line does not begin with "when", does not end with "is"
Bram Moolenaar51156d52006-01-26 22:17:47 +0000307 " where: start of current line
308 let s4 = '^\s*when\>'
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000309 if curs =~? s4
Bram Moolenaar9964e462007-05-05 17:54:07 +0000310 if prevs =~? s:NC.'\<is'.s:ES
311 return ind
312 elseif prevs !~? s4
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000313 return ind - &sw
314 else
315 return ind2
316 endif
Bram Moolenaar51156d52006-01-26 22:17:47 +0000317 endif
318
319 " indent: -sw
Bram Moolenaar9964e462007-05-05 17:54:07 +0000320 " keywords: "else", "elsif", "end" + "block", "for", "function", "generate", "if", "loop", "procedure", "process", "record", "units"
Bram Moolenaar51156d52006-01-26 22:17:47 +0000321 " where: start of current line
Bram Moolenaar9964e462007-05-05 17:54:07 +0000322 if curs =~? '^\s*\%(else\|elsif\|end\s\+\%(block\|for\|function\|generate\|if\|loop\|procedure\|process\|record\|units\)\)\>'
Bram Moolenaar51156d52006-01-26 22:17:47 +0000323 return ind - &sw
324 endif
325
Bram Moolenaar280f1262006-01-30 00:14:18 +0000326 " indent: backtrace previous non-comment lines
327 " keyword: "end" + "case", "component"
Bram Moolenaar51156d52006-01-26 22:17:47 +0000328 " where: start of current line
Bram Moolenaar280f1262006-01-30 00:14:18 +0000329 let m = 0
Bram Moolenaar51156d52006-01-26 22:17:47 +0000330 if curs =~? '^\s*end\s\+case\>'
Bram Moolenaar280f1262006-01-30 00:14:18 +0000331 let m = 1
332 elseif curs =~? '^\s*end\s\+component\>'
333 let m = 2
334 endif
335
336 if m > 0
Bram Moolenaar51156d52006-01-26 22:17:47 +0000337 " find following previous non-comment line
338 let pn = prevn
339 let ps = getline(pn)
340 while pn > 0
341 if ps !~ '^\s*--'
Bram Moolenaar280f1262006-01-30 00:14:18 +0000342 "indent: -2sw
343 "keywords: "end" + "case"
344 "where: start of previous non-comment line
345 "indent: -sw
346 "keywords: "when"
347 "where: start of previous non-comment line
348 "indent: follow
349 "keywords: "case"
350 "where: start of previous non-comment line
351 if m == 1
352 if ps =~? '^\s*end\s\+case\>'
353 return indent(pn) - 2 * &sw
354 elseif ps =~? '^\s*when\>'
355 return indent(pn) - &sw
356 elseif ps =~? '^\s*case\>'
357 return indent(pn)
358 endif
359 "indent: follow
360 "keyword: "component"
Bram Moolenaar9964e462007-05-05 17:54:07 +0000361 "where: start of previous non-comment line
Bram Moolenaar280f1262006-01-30 00:14:18 +0000362 elseif m == 2
Bram Moolenaar9964e462007-05-05 17:54:07 +0000363 if ps =~? '^\s*component\>'
Bram Moolenaar280f1262006-01-30 00:14:18 +0000364 return indent(pn)
365 endif
Bram Moolenaar51156d52006-01-26 22:17:47 +0000366 endif
367 endif
368 let pn = prevnonblank(pn - 1)
369 let ps = getline(pn)
370 endwhile
Bram Moolenaar280f1262006-01-30 00:14:18 +0000371 return ind - &sw
Bram Moolenaar51156d52006-01-26 22:17:47 +0000372 endif
373
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000374 " indent: -sw
375 " keyword: ")"
376 " where: start of current line
377 if curs =~ '^\s*)'
378 return ind - &sw
379 endif
380
Bram Moolenaar51156d52006-01-26 22:17:47 +0000381 " indent: 0
382 " keywords: "end" + "architecture", "configuration", "entity", "package"
383 " where: start of current line
384 if curs =~? '^\s*end\s\+\%(architecture\|configuration\|entity\|package\)\>'
385 return 0
386 endif
387
388 " indent: -sw
Bram Moolenaar9028b102010-07-11 16:58:51 +0200389 " keywords: "end" + identifier, ";"
Bram Moolenaar51156d52006-01-26 22:17:47 +0000390 " where: start of current line
Bram Moolenaar9964e462007-05-05 17:54:07 +0000391 "if curs =~? '^\s*end\s\+\w\+\>'
Bram Moolenaar9028b102010-07-11 16:58:51 +0200392 if curs =~? '^\s*end\%(\s\|;'.s:ES.'\)'
Bram Moolenaar51156d52006-01-26 22:17:47 +0000393 return ind - &sw
394 endif
395
396 " ****************************************************************************************
Bram Moolenaar280f1262006-01-30 00:14:18 +0000397 " indent: maintain indent of previous opening statement
Bram Moolenaar51156d52006-01-26 22:17:47 +0000398 " keywords: without "generic", "map", "port" + ":" but not ":=" + "in", "out", "inout", "buffer", "linkage", variable & ":="
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000399 " where: start of current line
400 if curs =~? '^\s*\%(\<\%(generic\|map\|port\)\>.*\)\@<!\S\+\s*:[^=]\@=\s*\%(\%(in\|out\|inout\|buffer\|linkage\)\>\|\w\+\s\+:=\)'
Bram Moolenaar51156d52006-01-26 22:17:47 +0000401 return ind2
402 endif
403
404 " return leftover filtered indent
405 return ind
406endfunction