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