blob: 5dee6c9f47a434087a25d349659b7b5abf091768 [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001" Vim indent file
2" Language: PHP
Bram Moolenaar9ff70112005-07-11 22:29:03 +00003" Author: John Wellesz <John.wellesz (AT) teaser (DOT) fr>
4" URL: http://www.2072productions.com/vim/indent/php.vim
Bram Moolenaare6ae6222013-05-21 21:01:10 +02005" Home: https://github.com/2072/PHP-Indenting-for-VIm
Bram Moolenaar0b0f0992018-05-22 21:41:30 +02006" Last Change: 2018 May 18th
7" Version: 1.66
Bram Moolenaar071d4272004-06-13 20:20:40 +00008"
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00009"
Bram Moolenaare6ae6222013-05-21 21:01:10 +020010" Type :help php-indent for available options
11"
12" A fully commented version of this file is available on github
Bram Moolenaara5792f52005-11-23 21:25:05 +000013"
14"
Bram Moolenaar259f26a2018-05-15 22:25:40 +020015" If you find a bug, please open a ticket on github.com
Bram Moolenaare6ae6222013-05-21 21:01:10 +020016" ( https://github.com/2072/PHP-Indenting-for-VIm/issues ) with an example of
17" code that breaks the algorithm.
Bram Moolenaar9ff70112005-07-11 22:29:03 +000018"
Bram Moolenaare6ae6222013-05-21 21:01:10 +020019
Bram Moolenaar9ff70112005-07-11 22:29:03 +000020" NOTE: This script must be used with PHP syntax ON and with the php syntax
Bram Moolenaare6ae6222013-05-21 21:01:10 +020021" script by Lutz Eymers (http://www.isp.de/data/php.vim ) or with the
Bram Moolenaarc236c162008-07-13 17:41:49 +000022" script by Peter Hodge (http://www.vim.org/scripts/script.php?script_id=1571 )
Bram Moolenaar5c736222010-01-06 20:54:52 +010023" the later is bunbdled by default with Vim 7.
Bram Moolenaar9ff70112005-07-11 22:29:03 +000024"
25"
Bram Moolenaarc236c162008-07-13 17:41:49 +000026" In the case you have syntax errors in your script such as HereDoc end
27" identifiers not at col 1 you'll have to indent your file 2 times (This
28" script will automatically put HereDoc end identifiers at col 1 if
29" they are followed by a ';').
Bram Moolenaarc9b4b052006-04-30 18:54:39 +000030"
Bram Moolenaare6ae6222013-05-21 21:01:10 +020031
Bram Moolenaar5c736222010-01-06 20:54:52 +010032" NOTE: If you are editing files in Unix file format and that (by accident)
33" there are '\r' before new lines, this script won't be able to proceed
34" correctly and will make many mistakes because it won't be able to match
35" '\s*$' correctly.
36" So you have to remove those useless characters first with a command like:
Bram Moolenaar9ff70112005-07-11 22:29:03 +000037"
Bram Moolenaar5c736222010-01-06 20:54:52 +010038" :%s /\r$//g
Bram Moolenaar9ff70112005-07-11 22:29:03 +000039"
Bram Moolenaar5c736222010-01-06 20:54:52 +010040" or simply 'let' the option PHP_removeCRwhenUnix to 1 and the script will
41" silently remove them when VIM load this script (at each bufread).
Bram Moolenaarbcb98982014-05-01 14:08:19 +020042
43
Bram Moolenaara5792f52005-11-23 21:25:05 +000044
Bram Moolenaar071d4272004-06-13 20:20:40 +000045if exists("b:did_indent")
Bram Moolenaar1e015462005-09-25 22:16:38 +000046 finish
Bram Moolenaar071d4272004-06-13 20:20:40 +000047endif
48let b:did_indent = 1
49
Bram Moolenaar9ff70112005-07-11 22:29:03 +000050
Bram Moolenaared32d942014-12-06 23:33:00 +010051let g:php_sync_method = 0
Bram Moolenaar9ff70112005-07-11 22:29:03 +000052
Bram Moolenaare6ae6222013-05-21 21:01:10 +020053
Bram Moolenaar9ff70112005-07-11 22:29:03 +000054if exists("PHP_default_indenting")
Bram Moolenaar3ec574f2017-06-13 18:12:01 +020055 let b:PHP_default_indenting = PHP_default_indenting * shiftwidth()
Bram Moolenaar9ff70112005-07-11 22:29:03 +000056else
Bram Moolenaar1e015462005-09-25 22:16:38 +000057 let b:PHP_default_indenting = 0
Bram Moolenaar9ff70112005-07-11 22:29:03 +000058endif
59
Bram Moolenaare6ae6222013-05-21 21:01:10 +020060if exists("PHP_outdentSLComments")
Bram Moolenaar3ec574f2017-06-13 18:12:01 +020061 let b:PHP_outdentSLComments = PHP_outdentSLComments * shiftwidth()
Bram Moolenaare6ae6222013-05-21 21:01:10 +020062else
63 let b:PHP_outdentSLComments = 0
64endif
65
Bram Moolenaar9ff70112005-07-11 22:29:03 +000066if exists("PHP_BracesAtCodeLevel")
Bram Moolenaar1e015462005-09-25 22:16:38 +000067 let b:PHP_BracesAtCodeLevel = PHP_BracesAtCodeLevel
Bram Moolenaar9ff70112005-07-11 22:29:03 +000068else
Bram Moolenaar1e015462005-09-25 22:16:38 +000069 let b:PHP_BracesAtCodeLevel = 0
Bram Moolenaar9ff70112005-07-11 22:29:03 +000070endif
71
Bram Moolenaarc236c162008-07-13 17:41:49 +000072
Bram Moolenaara5792f52005-11-23 21:25:05 +000073if exists("PHP_autoformatcomment")
74 let b:PHP_autoformatcomment = PHP_autoformatcomment
75else
76 let b:PHP_autoformatcomment = 1
77endif
Bram Moolenaar9ff70112005-07-11 22:29:03 +000078
Bram Moolenaar8408a9a2010-07-30 22:41:22 +020079if exists("PHP_outdentphpescape")
80 let b:PHP_outdentphpescape = PHP_outdentphpescape
81else
82 let b:PHP_outdentphpescape = 1
83endif
84
Bram Moolenaar0b0f0992018-05-22 21:41:30 +020085if exists("PHP_noArrowMatching")
86 let b:PHP_noArrowMatching = PHP_noArrowMatching
87else
88 let b:PHP_noArrowMatching = 0
89endif
90
Bram Moolenaar8408a9a2010-07-30 22:41:22 +020091
92if exists("PHP_vintage_case_default_indent") && PHP_vintage_case_default_indent
93 let b:PHP_vintage_case_default_indent = 1
Bram Moolenaarc236c162008-07-13 17:41:49 +000094else
95 let b:PHP_vintage_case_default_indent = 0
96endif
97
98
99
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000100let b:PHP_lastindented = 0
101let b:PHP_indentbeforelast = 0
102let b:PHP_indentinghuge = 0
103let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
104let b:PHP_LastIndentedWasComment = 0
105let b:PHP_InsideMultilineComment = 0
106let b:InPHPcode = 0
107let b:InPHPcode_checked = 0
108let b:InPHPcode_and_script = 0
109let b:InPHPcode_tofind = ""
110let b:PHP_oldchangetick = b:changedtick
111let b:UserIsTypingComment = 0
112let b:optionsset = 0
113
114setlocal nosmartindent
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000115setlocal noautoindent
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000116setlocal nocindent
Bram Moolenaar1e015462005-09-25 22:16:38 +0000117setlocal nolisp
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000118
Bram Moolenaar071d4272004-06-13 20:20:40 +0000119setlocal indentexpr=GetPhpIndent()
Bram Moolenaared32d942014-12-06 23:33:00 +0100120setlocal indentkeys=0{,0},0),0],:,!^F,o,O,e,*<Return>,=?>,=<?,=*/
Bram Moolenaar071d4272004-06-13 20:20:40 +0000121
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000122
Bram Moolenaar1e015462005-09-25 22:16:38 +0000123
124let s:searchpairflags = 'bWr'
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000125
126if &fileformat == "unix" && exists("PHP_removeCRwhenUnix") && PHP_removeCRwhenUnix
Bram Moolenaar1e015462005-09-25 22:16:38 +0000127 silent! %s/\r$//g
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000128endif
129
Bram Moolenaar071d4272004-06-13 20:20:40 +0000130if exists("*GetPhpIndent")
Bram Moolenaar5c736222010-01-06 20:54:52 +0100131 call ResetPhpOptions()
Bram Moolenaarcbebd482016-02-07 23:02:56 +0100132 finish
Bram Moolenaar071d4272004-06-13 20:20:40 +0000133endif
134
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200135
Bram Moolenaared32d942014-12-06 23:33:00 +0100136let s:PHP_validVariable = '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*'
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200137let s:notPhpHereDoc = '\%(break\|return\|continue\|exit\|die\|else\)'
138let s:blockstart = '\%(\%(\%(}\s*\)\=else\%(\s\+\)\=\)\=if\>\|\%(}\s*\)\?else\>\|do\>\|while\>\|switch\>\|case\>\|default\>\|for\%(each\)\=\>\|declare\>\|class\>\|trait\>\|use\>\|interface\>\|abstract\>\|final\>\|try\>\|\%(}\s*\)\=catch\>\|\%(}\s*\)\=finally\>\)'
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200139let s:functionDecl = '\<function\>\%(\s\+&\='.s:PHP_validVariable.'\)\=\s*(.*'
Bram Moolenaare0720cb2017-03-29 13:48:40 +0200140let s:endline = '\s*\%(//.*\|#.*\|/\*.*\*/\s*\)\=$'
141let s:unstated = '\%(^\s*'.s:blockstart.'.*)\|\%(//.*\)\@<!\<e'.'lse\>\)'.s:endline
Bram Moolenaared32d942014-12-06 23:33:00 +0100142
143
Bram Moolenaare0720cb2017-03-29 13:48:40 +0200144let s:terminated = '\%(\%(;\%(\s*\%(?>\|}\)\)\=\|<<<\s*[''"]\=\a\w*[''"]\=$\|^\s*}\|^\s*'.s:PHP_validVariable.':\)'.s:endline.'\)'
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000145let s:PHP_startindenttag = '<?\%(.*?>\)\@!\|<script[^>]*>\%(.*<\/script>\)\@!'
Bram Moolenaare0720cb2017-03-29 13:48:40 +0200146let s:structureHead = '^\s*\%(' . s:blockstart . '\)\|'. s:functionDecl . s:endline . '\|\<new\s\+class\>'
Bram Moolenaar071d4272004-06-13 20:20:40 +0000147
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000148
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200149let s:escapeDebugStops = 0
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200150function! DebugPrintReturn(scriptLine)
151
Bram Moolenaared32d942014-12-06 23:33:00 +0100152 if ! s:escapeDebugStops
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200153 echo "debug:" . a:scriptLine
154 let c = getchar()
155 if c == "\<Del>"
156 let s:escapeDebugStops = 1
157 end
158 endif
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200159
160endfunction
161
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000162function! GetLastRealCodeLNum(startline) " {{{
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000163
Bram Moolenaar1e015462005-09-25 22:16:38 +0000164 let lnum = a:startline
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000165
Bram Moolenaar05a7bb32006-01-19 22:09:32 +0000166 if b:GetLastRealCodeLNum_ADD && b:GetLastRealCodeLNum_ADD == lnum + 1
167 let lnum = b:GetLastRealCodeLNum_ADD
168 endif
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000169
Bram Moolenaar1e015462005-09-25 22:16:38 +0000170 while lnum > 1
171 let lnum = prevnonblank(lnum)
172 let lastline = getline(lnum)
173
174 if b:InPHPcode_and_script && lastline =~ '?>\s*$'
175 let lnum = lnum - 1
176 elseif lastline =~ '^\s*?>.*<?\%(php\)\=\s*$'
177 let lnum = lnum - 1
178 elseif lastline =~ '^\s*\%(//\|#\|/\*.*\*/\s*$\)'
179 let lnum = lnum - 1
180 elseif lastline =~ '\*/\s*$'
181 call cursor(lnum, 1)
182 if lastline !~ '^\*/'
183 call search('\*/', 'W')
184 endif
Bram Moolenaara5792f52005-11-23 21:25:05 +0000185 let lnum = searchpair('/\*', '', '\*/', s:searchpairflags, 'Skippmatch2()')
Bram Moolenaar1e015462005-09-25 22:16:38 +0000186
187 let lastline = getline(lnum)
188 if lastline =~ '^\s*/\*'
189 let lnum = lnum - 1
190 else
191 break
192 endif
193
194
195 elseif lastline =~? '\%(//\s*\|?>.*\)\@<!<?\%(php\)\=\s*$\|^\s*<script\>'
196
197 while lastline !~ '\(<?.*\)\@<!?>' && lnum > 1
198 let lnum = lnum - 1
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000199 let lastline = getline(lnum)
Bram Moolenaar1e015462005-09-25 22:16:38 +0000200 endwhile
201 if lastline =~ '^\s*?>'
202 let lnum = lnum - 1
203 else
204 break
205 endif
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000206
207
Bram Moolenaar8408a9a2010-07-30 22:41:22 +0200208 elseif lastline =~? '^\a\w*;\=$' && lastline !~? s:notPhpHereDoc
Bram Moolenaarcbebd482016-02-07 23:02:56 +0100209 let tofind=substitute( lastline, '\(\a\w*\);\=', '<<<\\s*[''"]\\=\1[''"]\\=$', '')
Bram Moolenaar1e015462005-09-25 22:16:38 +0000210 while getline(lnum) !~? tofind && lnum > 1
211 let lnum = lnum - 1
212 endwhile
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200213 elseif lastline =~ '^[^''"`]*[''"`][;,]'.s:endline
Bram Moolenaare0720cb2017-03-29 13:48:40 +0200214
215 let tofind=substitute( lastline, '^.*\([''"`]\)[;,].*$', '^[^\1]\\+[\1]$\\|^[^\1]\\+[=([]\\s*[\1]', '')
216 let trylnum = lnum
217 while getline(trylnum) !~? tofind && trylnum > 1
218 let trylnum = trylnum - 1
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200219 endwhile
Bram Moolenaare0720cb2017-03-29 13:48:40 +0200220
221 if trylnum == 1
222 break
223 else
224 if lastline =~ ';'.s:endline
225 while getline(trylnum) !~? s:terminated && getline(trylnum) !~? '{'.s:endline && trylnum > 1
226 let trylnum = prevnonblank(trylnum - 1)
227 endwhile
228
229
230 if trylnum == 1
231 break
232 end
233 end
234 let lnum = trylnum
235 end
Bram Moolenaar1e015462005-09-25 22:16:38 +0000236 else
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000237 break
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000238 endif
Bram Moolenaar1e015462005-09-25 22:16:38 +0000239 endwhile
240
Bram Moolenaar8408a9a2010-07-30 22:41:22 +0200241 if lnum==1 && getline(lnum) !~ '<?'
Bram Moolenaar1e015462005-09-25 22:16:38 +0000242 let lnum=0
243 endif
244
Bram Moolenaared32d942014-12-06 23:33:00 +0100245 if b:InPHPcode_and_script && 1 > b:InPHPcode
Bram Moolenaar1e015462005-09-25 22:16:38 +0000246 let b:InPHPcode_and_script = 0
247 endif
Bram Moolenaard5ab34b2007-05-05 17:15:44 +0000248
Bram Moolenaar1e015462005-09-25 22:16:38 +0000249 return lnum
250endfunction " }}}
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000251
Bram Moolenaara5792f52005-11-23 21:25:05 +0000252function! Skippmatch2()
253
254 let line = getline(".")
255
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200256 if line =~ "\\([\"']\\).*/\\*.*\\1" || line =~ '\%(//\|#\).*/\*'
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200257 return 1
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200258 else
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200259 return 0
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200260 endif
Bram Moolenaara5792f52005-11-23 21:25:05 +0000261endfun
262
Bram Moolenaar8408a9a2010-07-30 22:41:22 +0200263function! Skippmatch() " {{{
Bram Moolenaar1e015462005-09-25 22:16:38 +0000264 let synname = synIDattr(synID(line("."), col("."), 0), "name")
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200265 if synname ==? "Delimiter" || synname ==? "phpRegionDelimiter" || synname =~? "^phpParent" || synname ==? "phpArrayParens" || synname =~? '^php\%(Block\|Brace\)' || synname ==? "javaScriptBraces" || synname =~? '^php\%(Doc\)\?Comment' && b:UserIsTypingComment
Bram Moolenaar1e015462005-09-25 22:16:38 +0000266 return 0
267 else
268 return 1
269 endif
270endfun " }}}
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000271
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200272function! FindOpenBracket(lnum, blockStarter) " {{{
Bram Moolenaar1e015462005-09-25 22:16:38 +0000273 call cursor(a:lnum, 1)
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200274 let line = searchpair('{', '', '}', 'bW', 'Skippmatch()')
275
276 if a:blockStarter == 1
Bram Moolenaared32d942014-12-06 23:33:00 +0100277 while line > 1
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200278 let linec = getline(line)
279
Bram Moolenaare0720cb2017-03-29 13:48:40 +0200280 if linec =~ s:terminated || linec =~ s:structureHead
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200281 break
282 endif
283
284 let line = GetLastRealCodeLNum(line - 1)
285 endwhile
286 endif
287
288 return line
Bram Moolenaar1e015462005-09-25 22:16:38 +0000289endfun " }}}
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000290
Bram Moolenaare0720cb2017-03-29 13:48:40 +0200291let s:blockChars = {'{':1, '[': 1, '(': 1, ')':-1, ']':-1, '}':-1}
292function! BalanceDirection (str)
293
294 let balance = 0
295
296 for c in split(a:str, '\zs')
297 if has_key(s:blockChars, c)
298 let balance += s:blockChars[c]
299 endif
300 endfor
301
302 return balance
303endfun
304
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200305function! StripEndlineComments (line)
306 return substitute(a:line,"\\(//\\|#\\)\\(\\(\\([^\"']*\\([\"']\\)[^\"']*\\5\\)\\+[^\"']*$\\)\\|\\([^\"']*$\\)\\)",'','')
307endfun
308
309function! FindArrowIndent (lnum) " {{{
310
311 let parrentArrowPos = 0
312 let lnum = a:lnum
313 while lnum > 1
314 let last_line = getline(lnum)
315 if last_line =~ '^\s*->'
316 let parrentArrowPos = indent(a:lnum)
317 break
318 else
319 call cursor(lnum, 1)
320 let cleanedLnum = StripEndlineComments(last_line)
321 if cleanedLnum =~ '->'
322 if ! b:PHP_noArrowMatching
323 let parrentArrowPos = searchpos('->', 'W', lnum)[1] - 1
324 else
325 let parrentArrowPos = indent(lnum) + shiftwidth()
326 endif
327 break
328 elseif cleanedLnum =~ ')'.s:endline && BalanceDirection(last_line) < 0
329 call searchpos(')'.s:endline, 'cW', lnum)
330 let openedparent = searchpair('(', '', ')', 'bW', 'Skippmatch()')
331 if openedparent != lnum
332 let lnum = openedparent
333 else
334 let openedparent = -1
335 endif
336
337 else
338 let parrentArrowPos = indent(lnum) + shiftwidth()
339 break
340 endif
341 endif
342 endwhile
343
344 return parrentArrowPos
345endfun "}}}
346
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000347function! FindTheIfOfAnElse (lnum, StopAfterFirstPrevElse) " {{{
Bram Moolenaar1e015462005-09-25 22:16:38 +0000348
349 if getline(a:lnum) =~# '^\s*}\s*else\%(if\)\=\>'
350 let beforeelse = a:lnum
351 else
352 let beforeelse = GetLastRealCodeLNum(a:lnum - 1)
353 endif
354
355 if !s:level
356 let s:iftoskip = 0
357 endif
358
359 if getline(beforeelse) =~# '^\s*\%(}\s*\)\=else\%(\s*if\)\@!\>'
360 let s:iftoskip = s:iftoskip + 1
361 endif
362
363 if getline(beforeelse) =~ '^\s*}'
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200364 let beforeelse = FindOpenBracket(beforeelse, 0)
Bram Moolenaar1e015462005-09-25 22:16:38 +0000365
366 if getline(beforeelse) =~ '^\s*{'
367 let beforeelse = GetLastRealCodeLNum(beforeelse - 1)
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000368 endif
Bram Moolenaar1e015462005-09-25 22:16:38 +0000369 endif
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000370
371
Bram Moolenaar1e015462005-09-25 22:16:38 +0000372 if !s:iftoskip && a:StopAfterFirstPrevElse && getline(beforeelse) =~# '^\s*\%([}]\s*\)\=else\%(if\)\=\>'
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000373 return beforeelse
Bram Moolenaar1e015462005-09-25 22:16:38 +0000374 endif
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000375
Bram Moolenaar1e015462005-09-25 22:16:38 +0000376 if getline(beforeelse) !~# '^\s*if\>' && beforeelse>1 || s:iftoskip && beforeelse>1
377
Bram Moolenaar8408a9a2010-07-30 22:41:22 +0200378 if s:iftoskip && getline(beforeelse) =~# '^\s*if\>'
Bram Moolenaar1e015462005-09-25 22:16:38 +0000379 let s:iftoskip = s:iftoskip - 1
380 endif
381
382 let s:level = s:level + 1
383 let beforeelse = FindTheIfOfAnElse(beforeelse, a:StopAfterFirstPrevElse)
384 endif
385
386 return beforeelse
387
388endfunction " }}}
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000389
Bram Moolenaar8408a9a2010-07-30 22:41:22 +0200390let s:defaultORcase = '^\s*\%(default\|case\).*:'
391
392function! FindTheSwitchIndent (lnum) " {{{
393
Bram Moolenaar8408a9a2010-07-30 22:41:22 +0200394 let test = GetLastRealCodeLNum(a:lnum - 1)
395
396 if test <= 1
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200397 return indent(1) - shiftwidth() * b:PHP_vintage_case_default_indent
Bram Moolenaar8408a9a2010-07-30 22:41:22 +0200398 end
399
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200400 while getline(test) =~ '^\s*}' && test > 1
401 let test = GetLastRealCodeLNum(FindOpenBracket(test, 0) - 1)
Bram Moolenaar8408a9a2010-07-30 22:41:22 +0200402
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200403 if getline(test) =~ '^\s*switch\>'
404 let test = GetLastRealCodeLNum(test - 1)
Bram Moolenaar8408a9a2010-07-30 22:41:22 +0200405 endif
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200406 endwhile
Bram Moolenaar8408a9a2010-07-30 22:41:22 +0200407
408 if getline(test) =~# '^\s*switch\>'
409 return indent(test)
410 elseif getline(test) =~# s:defaultORcase
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200411 return indent(test) - shiftwidth() * b:PHP_vintage_case_default_indent
Bram Moolenaar8408a9a2010-07-30 22:41:22 +0200412 else
413 return FindTheSwitchIndent(test)
414 endif
415
416endfunction "}}}
417
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200418let s:SynPHPMatchGroups = {'phpparent':1, 'delimiter':1, 'define':1, 'storageclass':1, 'structure':1, 'exception':1}
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000419function! IslinePHP (lnum, tofind) " {{{
Bram Moolenaar1e015462005-09-25 22:16:38 +0000420 let cline = getline(a:lnum)
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000421
Bram Moolenaar1e015462005-09-25 22:16:38 +0000422 if a:tofind==""
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200423 let tofind = "^\\s*[\"'`]*\\s*\\zs\\S"
Bram Moolenaar1e015462005-09-25 22:16:38 +0000424 else
425 let tofind = a:tofind
426 endif
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000427
Bram Moolenaar1e015462005-09-25 22:16:38 +0000428 let tofind = tofind . '\c'
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000429
Bram Moolenaar1e015462005-09-25 22:16:38 +0000430 let coltotest = match (cline, tofind) + 1
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000431
Bram Moolenaar1e015462005-09-25 22:16:38 +0000432 let synname = synIDattr(synID(a:lnum, coltotest, 0), "name")
433
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200434 if synname ==? 'phpStringSingle' || synname ==? 'phpStringDouble' || synname ==? 'phpBacktick'
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200435 if cline !~ '^\s*[''"`]'
Bram Moolenaared32d942014-12-06 23:33:00 +0100436 return "SpecStringEntrails"
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200437 else
438 return synname
439 end
440 end
441
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200442 if get(s:SynPHPMatchGroups, tolower(synname)) || synname =~ '^php' || synname =~? '^javaScript'
Bram Moolenaar1e015462005-09-25 22:16:38 +0000443 return synname
444 else
445 return ""
446 endif
447endfunction " }}}
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000448
Bram Moolenaar5c736222010-01-06 20:54:52 +0100449let s:autoresetoptions = 0
450if ! s:autoresetoptions
451 let s:autoresetoptions = 1
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000452endif
453
Bram Moolenaar5c736222010-01-06 20:54:52 +0100454function! ResetPhpOptions()
Bram Moolenaared32d942014-12-06 23:33:00 +0100455 if ! b:optionsset && &filetype =~ "php"
Bram Moolenaara5792f52005-11-23 21:25:05 +0000456 if b:PHP_autoformatcomment
457
458 setlocal comments=s1:/*,mb:*,ex:*/,://,:#
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000459
Bram Moolenaarc236c162008-07-13 17:41:49 +0000460 setlocal formatoptions-=t
Bram Moolenaara5792f52005-11-23 21:25:05 +0000461 setlocal formatoptions+=q
462 setlocal formatoptions+=r
463 setlocal formatoptions+=o
Bram Moolenaara5792f52005-11-23 21:25:05 +0000464 setlocal formatoptions+=c
465 setlocal formatoptions+=b
466 endif
Bram Moolenaar1e015462005-09-25 22:16:38 +0000467 let b:optionsset = 1
468 endif
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000469endfunc
470
Bram Moolenaar5c736222010-01-06 20:54:52 +0100471call ResetPhpOptions()
472
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200473function! GetPhpIndentVersion()
474 return "1.66-bundle"
475endfun
476
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000477function! GetPhpIndent()
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000478
Bram Moolenaar05a7bb32006-01-19 22:09:32 +0000479 let b:GetLastRealCodeLNum_ADD = 0
480
Bram Moolenaar1e015462005-09-25 22:16:38 +0000481 let UserIsEditing=0
482 if b:PHP_oldchangetick != b:changedtick
483 let b:PHP_oldchangetick = b:changedtick
484 let UserIsEditing=1
485 endif
486
487 if b:PHP_default_indenting
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200488 let b:PHP_default_indenting = g:PHP_default_indenting * shiftwidth()
Bram Moolenaar1e015462005-09-25 22:16:38 +0000489 endif
490
491 let cline = getline(v:lnum)
492
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000493 if !b:PHP_indentinghuge && b:PHP_lastindented > b:PHP_indentbeforelast
Bram Moolenaar1e015462005-09-25 22:16:38 +0000494 if b:PHP_indentbeforelast
495 let b:PHP_indentinghuge = 1
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000496 endif
Bram Moolenaar1e015462005-09-25 22:16:38 +0000497 let b:PHP_indentbeforelast = b:PHP_lastindented
498 endif
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000499
Bram Moolenaar1e015462005-09-25 22:16:38 +0000500 if b:InPHPcode_checked && prevnonblank(v:lnum - 1) != b:PHP_lastindented
501 if b:PHP_indentinghuge
Bram Moolenaar1e015462005-09-25 22:16:38 +0000502 let b:PHP_indentinghuge = 0
503 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000504 endif
Bram Moolenaared32d942014-12-06 23:33:00 +0100505 let real_PHP_lastindented = v:lnum
Bram Moolenaar1e015462005-09-25 22:16:38 +0000506 let b:PHP_LastIndentedWasComment=0
507 let b:PHP_InsideMultilineComment=0
508 let b:PHP_indentbeforelast = 0
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000509
Bram Moolenaar1e015462005-09-25 22:16:38 +0000510 let b:InPHPcode = 0
511 let b:InPHPcode_checked = 0
512 let b:InPHPcode_and_script = 0
513 let b:InPHPcode_tofind = ""
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000514
Bram Moolenaar1e015462005-09-25 22:16:38 +0000515 elseif v:lnum > b:PHP_lastindented
516 let real_PHP_lastindented = b:PHP_lastindented
Bram Moolenaared32d942014-12-06 23:33:00 +0100517 else
518 let real_PHP_lastindented = v:lnum
Bram Moolenaar1e015462005-09-25 22:16:38 +0000519 endif
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000520
Bram Moolenaared32d942014-12-06 23:33:00 +0100521 let b:PHP_lastindented = v:lnum
522
Bram Moolenaar1e015462005-09-25 22:16:38 +0000523
524 if !b:InPHPcode_checked " {{{ One time check
525 let b:InPHPcode_checked = 1
Bram Moolenaarcbebd482016-02-07 23:02:56 +0100526 let b:UserIsTypingComment = 0
Bram Moolenaar1e015462005-09-25 22:16:38 +0000527
Bram Moolenaar05a7bb32006-01-19 22:09:32 +0000528 let synname = ""
529 if cline !~ '<?.*?>'
530 let synname = IslinePHP (prevnonblank(v:lnum), "")
531 endif
Bram Moolenaar1e015462005-09-25 22:16:38 +0000532
533 if synname!=""
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200534 if synname ==? "SpecStringEntrails"
Bram Moolenaare0720cb2017-03-29 13:48:40 +0200535 let b:InPHPcode = -1 " thumb down
Bram Moolenaared32d942014-12-06 23:33:00 +0100536 let b:InPHPcode_tofind = ""
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200537 elseif synname !=? "phpHereDoc" && synname !=? "phpHereDocDelimiter"
Bram Moolenaar1e015462005-09-25 22:16:38 +0000538 let b:InPHPcode = 1
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000539 let b:InPHPcode_tofind = ""
540
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200541 if synname =~? '^php\%(Doc\)\?Comment'
Bram Moolenaar1e015462005-09-25 22:16:38 +0000542 let b:UserIsTypingComment = 1
Bram Moolenaarcbebd482016-02-07 23:02:56 +0100543 let b:InPHPcode_checked = 0
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000544 endif
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000545
Bram Moolenaar1e015462005-09-25 22:16:38 +0000546 if synname =~? '^javaScript'
547 let b:InPHPcode_and_script = 1
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000548 endif
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000549
Bram Moolenaar1e015462005-09-25 22:16:38 +0000550 else
551 let b:InPHPcode = 0
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000552
Bram Moolenaar1e015462005-09-25 22:16:38 +0000553 let lnum = v:lnum - 1
Bram Moolenaarcbebd482016-02-07 23:02:56 +0100554 while getline(lnum) !~? '<<<\s*[''"]\=\a\w*[''"]\=$' && lnum > 1
Bram Moolenaar1e015462005-09-25 22:16:38 +0000555 let lnum = lnum - 1
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000556 endwhile
557
Bram Moolenaarcbebd482016-02-07 23:02:56 +0100558 let b:InPHPcode_tofind = substitute( getline(lnum), '^.*<<<\s*[''"]\=\(\a\w*\)[''"]\=$', '^\\s*\1;\\=$', '')
Bram Moolenaar1e015462005-09-25 22:16:38 +0000559 endif
560 else
561 let b:InPHPcode = 0
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200562 let b:InPHPcode_tofind = s:PHP_startindenttag
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000563 endif
Bram Moolenaar1e015462005-09-25 22:16:38 +0000564 endif "!b:InPHPcode_checked }}}
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000565
566
Bram Moolenaar1e015462005-09-25 22:16:38 +0000567 " Test if we are indenting PHP code {{{
568 let lnum = prevnonblank(v:lnum - 1)
569 let last_line = getline(lnum)
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200570 let endline= s:endline
Bram Moolenaar1e015462005-09-25 22:16:38 +0000571
572 if b:InPHPcode_tofind!=""
573 if cline =~? b:InPHPcode_tofind
Bram Moolenaar1e015462005-09-25 22:16:38 +0000574 let b:InPHPcode_tofind = ""
575 let b:UserIsTypingComment = 0
Bram Moolenaared32d942014-12-06 23:33:00 +0100576
577 if b:InPHPcode == -1
578 let b:InPHPcode = 1
579 return -1
580 end
581
582 let b:InPHPcode = 1
583
Bram Moolenaar1e015462005-09-25 22:16:38 +0000584 if cline =~ '\*/'
585 call cursor(v:lnum, 1)
586 if cline !~ '^\*/'
587 call search('\*/', 'W')
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000588 endif
Bram Moolenaara5792f52005-11-23 21:25:05 +0000589 let lnum = searchpair('/\*', '', '\*/', s:searchpairflags, 'Skippmatch2()')
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000590
Bram Moolenaar1e015462005-09-25 22:16:38 +0000591 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000592
Bram Moolenaar1e015462005-09-25 22:16:38 +0000593 let b:PHP_LastIndentedWasComment = 0
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000594
Bram Moolenaar1e015462005-09-25 22:16:38 +0000595 if cline =~ '^\s*\*/'
596 return indent(lnum) + 1
597 else
598 return indent(lnum)
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000599 endif
600
Bram Moolenaar1e015462005-09-25 22:16:38 +0000601 elseif cline =~? '<script\>'
602 let b:InPHPcode_and_script = 1
Bram Moolenaar05a7bb32006-01-19 22:09:32 +0000603 let b:GetLastRealCodeLNum_ADD = v:lnum
Bram Moolenaar1e015462005-09-25 22:16:38 +0000604 endif
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000605 endif
Bram Moolenaar1e015462005-09-25 22:16:38 +0000606 endif
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000607
Bram Moolenaared32d942014-12-06 23:33:00 +0100608 if 1 == b:InPHPcode
Bram Moolenaar1e015462005-09-25 22:16:38 +0000609
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200610 if !b:InPHPcode_and_script && last_line =~ '\%(<?.*\)\@<!?>\%(.*<?\)\@!' && IslinePHP(lnum, '?>')=~?"Delimiter"
Bram Moolenaar1e015462005-09-25 22:16:38 +0000611 if cline !~? s:PHP_startindenttag
612 let b:InPHPcode = 0
613 let b:InPHPcode_tofind = s:PHP_startindenttag
614 elseif cline =~? '<script\>'
615 let b:InPHPcode_and_script = 1
616 endif
617
Bram Moolenaare0720cb2017-03-29 13:48:40 +0200618 elseif last_line =~ '^[^''"`]\+[''"`]$' " a string identifier with nothing after it and no other string identifier before
Bram Moolenaared32d942014-12-06 23:33:00 +0100619 let b:InPHPcode = -1
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200620 let b:InPHPcode_tofind = substitute( last_line, '^.*\([''"`]\).*$', '^[^\1]*\1[;,]$', '')
Bram Moolenaarcbebd482016-02-07 23:02:56 +0100621 elseif last_line =~? '<<<\s*[''"]\=\a\w*[''"]\=$'
Bram Moolenaar1e015462005-09-25 22:16:38 +0000622 let b:InPHPcode = 0
Bram Moolenaarcbebd482016-02-07 23:02:56 +0100623 let b:InPHPcode_tofind = substitute( last_line, '^.*<<<\s*[''"]\=\(\a\w*\)[''"]\=$', '^\\s*\1;\\=$', '')
Bram Moolenaar1e015462005-09-25 22:16:38 +0000624
625 elseif !UserIsEditing && cline =~ '^\s*/\*\%(.*\*/\)\@!' && getline(v:lnum + 1) !~ '^\s*\*'
626 let b:InPHPcode = 0
627 let b:InPHPcode_tofind = '\*/'
628
629 elseif cline =~? '^\s*</script>'
630 let b:InPHPcode = 0
631 let b:InPHPcode_tofind = s:PHP_startindenttag
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000632 endif
Bram Moolenaar1e015462005-09-25 22:16:38 +0000633 endif " }}}
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000634
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000635
Bram Moolenaared32d942014-12-06 23:33:00 +0100636 if 1 > b:InPHPcode && !b:InPHPcode_and_script
Bram Moolenaar1e015462005-09-25 22:16:38 +0000637 return -1
638 endif
639
Bram Moolenaar1e015462005-09-25 22:16:38 +0000640 " Indent successive // or # comment the same way the first is {{{
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200641 let addSpecial = 0
Bram Moolenaar1e015462005-09-25 22:16:38 +0000642 if cline =~ '^\s*\%(//\|#\|/\*.*\*/\s*$\)'
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200643 let addSpecial = b:PHP_outdentSLComments
Bram Moolenaar1e015462005-09-25 22:16:38 +0000644 if b:PHP_LastIndentedWasComment == 1
645 return indent(real_PHP_lastindented)
646 endif
647 let b:PHP_LastIndentedWasComment = 1
648 else
649 let b:PHP_LastIndentedWasComment = 0
650 endif " }}}
651
652 " Indent multiline /* comments correctly {{{
653
654 if b:PHP_InsideMultilineComment || b:UserIsTypingComment
655 if cline =~ '^\s*\*\%(\/\)\@!'
656 if last_line =~ '^\s*/\*'
657 return indent(lnum) + 1
658 else
659 return indent(lnum)
660 endif
661 else
662 let b:PHP_InsideMultilineComment = 0
663 endif
664 endif
665
Bram Moolenaared32d942014-12-06 23:33:00 +0100666 if !b:PHP_InsideMultilineComment && cline =~ '^\s*/\*\%(.*\*/\)\@!'
Bram Moolenaar05a7bb32006-01-19 22:09:32 +0000667 if getline(v:lnum + 1) !~ '^\s*\*'
668 return -1
669 endif
Bram Moolenaar1e015462005-09-25 22:16:38 +0000670 let b:PHP_InsideMultilineComment = 1
Bram Moolenaar1e015462005-09-25 22:16:38 +0000671 endif " }}}
672
673
674 " Things always indented at col 1 (PHP delimiter: <?, ?>, Heredoc end) {{{
Bram Moolenaar8408a9a2010-07-30 22:41:22 +0200675 if cline =~# '^\s*<?' && cline !~ '?>' && b:PHP_outdentphpescape
Bram Moolenaar1e015462005-09-25 22:16:38 +0000676 return 0
677 endif
678
Bram Moolenaar8408a9a2010-07-30 22:41:22 +0200679 if cline =~ '^\s*?>' && cline !~# '<?' && b:PHP_outdentphpescape
Bram Moolenaar1e015462005-09-25 22:16:38 +0000680 return 0
681 endif
682
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200683 if cline =~? '^\s*\a\w*;$\|^\a\w*$\|^\s*[''"`][;,]' && cline !~? s:notPhpHereDoc
Bram Moolenaar1e015462005-09-25 22:16:38 +0000684 return 0
685 endif " }}}
686
687 let s:level = 0
688
689 let lnum = GetLastRealCodeLNum(v:lnum - 1)
Bram Moolenaar05a7bb32006-01-19 22:09:32 +0000690
Bram Moolenaar1e015462005-09-25 22:16:38 +0000691 let last_line = getline(lnum)
692 let ind = indent(lnum)
Bram Moolenaar1e015462005-09-25 22:16:38 +0000693
694 if ind==0 && b:PHP_default_indenting
695 let ind = b:PHP_default_indenting
696 endif
697
698 if lnum == 0
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200699 return b:PHP_default_indenting + addSpecial
Bram Moolenaar1e015462005-09-25 22:16:38 +0000700 endif
701
702
703 if cline =~ '^\s*}\%(}}\)\@!'
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200704 let ind = indent(FindOpenBracket(v:lnum, 1))
Bram Moolenaar1e015462005-09-25 22:16:38 +0000705 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000706 return ind
Bram Moolenaar1e015462005-09-25 22:16:38 +0000707 endif
708
709 if cline =~ '^\s*\*/'
710 call cursor(v:lnum, 1)
711 if cline !~ '^\*/'
712 call search('\*/', 'W')
713 endif
Bram Moolenaara5792f52005-11-23 21:25:05 +0000714 let lnum = searchpair('/\*', '', '\*/', s:searchpairflags, 'Skippmatch2()')
Bram Moolenaar1e015462005-09-25 22:16:38 +0000715
716 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
717
718 if cline =~ '^\s*\*/'
719 return indent(lnum) + 1
720 else
721 return indent(lnum)
722 endif
723 endif
724
Bram Moolenaar1e015462005-09-25 22:16:38 +0000725
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200726 if last_line =~ '[;}]'.endline && last_line !~ '^[)\]]' && last_line !~# s:defaultORcase
Bram Moolenaar1e015462005-09-25 22:16:38 +0000727 if ind==b:PHP_default_indenting
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200728 return b:PHP_default_indenting + addSpecial
Bram Moolenaar1e015462005-09-25 22:16:38 +0000729 elseif b:PHP_indentinghuge && ind==b:PHP_CurrentIndentLevel && cline !~# '^\s*\%(else\|\%(case\|default\).*:\|[})];\=\)' && last_line !~# '^\s*\%(\%(}\s*\)\=else\)' && getline(GetLastRealCodeLNum(lnum - 1))=~';'.endline
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200730 return b:PHP_CurrentIndentLevel + addSpecial
Bram Moolenaar1e015462005-09-25 22:16:38 +0000731 endif
732 endif
733
734 let LastLineClosed = 0
735
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200736 let terminated = s:terminated
Bram Moolenaar1e015462005-09-25 22:16:38 +0000737
Bram Moolenaare0720cb2017-03-29 13:48:40 +0200738 let unstated = s:unstated
739
Bram Moolenaar1e015462005-09-25 22:16:38 +0000740
741 if ind != b:PHP_default_indenting && cline =~# '^\s*else\%(if\)\=\>'
742 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
743 return indent(FindTheIfOfAnElse(v:lnum, 1))
Bram Moolenaar8408a9a2010-07-30 22:41:22 +0200744 elseif cline =~# s:defaultORcase
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200745 return FindTheSwitchIndent(v:lnum) + shiftwidth() * b:PHP_vintage_case_default_indent
Bram Moolenaarc236c162008-07-13 17:41:49 +0000746 elseif cline =~ '^\s*)\=\s*{'
Bram Moolenaar1e015462005-09-25 22:16:38 +0000747 let previous_line = last_line
748 let last_line_num = lnum
749
750 while last_line_num > 1
751
Bram Moolenaare0720cb2017-03-29 13:48:40 +0200752 if previous_line =~ terminated || previous_line =~ s:structureHead
Bram Moolenaar1e015462005-09-25 22:16:38 +0000753
754 let ind = indent(last_line_num)
755
756 if b:PHP_BracesAtCodeLevel
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200757 let ind = ind + shiftwidth()
Bram Moolenaar1e015462005-09-25 22:16:38 +0000758 endif
759
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000760 return ind
Bram Moolenaar1e015462005-09-25 22:16:38 +0000761 endif
762
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200763 let last_line_num = GetLastRealCodeLNum(last_line_num - 1)
Bram Moolenaar1e015462005-09-25 22:16:38 +0000764 let previous_line = getline(last_line_num)
765 endwhile
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200766 elseif cline =~ '^\s*->'
767 return FindArrowIndent(lnum)
Bram Moolenaarc236c162008-07-13 17:41:49 +0000768 elseif last_line =~# unstated && cline !~ '^\s*);\='.endline
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200769 let ind = ind + shiftwidth() " we indent one level further when the preceding line is not stated
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200770 return ind + addSpecial
Bram Moolenaar1e015462005-09-25 22:16:38 +0000771
Bram Moolenaared32d942014-12-06 23:33:00 +0100772 elseif (ind != b:PHP_default_indenting || last_line =~ '^[)\]]' ) && last_line =~ terminated
Bram Moolenaar1e015462005-09-25 22:16:38 +0000773 let previous_line = last_line
774 let last_line_num = lnum
775 let LastLineClosed = 1
776
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200777 let isSingleLineBlock = 0
Bram Moolenaar1e015462005-09-25 22:16:38 +0000778 while 1
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200779 if ! isSingleLineBlock && previous_line =~ '^\s*}\|;\s*}'.endline
Bram Moolenaar1e015462005-09-25 22:16:38 +0000780
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200781 call cursor(last_line_num, 1)
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200782 if previous_line !~ '^}'
783 call search('}\|;\s*}'.endline, 'W')
784 end
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200785 let oldLastLine = last_line_num
786 let last_line_num = searchpair('{', '', '}', 'bW', 'Skippmatch()')
787
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200788 if getline(last_line_num) =~ '^\s*{'
Bram Moolenaar1e015462005-09-25 22:16:38 +0000789 let last_line_num = GetLastRealCodeLNum(last_line_num - 1)
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200790 elseif oldLastLine == last_line_num
791 let isSingleLineBlock = 1
792 continue
Bram Moolenaar1e015462005-09-25 22:16:38 +0000793 endif
794
795 let previous_line = getline(last_line_num)
796
797 continue
798 else
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200799 let isSingleLineBlock = 0
Bram Moolenaar1e015462005-09-25 22:16:38 +0000800
801 if getline(last_line_num) =~# '^\s*else\%(if\)\=\>'
802 let last_line_num = FindTheIfOfAnElse(last_line_num, 0)
803 continue
804 endif
805
806
807 let last_match = last_line_num
808
809 let one_ahead_indent = indent(last_line_num)
810 let last_line_num = GetLastRealCodeLNum(last_line_num - 1)
811 let two_ahead_indent = indent(last_line_num)
812 let after_previous_line = previous_line
813 let previous_line = getline(last_line_num)
814
815
Bram Moolenaar8408a9a2010-07-30 22:41:22 +0200816 if previous_line =~# s:defaultORcase.'\|{'.endline
Bram Moolenaar1e015462005-09-25 22:16:38 +0000817 break
818 endif
819
820 if after_previous_line=~# '^\s*'.s:blockstart.'.*)'.endline && previous_line =~# '[;}]'.endline
821 break
822 endif
823
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000824 if one_ahead_indent == two_ahead_indent || last_line_num < 1
Bram Moolenaarc236c162008-07-13 17:41:49 +0000825 if previous_line =~# '\%(;\|^\s*}\)'.endline || last_line_num < 1
Bram Moolenaar1e015462005-09-25 22:16:38 +0000826 break
827 endif
828 endif
829 endif
830 endwhile
831
832 if indent(last_match) != ind
833 let ind = indent(last_match)
834 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
835
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200836 return ind + addSpecial
Bram Moolenaar1e015462005-09-25 22:16:38 +0000837 endif
838 endif
839
Bram Moolenaared32d942014-12-06 23:33:00 +0100840 if (last_line !~ '^\s*}\%(}}\)\@!')
841 let plinnum = GetLastRealCodeLNum(lnum - 1)
842 else
843 let plinnum = GetLastRealCodeLNum(FindOpenBracket(lnum, 1) - 1)
844 endif
845
Bram Moolenaar8408a9a2010-07-30 22:41:22 +0200846 let AntepenultimateLine = getline(plinnum)
Bram Moolenaar1e015462005-09-25 22:16:38 +0000847
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200848 let last_line = StripEndlineComments(last_line)
Bram Moolenaar1e015462005-09-25 22:16:38 +0000849
850 if ind == b:PHP_default_indenting
Bram Moolenaared32d942014-12-06 23:33:00 +0100851 if last_line =~ terminated && last_line !~# s:defaultORcase
Bram Moolenaar1e015462005-09-25 22:16:38 +0000852 let LastLineClosed = 1
853 endif
854 endif
855
856 if !LastLineClosed
857
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200858 let openedparent = -1
859
Bram Moolenaar5c736222010-01-06 20:54:52 +0100860
Bram Moolenaare0720cb2017-03-29 13:48:40 +0200861 if last_line =~# '[{(\[]'.endline || last_line =~? '\h\w*\s*(.*,$' && AntepenultimateLine !~ '[,(\[]'.endline && BalanceDirection(last_line) > 0
Bram Moolenaar1e015462005-09-25 22:16:38 +0000862
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200863 let dontIndent = 0
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200864 if last_line =~ '\S\+\s*{'.endline && last_line !~ '^\s*[)\]]\+\(\s*:\s*'.s:PHP_validVariable.'\)\=\s*{'.endline && last_line !~ s:structureHead
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200865 let dontIndent = 1
866 endif
867
868 if !dontIndent && (!b:PHP_BracesAtCodeLevel || last_line !~# '^\s*{')
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200869 let ind = ind + shiftwidth()
Bram Moolenaar1e015462005-09-25 22:16:38 +0000870 endif
871
Bram Moolenaar8408a9a2010-07-30 22:41:22 +0200872 if b:PHP_BracesAtCodeLevel || b:PHP_vintage_case_default_indent == 1
Bram Moolenaar1e015462005-09-25 22:16:38 +0000873 let b:PHP_CurrentIndentLevel = ind
Bram Moolenaarc236c162008-07-13 17:41:49 +0000874
Bram Moolenaar1e015462005-09-25 22:16:38 +0000875 endif
876
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200877 elseif last_line =~ '),'.endline && BalanceDirection(last_line) < 0
Bram Moolenaar1e015462005-09-25 22:16:38 +0000878 call cursor(lnum, 1)
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200879 call searchpos('),'.endline, 'cW')
Bram Moolenaar1e015462005-09-25 22:16:38 +0000880 let openedparent = searchpair('(', '', ')', 'bW', 'Skippmatch()')
881 if openedparent != lnum
882 let ind = indent(openedparent)
883 endif
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200884
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200885 elseif last_line =~ s:structureHead
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200886 let ind = ind + shiftwidth()
Bram Moolenaar1e015462005-09-25 22:16:38 +0000887
Bram Moolenaarc236c162008-07-13 17:41:49 +0000888
Bram Moolenaare0720cb2017-03-29 13:48:40 +0200889 elseif AntepenultimateLine =~ '{'.endline && AntepenultimateLine !~? '^\s*use\>' || AntepenultimateLine =~ terminated || AntepenultimateLine =~# s:defaultORcase
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200890 let ind = ind + shiftwidth()
Bram Moolenaar1e015462005-09-25 22:16:38 +0000891 endif
892
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200893
894 if openedparent >= 0
895 let last_line = StripEndlineComments(getline(openedparent))
896 endif
Bram Moolenaar1e015462005-09-25 22:16:38 +0000897 endif
898
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200899 if cline =~ '^\s*[)\]];\='
900 let ind = ind - shiftwidth()
901 endif
902
903 if last_line =~ '^\s*->' && last_line !~? s:structureHead && BalanceDirection(last_line) <= 0
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200904 let ind = ind - shiftwidth()
Bram Moolenaar1e015462005-09-25 22:16:38 +0000905 endif
906
907 let b:PHP_CurrentIndentLevel = ind
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200908 return ind + addSpecial
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000909endfunction