xref: /vim-8.2.3635/runtime/indent/php.vim (revision dee2e315)
1" Vim indent file
2" Language:	PHP
3" Author:	John Wellesz <John.wellesz (AT) teaser (DOT) fr>
4" URL:		http://www.2072productions.com/vim/indent/php.vim
5" Home:		https://github.com/2072/PHP-Indenting-for-VIm
6" Last Change:	2013 May 10th
7" Version:	1.37
8"
9"
10"	Type :help php-indent for available options
11"
12"	A fully commented version of this file is available on github
13"
14"
15"  If you find a bug, please open a ticket on github.org
16"  ( https://github.com/2072/PHP-Indenting-for-VIm/issues ) with an example of
17"  code that breaks the algorithm.
18"
19
20" NOTE: This script must be used with PHP syntax ON and with the php syntax
21"	script by Lutz Eymers (http://www.isp.de/data/php.vim ) or with the
22"	script by Peter Hodge (http://www.vim.org/scripts/script.php?script_id=1571 )
23"	the later is bunbdled by default with Vim 7.
24"
25"
26"	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 ';').
30"
31
32" 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:
37"
38"	:%s /\r$//g
39"
40"	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).
42"
43
44if exists("b:did_indent")
45    finish
46endif
47let b:did_indent = 1
48
49
50let php_sync_method = 0
51
52
53
54if exists("PHP_default_indenting")
55    let b:PHP_default_indenting = PHP_default_indenting * &sw
56else
57    let b:PHP_default_indenting = 0
58endif
59
60if exists("PHP_outdentSLComments")
61    let b:PHP_outdentSLComments = PHP_outdentSLComments * &sw
62else
63    let b:PHP_outdentSLComments = 0
64endif
65
66if exists("PHP_BracesAtCodeLevel")
67    let b:PHP_BracesAtCodeLevel = PHP_BracesAtCodeLevel
68else
69    let b:PHP_BracesAtCodeLevel = 0
70endif
71
72
73if exists("PHP_autoformatcomment")
74    let b:PHP_autoformatcomment = PHP_autoformatcomment
75else
76    let b:PHP_autoformatcomment = 1
77endif
78
79if exists("PHP_outdentphpescape")
80    let b:PHP_outdentphpescape = PHP_outdentphpescape
81else
82    let b:PHP_outdentphpescape = 1
83endif
84
85
86if exists("PHP_vintage_case_default_indent") && PHP_vintage_case_default_indent
87    let b:PHP_vintage_case_default_indent = 1
88else
89    let b:PHP_vintage_case_default_indent = 0
90endif
91
92
93
94let b:PHP_lastindented = 0
95let b:PHP_indentbeforelast = 0
96let b:PHP_indentinghuge = 0
97let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
98let b:PHP_LastIndentedWasComment = 0
99let b:PHP_InsideMultilineComment = 0
100let b:InPHPcode = 0
101let b:InPHPcode_checked = 0
102let b:InPHPcode_and_script = 0
103let b:InPHPcode_tofind = ""
104let b:PHP_oldchangetick = b:changedtick
105let b:UserIsTypingComment = 0
106let b:optionsset = 0
107
108setlocal nosmartindent
109setlocal noautoindent
110setlocal nocindent
111setlocal nolisp
112
113setlocal indentexpr=GetPhpIndent()
114setlocal indentkeys=0{,0},0),:,!^F,o,O,e,*<Return>,=?>,=<?,=*/
115
116
117
118let s:searchpairflags = 'bWr'
119
120if &fileformat == "unix" && exists("PHP_removeCRwhenUnix") && PHP_removeCRwhenUnix
121    silent! %s/\r$//g
122endif
123
124if exists("*GetPhpIndent")
125    call ResetPhpOptions()
126    finish " XXX -- comment this line for easy dev
127endif
128
129let s:endline= '\s*\%(//.*\|#.*\|/\*.*\*/\s*\)\=$'
130let s:PHP_startindenttag = '<?\%(.*?>\)\@!\|<script[^>]*>\%(.*<\/script>\)\@!'
131
132
133function! DebugPrintReturn(scriptLine)
134
135    echo "debug:" . a:scriptLine
136    call getchar()
137
138endfunction
139
140function! GetLastRealCodeLNum(startline) " {{{
141
142    let lnum = a:startline
143
144    if b:GetLastRealCodeLNum_ADD && b:GetLastRealCodeLNum_ADD == lnum + 1
145	let lnum = b:GetLastRealCodeLNum_ADD
146    endif
147
148    let old_lnum = lnum
149
150    while lnum > 1
151	let lnum = prevnonblank(lnum)
152	let lastline = getline(lnum)
153
154	if b:InPHPcode_and_script && lastline =~ '?>\s*$'
155	    let lnum = lnum - 1
156	elseif lastline =~ '^\s*?>.*<?\%(php\)\=\s*$'
157	    let lnum = lnum - 1
158	elseif lastline =~ '^\s*\%(//\|#\|/\*.*\*/\s*$\)'
159	    let lnum = lnum - 1
160	elseif lastline =~ '\*/\s*$'
161	    call cursor(lnum, 1)
162	    if lastline !~ '^\*/'
163		call search('\*/', 'W')
164	    endif
165	    let lnum = searchpair('/\*', '', '\*/', s:searchpairflags, 'Skippmatch2()')
166
167	    let lastline = getline(lnum)
168	    if lastline =~ '^\s*/\*'
169		let lnum = lnum - 1
170	    else
171		break
172	    endif
173
174
175	elseif lastline =~? '\%(//\s*\|?>.*\)\@<!<?\%(php\)\=\s*$\|^\s*<script\>'
176
177	    while lastline !~ '\(<?.*\)\@<!?>' && lnum > 1
178		let lnum = lnum - 1
179		let lastline = getline(lnum)
180	    endwhile
181	    if lastline =~ '^\s*?>'
182		let lnum = lnum - 1
183	    else
184		break
185	    endif
186
187
188	elseif lastline =~? '^\a\w*;\=$' && lastline !~? s:notPhpHereDoc
189	    let tofind=substitute( lastline, '\(\a\w*\);\=', '<<<''\\=\1''\\=$', '')
190	    while getline(lnum) !~? tofind && lnum > 1
191		let lnum = lnum - 1
192	    endwhile
193	else
194	    break
195	endif
196    endwhile
197
198    if lnum==1 && getline(lnum) !~ '<?'
199	let lnum=0
200    endif
201
202    if b:InPHPcode_and_script && !b:InPHPcode
203	let b:InPHPcode_and_script = 0
204    endif
205
206    return lnum
207endfunction " }}}
208
209function! Skippmatch2()
210
211    let line = getline(".")
212
213    if line =~ "\\([\"']\\).*/\\*.*\\1" || line =~ '\%(//\|#\).*/\*'
214        return 1
215    else
216        return 0
217    endif
218endfun
219
220function! Skippmatch()	" {{{
221    let synname = synIDattr(synID(line("."), col("."), 0), "name")
222    if synname == "Delimiter" || synname == "phpRegionDelimiter" || synname =~# "^phpParent" || synname == "phpArrayParens" || synname =~# '^php\%(Block\|Brace\)' || synname == "javaScriptBraces" || synname =~# "^phpComment" && b:UserIsTypingComment
223	return 0
224    else
225	return 1
226    endif
227endfun " }}}
228
229function! FindOpenBracket(lnum) " {{{
230    call cursor(a:lnum, 1)
231    return searchpair('{', '', '}', 'bW', 'Skippmatch()')
232endfun " }}}
233
234function! FindTheIfOfAnElse (lnum, StopAfterFirstPrevElse) " {{{
235
236    if getline(a:lnum) =~# '^\s*}\s*else\%(if\)\=\>'
237	let beforeelse = a:lnum
238    else
239	let beforeelse = GetLastRealCodeLNum(a:lnum - 1)
240    endif
241
242    if !s:level
243	let s:iftoskip = 0
244    endif
245
246    if getline(beforeelse) =~# '^\s*\%(}\s*\)\=else\%(\s*if\)\@!\>'
247	let s:iftoskip = s:iftoskip + 1
248    endif
249
250    if getline(beforeelse) =~ '^\s*}'
251	let beforeelse = FindOpenBracket(beforeelse)
252
253	if getline(beforeelse) =~ '^\s*{'
254	    let beforeelse = GetLastRealCodeLNum(beforeelse - 1)
255	endif
256    endif
257
258
259    if !s:iftoskip && a:StopAfterFirstPrevElse && getline(beforeelse) =~# '^\s*\%([}]\s*\)\=else\%(if\)\=\>'
260	return beforeelse
261    endif
262
263    if getline(beforeelse) !~# '^\s*if\>' && beforeelse>1 || s:iftoskip && beforeelse>1
264
265	if s:iftoskip && getline(beforeelse) =~# '^\s*if\>'
266	    let s:iftoskip = s:iftoskip - 1
267	endif
268
269	let s:level =  s:level + 1
270	let beforeelse = FindTheIfOfAnElse(beforeelse, a:StopAfterFirstPrevElse)
271    endif
272
273    return beforeelse
274
275endfunction " }}}
276
277let s:defaultORcase = '^\s*\%(default\|case\).*:'
278
279function! FindTheSwitchIndent (lnum) " {{{
280
281
282    let test = GetLastRealCodeLNum(a:lnum - 1)
283
284    if test <= 1
285	return indent(1) - &sw * b:PHP_vintage_case_default_indent
286    end
287
288    if getline(test) =~ '^\s*}'
289	let test = FindOpenBracket(test)
290
291	if getline(test) =~ '^\s*{'
292	    let test = GetLastRealCodeLNum(GetLastRealCodeLNum(test - 1) - 1)
293	endif
294    endif
295
296    if getline(test) =~# '^\s*switch\>'
297	return indent(test)
298    elseif getline(test) =~# s:defaultORcase
299	return indent(test) - &sw * b:PHP_vintage_case_default_indent
300    else
301	return FindTheSwitchIndent(test)
302    endif
303
304endfunction "}}}
305
306
307function! IslinePHP (lnum, tofind) " {{{
308    let cline = getline(a:lnum)
309
310    if a:tofind==""
311	let tofind = "^\\s*[\"']*\\s*\\zs\\S"
312    else
313	let tofind = a:tofind
314    endif
315
316    let tofind = tofind . '\c'
317
318    let coltotest = match (cline, tofind) + 1
319
320    let synname = synIDattr(synID(a:lnum, coltotest, 0), "name")
321
322    if synname =~ '^php' || synname=="Delimiter" || synname =~? '^javaScript'
323	return synname
324    else
325	return ""
326    endif
327endfunction " }}}
328
329let s:notPhpHereDoc = '\%(break\|return\|continue\|exit\|die\|else\)'
330let s:blockstart = '\%(\%(\%(}\s*\)\=else\%(\s\+\)\=\)\=if\>\|else\>\|while\>\|switch\>\|case\>\|default\>\|for\%(each\)\=\>\|declare\>\|class\>\|interface\>\|abstract\>\|try\>\|catch\>\)'
331
332let s:autoresetoptions = 0
333if ! s:autoresetoptions
334    let s:autoresetoptions = 1
335endif
336
337function! ResetPhpOptions()
338    if ! b:optionsset && &filetype == "php"
339	if b:PHP_autoformatcomment
340
341	    setlocal comments=s1:/*,mb:*,ex:*/,://,:#
342
343	    setlocal formatoptions-=t
344	    setlocal formatoptions+=q
345	    setlocal formatoptions+=r
346	    setlocal formatoptions+=o
347	    setlocal formatoptions+=w
348	    setlocal formatoptions+=c
349	    setlocal formatoptions+=b
350	endif
351	let b:optionsset = 1
352    endif
353endfunc
354
355call ResetPhpOptions()
356
357function! GetPhpIndent()
358
359    let b:GetLastRealCodeLNum_ADD = 0
360
361    let UserIsEditing=0
362    if	b:PHP_oldchangetick != b:changedtick
363	let b:PHP_oldchangetick = b:changedtick
364	let UserIsEditing=1
365    endif
366
367    if b:PHP_default_indenting
368	let b:PHP_default_indenting = g:PHP_default_indenting * &sw
369    endif
370
371    let cline = getline(v:lnum)
372
373    if !b:PHP_indentinghuge && b:PHP_lastindented > b:PHP_indentbeforelast
374	if b:PHP_indentbeforelast
375	    let b:PHP_indentinghuge = 1
376	endif
377	let b:PHP_indentbeforelast = b:PHP_lastindented
378    endif
379
380    if b:InPHPcode_checked && prevnonblank(v:lnum - 1) != b:PHP_lastindented
381	if b:PHP_indentinghuge
382	    let b:PHP_indentinghuge = 0
383	    let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
384	endif
385	let b:PHP_lastindented = v:lnum
386	let b:PHP_LastIndentedWasComment=0
387	let b:PHP_InsideMultilineComment=0
388	let b:PHP_indentbeforelast = 0
389
390	let b:InPHPcode = 0
391	let b:InPHPcode_checked = 0
392	let b:InPHPcode_and_script = 0
393	let b:InPHPcode_tofind = ""
394
395    elseif v:lnum > b:PHP_lastindented
396	let real_PHP_lastindented = b:PHP_lastindented
397	let b:PHP_lastindented = v:lnum
398    endif
399
400
401    if !b:InPHPcode_checked " {{{ One time check
402	let b:InPHPcode_checked = 1
403
404	let synname = ""
405	if cline !~ '<?.*?>'
406	    let synname = IslinePHP (prevnonblank(v:lnum), "")
407	endif
408
409	if synname!=""
410	    if synname != "phpHereDoc" && synname != "phpHereDocDelimiter"
411		let b:InPHPcode = 1
412		let b:InPHPcode_tofind = ""
413
414		if synname =~# "^phpComment"
415		    let b:UserIsTypingComment = 1
416		else
417		    let b:UserIsTypingComment = 0
418		endif
419
420		if synname =~? '^javaScript'
421		    let b:InPHPcode_and_script = 1
422		endif
423
424	    else
425		let b:InPHPcode = 0
426		let b:UserIsTypingComment = 0
427
428		let lnum = v:lnum - 1
429		while getline(lnum) !~? '<<<''\=\a\w*''\=$' && lnum > 1
430		    let lnum = lnum - 1
431		endwhile
432
433		let b:InPHPcode_tofind = substitute( getline(lnum), '^.*<<<''\=\(\a\w*\)''\=$', '^\\s*\1;\\=$', '')
434	    endif
435	else
436	    let b:InPHPcode = 0
437	    let b:UserIsTypingComment = 0
438	    let b:InPHPcode_tofind = s:PHP_startindenttag
439	endif
440    endif "!b:InPHPcode_checked }}}
441
442
443    " Test if we are indenting PHP code {{{
444    let lnum = prevnonblank(v:lnum - 1)
445    let last_line = getline(lnum)
446
447    if b:InPHPcode_tofind!=""
448	if cline =~? b:InPHPcode_tofind
449	    let b:InPHPcode = 1
450	    let b:InPHPcode_tofind = ""
451	    let b:UserIsTypingComment = 0
452	    if cline =~ '\*/'
453		call cursor(v:lnum, 1)
454		if cline !~ '^\*/'
455		    call search('\*/', 'W')
456		endif
457		let lnum = searchpair('/\*', '', '\*/', s:searchpairflags, 'Skippmatch2()')
458
459		let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
460
461		let b:PHP_LastIndentedWasComment = 0
462
463		if cline =~ '^\s*\*/'
464		    return indent(lnum) + 1
465		else
466		    return indent(lnum)
467		endif
468
469	    elseif cline =~? '<script\>'
470		let b:InPHPcode_and_script = 1
471		let b:GetLastRealCodeLNum_ADD = v:lnum
472	    endif
473	endif
474    endif
475
476    if b:InPHPcode
477
478	if !b:InPHPcode_and_script && last_line =~ '\%(<?.*\)\@<!?>\%(.*<?\)\@!' && IslinePHP(lnum, '?>')=~"Delimiter"
479	    if cline !~? s:PHP_startindenttag
480		let b:InPHPcode = 0
481		let b:InPHPcode_tofind = s:PHP_startindenttag
482	    elseif cline =~? '<script\>'
483		let b:InPHPcode_and_script = 1
484	    endif
485
486	elseif last_line =~? '<<<''\=\a\w*''\=$'
487	    let b:InPHPcode = 0
488	    let b:InPHPcode_tofind = substitute( last_line, '^.*<<<''\=\(\a\w*\)''\=$', '^\\s*\1;\\=$', '')
489
490	elseif !UserIsEditing && cline =~ '^\s*/\*\%(.*\*/\)\@!' && getline(v:lnum + 1) !~ '^\s*\*'
491	    let b:InPHPcode = 0
492	    let b:InPHPcode_tofind = '\*/'
493
494	elseif cline =~? '^\s*</script>'
495	    let b:InPHPcode = 0
496	    let b:InPHPcode_tofind = s:PHP_startindenttag
497	endif
498    endif " }}}
499
500
501    if !b:InPHPcode && !b:InPHPcode_and_script
502	return -1
503    endif
504
505    " Indent successive // or # comment the same way the first is {{{
506    let addSpecial = 0
507    if cline =~ '^\s*\%(//\|#\|/\*.*\*/\s*$\)'
508	let addSpecial = b:PHP_outdentSLComments
509	if b:PHP_LastIndentedWasComment == 1
510	    return indent(real_PHP_lastindented)
511	endif
512	let b:PHP_LastIndentedWasComment = 1
513    else
514	let b:PHP_LastIndentedWasComment = 0
515    endif " }}}
516
517    " Indent multiline /* comments correctly {{{
518
519    if b:PHP_InsideMultilineComment || b:UserIsTypingComment
520	if cline =~ '^\s*\*\%(\/\)\@!'
521	    if last_line =~ '^\s*/\*'
522		return indent(lnum) + 1
523	    else
524		return indent(lnum)
525	    endif
526	else
527	    let b:PHP_InsideMultilineComment = 0
528	endif
529    endif
530
531    if !b:PHP_InsideMultilineComment && cline =~ '^\s*/\*' && cline !~ '\*/\s*$'
532	if getline(v:lnum + 1) !~ '^\s*\*'
533	    return -1
534	endif
535	let b:PHP_InsideMultilineComment = 1
536    endif " }}}
537
538
539    " Things always indented at col 1 (PHP delimiter: <?, ?>, Heredoc end) {{{
540    if cline =~# '^\s*<?' && cline !~ '?>' && b:PHP_outdentphpescape
541	return 0
542    endif
543
544    if	cline =~ '^\s*?>' && cline !~# '<?' && b:PHP_outdentphpescape
545	return 0
546    endif
547
548    if cline =~? '^\s*\a\w*;$\|^\a\w*$' && cline !~? s:notPhpHereDoc
549	return 0
550    endif " }}}
551
552    let s:level = 0
553
554    let lnum = GetLastRealCodeLNum(v:lnum - 1)
555
556    let last_line = getline(lnum)
557    let ind = indent(lnum)
558    let endline= s:endline
559
560    if ind==0 && b:PHP_default_indenting
561	let ind = b:PHP_default_indenting
562    endif
563
564    if lnum == 0
565	return b:PHP_default_indenting + addSpecial
566    endif
567
568
569    if cline =~ '^\s*}\%(}}\)\@!'
570	let ind = indent(FindOpenBracket(v:lnum))
571	let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
572	return ind
573    endif
574
575    if cline =~ '^\s*\*/'
576	call cursor(v:lnum, 1)
577	if cline !~ '^\*/'
578	    call search('\*/', 'W')
579	endif
580	let lnum = searchpair('/\*', '', '\*/', s:searchpairflags, 'Skippmatch2()')
581
582	let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
583
584	if cline =~ '^\s*\*/'
585	    return indent(lnum) + 1
586	else
587	    return indent(lnum)
588	endif
589    endif
590
591
592    if last_line =~ '[;}]'.endline && last_line !~ '^[)\]]' && last_line !~# s:defaultORcase
593	if ind==b:PHP_default_indenting
594	    return b:PHP_default_indenting + addSpecial
595	elseif b:PHP_indentinghuge && ind==b:PHP_CurrentIndentLevel && cline !~# '^\s*\%(else\|\%(case\|default\).*:\|[})];\=\)' && last_line !~# '^\s*\%(\%(}\s*\)\=else\)' && getline(GetLastRealCodeLNum(lnum - 1))=~';'.endline
596	    return b:PHP_CurrentIndentLevel + addSpecial
597	endif
598    endif
599
600    let LastLineClosed = 0
601
602    let terminated = '\%(;\%(\s*\%(?>\|}\)\)\=\|<<<''\=\a\w*''\=$\|^\s*}\)'.endline
603
604    let unstated   = '\%(^\s*'.s:blockstart.'.*)\|\%(//.*\)\@<!\<e'.'lse\>\)'.endline
605
606    if ind != b:PHP_default_indenting && cline =~# '^\s*else\%(if\)\=\>'
607	let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
608	return indent(FindTheIfOfAnElse(v:lnum, 1))
609    elseif cline =~# s:defaultORcase
610	return FindTheSwitchIndent(v:lnum) + &sw * b:PHP_vintage_case_default_indent
611    elseif cline =~ '^\s*)\=\s*{'
612	let previous_line = last_line
613	let last_line_num = lnum
614
615	while last_line_num > 1
616
617	    if previous_line =~ '^\s*\%(' . s:blockstart . '\|\%([a-zA-Z]\s*\)*function\)'
618
619		let ind = indent(last_line_num)
620
621		if  b:PHP_BracesAtCodeLevel
622		    let ind = ind + &sw
623		endif
624
625		return ind
626	    endif
627
628	    let last_line_num = last_line_num - 1
629	    let previous_line = getline(last_line_num)
630	endwhile
631
632    elseif last_line =~# unstated && cline !~ '^\s*);\='.endline
633	let ind = ind + &sw " we indent one level further when the preceding line is not stated
634	return ind + addSpecial
635
636    elseif (ind != b:PHP_default_indenting || last_line =~ '^[)\]]' ) && last_line =~ terminated " Added || last_line =~ '^)' on 2007-12-30 (array indenting problem broke other things)
637	let previous_line = last_line
638	let last_line_num = lnum
639	let LastLineClosed = 1
640
641	while 1
642	    if previous_line =~ '^\s*}\|;\s*}'.endline " XXX
643
644		call cursor(last_line_num, 1)
645		call search('}\|;\s*}'.endline, 'W')
646		let oldLastLine = last_line_num
647		let last_line_num = searchpair('{', '', '}', 'bW', 'Skippmatch()')
648
649		if oldLastLine == last_line_num || getline(last_line_num) =~ '^\s*{'
650		    let last_line_num = GetLastRealCodeLNum(last_line_num - 1)
651		endif
652
653		let previous_line = getline(last_line_num)
654
655		continue
656	    else
657
658		if getline(last_line_num) =~# '^\s*else\%(if\)\=\>'
659		    let last_line_num = FindTheIfOfAnElse(last_line_num, 0)
660		    continue
661		endif
662
663
664		let last_match = last_line_num
665
666		let one_ahead_indent = indent(last_line_num)
667		let last_line_num = GetLastRealCodeLNum(last_line_num - 1)
668		let two_ahead_indent = indent(last_line_num)
669		let after_previous_line = previous_line
670		let previous_line = getline(last_line_num)
671
672
673		if previous_line =~# s:defaultORcase.'\|{'.endline
674		    break
675		endif
676
677		if after_previous_line=~# '^\s*'.s:blockstart.'.*)'.endline && previous_line =~# '[;}]'.endline
678		    break
679		endif
680
681		if one_ahead_indent == two_ahead_indent || last_line_num < 1
682		    if previous_line =~# '\%(;\|^\s*}\)'.endline || last_line_num < 1
683			break
684		    endif
685		endif
686	    endif
687	endwhile
688
689	if indent(last_match) != ind
690	    let ind = indent(last_match)
691	    let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
692
693	    return ind + addSpecial
694	endif
695    endif
696
697    let plinnum = GetLastRealCodeLNum(lnum - 1)
698    let AntepenultimateLine = getline(plinnum)
699
700    let last_line = substitute(last_line,"\\(//\\|#\\)\\(\\(\\([^\"']*\\([\"']\\)[^\"']*\\5\\)\\+[^\"']*$\\)\\|\\([^\"']*$\\)\\)",'','')
701
702
703    if ind == b:PHP_default_indenting
704	if last_line =~ terminated
705	    let LastLineClosed = 1
706	endif
707    endif
708
709    if !LastLineClosed
710
711
712	if last_line =~# '[{(\[]'.endline || last_line =~? '\h\w*\s*(.*,$' && AntepenultimateLine !~ '[,(]'.endline
713
714	    if !b:PHP_BracesAtCodeLevel || last_line !~# '^\s*{'
715		let ind = ind + &sw
716	    endif
717
718	    if b:PHP_BracesAtCodeLevel || b:PHP_vintage_case_default_indent == 1
719		let b:PHP_CurrentIndentLevel = ind
720
721		return ind + addSpecial
722	    endif
723
724	elseif last_line =~ '\S\+\s*),'.endline
725	    call cursor(lnum, 1)
726	    call search('),'.endline, 'W')
727	    let openedparent = searchpair('(', '', ')', 'bW', 'Skippmatch()')
728	    if openedparent != lnum
729		let ind = indent(openedparent)
730	    endif
731
732	elseif last_line =~ '^\s*'.s:blockstart
733	    let ind = ind + &sw
734
735
736	elseif AntepenultimateLine =~ '\%(;\%(\s*\%(?>\|}\)\)\=\|<<<''\=\a\w*''\=$\|^\s*}\|{\)'.endline . '\|' . s:defaultORcase
737	    let ind = ind + &sw
738	endif
739
740    endif
741
742    if cline =~  '^\s*[)\]];\='
743	let ind = ind - &sw
744    endif
745
746    let b:PHP_CurrentIndentLevel = ind
747    return ind + addSpecial
748endfunction
749