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