blob: 42a05a03aac5e9e13a46b98b4ead09a465b1919f [file] [log] [blame]
Bram Moolenaar92dff182014-02-11 19:15:50 +01001" Vim indent file
2" Language: SystemVerilog
3" Maintainer: kocha <kocha.lsifrontend@gmail.com>
Bram Moolenaar5be4cee2019-09-27 19:34:08 +02004" Last Change: 05-Feb-2017 by Bilal Wasim
Bram Moolenaar48c3f4e2022-08-08 15:42:38 +01005" 03-Aug-2022 Improved indent
Bram Moolenaar92dff182014-02-11 19:15:50 +01006
7" Only load this indent file when no other was loaded.
8if exists("b:did_indent")
9 finish
10endif
11let b:did_indent = 1
12
13setlocal indentexpr=SystemVerilogIndent()
14setlocal indentkeys=!^F,o,O,0),0},=begin,=end,=join,=endcase,=join_any,=join_none
15setlocal indentkeys+==endmodule,=endfunction,=endtask,=endspecify
16setlocal indentkeys+==endclass,=endpackage,=endsequence,=endclocking
17setlocal indentkeys+==endinterface,=endgroup,=endprogram,=endproperty,=endchecker
Bram Moolenaar48c3f4e2022-08-08 15:42:38 +010018setlocal indentkeys+==`else,=`elsif,=`endif
Bram Moolenaar92dff182014-02-11 19:15:50 +010019
Bram Moolenaarcbaff5e2022-04-08 17:45:08 +010020let b:undo_indent = "setl inde< indk<"
21
Bram Moolenaar92dff182014-02-11 19:15:50 +010022" Only define the function once.
23if exists("*SystemVerilogIndent")
24 finish
25endif
26
27let s:cpo_save = &cpo
28set cpo&vim
29
Bram Moolenaar48c3f4e2022-08-08 15:42:38 +010030let s:multiple_comment = 0
31let s:open_statement = 0
32
Bram Moolenaar92dff182014-02-11 19:15:50 +010033function SystemVerilogIndent()
34
35 if exists('b:systemverilog_indent_width')
36 let offset = b:systemverilog_indent_width
37 else
Bram Moolenaar3ec574f2017-06-13 18:12:01 +020038 let offset = shiftwidth()
Bram Moolenaar92dff182014-02-11 19:15:50 +010039 endif
40 if exists('b:systemverilog_indent_modules')
41 let indent_modules = offset
42 else
43 let indent_modules = 0
44 endif
45
Bram Moolenaar48c3f4e2022-08-08 15:42:38 +010046 if exists('b:systemverilog_indent_ifdef_off')
47 let indent_ifdef = 0
48 else
49 let indent_ifdef = 1
50 endif
51
Bram Moolenaar92dff182014-02-11 19:15:50 +010052 " Find a non-blank line above the current line.
53 let lnum = prevnonblank(v:lnum - 1)
54
55 " At the start of the file use zero indent.
56 if lnum == 0
57 return 0
58 endif
59
60 let lnum2 = prevnonblank(lnum - 1)
61 let curr_line = getline(v:lnum)
62 let last_line = getline(lnum)
63 let last_line2 = getline(lnum2)
64 let ind = indent(lnum)
65 let ind2 = indent(lnum - 1)
Bram Moolenaar92dff182014-02-11 19:15:50 +010066 " Define the condition of an open statement
67 " Exclude the match of //, /* or */
68 let sv_openstat = '\(\<or\>\|\([*/]\)\@<![*(,{><+-/%^&|!=?:]\([*/]\)\@!\)'
69 " Define the condition when the statement ends with a one-line comment
70 let sv_comment = '\(//.*\|/\*.*\*/\s*\)'
Bram Moolenaar48c3f4e2022-08-08 15:42:38 +010071 if exists('b:systemverilog_indent_verbose')
72 let vverb_str = 'INDENT VERBOSE: '. v:lnum .":"
Bram Moolenaar92dff182014-02-11 19:15:50 +010073 let vverb = 1
74 else
75 let vverb = 0
76 endif
77
Bram Moolenaar48c3f4e2022-08-08 15:42:38 +010078 " Multiple-line comment count
79 if curr_line =~ '^\s*/\*' && curr_line !~ '/\*.\{-}\*/'
80 let s:multiple_comment += 1
Viktor Szépedbf749b2023-10-16 09:53:37 +020081 if vverb | echom vverb_str "Start of multiple-line comment" | endif
Bram Moolenaar48c3f4e2022-08-08 15:42:38 +010082 elseif curr_line =~ '\*/\s*$' && curr_line !~ '/\*.\{-}\*/'
83 let s:multiple_comment -= 1
Viktor Szépedbf749b2023-10-16 09:53:37 +020084 if vverb | echom vverb_str "End of multiple-line comment" | endif
Bram Moolenaar48c3f4e2022-08-08 15:42:38 +010085 return ind
86 endif
87 " Maintain indentation during commenting.
88 if s:multiple_comment > 0
89 return ind
90 endif
Bram Moolenaar92dff182014-02-11 19:15:50 +010091
92 " Indent after if/else/for/case/always/initial/specify/fork blocks
Bram Moolenaar48c3f4e2022-08-08 15:42:38 +010093 if last_line =~ '^\s*\(end\)\=\s*`\@<!\<\(if\|else\)\>' ||
94 \ last_line =~ '^\s*\<\(for\|while\|repeat\|case\%[[zx]]\|do\|foreach\|forever\|randcase\)\>' ||
Bram Moolenaar92dff182014-02-11 19:15:50 +010095 \ last_line =~ '^\s*\<\(always\|always_comb\|always_ff\|always_latch\)\>' ||
96 \ last_line =~ '^\s*\<\(initial\|specify\|fork\|final\)\>'
Bram Moolenaar48c3f4e2022-08-08 15:42:38 +010097 if last_line !~ '\(;\|\<end\>\|\*/\)\s*' . sv_comment . '*$' ||
Bram Moolenaar92dff182014-02-11 19:15:50 +010098 \ last_line =~ '\(//\|/\*\).*\(;\|\<end\>\)\s*' . sv_comment . '*$'
99 let ind = ind + offset
Bram Moolenaar48c3f4e2022-08-08 15:42:38 +0100100 if vverb | echom vverb_str "Indent after a block statement." | endif
Bram Moolenaar92dff182014-02-11 19:15:50 +0100101 endif
102 " Indent after function/task/class/package/sequence/clocking/
103 " interface/covergroup/property/checkerprogram blocks
104 elseif last_line =~ '^\s*\<\(function\|task\|class\|package\)\>' ||
105 \ last_line =~ '^\s*\<\(sequence\|clocking\|interface\)\>' ||
106 \ last_line =~ '^\s*\(\w\+\s*:\)\=\s*\<covergroup\>' ||
Bram Moolenaar48c3f4e2022-08-08 15:42:38 +0100107 \ last_line =~ '^\s*\<\(property\|checker\|program\)\>' ||
108 \ ( last_line =~ '^\s*\<virtual\>' && last_line =~ '\<\(function\|task\|class\|interface\)\>' ) ||
109 \ ( last_line =~ '^\s*\<pure\>' && last_line =~ '\<virtual\>' && last_line =~ '\<\(function\|task\)\>' )
Bram Moolenaar92dff182014-02-11 19:15:50 +0100110 if last_line !~ '\<end\>\s*' . sv_comment . '*$' ||
111 \ last_line =~ '\(//\|/\*\).*\(;\|\<end\>\)\s*' . sv_comment . '*$'
112 let ind = ind + offset
113 if vverb
Bram Moolenaar48c3f4e2022-08-08 15:42:38 +0100114 echom vverb_str "Indent after function/task/class block statement."
Bram Moolenaar92dff182014-02-11 19:15:50 +0100115 endif
116 endif
117
118 " Indent after module/function/task/specify/fork blocks
119 elseif last_line =~ '^\s*\(\<extern\>\s*\)\=\<module\>'
120 let ind = ind + indent_modules
121 if vverb && indent_modules
Bram Moolenaar48c3f4e2022-08-08 15:42:38 +0100122 echom vverb_str "Indent after module statement."
Bram Moolenaar92dff182014-02-11 19:15:50 +0100123 endif
124 if last_line =~ '[(,]\s*' . sv_comment . '*$' &&
125 \ last_line !~ '\(//\|/\*\).*[(,]\s*' . sv_comment . '*$'
126 let ind = ind + offset
127 if vverb
Bram Moolenaar48c3f4e2022-08-08 15:42:38 +0100128 echom vverb_str "Indent after a multiple-line module statement."
Bram Moolenaar92dff182014-02-11 19:15:50 +0100129 endif
130 endif
131
132 " Indent after a 'begin' statement
133 elseif last_line =~ '\(\<begin\>\)\(\s*:\s*\w\+\)*' . sv_comment . '*$' &&
134 \ last_line !~ '\(//\|/\*\).*\(\<begin\>\)' &&
135 \ ( last_line2 !~ sv_openstat . '\s*' . sv_comment . '*$' ||
136 \ last_line2 =~ '^\s*[^=!]\+\s*:\s*' . sv_comment . '*$' )
137 let ind = ind + offset
Bram Moolenaar48c3f4e2022-08-08 15:42:38 +0100138 if vverb | echom vverb_str "Indent after begin statement." | endif
Bram Moolenaar92dff182014-02-11 19:15:50 +0100139
140 " Indent after a '{' or a '('
141 elseif last_line =~ '[{(]' . sv_comment . '*$' &&
142 \ last_line !~ '\(//\|/\*\).*[{(]' &&
143 \ ( last_line2 !~ sv_openstat . '\s*' . sv_comment . '*$' ||
144 \ last_line2 =~ '^\s*[^=!]\+\s*:\s*' . sv_comment . '*$' )
145 let ind = ind + offset
Bram Moolenaar48c3f4e2022-08-08 15:42:38 +0100146 if vverb | echom vverb_str "Indent after begin statement." | endif
147
148 " Ignore de-indent for the end of one-line block
149 elseif ( last_line !~ '\<begin\>' ||
150 \ last_line =~ '\(//\|/\*\).*\<begin\>' ) &&
151 \ last_line2 =~ '\<\(`\@<!if\|`\@<!else\|for\|always\|initial\|do\|foreach\|forever\|final\)\>.*' .
152 \ sv_comment . '*$' &&
153 \ last_line2 !~ '\(//\|/\*\).*\<\(`\@<!if\|`\@<!else\|for\|always\|initial\|do\|foreach\|forever\|final\)\>' &&
154 \ last_line2 !~ sv_openstat . '\s*' . sv_comment . '*$' &&
155 \ ( last_line2 !~ '\<begin\>' ||
156 \ last_line2 =~ '\(//\|/\*\).*\<begin\>' ) &&
157 \ last_line2 =~ ')*\s*;\s*' . sv_comment . '*$'
158 if vverb
159 echom vverb_str "Ignore de-indent after the end of one-line statement."
160 endif
Bram Moolenaar92dff182014-02-11 19:15:50 +0100161
162 " De-indent for the end of one-line block
163 elseif ( last_line !~ '\<begin\>' ||
164 \ last_line =~ '\(//\|/\*\).*\<begin\>' ) &&
Bram Moolenaar5be4cee2019-09-27 19:34:08 +0200165 \ last_line2 =~ '\<\(`\@<!if\|`\@<!else\|for\|always\|initial\|do\|foreach\|forever\|final\)\>.*' .
Bram Moolenaar92dff182014-02-11 19:15:50 +0100166 \ sv_comment . '*$' &&
Bram Moolenaar5be4cee2019-09-27 19:34:08 +0200167 \ last_line2 !~ '\(//\|/\*\).*\<\(`\@<!if\|`\@<!else\|for\|always\|initial\|do\|foreach\|forever\|final\)\>' &&
Bram Moolenaar92dff182014-02-11 19:15:50 +0100168 \ last_line2 !~ sv_openstat . '\s*' . sv_comment . '*$' &&
Bram Moolenaar48c3f4e2022-08-08 15:42:38 +0100169 \ last_line2 !~ '\(;\|\<end\>\|\*/\)\s*' . sv_comment . '*$' &&
Bram Moolenaar92dff182014-02-11 19:15:50 +0100170 \ ( last_line2 !~ '\<begin\>' ||
171 \ last_line2 =~ '\(//\|/\*\).*\<begin\>' )
172 let ind = ind - offset
173 if vverb
Bram Moolenaar48c3f4e2022-08-08 15:42:38 +0100174 echom vverb_str "De-indent after the end of one-line statement."
Bram Moolenaar92dff182014-02-11 19:15:50 +0100175 endif
176
Bram Moolenaar48c3f4e2022-08-08 15:42:38 +0100177 " Multiple-line statement (including case statement)
178 " Open statement
179 " Ident the first open line
180 elseif last_line =~ sv_openstat . '\s*' . sv_comment . '*$' &&
181 \ last_line !~ '\(//\|/\*\).*' . sv_openstat . '\s*$' &&
182 \ last_line2 !~ sv_openstat . '\s*' . sv_comment . '*$'
183 let ind = ind + offset
184 let s:open_statement = 1
185 if vverb | echom vverb_str "Indent after an open statement." | endif
Bram Moolenaar92dff182014-02-11 19:15:50 +0100186
Bram Moolenaar48c3f4e2022-08-08 15:42:38 +0100187 " `ifdef or `ifndef or `elsif or `else
188 elseif last_line =~ '^\s*`\<\(ifn\?def\|elsif\|else\)\>' && indent_ifdef
Bram Moolenaar92dff182014-02-11 19:15:50 +0100189 let ind = ind + offset
190 if vverb
Bram Moolenaar48c3f4e2022-08-08 15:42:38 +0100191 echom vverb_str "Indent after a `ifdef or `ifndef or `elsif or `else statement."
Bram Moolenaar92dff182014-02-11 19:15:50 +0100192 endif
193
194 endif
195
196 " Re-indent current line
197
198 " De-indent on the end of the block
199 " join/end/endcase/endfunction/endtask/endspecify
Bram Moolenaar48c3f4e2022-08-08 15:42:38 +0100200 if curr_line =~ '^\s*\<\(join\|join_any\|join_none\|\|end\|endcase\)\>' ||
Bram Moolenaar92dff182014-02-11 19:15:50 +0100201 \ curr_line =~ '^\s*\<\(endfunction\|endtask\|endspecify\|endclass\)\>' ||
202 \ curr_line =~ '^\s*\<\(endpackage\|endsequence\|endclocking\|endinterface\)\>' ||
Bram Moolenaar48c3f4e2022-08-08 15:42:38 +0100203 \ curr_line =~ '^\s*\<\(endgroup\|endproperty\|endchecker\|endprogram\)\>'
Bram Moolenaar92dff182014-02-11 19:15:50 +0100204 let ind = ind - offset
Bram Moolenaar48c3f4e2022-08-08 15:42:38 +0100205 if vverb | echom vverb_str "De-indent the end of a block." | endif
206 if s:open_statement == 1
207 let ind = ind - offset
208 let s:open_statement = 0
209 if vverb | echom vverb_str "De-indent the close statement." | endif
210 endif
Bram Moolenaar92dff182014-02-11 19:15:50 +0100211 elseif curr_line =~ '^\s*\<endmodule\>'
212 let ind = ind - indent_modules
213 if vverb && indent_modules
Bram Moolenaar48c3f4e2022-08-08 15:42:38 +0100214 echom vverb_str "De-indent the end of a module."
Bram Moolenaar92dff182014-02-11 19:15:50 +0100215 endif
216
217 " De-indent on a stand-alone 'begin'
218 elseif curr_line =~ '^\s*\<begin\>'
219 if last_line !~ '^\s*\<\(function\|task\|specify\|module\|class\|package\)\>' ||
220 \ last_line !~ '^\s*\<\(sequence\|clocking\|interface\|covergroup\)\>' ||
221 \ last_line !~ '^\s*\<\(property\|checker\|program\)\>' &&
222 \ last_line !~ '^\s*\()*\s*;\|)\+\)\s*' . sv_comment . '*$' &&
223 \ ( last_line =~
Bram Moolenaar5be4cee2019-09-27 19:34:08 +0200224 \ '\<\(`\@<!if\|`\@<!else\|for\|case\%[[zx]]\|always\|initial\|do\|foreach\|forever\|randcase\|final\)\>' ||
Bram Moolenaar92dff182014-02-11 19:15:50 +0100225 \ last_line =~ ')\s*' . sv_comment . '*$' ||
226 \ last_line =~ sv_openstat . '\s*' . sv_comment . '*$' )
227 let ind = ind - offset
228 if vverb
Bram Moolenaar48c3f4e2022-08-08 15:42:38 +0100229 echom vverb_str "De-indent a stand alone begin statement."
230 endif
231 if s:open_statement == 1
232 let ind = ind - offset
233 let s:open_statement = 0
234 if vverb | echom vverb_str "De-indent the close statement." | endif
Bram Moolenaar92dff182014-02-11 19:15:50 +0100235 endif
236 endif
237
Bram Moolenaar48c3f4e2022-08-08 15:42:38 +0100238 " " Close statement
239 " " De-indent for an optional close parenthesis and a semicolon, and only
240 " " if there exists precedent non-whitespace char
241 " elseif last_line =~ ')*\s*;\s*' . sv_comment . '*$' &&
242 " \ last_line !~ '^\s*)*\s*;\s*' . sv_comment . '*$' &&
243 " \ last_line !~ '\(//\|/\*\).*\S)*\s*;\s*' . sv_comment . '*$' &&
244 " \ ( last_line2 =~ sv_openstat . '\s*' . sv_comment . '*$' &&
245 " \ last_line2 !~ ';\s*//.*$') &&
246 " \ last_line2 !~ '^\s*' . sv_comment . '$'
247 " let ind = ind - offset
248 " if vverb | echom vverb_str "De-indent after a close statement." | endif
249
250 " " De-indent after the end of multiple-line statement
251 " elseif curr_line =~ '^\s*)' &&
252 " \ ( last_line =~ sv_openstat . '\s*' . sv_comment . '*$' ||
253 " \ last_line !~ sv_openstat . '\s*' . sv_comment . '*$' &&
254 " \ last_line2 =~ sv_openstat . '\s*' . sv_comment . '*$' )
255 " let ind = ind - offset
256 " if vverb
257 " echom vverb_str "De-indent the end of a multiple statement."
258 " endif
259
260 " De-indent `elsif or `else or `endif
261 elseif curr_line =~ '^\s*`\<\(elsif\|else\|endif\)\>' && indent_ifdef
Bram Moolenaar92dff182014-02-11 19:15:50 +0100262 let ind = ind - offset
Bram Moolenaar48c3f4e2022-08-08 15:42:38 +0100263 if vverb | echom vverb_str "De-indent `elsif or `else or `endif statement." | endif
264 if b:systemverilog_open_statement == 1
265 let ind = ind - offset
266 let b:systemverilog_open_statement = 0
267 if vverb | echom vverb_str "De-indent the open statement." | endif
Bram Moolenaar92dff182014-02-11 19:15:50 +0100268 endif
Bram Moolenaar92dff182014-02-11 19:15:50 +0100269 endif
270
Bram Moolenaar6c391a72021-09-09 21:55:11 +0200271 " Return the indentation
Bram Moolenaar92dff182014-02-11 19:15:50 +0100272 return ind
273endfunction
274
275let &cpo = s:cpo_save
276unlet s:cpo_save
277
Bram Moolenaar82be4842021-01-11 19:40:15 +0100278" vim:sw=2
Bram Moolenaar48c3f4e2022-08-08 15:42:38 +0100279