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