blob: 8176673a812c1e7a569daf345692c00490e33a76 [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 Moolenaar7fc904b2006-04-13 20:37:35 +00004" Version: 1.36
5" Last Change: 2006 Apr 12
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
Bram Moolenaar7fc904b2006-04-13 20:37:35 +000018setlocal indentkeys+==~begin,=~is,=~select
Bram Moolenaar51156d52006-01-26 22:17:47 +000019
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000020" count repeat
Bram Moolenaar7fc904b2006-04-13 20:37:35 +000021"function! <SID>CountWrapper(cmd)
22" let i = v:count1
23" if a:cmd[0] == ":"
24" while i > 0
25" execute a:cmd
26" let i = i - 1
27" endwhile
28" else
29" execute "normal! gv\<Esc>"
30" execute "normal ".i.a:cmd
31" let curcol = col(".")
32" let curline = line(".")
33" normal! gv
34" call cursor(curline, curcol)
35" endif
36"endfunction
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000037
38" explore motion
Bram Moolenaar51156d52006-01-26 22:17:47 +000039" keywords: "architecture", "block", "configuration", "component", "entity", "function", "package", "procedure", "process", "record", "units"
Bram Moolenaar7fc904b2006-04-13 20:37:35 +000040"let b:vhdl_explore = '\%(architecture\|block\|configuration\|component\|entity\|function\|package\|procedure\|process\|record\|units\)'
41"noremap <buffer><silent>[[ :<C-u>cal <SID>CountWrapper(':cal search("\\%(--.*\\)\\@<!\\%(\\<end\\s\\+\\)\\@<!\\<".b:vhdl_explore."\\>\\c\\<Bar>\\%^","bW")')<CR>
42"noremap <buffer><silent>]] :<C-u>cal <SID>CountWrapper(':cal search("\\%(--.*\\)\\@<!\\%(\\<end\\s\\+\\)\\@<!\\<".b:vhdl_explore."\\>\\c\\<Bar>\\%$","W")')<CR>
43"noremap <buffer><silent>[] :<C-u>cal <SID>CountWrapper(':cal search("\\%(--.*\\)\\@<!\\<end\\s\\+".b:vhdl_explore."\\>\\c\\<Bar>\\%^","bW")')<CR>
44"noremap <buffer><silent>][ :<C-u>cal <SID>CountWrapper(':cal search("\\%(--.*\\)\\@<!\\<end\\s\\+".b:vhdl_explore."\\>\\c\\<Bar>\\%$","W")')<CR>
45"vnoremap <buffer><silent>[[ :<C-u>cal <SID>CountWrapper('[[')<CR>
46"vnoremap <buffer><silent>]] :<C-u>cal <SID>CountWrapper(']]')<CR>
47"vnoremap <buffer><silent>[] :<C-u>cal <SID>CountWrapper('[]')<CR>
48"vnoremap <buffer><silent>][ :<C-u>cal <SID>CountWrapper('][')<CR>
Bram Moolenaar51156d52006-01-26 22:17:47 +000049
50" constants
51" not a comment
52let s:NC = '\%(--.*\)\@<!'
53" end of string
54let s:ES = '\s*\%(--.*\)\=$'
55" no "end" keyword in front
56let s:NE = '\%(\<end\s\+\)\@<!'
57
58" for matchit plugin
Bram Moolenaar7fc904b2006-04-13 20:37:35 +000059"if exists("loaded_matchit")
60" let b:match_ignorecase = 1
61" let b:match_words =
62" \ s:NE.'\<if\>:\<elsif\>:\<else\>:\<end\s\+if\>,'.
63" \ s:NE.'\<case\>:\<when\>:\<end\s\+case\>,'.
64" \ s:NE.'\<loop\>:\<end\s\+loop\>,'.
65" \ s:NE.'\<for\>:\<end\s\+for\>,'.
66" \ s:NE.'\<generate\>:\<end\s\+generate\>,'.
67" \ s:NE.'\<record\>:\<end\s\+record\>,'.
68" \ s:NE.'\<units\>:\<end\s\+units\>,'.
69" \ s:NE.'\<process\>:\<end\s\+process\>,'.
70" \ s:NE.'\<block\>:\<end\s\+block\>,'.
71" \ s:NE.'\<function\>:\<end\s\+function\>,'.
72" \ s:NE.'\<entity\>:\<end\s\+entity\>,'.
73" \ s:NE.'\<component\>:\<end\s\+component\>,'.
74" \ s:NE.'\<architecture\>:\<end\s\+architecture\>,'.
75" \ s:NE.'\<package\>:\<end\s\+package\>,'.
76" \ s:NE.'\<procedure\>:\<end\s\+procedure\>,'.
77" \ s:NE.'\<configuration\>:\<end\s\+configuration\>'
78"endif
Bram Moolenaar51156d52006-01-26 22:17:47 +000079
80" only define indent function once
81if exists("*GetVHDLindent")
82 finish
83endif
84
85function GetVHDLindent()
86 " store current line & string
87 let curn = v:lnum
88 let curs = getline(curn)
89
90 " find previous line that is not a comment
91 let prevn = prevnonblank(curn - 1)
92 let prevs = getline(prevn)
93 while prevn > 0 && prevs =~ '^\s*--'
94 let prevn = prevnonblank(prevn - 1)
95 let prevs = getline(prevn)
96 endwhile
97
98 " default indent starts as previous non-comment line's indent
99 let ind = prevn > 0 ? indent(prevn) : 0
100 " backup default
101 let ind2 = ind
102
Bram Moolenaar280f1262006-01-30 00:14:18 +0000103 " indent: special; kill string so it would not affect other filters
104 " keywords: "report" + string
105 " where: anywhere in current or previous line
106 let s0 = s:NC.'\<report\>\s*".*"'
107 if curs =~? s0
108 let curs = ""
109 endif
110 if prevs =~? s0
111 let prevs = ""
112 endif
113
Bram Moolenaar51156d52006-01-26 22:17:47 +0000114 " indent: previous line's comment position, otherwise follow next non-comment line if possible
115 " keyword: "--"
116 " where: start of current line
117 if curs =~ '^\s*--'
118 let pn = curn - 1
119 let ps = getline(pn)
120 if ps =~ '--'
121 return stridx(ps, '--')
122 else
123 " find nextnonblank line that is not a comment
124 let nn = nextnonblank(curn + 1)
125 let ns = getline(nn)
126 while nn > 0 && ns =~ '^\s*--'
127 let nn = nextnonblank(nn + 1)
128 let ns = getline(nn)
129 endwhile
130 let n = indent(nn)
131 return n != -1 ? n : ind
132 endif
133 endif
134
135 " ****************************************************************************************
136 " indent: align generic variables & port names
137 " keywords: "generic", "map", "port" + "(", provided current line is part of mapping
138 " where: anywhere in previous 2 lines
139 " find following previous non-comment line
140 let pn = prevnonblank(prevn - 1)
141 let ps = getline(pn)
142 while pn > 0 && ps =~ '^\s*--'
143 let pn = prevnonblank(pn - 1)
144 let ps = getline(pn)
145 endwhile
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000146 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 +0000147 " align closing ")" with opening "("
148 if curs =~ '^\s*)'
149 return stridx(prevs, '(')
150 endif
151 let m = matchend(prevs, '(\s*\ze\w')
152 if m != -1
153 return m
154 else
155 return stridx(prevs, '(') + &sw
156 endif
157 endif
158
159 " indent: align conditional/select statement
Bram Moolenaar280f1262006-01-30 00:14:18 +0000160 " keywords: variable + "<=" without ";" ending
161 " where: start of previous line
162 if prevs =~? '^\s*\S\+\s*<=[^;]*'.s:ES
Bram Moolenaar51156d52006-01-26 22:17:47 +0000163 return matchend(prevs, '<=\s*\ze.')
164 endif
165
166 " indent: backtrace previous non-comment lines for next smaller or equal size indent
167 " keywords: "end" + "record", "units"
168 " where: start of previous line
169 " keyword: ")"
170 " where: start of previous line
171 " keyword: without "<=" + ";" ending
172 " where: anywhere in previous line
173 " keyword: "=>" + ")" ending, provided current line does not begin with ")"
174 " where: anywhere in previous line
175 " _note_: indent allowed to leave this filter
176 let m = 0
177 if prevs =~? '^\s*end\s\+\%(record\|units\)\>'
178 let m = 3
179 elseif prevs =~ '^\s*)'
180 let m = 1
181 elseif prevs =~ s:NC.'\%(<=.*\)\@<!;'.s:ES || (curs !~ '^\s*)' && prevs =~ s:NC.'=>.*'.s:NC.')'.s:ES)
182 let m = 2
183 endif
184
185 if m > 0
186 let pn = prevnonblank(prevn - 1)
187 let ps = getline(pn)
188 while pn > 0
189 let t = indent(pn)
190 if ps !~ '^\s*--' && t < ind
191 " make sure one of these is true
Bram Moolenaar280f1262006-01-30 00:14:18 +0000192 " keywords: variable + "<=" without ";" ending
193 " where: start of previous non-comment line
Bram Moolenaar51156d52006-01-26 22:17:47 +0000194 " keywords: "generic", "map", "port"
195 " where: anywhere in previous non-comment line
196 " keyword: "("
197 " where: start of previous non-comment line
Bram Moolenaar280f1262006-01-30 00:14:18 +0000198 if m < 3 && ps !~? '^\s*\S\+\s*<=[^;]*'.s:ES
Bram Moolenaar51156d52006-01-26 22:17:47 +0000199 if ps =~? s:NC.'\<\%(generic\|map\|port\)\>' || ps =~ '^\s*('
200 let ind = t
201 endif
202 break
203 endif
204 let ind = t
205 if m > 1
206 " find following previous non-comment line
207 let ppn = prevnonblank(pn - 1)
208 let pps = getline(ppn)
209 while ppn > 0 && pps =~ '^\s*--'
210 let ppn = prevnonblank(ppn - 1)
211 let pps = getline(ppn)
212 endwhile
213 " indent: follow
214 " keyword: "select"
215 " where: end of following previous non-comment line
216 " keyword: "type"
217 " where: start of following previous non-comment line
218 if m == 2
219 let s1 = s:NC.'\<select'.s:ES
220 if ps !~? s1 && pps =~? s1
221 let ind = indent(ppn)
222 endif
223 elseif m == 3
224 let s1 = '^\s*type\>'
225 if ps !~? s1 && pps =~? s1
226 let ind = indent(ppn)
227 endif
228 endif
229 endif
230 break
231 endif
232 let pn = prevnonblank(pn - 1)
233 let ps = getline(pn)
234 endwhile
235 endif
236
237 " indent: follow indent of previous opening statement, otherwise -sw
238 " keyword: "begin"
239 " where: anywhere in current line
240 if curs =~? s:NC.'\<begin\>'
241 let ind = ind - &sw
242 " find previous opening statement of
243 " keywords: "architecture", "block", "entity", "function", "generate", "procedure", "process"
244 let s2 = s:NC.s:NE.'\<\%(architecture\|block\|entity\|function\|generate\|procedure\|process\)\>'
245 if curs !~? s2.'.*'.s:NC.'\<begin\>.*'.s:ES && prevs =~? s2
246 let ind = ind + &sw
247 endif
248 return ind
249 endif
250
251 " indent: +sw if previous line is previous opening statement
252 " keywords: "record", "units"
253 " where: anywhere in current line
254 if curs =~? s:NC.s:NE.'\<\%(record\|units\)\>'
255 " find previous opening statement of
256 " keyword: "type"
257 let s3 = s:NC.s:NE.'\<type\>'
258 if curs !~? s3.'.*'.s:NC.'\<\%(record\|units\)\>.*'.s:ES && prevs =~? s3
259 let ind = ind + &sw
260 endif
261 return ind
262 endif
263
264 " ****************************************************************************************
265 " indent: 0
266 " keywords: "architecture", "configuration", "entity", "library", "package"
267 " where: start of current line
268 if curs =~? '^\s*\%(architecture\|configuration\|entity\|library\|package\)\>'
269 return 0
270 endif
271
Bram Moolenaar280f1262006-01-30 00:14:18 +0000272 " indent: maintain indent of previous opening statement
Bram Moolenaar51156d52006-01-26 22:17:47 +0000273 " keyword: "is"
274 " where: start of current line
275 " find previous opening statement of
276 " keywords: "architecture", "block", "configuration", "entity", "function", "package", "procedure", "process", "type"
277 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 +0000278 return ind2
Bram Moolenaar51156d52006-01-26 22:17:47 +0000279 endif
280
Bram Moolenaar280f1262006-01-30 00:14:18 +0000281 " indent: maintain indent of previous opening statement
Bram Moolenaar51156d52006-01-26 22:17:47 +0000282 " keyword: "then"
283 " where: start of current line
284 " find previous opening statement of
285 " keywords: "elsif", "if"
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000286 if curs =~? '^\s*\<then\>' && prevs =~? s:NC.'\%(\<elsif\>\|'.s:NE.'\<if\>\)'
Bram Moolenaar280f1262006-01-30 00:14:18 +0000287 return ind2
Bram Moolenaar51156d52006-01-26 22:17:47 +0000288 endif
289
Bram Moolenaar280f1262006-01-30 00:14:18 +0000290 " indent: maintain indent of previous opening statement
Bram Moolenaar51156d52006-01-26 22:17:47 +0000291 " keyword: "generate"
292 " where: start of current line
293 " find previous opening statement of
294 " keywords: "for", "if"
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000295 if curs =~? '^\s*\<generate\>' && prevs =~? s:NC.s:NE.'\%(\%(\<wait\s\+\)\@<!\<for\>\|\<if\>\)'
Bram Moolenaar280f1262006-01-30 00:14:18 +0000296 return ind2
Bram Moolenaar51156d52006-01-26 22:17:47 +0000297 endif
298
299 " indent: +sw
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000300 " keywords: "begin", "block", "loop", "process", "record", "units"
301 " removed: "case", "elsif", "if", "while"
Bram Moolenaar51156d52006-01-26 22:17:47 +0000302 " where: anywhere in previous line
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000303 if prevs =~? s:NC.'\%(\<begin\>\|'.s:NE.'\<\%(block\|loop\|process\|record\|units\)\>\)'
Bram Moolenaar51156d52006-01-26 22:17:47 +0000304 return ind + &sw
305 endif
306
307 " indent: +sw
Bram Moolenaar280f1262006-01-30 00:14:18 +0000308 " keywords: "architecture", "component", "configuration", "entity", "for", "package"
309 " removed: "when", "with"
Bram Moolenaar51156d52006-01-26 22:17:47 +0000310 " where: start of previous line
Bram Moolenaar280f1262006-01-30 00:14:18 +0000311 if prevs =~? '^\s*\%(architecture\|component\|configuration\|entity\|for\|package\)\>'
Bram Moolenaar51156d52006-01-26 22:17:47 +0000312 return ind + &sw
313 endif
314
315 " indent: +sw
316 " keyword: "generate", "is", "select", "=>"
317 " where: end of previous line
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000318 if prevs =~? s:NC.'\%(\%('.s:NE.'\<generate\|\<is\|\<select\)\|=>\)'.s:ES
Bram Moolenaar51156d52006-01-26 22:17:47 +0000319 return ind + &sw
320 endif
321
322 " indent: +sw
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000323 " keyword: "else"
324 " where: start of previous line
325 " keyword: "then"
Bram Moolenaar51156d52006-01-26 22:17:47 +0000326 " where: end of previous line
327 " _note_: indent allowed to leave this filter
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000328 if prevs =~? '^\s*else\>' || prevs =~? s:NC.'\<then'.s:ES
Bram Moolenaar51156d52006-01-26 22:17:47 +0000329 let ind = ind + &sw
330 endif
331
332 " ****************************************************************************************
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000333 " indent: -sw
334 " keywords: "when", provided previous line does not begin with "when"
Bram Moolenaar51156d52006-01-26 22:17:47 +0000335 " where: start of current line
336 let s4 = '^\s*when\>'
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000337 if curs =~? s4
338 if prevs !~? s4
339 return ind - &sw
340 else
341 return ind2
342 endif
Bram Moolenaar51156d52006-01-26 22:17:47 +0000343 endif
344
345 " indent: -sw
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000346 " keywords: "else", "elsif", provided previous line does not contain "then"
Bram Moolenaar51156d52006-01-26 22:17:47 +0000347 " where: start of current line
348 if curs =~? '^\s*\%(else\|elsif\)\>'
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000349 if prevs !~? s:NC.'\<then\>'
350 return ind - &sw
351 else
352 return ind2
353 endif
Bram Moolenaar51156d52006-01-26 22:17:47 +0000354 endif
355
356 " indent: -sw
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000357 " keywords: "end" + "if", provided previous line does not begin with "else", not contain "then"
Bram Moolenaar51156d52006-01-26 22:17:47 +0000358 " where: start of current line
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000359 if curs =~? '^\s*end\s\+if\>'
360 if prevs !~? '^\s*else\>' && prevs !~? s:NC.'\<then\>'
361 return ind - &sw
362 else
363 return ind2
364 endif
365 endif
366
367 " indent: -sw
368 " keywords: "end" + "function", "procedure", provided previous line does not contain "begin"
Bram Moolenaar51156d52006-01-26 22:17:47 +0000369 " where: start of current line
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000370 if curs =~? '^\s*end\s\+\%(function\|procedure\)\>'
371 if prevs !~? s:NC.'\<begin\>'
372 return ind - &sw
373 else
374 return ind2
375 endif
376 endif
377
378 " indent: -sw
379 " keywords: "end" + "block", "for", "generate", "loop", "process", "record", "units"
380 " where: start of current line
381 if curs =~? '^\s*end\s\+\%(block\|for\|generate\|loop\|process\|record\|units\)\>'
Bram Moolenaar51156d52006-01-26 22:17:47 +0000382 return ind - &sw
383 endif
384
Bram Moolenaar280f1262006-01-30 00:14:18 +0000385 " indent: backtrace previous non-comment lines
386 " keyword: "end" + "case", "component"
Bram Moolenaar51156d52006-01-26 22:17:47 +0000387 " where: start of current line
Bram Moolenaar280f1262006-01-30 00:14:18 +0000388 let m = 0
Bram Moolenaar51156d52006-01-26 22:17:47 +0000389 if curs =~? '^\s*end\s\+case\>'
Bram Moolenaar280f1262006-01-30 00:14:18 +0000390 let m = 1
391 elseif curs =~? '^\s*end\s\+component\>'
392 let m = 2
393 endif
394
395 if m > 0
Bram Moolenaar51156d52006-01-26 22:17:47 +0000396 " find following previous non-comment line
397 let pn = prevn
398 let ps = getline(pn)
399 while pn > 0
400 if ps !~ '^\s*--'
Bram Moolenaar280f1262006-01-30 00:14:18 +0000401 "indent: -2sw
402 "keywords: "end" + "case"
403 "where: start of previous non-comment line
404 "indent: -sw
405 "keywords: "when"
406 "where: start of previous non-comment line
407 "indent: follow
408 "keywords: "case"
409 "where: start of previous non-comment line
410 if m == 1
411 if ps =~? '^\s*end\s\+case\>'
412 return indent(pn) - 2 * &sw
413 elseif ps =~? '^\s*when\>'
414 return indent(pn) - &sw
415 elseif ps =~? '^\s*case\>'
416 return indent(pn)
417 endif
418 "indent: follow
419 "keyword: "component"
420 "where: anywhere in previous non-comment line
421 elseif m == 2
422 if ps =~? s:NC.s:NE.'\<component\>'
423 return indent(pn)
424 endif
Bram Moolenaar51156d52006-01-26 22:17:47 +0000425 endif
426 endif
427 let pn = prevnonblank(pn - 1)
428 let ps = getline(pn)
429 endwhile
Bram Moolenaar280f1262006-01-30 00:14:18 +0000430 return ind - &sw
Bram Moolenaar51156d52006-01-26 22:17:47 +0000431 endif
432
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000433 " indent: -sw
434 " keyword: ")"
435 " where: start of current line
436 if curs =~ '^\s*)'
437 return ind - &sw
438 endif
439
Bram Moolenaar51156d52006-01-26 22:17:47 +0000440 " indent: 0
441 " keywords: "end" + "architecture", "configuration", "entity", "package"
442 " where: start of current line
443 if curs =~? '^\s*end\s\+\%(architecture\|configuration\|entity\|package\)\>'
444 return 0
445 endif
446
447 " indent: -sw
448 " keywords: "end" + identifier
449 " where: start of current line
450 if curs =~? '^\s*end\s\+\w\+\>'
451 return ind - &sw
452 endif
453
454 " ****************************************************************************************
Bram Moolenaar280f1262006-01-30 00:14:18 +0000455 " indent: maintain indent of previous opening statement
Bram Moolenaar51156d52006-01-26 22:17:47 +0000456 " keywords: without "generic", "map", "port" + ":" but not ":=" + "in", "out", "inout", "buffer", "linkage", variable & ":="
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000457 " where: start of current line
458 if curs =~? '^\s*\%(\<\%(generic\|map\|port\)\>.*\)\@<!\S\+\s*:[^=]\@=\s*\%(\%(in\|out\|inout\|buffer\|linkage\)\>\|\w\+\s\+:=\)'
Bram Moolenaar51156d52006-01-26 22:17:47 +0000459 return ind2
460 endif
461
462 " return leftover filtered indent
463 return ind
464endfunction