codekingpro/portable-devtools
114k
1" Language: PHP2" Author: John Wellesz <John.wellesz (AT) gmail (DOT) com>3" URL: https://www.2072productions.com/vim/indent/php.vim4" Home: https://github.com/2072/PHP-Indenting-for-VIm5" Last Change: 2025 November 16th6" Version: 1.767"8"9" Type :help php-indent for available options10"11" A fully commented version of this file is available on github12"13"14" If you find a bug, please open a ticket on github.com15" ( https://github.com/2072/PHP-Indenting-for-VIm/issues ) with an example of16" code that breaks the algorithm.17"18 19" NOTE: This script must be used with PHP syntax ON and with the php syntax20" script by Lutz Eymers (http://www.isp.de/data/php.vim ) or with the21" script by Peter Hodge (https://www.vim.org/scripts/script.php?script_id=1571 )22" the later is bunbdled by default with Vim 7.23"24"25" In the case you have syntax errors in your script such as HereDoc end26" identifiers not at col 1 you'll have to indent your file 2 times (This27" script will automatically put HereDoc end identifiers at col 1 if28" they are followed by a ';').29"30 31" NOTE: If you are editing files in Unix file format and that (by accident)32" there are '\r' before new lines, this script won't be able to proceed33" correctly and will make many mistakes because it won't be able to match34" '\s*$' correctly.35" So you have to remove those useless characters first with a command like:36"37" :%s /\r$//g38"39" or simply 'let' the option PHP_removeCRwhenUnix to 1 and the script will40" silently remove them when VIM load this script (at each bufread).41 42 43if exists("b:did_indent")44 finish45endif46let b:did_indent = 147 48 49let g:php_sync_method = 050 51 52if exists("PHP_default_indenting")53 let b:PHP_default_indenting = PHP_default_indenting * shiftwidth()54else55 let b:PHP_default_indenting = 056endif57 58if exists("PHP_outdentSLComments")59 let b:PHP_outdentSLComments = PHP_outdentSLComments * shiftwidth()60else61 let b:PHP_outdentSLComments = 062endif63 64if exists("PHP_BracesAtCodeLevel")65 let b:PHP_BracesAtCodeLevel = PHP_BracesAtCodeLevel66else67 let b:PHP_BracesAtCodeLevel = 068endif69 70 71if exists("PHP_autoformatcomment")72 let b:PHP_autoformatcomment = PHP_autoformatcomment73else74 let b:PHP_autoformatcomment = 175endif76 77if exists("PHP_outdentphpescape")78 let b:PHP_outdentphpescape = PHP_outdentphpescape79else80 let b:PHP_outdentphpescape = 181endif82 83if exists("PHP_noArrowMatching")84 let b:PHP_noArrowMatching = PHP_noArrowMatching85else86 let b:PHP_noArrowMatching = 087endif88 89 90if exists("PHP_vintage_case_default_indent") && PHP_vintage_case_default_indent91 let b:PHP_vintage_case_default_indent = 192else93 let b:PHP_vintage_case_default_indent = 094endif95 96if exists("PHP_IndentFunctionCallParameters")97 let b:PHP_IndentFunctionCallParameters = PHP_IndentFunctionCallParameters98else99 let b:PHP_IndentFunctionCallParameters = 0100endif101 102if exists("PHP_IndentFunctionDeclarationParameters")103 let b:PHP_IndentFunctionDeclarationParameters = PHP_IndentFunctionDeclarationParameters104else105 let b:PHP_IndentFunctionDeclarationParameters = 0106endif107 108let b:PHP_lastindented = 0109let b:PHP_indentbeforelast = 0110let b:PHP_indentinghuge = 0111let b:PHP_CurrentIndentLevel = b:PHP_default_indenting112let b:PHP_LastIndentedWasComment = 0113let b:PHP_InsideMultilineComment = 0114let b:InPHPcode = 0115let b:InPHPcode_checked = 0116let b:InPHPcode_and_script = 0117let b:InPHPcode_tofind = ""118let b:PHP_oldchangetick = b:changedtick119let b:UserIsTypingComment = 0120let b:optionsset = 0121 122setlocal nosmartindent123setlocal noautoindent124setlocal nocindent125setlocal nolisp126 127setlocal indentexpr=GetPhpIndent()128setlocal indentkeys=0{,0},0),0],:,!^F,o,O,e,*<Return>,=?>,=<?,=*/129 130let b:undo_indent = "setl ai< cin< inde< indk< lisp< si<"131 132let s:searchpairflags = 'bWr'133 134if &fileformat == "unix" && exists("PHP_removeCRwhenUnix") && PHP_removeCRwhenUnix135 silent! %s/\r$//g136endif137 138if exists("*GetPhpIndent")139 call ResetPhpOptions()140 finish " XXX -- comment this line for easy dev141endif142 143 144let s:endline = '\s*\%(//.*\|#\[\@!.*\|/\*.*\*/\s*\)\=$'145let s:PHP_validVariable = '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*'146let s:notPhpHereDoc = '\<\%(break\|return\|continue\|exit\|die\|true\|false\|elseif\|else\|end\%(if\|while\|for\|foreach\|match\|switch\)\)\>'147let s:blockstart = '\%(\%(\%(}\s*\)\=else\%(\s\+\)\=\)\=if\>\|\%(}\s*\)\?else\>\|do\>\|while\>\|match\>\|switch\>\|case\>\|default\>\|for\%(each\)\=\>\|declare\>\|class\>\|trait\>\|\%()\s*\)\=use\>\|interface\>\|abstract\>\|final\>\|try\>\|\%(}\s*\)\=catch\>\|\%(}\s*\)\=finally\>\)'148let s:functionDeclPrefix = '\<function\>\%(\s\+&\='.s:PHP_validVariable.'\)\=\s*('149let s:functionDecl = s:functionDeclPrefix.'.*'150let s:multilineFunctionDecl = s:functionDeclPrefix.s:endline151let s:arrayDecl = '\<array\>\s*(.*'152let s:multilineFunctionCall = s:PHP_validVariable.'\s*('.s:endline153let s:unstated = '\%(^\s*'.s:blockstart.'.*)\|\%(//.*\)\@<!\<e'.'lse\>\)'.s:endline154 155 156let s:terminated = '\%(\%(;\%(\s*\%(?>\|}\)\)\=\|<<<\s*[''"]\=\a\w*[''"]\=$\|^\s*}\|^\s*'.s:PHP_validVariable.':\)'.s:endline.'\)'157let s:PHP_startindenttag = '<?\%(.*?>\)\@!\|<script[^>]*>\%(.*<\/script>\)\@!'158let s:matchStart = 'match\s*(\s*\$\?'.s:PHP_validVariable.'\s*)\s*{'. s:endline159let s:structureHead = '^\s*\%(' . s:blockstart . '\)\|'. s:functionDecl . s:endline . '\|\<new\s\+class\>\|' . s:matchStart160 161 162let s:escapeDebugStops = 0163function! DebugPrintReturn(scriptLine)164 165 if ! s:escapeDebugStops166 echo "debug:" . a:scriptLine167 let c = getchar()168 if c == "\<Del>"169 let s:escapeDebugStops = 1170 end171 endif172 173endfunction174 175function! GetLastRealCodeLNum(startline) " {{{176 177 let lnum = a:startline178 179 if b:GetLastRealCodeLNum_ADD && b:GetLastRealCodeLNum_ADD == lnum + 1180 let lnum = b:GetLastRealCodeLNum_ADD181 endif182 183 while lnum > 1184 let lnum = prevnonblank(lnum)185 let lastline = getline(lnum)186 187 if b:InPHPcode_and_script && lastline =~ '?>\s*$'188 let lnum = lnum - 1189 elseif lastline =~ '^\s*?>.*<?\%(php\)\=\s*$'190 let lnum = lnum - 1191 elseif lastline =~ '^\s*\%(//\|#\|/\*.*\*/\s*$\)'192 let lnum = lnum - 1193 elseif lastline =~ '\*/\s*$'194 call cursor(lnum, 1)195 if lastline !~ '^\*/'196 call search('\*/', 'W')197 endif198 let lnum = searchpair('/\*', '', '\*/', s:searchpairflags, 'Skippmatch2()')199 200 let lastline = getline(lnum)201 if lastline =~ '^\s*/\*'202 let lnum = lnum - 1203 else204 break205 endif206 207 208 elseif lastline =~? '\%(//\s*\|?>.*\)\@<!<?\%(php\)\=\s*$\|^\s*<script\>'209 210 while lastline !~ '\(<?.*\)\@<!?>' && lnum > 1211 let lnum = lnum - 1212 let lastline = getline(lnum)213 endwhile214 if lastline =~ '^\s*?>'215 let lnum = lnum - 1216 else217 break218 endif219 220 221 elseif lastline =~? '^\a\w*;\=$' && lastline !~? s:notPhpHereDoc222 let tofind=substitute( lastline, '\(\a\w*\);\=', '<<<\\s*[''"]\\=\1[''"]\\=$', '')223 while getline(lnum) !~? tofind && lnum > 1224 let lnum = lnum - 1225 endwhile226 elseif lastline =~ '^\s*[''"`][;,]'.s:endline || (lastline =~ '^[^''"`]*[''"`][;,]'.s:endline && IslinePHP(lnum, "") == "SpecStringEntrails")227 228 let tofind=substitute( lastline, '^.*\([''"`]\)[;,].*$', '^[^\1]\\+[\1]$\\|^[^\1]\\+[=([]\\s*[\1]', '')229 let trylnum = lnum230 while getline(trylnum) !~? tofind && trylnum > 1231 let trylnum = trylnum - 1232 endwhile233 234 if trylnum == 1235 break236 else237 if lastline =~ ';'.s:endline238 while getline(trylnum) !~? s:terminated && getline(trylnum) !~? '{'.s:endline && trylnum > 1239 let trylnum = prevnonblank(trylnum - 1)240 endwhile241 242 243 if trylnum == 1244 break245 end246 end247 let lnum = trylnum248 end249 else250 break251 endif252 endwhile253 254 if lnum==1 && getline(lnum) !~ '<?'255 let lnum=0256 endif257 258 if b:InPHPcode_and_script && 1 > b:InPHPcode259 let b:InPHPcode_and_script = 0260 endif261 262 return lnum263endfunction " }}}264 265function! Skippmatch2()266 267 let line = getline(".")268 269 if line =~ "\\([\"']\\).*/\\*.*\\1" || line =~ '\%(//\|#\[\@!\).*/\*'270 return 1271 else272 return 0273 endif274endfun275 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:UserIsTypingComment279 return 0280 else281 return 1282 endif283endfun " }}}284 285function! FindOpenBracket(lnum, blockStarter) " {{{286 call cursor(a:lnum, 1)287 let line = searchpair('{', '', '}', 'bW', 'Skippmatch()')288 289 if a:blockStarter == 1290 while line > 1291 let linec = getline(line)292 293 if linec =~ s:terminated || linec =~ s:structureHead294 break295 endif296 297 let line = GetLastRealCodeLNum(line - 1)298 endwhile299 endif300 301 return line302endfun " }}}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 endif318 endif319 endfor320 321 return balance[director]322endfun323 324function! StripEndlineComments (line)325 326 let cleaned = substitute(a:line,'\v(//|#\[\@!)((([^"'']*(["''])[^"'']*\5)+[^"'']*$)|([^"'']*$))','','')327 if cleaned != a:line328 endif329 return cleaned330endfun331 332function! FindArrowIndent (lnum) " {{{333 334 let parentArrowPos = -1335 let cursorPos = -1336 let lnum = a:lnum337 while lnum > 1338 let last_line = getline(lnum)339 if last_line =~ '^\s*->'340 let parentArrowPos = indent(a:lnum)341 break342 else343 344 if b:PHP_noArrowMatching345 break346 endif347 348 let cleanedLnum = StripEndlineComments(last_line)349 350 if cleanedLnum =~ ')'.s:endline351 if BalanceDirection(cleanedLnum) <= 0352 call cursor(lnum, 1)353 call searchpos(')'.s:endline, 'cW', lnum)354 let openedparent = searchpair('(', '', ')', 'bW', 'Skippmatch()')355 let cursorPos = col(".")356 if openedparent != lnum357 let lnum = openedparent358 continue359 else360 endif361 else362 let parentArrowPos = -1363 break364 end365 endif366 367 if cleanedLnum =~ '->'368 call cursor(lnum, cursorPos == -1 ? strwidth(cleanedLnum) : cursorPos)369 let parentArrowPos = searchpos('->', 'cWb', lnum)[1] - 1370 371 break372 else373 let parentArrowPos = -1374 break375 endif376 endif377 endwhile378 379 if parentArrowPos == -1380 let parentArrowPos = indent(lnum) + shiftwidth()381 end382 383 return parentArrowPos384endfun "}}}385 386function! FindTheIfOfAnElse (lnum, StopAfterFirstPrevElse) " {{{387 388 if getline(a:lnum) =~# '^\s*}\s*else\%(if\)\=\>'389 let beforeelse = a:lnum390 else391 let beforeelse = GetLastRealCodeLNum(a:lnum - 1)392 endif393 394 if !s:level395 let s:iftoskip = 0396 endif397 398 if getline(beforeelse) =~# '^\s*\%(}\s*\)\=else\%(\s*if\)\@!\>'399 let s:iftoskip = s:iftoskip + 1400 endif401 402 if getline(beforeelse) =~ '^\s*}'403 let beforeelse = FindOpenBracket(beforeelse, 0)404 405 if getline(beforeelse) =~ '^\s*{'406 let beforeelse = GetLastRealCodeLNum(beforeelse - 1)407 endif408 endif409 410 411 if !s:iftoskip && a:StopAfterFirstPrevElse && getline(beforeelse) =~# '^\s*\%([}]\s*\)\=else\%(if\)\=\>'412 return beforeelse413 endif414 415 if getline(beforeelse) !~# '^\s*if\>' && beforeelse>1 || s:iftoskip && beforeelse>1416 417 if s:iftoskip && getline(beforeelse) =~# '^\s*if\>'418 let s:iftoskip = s:iftoskip - 1419 endif420 421 let s:level = s:level + 1422 let beforeelse = FindTheIfOfAnElse(beforeelse, a:StopAfterFirstPrevElse)423 endif424 425 return beforeelse426 427endfunction " }}}428 429let s:defaultORcase = '^\s*\%(default\|case\).*:'430 431function! FindTheSwitchIndent (lnum) " {{{432 433 let test = GetLastRealCodeLNum(a:lnum - 1)434 435 if test <= 1436 return indent(1) - shiftwidth() * b:PHP_vintage_case_default_indent437 end438 439 while getline(test) =~ '^\s*}' && test > 1440 let test = GetLastRealCodeLNum(FindOpenBracket(test, 0) - 1)441 442 if getline(test) =~ '^\s*switch\>'443 let test = GetLastRealCodeLNum(test - 1)444 endif445 endwhile446 447 if getline(test) =~# '^\s*switch\>'448 return indent(test)449 elseif getline(test) =~# s:defaultORcase450 return indent(test) - shiftwidth() * b:PHP_vintage_case_default_indent451 else452 return FindTheSwitchIndent(test)453 endif454 455endfunction "}}}456 457let s:SynPHPMatchGroups = {'phpparent':1, 'delimiter':1, 'define':1, 'storageclass':1, 'structure':1, 'exception':1}458function! IslinePHP (lnum, tofind) " {{{459 let cline = getline(a:lnum)460 461 if a:tofind==""462 let tofind = "^\\s*[\"'`]*\\s*\\zs\\S"463 else464 let tofind = a:tofind465 endif466 467 let tofind = tofind . '\c'468 469 let coltotest = match (cline, tofind) + 1470 471 let synname = synIDattr(synID(a:lnum, coltotest, 0), "name")472 473 if synname ==? 'phpStringSingle' || synname ==? 'phpStringDouble' || synname ==? 'phpBacktick'474 if cline !~ '^\s*[''"`]' " ??? XXX475 return "SpecStringEntrails"476 else477 return synname478 end479 end480 481 if get(s:SynPHPMatchGroups, tolower(synname)) || synname =~ '^php' || synname =~? '^javaScript'482 return synname483 else484 return ""485 endif486endfunction " }}}487 488let s:autoresetoptions = 0489if ! s:autoresetoptions490 let s:autoresetoptions = 1491endif492 493function! ResetPhpOptions()494 if ! b:optionsset && &filetype =~ "php"495 if b:PHP_autoformatcomment496 497 setlocal comments=s1:/*,mb:*,ex:*/,://,f:#[,:#498 499 setlocal formatoptions-=t500 setlocal formatoptions+=q501 setlocal formatoptions+=r502 setlocal formatoptions+=o503 setlocal formatoptions+=c504 setlocal formatoptions+=b505 endif506 let b:optionsset = 1507 endif508endfunc509 510call ResetPhpOptions()511 512function! GetPhpIndentVersion()513 return "1.75"514endfun515 516function! GetPhpIndent()517 518 let b:GetLastRealCodeLNum_ADD = 0519 520 let UserIsEditing=0521 if b:PHP_oldchangetick != b:changedtick522 let b:PHP_oldchangetick = b:changedtick523 let UserIsEditing=1524 endif525 526 if b:PHP_default_indenting527 let b:PHP_default_indenting = g:PHP_default_indenting * shiftwidth()528 endif529 530 let cline = getline(v:lnum)531 532 if !b:PHP_indentinghuge && b:PHP_lastindented > b:PHP_indentbeforelast533 if b:PHP_indentbeforelast534 let b:PHP_indentinghuge = 1535 endif536 let b:PHP_indentbeforelast = b:PHP_lastindented537 endif538 539 if b:InPHPcode_checked && prevnonblank(v:lnum - 1) != b:PHP_lastindented540 if b:PHP_indentinghuge541 let b:PHP_indentinghuge = 0542 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting543 endif544 let real_PHP_lastindented = v:lnum545 let b:PHP_LastIndentedWasComment=0546 let b:PHP_InsideMultilineComment=0547 let b:PHP_indentbeforelast = 0548 549 let b:InPHPcode = 0550 let b:InPHPcode_checked = 0551 let b:InPHPcode_and_script = 0552 let b:InPHPcode_tofind = ""553 554 elseif v:lnum > b:PHP_lastindented555 let real_PHP_lastindented = b:PHP_lastindented556 else557 let real_PHP_lastindented = v:lnum558 endif559 560 let b:PHP_lastindented = v:lnum561 562 563 if !b:InPHPcode_checked " {{{ One time check564 let b:InPHPcode_checked = 1565 let b:UserIsTypingComment = 0566 567 let synname = ""568 if cline !~ '<?.*?>'569 let synname = IslinePHP (prevnonblank(v:lnum), "")570 endif571 572 if synname!=""573 if synname ==? "SpecStringEntrails"574 let b:InPHPcode = -1 " thumb down575 let b:InPHPcode_tofind = ""576 elseif synname !=? "phpHereDoc" && synname !=? "phpHereDocDelimiter"577 let b:InPHPcode = 1578 let b:InPHPcode_tofind = ""579 580 if synname =~? '^php\%(Doc\)\?Comment'581 let b:UserIsTypingComment = 1582 let b:InPHPcode_checked = 0583 endif584 585 if synname =~? '^javaScript'586 let b:InPHPcode_and_script = 1587 endif588 589 else590 let b:InPHPcode = 0591 592 let lnum = v:lnum - 1593 while getline(lnum) !~? '<<<\s*[''"]\=\a\w*[''"]\=$' && lnum > 1594 let lnum = lnum - 1595 endwhile596 597 let b:InPHPcode_tofind = substitute( getline(lnum), '^.*<<<\s*[''"]\=\(\a\w*\)[''"]\=$', '^\\s*\1;\\=$', '')598 endif599 else600 let b:InPHPcode = 0601 let b:InPHPcode_tofind = s:PHP_startindenttag602 endif603 endif "!b:InPHPcode_checked }}}604 605 606 " Test if we are indenting PHP code {{{607 let lnum = prevnonblank(v:lnum - 1)608 let last_line = getline(lnum)609 let endline= s:endline610 611 if b:InPHPcode_tofind!=""612 if cline =~? b:InPHPcode_tofind613 let b:InPHPcode_tofind = ""614 let b:UserIsTypingComment = 0615 616 if b:InPHPcode == -1617 let b:InPHPcode = 1618 return -1619 end620 621 let b:InPHPcode = 1622 623 if cline =~ '\*/'624 call cursor(v:lnum, 1)625 if cline !~ '^\*/'626 call search('\*/', 'W')627 endif628 let lnum = searchpair('/\*', '', '\*/', s:searchpairflags, 'Skippmatch2()')629 630 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting631 632 let b:PHP_LastIndentedWasComment = 0633 634 if cline =~ '^\s*\*/'635 return indent(lnum) + 1636 else637 return indent(lnum)638 endif639 640 elseif cline =~? '<script\>'641 let b:InPHPcode_and_script = 1642 let b:GetLastRealCodeLNum_ADD = v:lnum643 endif644 endif645 endif646 647 if 1 == b:InPHPcode648 649 if !b:InPHPcode_and_script && last_line =~ '\%(<?.*\)\@<!?>\%(.*<?\)\@!' && IslinePHP(lnum, '?>')=~?"Delimiter"650 if cline !~? s:PHP_startindenttag651 let b:InPHPcode = 0652 let b:InPHPcode_tofind = s:PHP_startindenttag653 elseif cline =~? '<script\>'654 let b:InPHPcode_and_script = 1655 endif656 657 elseif last_line =~ '^[^''"`]\+[''"`]$' && last_line !~ '^\s*\%(//\|#\[\@!\|/\*.*\*/\s*$\)' " a string identifier with nothing after it and no other string identifier before658 let b:InPHPcode = -1659 let b:InPHPcode_tofind = substitute( last_line, '^.*\([''"`]\).*$', '^[^\1]*\1[;,]$', '')660 elseif last_line =~? '<<<\s*[''"]\=\a\w*[''"]\=$'661 let b:InPHPcode = 0662 let b:InPHPcode_tofind = substitute( last_line, '^.*<<<\s*[''"]\=\(\a\w*\)[''"]\=$', '^\\s*\1;\\=$', '')663 664 elseif !UserIsEditing && cline =~ '^\s*/\*\%(.*\*/\)\@!' && getline(v:lnum + 1) !~ '^\s*\*'665 let b:InPHPcode = 0666 let b:InPHPcode_tofind = '\*/'667 668 elseif cline =~? '^\s*</script>'669 let b:InPHPcode = 0670 let b:InPHPcode_tofind = s:PHP_startindenttag671 endif672 endif " }}}673 674 675 if 1 > b:InPHPcode && !b:InPHPcode_and_script676 return -1677 endif678 679 " Indent successive // or # comment the same way the first is {{{680 let addSpecial = 0681 if cline =~ '^\s*\%(//\|#\[\@!\|/\*.*\*/\s*$\)'682 let addSpecial = b:PHP_outdentSLComments683 if b:PHP_LastIndentedWasComment == 1684 return indent(real_PHP_lastindented)685 endif686 let b:PHP_LastIndentedWasComment = 1687 else688 let b:PHP_LastIndentedWasComment = 0689 endif " }}}690 691 " Indent multiline /* comments correctly {{{692 693 if b:PHP_InsideMultilineComment || b:UserIsTypingComment694 if cline =~ '^\s*\*\%(\/\)\@!'695 if last_line =~ '^\s*/\*'696 return indent(lnum) + 1697 else698 return indent(lnum)699 endif700 else701 let b:PHP_InsideMultilineComment = 0702 endif703 endif704 705 if !b:PHP_InsideMultilineComment && cline =~ '^\s*/\*\%(.*\*/\)\@!'706 if getline(v:lnum + 1) !~ '^\s*\*'707 return -1708 endif709 let b:PHP_InsideMultilineComment = 1710 endif " }}}711 712 713 " Things always indented at col 1 (PHP delimiter: <?, ?>, Heredoc end) {{{714 if cline =~# '^\s*<?' && cline !~ '?>' && b:PHP_outdentphpescape715 return 0716 endif717 718 if cline =~ '^\s*?>' && cline !~# '<?' && b:PHP_outdentphpescape719 return 0720 endif721 722 if (cline =~? '^\s*\a\w*;$\|^\a\w*$' || (cline =~? '^\s*[''"`][;,]' && IslinePHP(v:lnum, '[;,]') !~? '^\(phpString[SD]\|phpBacktick\)') ) && cline !~? s:notPhpHereDoc723 return 0724 endif " }}}725 726 let s:level = 0727 728 let lnum = GetLastRealCodeLNum(v:lnum - 1)729 730 let last_line = getline(lnum)731 let ind = indent(lnum)732 733 if ind==0 && b:PHP_default_indenting734 let ind = b:PHP_default_indenting735 endif736 737 if lnum == 0738 return b:PHP_default_indenting + addSpecial739 endif740 741 742 if cline =~ '^\s*}\%(}}\)\@!'743 let ind = indent(FindOpenBracket(v:lnum, 1))744 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting745 if b:PHP_BracesAtCodeLevel746 let ind = ind + shiftwidth()747 endif748 return ind749 endif750 751 if cline =~ '^\s*\*/'752 call cursor(v:lnum, 1)753 if cline !~ '^\*/'754 call search('\*/', 'W')755 endif756 let lnum = searchpair('/\*', '', '\*/', s:searchpairflags, 'Skippmatch2()')757 758 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting759 760 if cline =~ '^\s*\*/'761 return indent(lnum) + 1762 else763 return indent(lnum)764 endif765 endif766 767 768 if last_line =~ '[;}]'.endline && last_line !~ '^[)\]]' && last_line !~# s:defaultORcase && last_line !~ '^\s*[''"`][;,]'769 if ind==b:PHP_default_indenting770 return b:PHP_default_indenting + addSpecial771 elseif b:PHP_indentinghuge && ind==b:PHP_CurrentIndentLevel && cline !~# '^\s*\%(else\|\%(case\|default\).*:\|[})];\=\)' && last_line !~# '^\s*\%(\%(}\s*\)\=else\)\|^\(\s*\S\+\s*\)\+}'.endline && getline(GetLastRealCodeLNum(lnum - 1))=~';'.endline772 return b:PHP_CurrentIndentLevel + addSpecial773 endif774 endif775 776 let LastLineClosed = 0777 778 let terminated = s:terminated779 780 let unstated = s:unstated781 782 783 if ind != b:PHP_default_indenting && cline =~# '^\s*else\%(if\)\=\>'784 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting785 return indent(FindTheIfOfAnElse(v:lnum, 1))786 elseif cline =~# s:defaultORcase787 return FindTheSwitchIndent(v:lnum) + shiftwidth() * b:PHP_vintage_case_default_indent788 elseif cline =~ '^\s*)\=\s*{'789 let previous_line = last_line790 let last_line_num = lnum791 792 while last_line_num > 1793 794 if previous_line =~ terminated || previous_line =~ s:structureHead795 796 let ind = indent(last_line_num)797 798 if b:PHP_BracesAtCodeLevel799 let ind = ind + shiftwidth()800 endif801 802 return ind803 endif804 805 let last_line_num = GetLastRealCodeLNum(last_line_num - 1)806 let previous_line = getline(last_line_num)807 endwhile808 elseif cline =~ '^\s*->'809 return FindArrowIndent(lnum)810 elseif last_line =~# unstated && cline !~ '^\s*);\='.endline811 let ind = ind + shiftwidth() " we indent one level further when the preceding line is not stated812 return ind + addSpecial813 814 elseif (ind != b:PHP_default_indenting || last_line =~ '^[)\]]' ) && last_line =~ terminated815 let previous_line = last_line816 let last_line_num = lnum817 let LastLineClosed = 1818 819 let isSingleLineBlock = 0820 while 1821 if ! isSingleLineBlock && previous_line =~ '^\s*}\|;\s*}'.endline822 823 call cursor(last_line_num, 1)824 if previous_line !~ '^}'825 call search('}\|;\s*}'.endline, 'W')826 end827 let oldLastLine = last_line_num828 let last_line_num = searchpair('{', '', '}', 'bW', 'Skippmatch()')829 830 if getline(last_line_num) =~ '^\s*{'831 let last_line_num = GetLastRealCodeLNum(last_line_num - 1)832 elseif oldLastLine == last_line_num833 let isSingleLineBlock = 1834 continue835 endif836 837 let previous_line = getline(last_line_num)838 839 continue840 else841 842 if getline(last_line_num) =~# '^\s*else\%(if\)\=\>' && !isSingleLineBlock843 let last_line_num = FindTheIfOfAnElse(last_line_num, 0)844 let isSingleLineBlock = 0845 continue846 endif847 848 let isSingleLineBlock = 0849 850 851 let last_match = last_line_num852 853 let one_ahead_indent = indent(last_line_num)854 let last_line_num = GetLastRealCodeLNum(last_line_num - 1)855 let two_ahead_indent = indent(last_line_num)856 let after_previous_line = previous_line857 let previous_line = getline(last_line_num)858 859 860 if previous_line =~# s:defaultORcase.'\|{'.endline861 break862 endif863 864 if after_previous_line=~# '^\s*'.s:blockstart.'.*)'.endline && previous_line =~# '[;}]'.endline865 break866 endif867 868 if one_ahead_indent == two_ahead_indent || last_line_num < 1869 if previous_line =~# '\%(;\|^\s*}\)'.endline || last_line_num < 1870 break871 endif872 endif873 endif874 endwhile875 876 if indent(last_match) != ind877 let ind = indent(last_match)878 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting879 880 return ind + addSpecial881 endif882 endif883 884 if (last_line !~ '^\s*}\%(}}\)\@!')885 let plinnum = GetLastRealCodeLNum(lnum - 1)886 else887 let plinnum = GetLastRealCodeLNum(FindOpenBracket(lnum, 1) - 1)888 endif889 890 let AntepenultimateLine = getline(plinnum)891 892 let last_line = StripEndlineComments(last_line)893 894 if ind == b:PHP_default_indenting895 if last_line =~ terminated && last_line !~# s:defaultORcase896 let LastLineClosed = 1897 endif898 endif899 900 if !LastLineClosed901 902 let openedparent = -1903 904 905 if last_line =~# '[{(\[]'.endline || last_line =~? '\h\w*\s*(.*,$' && AntepenultimateLine !~ '[,(\[]'.endline && BalanceDirection(last_line) > 0906 907 let dontIndent = 0908 if last_line =~ '\S\+\s*{'.endline && last_line !~ '^\s*[)\]]\+\(\s*:\s*'.s:PHP_validVariable.'\)\=\s*{'.endline && last_line !~ s:structureHead909 let dontIndent = 1910 endif911 912 if !dontIndent && (!b:PHP_BracesAtCodeLevel || last_line !~# '^\s*{')913 let ind = ind + shiftwidth()914 endif915 916 if b:PHP_IndentFunctionCallParameters && last_line =~ s:multilineFunctionCall && last_line !~ s:structureHead && last_line !~ s:arrayDecl917 let ind = ind + b:PHP_IndentFunctionCallParameters * shiftwidth()918 endif919 920 if b:PHP_IndentFunctionDeclarationParameters && last_line =~ s:multilineFunctionDecl921 let ind = ind + b:PHP_IndentFunctionDeclarationParameters * shiftwidth()922 endif923 924 if b:PHP_BracesAtCodeLevel || b:PHP_vintage_case_default_indent == 1925 let b:PHP_CurrentIndentLevel = ind926 927 endif928 929 elseif last_line =~ '),'.endline && BalanceDirection(last_line) < 0930 call cursor(lnum, 1)931 call searchpos('),'.endline, 'cW')932 let openedparent = searchpair('(', '', ')', 'bW', 'Skippmatch()')933 if openedparent != lnum934 let ind = indent(openedparent)935 endif936 937 elseif last_line =~ s:structureHead938 let ind = ind + shiftwidth()939 940 941 elseif AntepenultimateLine =~ '{'.endline && AntepenultimateLine !~? '^\s*use\>' && AntepenultimateLine !~? s:matchStart || AntepenultimateLine =~ terminated || AntepenultimateLine =~# s:defaultORcase942 let ind = ind + shiftwidth()943 endif944 945 946 if openedparent >= 0947 let last_line = StripEndlineComments(getline(openedparent))948 endif949 endif950 951 if cline =~ '^\s*[)\]];\='952 call cursor(v:lnum, 1)953 call searchpos('[)\]]', 'cW')954 let matchedBlockChar = cline[col('.')-1]955 let openedparent = searchpair('\M'.s:blockCharsLUT[matchedBlockChar], '', '\M'.matchedBlockChar, 'bW', 'Skippmatch()')956 if openedparent != v:lnum957 let ind = indent(openedparent)958 endif959 960 elseif last_line =~ '^\s*->' && last_line !~? s:structureHead && BalanceDirection(last_line) <= 0961 let ind = ind - shiftwidth()962 endif963 964 let b:PHP_CurrentIndentLevel = ind965 return ind + addSpecial966endfunction967 