" VHDL indent ('93 syntax)
" Language: VHDL
" Maintainer: Gerald Lai
" Version: 1.58
" Last Change: 2011 Sep 27
" URL: http://www.vim.org/scripts/script.php?script_id=1450
" only load this indent file when no other was loaded
if exists("b:did_indent")
finish
endif
let b:did_indent = 1
" setup indent options for local VHDL buffer
setlocal indentexpr=GetVHDLindent()
setlocal indentkeys=!^F,o,O,0(,0)
setlocal indentkeys+==~begin,=~end\ ,=~end\ ,=~is,=~select,=~when
setlocal indentkeys+==~if,=~then,=~elsif,=~else
setlocal indentkeys+==~case,=~loop,=~for,=~generate,=~record,=~units,=~process,=~block,=~function,=~component,=~procedure
setlocal indentkeys+==~architecture,=~configuration,=~entity,=~package
" constants
" not a comment
let s:NC = '\%(--.*\)\@ 0 && prevs =~ '^\s*--'
let prevn = prevnonblank(prevn - 1)
let prevs = getline(prevn)
endwhile
let prevs_noi = substitute(prevs, '^\s*', '', '')
" default indent starts as previous non-comment line's indent
let ind = prevn > 0 ? indent(prevn) : 0
" backup default
let ind2 = ind
" indent: special; kill string so it would not affect other filters
" keywords: "report" + string
" where: anywhere in current or previous line
let s0 = s:NC.'\\s*".*"'
if curs =~? s0
let curs = ""
endif
if prevs =~? s0
let prevs = ""
endif
" indent: previous line's comment position, otherwise follow next non-comment line if possible
" keyword: "--"
" where: start of current line
if curs =~ '^\s*--'
let pn = curn - 1
let ps = getline(pn)
if curs =~ '^\s*--\s' && ps =~ '--'
return indent(pn) + stridx(substitute(ps, '^\s*', '', ''), '--')
else
" find nextnonblank line that is not a comment
let nn = nextnonblank(curn + 1)
let ns = getline(nn)
while nn > 0 && ns =~ '^\s*--'
let nn = nextnonblank(nn + 1)
let ns = getline(nn)
endwhile
let n = indent(nn)
return n != -1 ? n : ind
endif
endif
" ****************************************************************************************
" indent: align generic variables & port names
" keywords: "procedure" + name, "generic", "map", "port" + "(", provided current line is part of mapping
" where: anywhere in previous 2 lines
" find following previous non-comment line
let pn = prevnonblank(prevn - 1)
let ps = getline(pn)
while pn > 0 && ps =~ '^\s*--'
let pn = prevnonblank(pn - 1)
let ps = getline(pn)
endwhile
if (curs =~ '^\s*)' || curs =~? '^\s*\%(\<\%(procedure\|generic\|map\|port\)\>.*\)\@\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*('))
" align closing ")" with opening "("
if curs =~ '^\s*)'
return ind2 + stridx(prevs_noi, '(')
endif
let m = matchend(prevs_noi, '(\s*\ze\w')
if m != -1
return ind2 + m
else
if g:vhdl_indent_genportmap
return ind2 + stridx(prevs_noi, '(') + &sw
else
return ind2 + &sw
endif
endif
endif
" indent: align conditional/select statement
" keywords: variable + "<=" without ";" ending
" where: start of previous line
if prevs =~? '^\s*\S\+\s*<=[^;]*'.s:ES
if g:vhdl_indent_rhsassign
return ind2 + matchend(prevs_noi, '<=\s*\ze.')
else
return ind2 + &sw
endif
endif
" indent: backtrace previous non-comment lines for next smaller or equal size indent
" keywords: "end" + "record", "units"
" where: start of previous line
" keyword: ")"
" where: start of previous line
" keyword: without "<=" + ";" ending
" where: anywhere in previous line
" keyword: "=>" + ")" ending, provided current line does not begin with ")"
" where: anywhere in previous line
" _note_: indent allowed to leave this filter
let m = 0
if prevs =~? '^\s*end\s\+\%(record\|units\)\>'
let m = 3
elseif prevs =~ '^\s*)'
let m = 1
elseif prevs =~ s:NC.'\%(<=.*\)\@.*'.s:NC.')'.s:ES)
let m = 2
endif
if m > 0
let pn = prevnonblank(prevn - 1)
let ps = getline(pn)
while pn > 0
let t = indent(pn)
if ps !~ '^\s*--' && (t < ind || (t == ind && m == 3))
" make sure one of these is true
" keywords: variable + "<=" without ";" ending
" where: start of previous non-comment line
" keywords: "procedure", "generic", "map", "port"
" where: anywhere in previous non-comment line
" keyword: "("
" where: start of previous non-comment line
if m < 3 && ps !~? '^\s*\S\+\s*<=[^;]*'.s:ES
if ps =~? s:NC.'\<\%(procedure\|generic\|map\|port\)\>' || ps =~ '^\s*('
let ind = t
endif
break
endif
let ind = t
if m > 1
" find following previous non-comment line
let ppn = prevnonblank(pn - 1)
let pps = getline(ppn)
while ppn > 0 && pps =~ '^\s*--'
let ppn = prevnonblank(ppn - 1)
let pps = getline(ppn)
endwhile
" indent: follow
" keyword: "select"
" where: end of following previous non-comment line
" keyword: "type"
" where: start of following previous non-comment line
if m == 2
let s1 = s:NC.'\