├── .gitignore ├── Comment-stripped-version ├── README.md └── php-indent_1-75 │ ├── VimPHPIndentHelpFile.txt │ └── indent │ └── php.vim ├── README.md ├── doc └── PHPIndent.txt └── indent └── php.vim /.gitignore: -------------------------------------------------------------------------------- 1 | tags 2 | -------------------------------------------------------------------------------- /Comment-stripped-version/README.md: -------------------------------------------------------------------------------- 1 | The comment-stripped version is the one sent to Bram Moolenaar to be 2 | bundled in Vim releases. It is manually updated when a new tagged release is made. 3 | -------------------------------------------------------------------------------- /Comment-stripped-version/php-indent_1-75/VimPHPIndentHelpFile.txt: -------------------------------------------------------------------------------- 1 | PHP *ft-php-indent* *php-indent* *php-indenting* 2 | 3 | NOTE: PHP files will be indented correctly only if PHP |syntax| is active. 4 | 5 | If you are editing a file in Unix 'fileformat' and '\r' characters are present 6 | before new lines, indentation won't proceed correctly ; you have to remove 7 | those useless characters first with a command like: > 8 | 9 | :%s /\r$//g 10 | 11 | Or, you can simply |:let| the variable PHP_removeCRwhenUnix to 1 and the 12 | script will silently remove them when Vim loads a PHP file (at each |BufRead|). 13 | 14 | OPTIONS: ~ 15 | 16 | PHP indenting can be altered in several ways by modifying the values of some 17 | global variables: 18 | 19 | *php-comment* *PHP_autoformatcomment* 20 | To not enable auto-formating of comments by default (if you want to use your 21 | own 'formatoptions'): > 22 | :let g:PHP_autoformatcomment = 0 23 | 24 | Else, 't' will be removed from the 'formatoptions' string and "qrowcb" will be 25 | added, see |fo-table| for more information. 26 | ------------- 27 | 28 | *PHP_outdentSLComments* 29 | To add extra indentation to single-line comments: > 30 | :let g:PHP_outdentSLComments = N 31 | 32 | With N being the number of 'shiftwidth' to add. 33 | 34 | Only single-line comments will be affected such as: > 35 | # Comment 36 | // Comment 37 | /* Comment */ 38 | ------------- 39 | 40 | *PHP_default_indenting* 41 | To add extra indentation to every PHP lines with N being the number of 42 | 'shiftwidth' to add: > 43 | :let g:PHP_default_indenting = N 44 | 45 | For example, with N = 1, this will give: 46 | > 47 | 57 | (Notice the extra indentation between the PHP container markers and the code) 58 | ------------- 59 | 60 | *PHP_outdentphpescape* 61 | To indent PHP escape tags as the surrounding non-PHP code (only affects the 62 | PHP escape tags): > 63 | :let g:PHP_outdentphpescape = 0 64 | ------------- 65 | 66 | *PHP_removeCRwhenUnix* 67 | To automatically remove '\r' characters when the 'fileformat' is set to Unix: > 68 | :let g:PHP_removeCRwhenUnix = 1 69 | ------------- 70 | 71 | *PHP_BracesAtCodeLevel* 72 | To indent braces at the same level than the code they contain: > 73 | :let g:PHP_BracesAtCodeLevel = 1 74 | 75 | This will give the following result: > 76 | if ($foo) 77 | { 78 | foo(); 79 | } 80 | Instead of: > 81 | if ($foo) 82 | { 83 | foo(); 84 | } 85 | 86 | NOTE: Indenting will be a bit slower if this option is used because some 87 | optimizations won't be available. 88 | ------------- 89 | 90 | *PHP_vintage_case_default_indent* 91 | To indent 'case:' and 'default:' statements in switch() blocks: > 92 | :let g:PHP_vintage_case_default_indent = 1 93 | 94 | In PHP braces are not required inside 'case/default' blocks therefore 'case:' 95 | and 'default:' are indented at the same level than the 'switch()' to avoid 96 | meaningless indentation. You can use the above option to return to the 97 | traditional way. 98 | ------------- 99 | 100 | *PHP_noArrowMatching* 101 | By default the indent script will indent multi-line chained calls by matching 102 | the position of the '->': > 103 | 104 | $user_name_very_long->name() 105 | ->age() 106 | ->info(); 107 | 108 | You can revert to the classic way of indenting by setting this option to 1: > 109 | :let g:PHP_noArrowMatching = 1 110 | 111 | You will obtain the following result: > 112 | 113 | $user_name_very_long->name() 114 | ->age() 115 | ->info(); 116 | 117 | ------------- 118 | 119 | *PHP_IndentFunctionCallParameters* 120 | Extra indentation levels to add to parameters in multi-line function calls. > 121 | let g:PHP_IndentFunctionCallParameters = 1 122 | 123 | Function call arguments will indent 1 extra level. For two-space indentation: > 124 | 125 | function call_the_thing( 126 | $with_this, 127 | $and_that 128 | ) { 129 | $this->do_the_thing( 130 | $with_this, 131 | $and_that 132 | ); 133 | } 134 | 135 | ------------- 136 | 137 | *PHP_IndentFunctionDeclarationParameters* 138 | Extra indentation levels to add to arguments in multi-line function definitions. > 139 | let g:PHP_IndentFunctionDeclarationParameters = 1 140 | 141 | Function arguments in declarations will indent 1 extra level. For two-space indentation: > 142 | 143 | function call_the_thing( 144 | $with_this, 145 | $and_that 146 | ) { 147 | $this->do_the_thing( 148 | $with_this, 149 | $and_that 150 | ); 151 | } 152 | 153 | vim:tw=78:ts=8:ft=help:norl: 154 | -------------------------------------------------------------------------------- /Comment-stripped-version/php-indent_1-75/indent/php.vim: -------------------------------------------------------------------------------- 1 | " Vim indent file 2 | " Language: PHP 3 | " Author: John Wellesz 4 | " URL: https://www.2072productions.com/vim/indent/php.vim 5 | " Home: https://github.com/2072/PHP-Indenting-for-VIm 6 | " Last Change: 2023 August 18th 7 | " Version: 1.75 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 | 44 | if exists("b:did_indent") 45 | finish 46 | endif 47 | let b:did_indent = 1 48 | 49 | 50 | let g:php_sync_method = 0 51 | 52 | 53 | if exists("PHP_default_indenting") 54 | let b:PHP_default_indenting = PHP_default_indenting * shiftwidth() 55 | else 56 | let b:PHP_default_indenting = 0 57 | endif 58 | 59 | if exists("PHP_outdentSLComments") 60 | let b:PHP_outdentSLComments = PHP_outdentSLComments * shiftwidth() 61 | else 62 | let b:PHP_outdentSLComments = 0 63 | endif 64 | 65 | if exists("PHP_BracesAtCodeLevel") 66 | let b:PHP_BracesAtCodeLevel = PHP_BracesAtCodeLevel 67 | else 68 | let b:PHP_BracesAtCodeLevel = 0 69 | endif 70 | 71 | 72 | if exists("PHP_autoformatcomment") 73 | let b:PHP_autoformatcomment = PHP_autoformatcomment 74 | else 75 | let b:PHP_autoformatcomment = 1 76 | endif 77 | 78 | if exists("PHP_outdentphpescape") 79 | let b:PHP_outdentphpescape = PHP_outdentphpescape 80 | else 81 | let b:PHP_outdentphpescape = 1 82 | endif 83 | 84 | if exists("PHP_noArrowMatching") 85 | let b:PHP_noArrowMatching = PHP_noArrowMatching 86 | else 87 | let b:PHP_noArrowMatching = 0 88 | endif 89 | 90 | 91 | if exists("PHP_vintage_case_default_indent") && PHP_vintage_case_default_indent 92 | let b:PHP_vintage_case_default_indent = 1 93 | else 94 | let b:PHP_vintage_case_default_indent = 0 95 | endif 96 | 97 | if exists("PHP_IndentFunctionCallParameters") 98 | let b:PHP_IndentFunctionCallParameters = PHP_IndentFunctionCallParameters 99 | else 100 | let b:PHP_IndentFunctionCallParameters = 0 101 | endif 102 | 103 | if exists("PHP_IndentFunctionDeclarationParameters") 104 | let b:PHP_IndentFunctionDeclarationParameters = PHP_IndentFunctionDeclarationParameters 105 | else 106 | let b:PHP_IndentFunctionDeclarationParameters = 0 107 | endif 108 | 109 | let b:PHP_lastindented = 0 110 | let b:PHP_indentbeforelast = 0 111 | let b:PHP_indentinghuge = 0 112 | let b:PHP_CurrentIndentLevel = b:PHP_default_indenting 113 | let b:PHP_LastIndentedWasComment = 0 114 | let b:PHP_InsideMultilineComment = 0 115 | let b:InPHPcode = 0 116 | let b:InPHPcode_checked = 0 117 | let b:InPHPcode_and_script = 0 118 | let b:InPHPcode_tofind = "" 119 | let b:PHP_oldchangetick = b:changedtick 120 | let b:UserIsTypingComment = 0 121 | let b:optionsset = 0 122 | 123 | setlocal nosmartindent 124 | setlocal noautoindent 125 | setlocal nocindent 126 | setlocal nolisp 127 | 128 | setlocal indentexpr=GetPhpIndent() 129 | setlocal indentkeys=0{,0},0),0],:,!^F,o,O,e,*,=?>,=' 148 | let 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\>\)' 149 | let s:functionDeclPrefix = '\\%(\s\+&\='.s:PHP_validVariable.'\)\=\s*(' 150 | let s:functionDecl = s:functionDeclPrefix.'.*' 151 | let s:multilineFunctionDecl = s:functionDeclPrefix.s:endline 152 | let s:arrayDecl = '\\s*(.*' 153 | let s:multilineFunctionCall = s:PHP_validVariable.'\s*('.s:endline 154 | let s:unstated = '\%(^\s*'.s:blockstart.'.*)\|\%(//.*\)\@\)'.s:endline 155 | 156 | 157 | let s:terminated = '\%(\%(;\%(\s*\%(?>\|}\)\)\=\|<<<\s*[''"]\=\a\w*[''"]\=$\|^\s*}\|^\s*'.s:PHP_validVariable.':\)'.s:endline.'\)' 158 | let s:PHP_startindenttag = '\)\@!\|]*>\%(.*<\/script>\)\@!' 159 | let s:matchStart = 'match\s*(\s*\$\?'.s:PHP_validVariable.'\s*)\s*{'. s:endline 160 | let s:structureHead = '^\s*\%(' . s:blockstart . '\)\|'. s:functionDecl . s:endline . '\|\\|' . s:matchStart 161 | 162 | 163 | let s:escapeDebugStops = 0 164 | function! DebugPrintReturn(scriptLine) 165 | 166 | if ! s:escapeDebugStops 167 | echo "debug:" . a:scriptLine 168 | let c = getchar() 169 | if c == "\" 170 | let s:escapeDebugStops = 1 171 | end 172 | endif 173 | 174 | endfunction 175 | 176 | function! GetLastRealCodeLNum(startline) " {{{ 177 | 178 | let lnum = a:startline 179 | 180 | if b:GetLastRealCodeLNum_ADD && b:GetLastRealCodeLNum_ADD == lnum + 1 181 | let lnum = b:GetLastRealCodeLNum_ADD 182 | endif 183 | 184 | while lnum > 1 185 | let lnum = prevnonblank(lnum) 186 | let lastline = getline(lnum) 187 | 188 | if b:InPHPcode_and_script && lastline =~ '?>\s*$' 189 | let lnum = lnum - 1 190 | elseif lastline =~ '^\s*?>.*.*\)\@' 210 | 211 | while lastline !~ '\(' && lnum > 1 212 | let lnum = lnum - 1 213 | let lastline = getline(lnum) 214 | endwhile 215 | if lastline =~ '^\s*?>' 216 | let lnum = lnum - 1 217 | else 218 | break 219 | endif 220 | 221 | 222 | elseif lastline =~? '^\a\w*;\=$' && lastline !~? s:notPhpHereDoc 223 | let tofind=substitute( lastline, '\(\a\w*\);\=', '<<<\\s*[''"]\\=\1[''"]\\=$', '') 224 | while getline(lnum) !~? tofind && lnum > 1 225 | let lnum = lnum - 1 226 | endwhile 227 | elseif lastline =~ '^\s*[''"`][;,]'.s:endline || (lastline =~ '^[^''"`]*[''"`][;,]'.s:endline && IslinePHP(lnum, "") == "SpecStringEntrails") 228 | 229 | let tofind=substitute( lastline, '^.*\([''"`]\)[;,].*$', '^[^\1]\\+[\1]$\\|^[^\1]\\+[=([]\\s*[\1]', '') 230 | let trylnum = lnum 231 | while getline(trylnum) !~? tofind && trylnum > 1 232 | let trylnum = trylnum - 1 233 | endwhile 234 | 235 | if trylnum == 1 236 | break 237 | else 238 | if lastline =~ ';'.s:endline 239 | while getline(trylnum) !~? s:terminated && getline(trylnum) !~? '{'.s:endline && trylnum > 1 240 | let trylnum = prevnonblank(trylnum - 1) 241 | endwhile 242 | 243 | 244 | if trylnum == 1 245 | break 246 | end 247 | end 248 | let lnum = trylnum 249 | end 250 | else 251 | break 252 | endif 253 | endwhile 254 | 255 | if lnum==1 && getline(lnum) !~ ' b:InPHPcode 260 | let b:InPHPcode_and_script = 0 261 | endif 262 | 263 | return lnum 264 | endfunction " }}} 265 | 266 | function! Skippmatch2() 267 | 268 | let line = getline(".") 269 | 270 | if line =~ "\\([\"']\\).*/\\*.*\\1" || line =~ '\%(//\|#\[\@!\).*/\*' 271 | return 1 272 | else 273 | return 0 274 | endif 275 | endfun 276 | 277 | function! Skippmatch() " {{{ 278 | let synname = synIDattr(synID(line("."), col("."), 0), "name") 279 | if synname ==? "Delimiter" || synname ==? "phpRegionDelimiter" || synname =~? "^phpParent" || synname ==? "phpArrayParens" || synname =~? '^php\%(Block\|Brace\)' || synname ==? "javaScriptBraces" || synname =~? '^php\%(Doc\)\?Comment' && b:UserIsTypingComment 280 | return 0 281 | else 282 | return 1 283 | endif 284 | endfun " }}} 285 | 286 | function! FindOpenBracket(lnum, blockStarter) " {{{ 287 | call cursor(a:lnum, 1) 288 | let line = searchpair('{', '', '}', 'bW', 'Skippmatch()') 289 | 290 | if a:blockStarter == 1 291 | while line > 1 292 | let linec = getline(line) 293 | 294 | if linec =~ s:terminated || linec =~ s:structureHead 295 | break 296 | endif 297 | 298 | let line = GetLastRealCodeLNum(line - 1) 299 | endwhile 300 | endif 301 | 302 | return line 303 | endfun " }}} 304 | 305 | let s:blockChars = {'{':1, '[': 1, '(': 1, ')':-1, ']':-1, '}':-1} 306 | let s:blockCharsLUT = {'{':'{', '}':'{', '[':'[', ']':'[', '(':'(', ')':'('} 307 | function! BalanceDirection (str) 308 | 309 | let balance = {'{':0, '[': 0, '(': 0, 'none':0} 310 | let director = 'none' 311 | 312 | for c in split(a:str, '\zs') 313 | if has_key(s:blockChars, c) 314 | let balance[s:blockCharsLUT[c]] += s:blockChars[c] 315 | 316 | if balance[s:blockCharsLUT[c]] 317 | let director = s:blockCharsLUT[c] 318 | endif 319 | endif 320 | endfor 321 | 322 | return balance[director] 323 | endfun 324 | 325 | function! StripEndlineComments (line) 326 | 327 | let cleaned = substitute(a:line,'\v(//|#\[\@!)((([^"'']*(["''])[^"'']*\5)+[^"'']*$)|([^"'']*$))','','') 328 | if cleaned != a:line 329 | endif 330 | return cleaned 331 | endfun 332 | 333 | function! FindArrowIndent (lnum) " {{{ 334 | 335 | let parentArrowPos = -1 336 | let cursorPos = -1 337 | let lnum = a:lnum 338 | while lnum > 1 339 | let last_line = getline(lnum) 340 | if last_line =~ '^\s*->' 341 | let parentArrowPos = indent(a:lnum) 342 | break 343 | else 344 | 345 | if b:PHP_noArrowMatching 346 | break 347 | endif 348 | 349 | let cleanedLnum = StripEndlineComments(last_line) 350 | 351 | if cleanedLnum =~ ')'.s:endline 352 | if BalanceDirection(cleanedLnum) <= 0 353 | call cursor(lnum, 1) 354 | call searchpos(')'.s:endline, 'cW', lnum) 355 | let openedparent = searchpair('(', '', ')', 'bW', 'Skippmatch()') 356 | let cursorPos = col(".") 357 | if openedparent != lnum 358 | let lnum = openedparent 359 | continue 360 | else 361 | endif 362 | else 363 | let parentArrowPos = -1 364 | break 365 | end 366 | endif 367 | 368 | if cleanedLnum =~ '->' 369 | call cursor(lnum, cursorPos == -1 ? strwidth(cleanedLnum) : cursorPos) 370 | let parentArrowPos = searchpos('->', 'cWb', lnum)[1] - 1 371 | 372 | break 373 | else 374 | let parentArrowPos = -1 375 | break 376 | endif 377 | endif 378 | endwhile 379 | 380 | if parentArrowPos == -1 381 | let parentArrowPos = indent(lnum) + shiftwidth() 382 | end 383 | 384 | return parentArrowPos 385 | endfun "}}} 386 | 387 | function! FindTheIfOfAnElse (lnum, StopAfterFirstPrevElse) " {{{ 388 | 389 | if getline(a:lnum) =~# '^\s*}\s*else\%(if\)\=\>' 390 | let beforeelse = a:lnum 391 | else 392 | let beforeelse = GetLastRealCodeLNum(a:lnum - 1) 393 | endif 394 | 395 | if !s:level 396 | let s:iftoskip = 0 397 | endif 398 | 399 | if getline(beforeelse) =~# '^\s*\%(}\s*\)\=else\%(\s*if\)\@!\>' 400 | let s:iftoskip = s:iftoskip + 1 401 | endif 402 | 403 | if getline(beforeelse) =~ '^\s*}' 404 | let beforeelse = FindOpenBracket(beforeelse, 0) 405 | 406 | if getline(beforeelse) =~ '^\s*{' 407 | let beforeelse = GetLastRealCodeLNum(beforeelse - 1) 408 | endif 409 | endif 410 | 411 | 412 | if !s:iftoskip && a:StopAfterFirstPrevElse && getline(beforeelse) =~# '^\s*\%([}]\s*\)\=else\%(if\)\=\>' 413 | return beforeelse 414 | endif 415 | 416 | if getline(beforeelse) !~# '^\s*if\>' && beforeelse>1 || s:iftoskip && beforeelse>1 417 | 418 | if s:iftoskip && getline(beforeelse) =~# '^\s*if\>' 419 | let s:iftoskip = s:iftoskip - 1 420 | endif 421 | 422 | let s:level = s:level + 1 423 | let beforeelse = FindTheIfOfAnElse(beforeelse, a:StopAfterFirstPrevElse) 424 | endif 425 | 426 | return beforeelse 427 | 428 | endfunction " }}} 429 | 430 | let s:defaultORcase = '^\s*\%(default\|case\).*:' 431 | 432 | function! FindTheSwitchIndent (lnum) " {{{ 433 | 434 | let test = GetLastRealCodeLNum(a:lnum - 1) 435 | 436 | if test <= 1 437 | return indent(1) - shiftwidth() * b:PHP_vintage_case_default_indent 438 | end 439 | 440 | while getline(test) =~ '^\s*}' && test > 1 441 | let test = GetLastRealCodeLNum(FindOpenBracket(test, 0) - 1) 442 | 443 | if getline(test) =~ '^\s*switch\>' 444 | let test = GetLastRealCodeLNum(test - 1) 445 | endif 446 | endwhile 447 | 448 | if getline(test) =~# '^\s*switch\>' 449 | return indent(test) 450 | elseif getline(test) =~# s:defaultORcase 451 | return indent(test) - shiftwidth() * b:PHP_vintage_case_default_indent 452 | else 453 | return FindTheSwitchIndent(test) 454 | endif 455 | 456 | endfunction "}}} 457 | 458 | let s:SynPHPMatchGroups = {'phpparent':1, 'delimiter':1, 'define':1, 'storageclass':1, 'structure':1, 'exception':1} 459 | function! IslinePHP (lnum, tofind) " {{{ 460 | let cline = getline(a:lnum) 461 | 462 | if a:tofind=="" 463 | let tofind = "^\\s*[\"'`]*\\s*\\zs\\S" 464 | else 465 | let tofind = a:tofind 466 | endif 467 | 468 | let tofind = tofind . '\c' 469 | 470 | let coltotest = match (cline, tofind) + 1 471 | 472 | let synname = synIDattr(synID(a:lnum, coltotest, 0), "name") 473 | 474 | if synname ==? 'phpStringSingle' || synname ==? 'phpStringDouble' || synname ==? 'phpBacktick' 475 | if cline !~ '^\s*[''"`]' " ??? XXX 476 | return "SpecStringEntrails" 477 | else 478 | return synname 479 | end 480 | end 481 | 482 | if get(s:SynPHPMatchGroups, tolower(synname)) || synname =~ '^php' || synname =~? '^javaScript' 483 | return synname 484 | else 485 | return "" 486 | endif 487 | endfunction " }}} 488 | 489 | let s:autoresetoptions = 0 490 | if ! s:autoresetoptions 491 | let s:autoresetoptions = 1 492 | endif 493 | 494 | function! ResetPhpOptions() 495 | if ! b:optionsset && &filetype =~ "php" 496 | if b:PHP_autoformatcomment 497 | 498 | setlocal comments=s1:/*,mb:*,ex:*/,://,f:#[,:# 499 | 500 | setlocal formatoptions-=t 501 | setlocal formatoptions+=q 502 | setlocal formatoptions+=r 503 | setlocal formatoptions+=o 504 | setlocal formatoptions+=c 505 | setlocal formatoptions+=b 506 | endif 507 | let b:optionsset = 1 508 | endif 509 | endfunc 510 | 511 | call ResetPhpOptions() 512 | 513 | function! GetPhpIndentVersion() 514 | return "1.75" 515 | endfun 516 | 517 | function! GetPhpIndent() 518 | 519 | let b:GetLastRealCodeLNum_ADD = 0 520 | 521 | let UserIsEditing=0 522 | if b:PHP_oldchangetick != b:changedtick 523 | let b:PHP_oldchangetick = b:changedtick 524 | let UserIsEditing=1 525 | endif 526 | 527 | if b:PHP_default_indenting 528 | let b:PHP_default_indenting = g:PHP_default_indenting * shiftwidth() 529 | endif 530 | 531 | let cline = getline(v:lnum) 532 | 533 | if !b:PHP_indentinghuge && b:PHP_lastindented > b:PHP_indentbeforelast 534 | if b:PHP_indentbeforelast 535 | let b:PHP_indentinghuge = 1 536 | endif 537 | let b:PHP_indentbeforelast = b:PHP_lastindented 538 | endif 539 | 540 | if b:InPHPcode_checked && prevnonblank(v:lnum - 1) != b:PHP_lastindented 541 | if b:PHP_indentinghuge 542 | let b:PHP_indentinghuge = 0 543 | let b:PHP_CurrentIndentLevel = b:PHP_default_indenting 544 | endif 545 | let real_PHP_lastindented = v:lnum 546 | let b:PHP_LastIndentedWasComment=0 547 | let b:PHP_InsideMultilineComment=0 548 | let b:PHP_indentbeforelast = 0 549 | 550 | let b:InPHPcode = 0 551 | let b:InPHPcode_checked = 0 552 | let b:InPHPcode_and_script = 0 553 | let b:InPHPcode_tofind = "" 554 | 555 | elseif v:lnum > b:PHP_lastindented 556 | let real_PHP_lastindented = b:PHP_lastindented 557 | else 558 | let real_PHP_lastindented = v:lnum 559 | endif 560 | 561 | let b:PHP_lastindented = v:lnum 562 | 563 | 564 | if !b:InPHPcode_checked " {{{ One time check 565 | let b:InPHPcode_checked = 1 566 | let b:UserIsTypingComment = 0 567 | 568 | let synname = "" 569 | if cline !~ '' 570 | let synname = IslinePHP (prevnonblank(v:lnum), "") 571 | endif 572 | 573 | if synname!="" 574 | if synname ==? "SpecStringEntrails" 575 | let b:InPHPcode = -1 " thumb down 576 | let b:InPHPcode_tofind = "" 577 | elseif synname !=? "phpHereDoc" && synname !=? "phpHereDocDelimiter" 578 | let b:InPHPcode = 1 579 | let b:InPHPcode_tofind = "" 580 | 581 | if synname =~? '^php\%(Doc\)\?Comment' 582 | let b:UserIsTypingComment = 1 583 | let b:InPHPcode_checked = 0 584 | endif 585 | 586 | if synname =~? '^javaScript' 587 | let b:InPHPcode_and_script = 1 588 | endif 589 | 590 | else 591 | let b:InPHPcode = 0 592 | 593 | let lnum = v:lnum - 1 594 | while getline(lnum) !~? '<<<\s*[''"]\=\a\w*[''"]\=$' && lnum > 1 595 | let lnum = lnum - 1 596 | endwhile 597 | 598 | let b:InPHPcode_tofind = substitute( getline(lnum), '^.*<<<\s*[''"]\=\(\a\w*\)[''"]\=$', '^\\s*\1;\\=$', '') 599 | endif 600 | else 601 | let b:InPHPcode = 0 602 | let b:InPHPcode_tofind = s:PHP_startindenttag 603 | endif 604 | endif "!b:InPHPcode_checked }}} 605 | 606 | 607 | " Test if we are indenting PHP code {{{ 608 | let lnum = prevnonblank(v:lnum - 1) 609 | let last_line = getline(lnum) 610 | let endline= s:endline 611 | 612 | if b:InPHPcode_tofind!="" 613 | if cline =~? b:InPHPcode_tofind 614 | let b:InPHPcode_tofind = "" 615 | let b:UserIsTypingComment = 0 616 | 617 | if b:InPHPcode == -1 618 | let b:InPHPcode = 1 619 | return -1 620 | end 621 | 622 | let b:InPHPcode = 1 623 | 624 | if cline =~ '\*/' 625 | call cursor(v:lnum, 1) 626 | if cline !~ '^\*/' 627 | call search('\*/', 'W') 628 | endif 629 | let lnum = searchpair('/\*', '', '\*/', s:searchpairflags, 'Skippmatch2()') 630 | 631 | let b:PHP_CurrentIndentLevel = b:PHP_default_indenting 632 | 633 | let b:PHP_LastIndentedWasComment = 0 634 | 635 | if cline =~ '^\s*\*/' 636 | return indent(lnum) + 1 637 | else 638 | return indent(lnum) 639 | endif 640 | 641 | elseif cline =~? '' 642 | let b:InPHPcode_and_script = 1 643 | let b:GetLastRealCodeLNum_ADD = v:lnum 644 | endif 645 | endif 646 | endif 647 | 648 | if 1 == b:InPHPcode 649 | 650 | if !b:InPHPcode_and_script && last_line =~ '\%(\%(.*')=~?"Delimiter" 651 | if cline !~? s:PHP_startindenttag 652 | let b:InPHPcode = 0 653 | let b:InPHPcode_tofind = s:PHP_startindenttag 654 | elseif cline =~? '' 655 | let b:InPHPcode_and_script = 1 656 | endif 657 | 658 | elseif last_line =~ '^[^''"`]\+[''"`]$' && last_line !~ '^\s*\%(//\|#\[\@!\|/\*.*\*/\s*$\)' " a string identifier with nothing after it and no other string identifier before 659 | let b:InPHPcode = -1 660 | let b:InPHPcode_tofind = substitute( last_line, '^.*\([''"`]\).*$', '^[^\1]*\1[;,]$', '') 661 | elseif last_line =~? '<<<\s*[''"]\=\a\w*[''"]\=$' 662 | let b:InPHPcode = 0 663 | let b:InPHPcode_tofind = substitute( last_line, '^.*<<<\s*[''"]\=\(\a\w*\)[''"]\=$', '^\\s*\1;\\=$', '') 664 | 665 | elseif !UserIsEditing && cline =~ '^\s*/\*\%(.*\*/\)\@!' && getline(v:lnum + 1) !~ '^\s*\*' 666 | let b:InPHPcode = 0 667 | let b:InPHPcode_tofind = '\*/' 668 | 669 | elseif cline =~? '^\s*' 670 | let b:InPHPcode = 0 671 | let b:InPHPcode_tofind = s:PHP_startindenttag 672 | endif 673 | endif " }}} 674 | 675 | 676 | if 1 > b:InPHPcode && !b:InPHPcode_and_script 677 | return -1 678 | endif 679 | 680 | " Indent successive // or # comment the same way the first is {{{ 681 | let addSpecial = 0 682 | if cline =~ '^\s*\%(//\|#\[\@!\|/\*.*\*/\s*$\)' 683 | let addSpecial = b:PHP_outdentSLComments 684 | if b:PHP_LastIndentedWasComment == 1 685 | return indent(real_PHP_lastindented) 686 | endif 687 | let b:PHP_LastIndentedWasComment = 1 688 | else 689 | let b:PHP_LastIndentedWasComment = 0 690 | endif " }}} 691 | 692 | " Indent multiline /* comments correctly {{{ 693 | 694 | if b:PHP_InsideMultilineComment || b:UserIsTypingComment 695 | if cline =~ '^\s*\*\%(\/\)\@!' 696 | if last_line =~ '^\s*/\*' 697 | return indent(lnum) + 1 698 | else 699 | return indent(lnum) 700 | endif 701 | else 702 | let b:PHP_InsideMultilineComment = 0 703 | endif 704 | endif 705 | 706 | if !b:PHP_InsideMultilineComment && cline =~ '^\s*/\*\%(.*\*/\)\@!' 707 | if getline(v:lnum + 1) !~ '^\s*\*' 708 | return -1 709 | endif 710 | let b:PHP_InsideMultilineComment = 1 711 | endif " }}} 712 | 713 | 714 | " Things always indented at col 1 (PHP delimiter: , Heredoc end) {{{ 715 | if cline =~# '^\s*' && b:PHP_outdentphpescape 716 | return 0 717 | endif 718 | 719 | if cline =~ '^\s*?>' && cline !~# '' 785 | let b:PHP_CurrentIndentLevel = b:PHP_default_indenting 786 | return indent(FindTheIfOfAnElse(v:lnum, 1)) 787 | elseif cline =~# s:defaultORcase 788 | return FindTheSwitchIndent(v:lnum) + shiftwidth() * b:PHP_vintage_case_default_indent 789 | elseif cline =~ '^\s*)\=\s*{' 790 | let previous_line = last_line 791 | let last_line_num = lnum 792 | 793 | while last_line_num > 1 794 | 795 | if previous_line =~ terminated || previous_line =~ s:structureHead 796 | 797 | let ind = indent(last_line_num) 798 | 799 | if b:PHP_BracesAtCodeLevel 800 | let ind = ind + shiftwidth() 801 | endif 802 | 803 | return ind 804 | endif 805 | 806 | let last_line_num = GetLastRealCodeLNum(last_line_num - 1) 807 | let previous_line = getline(last_line_num) 808 | endwhile 809 | elseif cline =~ '^\s*->' 810 | return FindArrowIndent(lnum) 811 | elseif last_line =~# unstated && cline !~ '^\s*);\='.endline 812 | let ind = ind + shiftwidth() " we indent one level further when the preceding line is not stated 813 | return ind + addSpecial 814 | 815 | elseif (ind != b:PHP_default_indenting || last_line =~ '^[)\]]' ) && last_line =~ terminated 816 | let previous_line = last_line 817 | let last_line_num = lnum 818 | let LastLineClosed = 1 819 | 820 | let isSingleLineBlock = 0 821 | while 1 822 | if ! isSingleLineBlock && previous_line =~ '^\s*}\|;\s*}'.endline 823 | 824 | call cursor(last_line_num, 1) 825 | if previous_line !~ '^}' 826 | call search('}\|;\s*}'.endline, 'W') 827 | end 828 | let oldLastLine = last_line_num 829 | let last_line_num = searchpair('{', '', '}', 'bW', 'Skippmatch()') 830 | 831 | if getline(last_line_num) =~ '^\s*{' 832 | let last_line_num = GetLastRealCodeLNum(last_line_num - 1) 833 | elseif oldLastLine == last_line_num 834 | let isSingleLineBlock = 1 835 | continue 836 | endif 837 | 838 | let previous_line = getline(last_line_num) 839 | 840 | continue 841 | else 842 | let isSingleLineBlock = 0 843 | 844 | if getline(last_line_num) =~# '^\s*else\%(if\)\=\>' 845 | let last_line_num = FindTheIfOfAnElse(last_line_num, 0) 846 | continue 847 | endif 848 | 849 | 850 | let last_match = last_line_num 851 | 852 | let one_ahead_indent = indent(last_line_num) 853 | let last_line_num = GetLastRealCodeLNum(last_line_num - 1) 854 | let two_ahead_indent = indent(last_line_num) 855 | let after_previous_line = previous_line 856 | let previous_line = getline(last_line_num) 857 | 858 | 859 | if previous_line =~# s:defaultORcase.'\|{'.endline 860 | break 861 | endif 862 | 863 | if after_previous_line=~# '^\s*'.s:blockstart.'.*)'.endline && previous_line =~# '[;}]'.endline 864 | break 865 | endif 866 | 867 | if one_ahead_indent == two_ahead_indent || last_line_num < 1 868 | if previous_line =~# '\%(;\|^\s*}\)'.endline || last_line_num < 1 869 | break 870 | endif 871 | endif 872 | endif 873 | endwhile 874 | 875 | if indent(last_match) != ind 876 | let ind = indent(last_match) 877 | let b:PHP_CurrentIndentLevel = b:PHP_default_indenting 878 | 879 | return ind + addSpecial 880 | endif 881 | endif 882 | 883 | if (last_line !~ '^\s*}\%(}}\)\@!') 884 | let plinnum = GetLastRealCodeLNum(lnum - 1) 885 | else 886 | let plinnum = GetLastRealCodeLNum(FindOpenBracket(lnum, 1) - 1) 887 | endif 888 | 889 | let AntepenultimateLine = getline(plinnum) 890 | 891 | let last_line = StripEndlineComments(last_line) 892 | 893 | if ind == b:PHP_default_indenting 894 | if last_line =~ terminated && last_line !~# s:defaultORcase 895 | let LastLineClosed = 1 896 | endif 897 | endif 898 | 899 | if !LastLineClosed 900 | 901 | let openedparent = -1 902 | 903 | 904 | if last_line =~# '[{(\[]'.endline || last_line =~? '\h\w*\s*(.*,$' && AntepenultimateLine !~ '[,(\[]'.endline && BalanceDirection(last_line) > 0 905 | 906 | let dontIndent = 0 907 | if last_line =~ '\S\+\s*{'.endline && last_line !~ '^\s*[)\]]\+\(\s*:\s*'.s:PHP_validVariable.'\)\=\s*{'.endline && last_line !~ s:structureHead 908 | let dontIndent = 1 909 | endif 910 | 911 | if !dontIndent && (!b:PHP_BracesAtCodeLevel || last_line !~# '^\s*{') 912 | let ind = ind + shiftwidth() 913 | endif 914 | 915 | if b:PHP_IndentFunctionCallParameters && last_line =~ s:multilineFunctionCall && last_line !~ s:structureHead && last_line !~ s:arrayDecl 916 | let ind = ind + b:PHP_IndentFunctionCallParameters * shiftwidth() 917 | endif 918 | 919 | if b:PHP_IndentFunctionDeclarationParameters && last_line =~ s:multilineFunctionDecl 920 | let ind = ind + b:PHP_IndentFunctionDeclarationParameters * shiftwidth() 921 | endif 922 | 923 | if b:PHP_BracesAtCodeLevel || b:PHP_vintage_case_default_indent == 1 924 | let b:PHP_CurrentIndentLevel = ind 925 | 926 | endif 927 | 928 | elseif last_line =~ '),'.endline && BalanceDirection(last_line) < 0 929 | call cursor(lnum, 1) 930 | call searchpos('),'.endline, 'cW') 931 | let openedparent = searchpair('(', '', ')', 'bW', 'Skippmatch()') 932 | if openedparent != lnum 933 | let ind = indent(openedparent) 934 | endif 935 | 936 | elseif last_line =~ s:structureHead 937 | let ind = ind + shiftwidth() 938 | 939 | 940 | elseif AntepenultimateLine =~ '{'.endline && AntepenultimateLine !~? '^\s*use\>' && AntepenultimateLine !~? s:matchStart || AntepenultimateLine =~ terminated || AntepenultimateLine =~# s:defaultORcase 941 | let ind = ind + shiftwidth() 942 | endif 943 | 944 | 945 | if openedparent >= 0 946 | let last_line = StripEndlineComments(getline(openedparent)) 947 | endif 948 | endif 949 | 950 | if cline =~ '^\s*[)\]];\=' 951 | call cursor(v:lnum, 1) 952 | call searchpos('[)\]]', 'cW') 953 | let matchedBlockChar = cline[col('.')-1] 954 | let openedparent = searchpair('\M'.s:blockCharsLUT[matchedBlockChar], '', '\M'.matchedBlockChar, 'bW', 'Skippmatch()') 955 | if openedparent != v:lnum 956 | let ind = indent(openedparent) 957 | endif 958 | 959 | elseif last_line =~ '^\s*->' && last_line !~? s:structureHead && BalanceDirection(last_line) <= 0 960 | let ind = ind - shiftwidth() 961 | endif 962 | 963 | let b:PHP_CurrentIndentLevel = ind 964 | return ind + addSpecial 965 | endfunction 966 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## About 2 | 3 | 4 | This is the official PHP indentation plug-in for VIm (version 1.39 is bundled with VIm 7.4). 5 | 6 | Please, visit [the homepage](https://www.2072productions.com/to/phpindent.txt) of the PHP indentation script to see all the details about its features and capabilities. 7 | 8 | ### Options 9 | 10 | Just type `:help php-indent` inside VIm. 11 | 12 | ### Optional updated Syntax script 13 | 14 | Feel free to use [my updated version](https://github.com/2072/vim-syntax-for-PHP) of the official VIm syntax 15 | script for PHP which fixes a few issues and add support for some of the newest PHP 16 | features (see the [change log](https://github.com/2072/vim-syntax-for-PHP/commits/master) for the details). 17 | 18 | ## Install 19 | 20 | 21 | ### Vundle 22 | 1. Install and configure the [Vundle](https://github.com/gmarik/vundle) plug-in manager, [follow the instructions here](https://github.com/gmarik/vundle#quick-start) 23 | 2. Add the following line to your `.vimrc`: 24 | 25 | Plugin '2072/PHP-Indenting-for-VIm' 26 | 3. Source your `.vimrc` with `:so %` or otherwise reload your VIm 27 | 4. Run the `:BundleInstall` command 28 | 29 | ### Pathogen 30 | 1. Install the [pathogen.vim](https://github.com/tpope/vim-pathogen) plug-in, [follow the instructions here](https://github.com/tpope/vim-pathogen#installation) 31 | 2. Clone the repository under your `~/.vim/bundle/` directory: 32 | 33 | cd ~/.vim/bundle 34 | git clone https://github.com/2072/PHP-Indenting-for-VIm.git 35 | 36 | ### Debugging 37 | This script uses a lot of heuristics to do its job, when debugging you need to do 2 things: 38 | - Comment out the `finish` here (search for 'XXX'): 39 | 40 | ```viml 41 | " Only define the functions once per Vim session. 42 | if exists("*GetPhpIndent") 43 | call ResetPhpOptions() 44 | finish " XXX -- comment this line for easy dev 45 | endif 46 | ``` 47 | 48 | Doing this allows you to easily reload the indent script after a modification by just reloading your test `.php` file. 49 | 50 | - Enable the step debug printing by executing the command: `:%s /" DEBUG \zec//g`. 51 | This will cause the script to pause at key steps, look for the number printed and search it in the indent script. 52 | You can add more debug call, the convention is to use the current line number as the hint + any other relevant useful information. 53 | You can disable them again with `:%s /^\s*\zs\zecall DebugPrintReturn/" DEBUG /g`. 54 | 55 | Then try to indent the line causing issues and follow what is happening to find out which part of the script is causing the issue. 56 | You can disable the print function interruptions by hitting the `` key of your keyboard. 57 | 58 | Note that the indent script switches to an "optimized mode" when you indent several lines in a row so there can be bugs that only happen in this optimized mode. 59 | This mode is automatic on the 3rd consecutive line indentation, just indent a line above the line you last indented to switch back to the default mode. 60 | 61 | If you make a modification, make sure to run the command `:setlocal debug=msg` to enable vim debug messages. 62 | 63 | -------------------------------------------------------------------------------- /doc/PHPIndent.txt: -------------------------------------------------------------------------------- 1 | PHP *ft-php-indent* *php-indent* *php-indenting* 2 | 3 | NOTE: PHP files will be indented correctly only if PHP |syntax| is active. 4 | 5 | If you are editing a file in Unix 'fileformat' and '\r' characters are present 6 | before new lines, indentation won't proceed correctly ; you have to remove 7 | those useless characters first with a command like: > 8 | 9 | :%s /\r$//g 10 | 11 | Or, you can simply |:let| the variable PHP_removeCRwhenUnix to 1 and the 12 | script will silently remove them when Vim loads a PHP file (at each |BufRead|). 13 | 14 | OPTIONS: ~ 15 | 16 | PHP indenting can be altered in several ways by modifying the values of some 17 | global variables: 18 | 19 | *php-comment* *PHP_autoformatcomment* 20 | To not enable auto-formating of comments by default (if you want to use your 21 | own 'formatoptions'): > 22 | :let g:PHP_autoformatcomment = 0 23 | 24 | Else, 't' will be removed from the 'formatoptions' string and "qrowcb" will be 25 | added, see |fo-table| for more information. 26 | ------------- 27 | 28 | *PHP_outdentSLComments* 29 | To add extra indentation to single-line comments: > 30 | :let g:PHP_outdentSLComments = N 31 | 32 | With N being the number of 'shiftwidth' to add. 33 | 34 | Only single-line comments will be affected such as: > 35 | # Comment 36 | // Comment 37 | /* Comment */ 38 | ------------- 39 | 40 | *PHP_default_indenting* 41 | To add extra indentation to every PHP lines with N being the number of 42 | 'shiftwidth' to add: > 43 | :let g:PHP_default_indenting = N 44 | 45 | For example, with N = 1, this will give: 46 | > 47 | 57 | (Notice the extra indentation between the PHP container markers and the code) 58 | ------------- 59 | 60 | *PHP_outdentphpescape* 61 | To indent PHP escape tags as the surrounding non-PHP code (only affects the 62 | PHP escape tags): > 63 | :let g:PHP_outdentphpescape = 0 64 | ------------- 65 | 66 | *PHP_removeCRwhenUnix* 67 | To automatically remove '\r' characters when the 'fileformat' is set to Unix: > 68 | :let g:PHP_removeCRwhenUnix = 1 69 | ------------- 70 | 71 | *PHP_BracesAtCodeLevel* 72 | To indent braces at the same level than the code they contain: > 73 | :let g:PHP_BracesAtCodeLevel = 1 74 | 75 | This will give the following result: > 76 | if ($foo) 77 | { 78 | foo(); 79 | } 80 | Instead of: > 81 | if ($foo) 82 | { 83 | foo(); 84 | } 85 | 86 | NOTE: Indenting will be a bit slower if this option is used because some 87 | optimizations won't be available. 88 | ------------- 89 | 90 | *PHP_vintage_case_default_indent* 91 | To indent 'case:' and 'default:' statements in switch() blocks: > 92 | :let g:PHP_vintage_case_default_indent = 1 93 | 94 | In PHP braces are not required inside 'case/default' blocks therefore 'case:' 95 | and 'default:' are indented at the same level than the 'switch()' to avoid 96 | meaningless indentation. You can use the above option to return to the 97 | traditional way. 98 | ------------- 99 | 100 | *PHP_noArrowMatching* 101 | By default the indent script will indent multi-line chained calls by matching 102 | the position of the '->': > 103 | 104 | $user_name_very_long->name() 105 | ->age() 106 | ->info(); 107 | 108 | You can revert to the classic way of indenting by setting this option to 1: > 109 | :let g:PHP_noArrowMatching = 1 110 | 111 | You will obtain the following result: > 112 | 113 | $user_name_very_long->name() 114 | ->age() 115 | ->info(); 116 | 117 | ------------- 118 | 119 | *PHP_IndentFunctionCallParameters* 120 | Extra indentation levels to add to parameters in multi-line function calls. > 121 | let g:PHP_IndentFunctionCallParameters = 1 122 | 123 | Function call arguments will indent 1 extra level. For two-space indentation: > 124 | 125 | function call_the_thing( 126 | $with_this, 127 | $and_that 128 | ) { 129 | $this->do_the_thing( 130 | $with_this, 131 | $and_that 132 | ); 133 | } 134 | 135 | ------------- 136 | 137 | *PHP_IndentFunctionDeclarationParameters* 138 | Extra indentation levels to add to arguments in multi-line function definitions. > 139 | let g:PHP_IndentFunctionDeclarationParameters = 1 140 | 141 | Function arguments in declarations will indent 1 extra level. For two-space indentation: > 142 | 143 | function call_the_thing( 144 | $with_this, 145 | $and_that 146 | ) { 147 | $this->do_the_thing( 148 | $with_this, 149 | $and_that 150 | ); 151 | } 152 | 153 | vim:tw=78:ts=8:ft=help:norl: 154 | -------------------------------------------------------------------------------- /indent/php.vim: -------------------------------------------------------------------------------- 1 | " Vim indent file 2 | " Language: PHP 3 | " Author: John Wellesz 4 | " URL: https://www.2072productions.com/vim/indent/php.vim 5 | " Home: https://github.com/2072/PHP-Indenting-for-VIm 6 | " Last Change: 2023 August 18th 7 | " Version: 1.75 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 | " 44 | " Changes: 1.75 - Fix #87: The indent optimization was causing wrong 45 | " indentation of lines preceded by a line ending with 46 | " '}' when preceded by non white characters. 47 | " - Fix long standing non-reported regex escaping issue 48 | " in cleaning end of line comments function. This 49 | " should help fixing some other unreported issues when 50 | " parts of codes are commented out at ends of lines... 51 | " 52 | " 53 | " Changes: 1.74 - Fix #86: Add support for `match` expression. 54 | " 55 | " 56 | " Changes: 1.73 - Fix #77 where multi line strings and true/false 57 | " keywords at beginning of a line would cause indentation failures. 58 | " 59 | " 60 | " Changes: 1.72 - Fix vim/vim#5722 where it was reported that the 61 | " option PHP_BracesAtCodeLevel had not been working for the last 6 years. 62 | " 63 | " Changes: 1.71 - Fix #75 where the indent script would hang on 64 | " some multi-line quoted strings. 65 | " 66 | " Changes: 1.70 - Rename PHP_IndentFunctionParameters to PHP_IndentFunctionCallParameters and 67 | " also implement PHP_IndentFunctionDeclarationParameters. 68 | " - Update documentation. 69 | " 70 | " Changes: 1.69 - Fix vim/vim#4562 where Vim would freeze on multiline-string declarations ending with a comma. 71 | " - Fix #69: Indenting was incorrect for closures with single-line `use` statements. 72 | " - Always indent `^\s*[)\]]` according to their opening counterpart. This is slower but computers have 73 | " improved in the last 15 years... 74 | " - Implement feature request #71: added option PHP_IndentFunctionParameters to be set to the number of 75 | " additional indents you want for your function parameters. 76 | " - Fix #60 where multiline-string declarations endings with nothing else before would break indentation. 77 | " - Fix unreported issue where a comment ending with a ', " or ` would stop indentation after this line. 78 | " 79 | " Changes: 1.68 - Fix #68: end(if|for|foreach|while|switch) 80 | " identifiers were treated as here doc ending indentifiers and set at column 0. 81 | " - WIP: More work on #67: arrow matching involving () not behaving as expected (better but not perfect). 82 | " 83 | " Changes: 1.67 - Fix #67: chained calls indentation was aligning on the 84 | " first matching '->' instead of the last one. 85 | " 86 | " Changes: 1.66 - Add support for return type declaration on multi-line 87 | " function declarations (issue #64) 88 | " - Fix to multi-line function declaration argument 89 | " indentation (issue #63) 90 | " 91 | " Changes: 1.65 - Functions declared as returning references were not 92 | " indented properly (issue #62). 93 | " 94 | " Changes: 1.64 - Always ignore case when using syntax highlighting names (issue #52) 95 | " - Fix bug introduced in 1.63 (the content of anonymous function 96 | " declarations preceded by a '->' was no longer 97 | " indented correctly) (issue #59) 98 | " - Add a new PHP_noArrowMatching option to disable '->' 99 | " indentation matching on multi-line chained calls (issue #59). 100 | " 101 | " 102 | " Changes: 1.63 - Fix chained multi-line '->' indentation (issue #54 and #59) 103 | " - Fix array indentation when PHP_vintage_case_default_indent is set (issue #58) 104 | " 105 | " Changes: 1.62 - Fix some multi-line block declaration interferences (issue #49) 106 | " - Fix Grouped 'use' declaration (issue #48) 107 | " - Fix array index issue with function call (issue #54) 108 | " - Add anonymous class declaration support (issue #55) 109 | " 110 | " Changes: 1.61 - Prevent multi-line strings declaration from breaking 111 | " indentation. (issue #47) 112 | " 113 | " Changes: 1.60 - Multi-line indenting could get wrong whenever started 114 | " on a commented line. (issue #44) 115 | " 116 | " Changes: 1.59 - Add support for optional spaces before and double 117 | " quotes around (Here|Now)Document identifiers (issue #40) 118 | " 119 | " Changes: 1.58 - Check shiftwidth() instead of 'shiftwidth' (will use 120 | " the 'tabstop' value if 'shiftwidth' is 0) 121 | " 122 | " Changes: 1.57 - Fix an unreported non-blocking syntax error (VimLint) 123 | " 124 | " Changes: 1.56 - Enhance closure support in array definition 125 | " - Correctly indent line starting by a /**/ comment 126 | " - Don't indent last line of multiline string 127 | " declarations. 128 | " 129 | " Changes: 1.55 - Remove optimization related to labels detection that 130 | " could trigger indent issues when URLs are found in 131 | " comments at end of lines... 132 | " 133 | " Changes: 1.54 - Add support for 'phpDocComment' syntax identifier 134 | " 135 | " Changes: 1.53 - Add support for `label:` (used with `goto`) 136 | " - Add `0]` to indentkeys 137 | " 138 | " Changes: 1.52 - Fix an edge case in conditional block declarations 139 | " when the ')' of the condition is put on the same 140 | " line as the following '{' (complement to issue #4) 141 | " 142 | " Changes: 1.51 - Fix issue #34 where indentation could get wrong with 143 | " arrays defined using the short [] declaration. 144 | " 145 | " Changes: 1.50 - Allow the PHP_autoformatcomment option (default on) 146 | " to work for any filetype containing 'php'. 147 | " 148 | " Changes: 1.49 - Added 'finally' as a block starter 149 | " 150 | " Changes: 1.48 - The 'use' keyword is now seen as a block starter (as 151 | " used to handle trait conflicts resolution). 152 | " 153 | " - Fix a issue with lines following a {} block defined 154 | " on a single line if this {} block was just beneath a '{' 155 | " 156 | " Changes: 1.47 - Code in traits was not indented 157 | " 158 | " Changes: 1.46 - Fix issue #32 ('case:/default:' indentation issues in 159 | " complex 'switch' blocks) 160 | " 161 | " Changes: 1.45 - Implemented support for multi-line block 162 | " declarations (issue #4). 163 | " 164 | " - Other small and very specific issues were discovered 165 | " and fixed while implementing this. 166 | " 167 | " Changes: 1.44 - Fix issue #31 introduced in 1.43 168 | " 169 | " Changes: 1.43 - Fix issue #17 where closures' content would get 170 | " extra indenting. 171 | " 172 | " Changes: 1.42 - Added support (with some restrictions) for 173 | " multi-line string declarations (issue #22). 174 | " 175 | " Changes: 1.41 - Fix handing of ^}\s*else\n{ blocks which were not 176 | " detected as new blocks and resulted in wrong indentation. 177 | " 178 | " - Fix issue #23 where the script could hang in some 179 | " specific cases involving closing braces at column 0; 180 | " 181 | " - Fix issue #6 where nested switches would not indent 182 | " correctly. 183 | " 184 | " Changes: 1.40 - Added the 'final' keyword as a block starter so final 185 | " classes' code is indented correctly. 186 | " 187 | " - No longer add 'w' to formatoptions VIm' setting as 188 | " no other file-type plug-in uses it by default. This 189 | " prevents leaving trailing white spaces when text 190 | " wrapping. 191 | " 192 | " Changes: 1.39 - Also add 'StorageClass' syntax identifier (with an uppercase C) as it 193 | " also exists in the syntax file. 194 | " 195 | " Changes: 1.38 - Fix an incredibly old bug that managed to survive 196 | " unnoticed until today: the PHP code identifier routine was missing a few 197 | " syntax names (Define, Structure, Storageclass and Exception). If you started 198 | " indenting on such a line, nothing would happen as 199 | " the script thought it wasn't actual PHP code... 200 | " 201 | " Changes: 1.37 - Fix a bug for inline script element [imicky] 202 | " - Fix issue #11: https://github.com/2072/PHP-Indenting-for-VIm/issues/11 203 | " 204 | " Changes: 1.36 - Added support for short array declaration (Thanks to 205 | " Warren Seymour) 206 | " 207 | " Changes: 1.35 - New option: PHP_outdentSLComments to add extra 208 | " indentation to single-line comments. 209 | " 210 | " 211 | " Changes: 1.34 - Fix: string with /* would be treated as comment 212 | " start when using single quote. (Thanks to Manic Chuang 213 | " for the fix) 214 | " 215 | " 216 | " Changes: 1.33 - Rewrote Switch(){case:default:} handling from 217 | " scratch in a simpler more logical and infallible way... 218 | " - Removed PHP_ANSI_indenting which is no longer 219 | " needed. 220 | " 221 | " 222 | " Changes: 1.32b - Added PHP_ANSI_indenting and PHP_outdentphpescape 223 | " options details to VIm documentation (:help php-indent). 224 | " 225 | " 226 | " Changes: 1.32 - Added a new option: PHP_ANSI_indenting 227 | " 228 | " 229 | " Changes: 1.31a - Added a new option: PHP_outdentphpescape to indent 230 | " PHP tags as the surrounding code. 231 | " 232 | " Changes: 1.30 - Fixed empty case/default indentation again :/ 233 | " - The ResetOptions() function will be called each time 234 | " the ftplugin calls this script, previously it was 235 | " executed on BufWinEnter and Syntax events. 236 | " 237 | " 238 | " Changes: 1.29 - Fixed php file detection for ResetOptions() used for 239 | " comments formatting. It now uses the same tests as 240 | " filetype.vim. ResetOptions() will be correctly 241 | " called for *.phtml, *.ctp and *.inc files. 242 | " 243 | " 244 | " Changes: 1.28 - End HEREDOC delimiters were not considered as such 245 | " if they were not followed by a ';'. 246 | " - Added support for NOWDOC tags ($foo = <<<'bar') 247 | " 248 | " 249 | " Changes: 1.27 - if a "case" was preceded by another "case" on the 250 | " previous line, the second "case" was indented incorrectly. 251 | " 252 | " Changes: 1.26 - '/*' character sequences found on a line 253 | " starting by a '#' were not dismissed by the indenting algorithm 254 | " and could cause indentation problem in some cases. 255 | " 256 | " 257 | " Changes: 1.25 - Fix some indentation errors on multi line conditions 258 | " and multi line statements. 259 | " - Fix when array indenting is broken and a closing 260 | " ');' is placed at the start of the line, following 261 | " lines will be indented correctly. 262 | " - New option: PHP_vintage_case_default_indent (default off) 263 | " - Minor fixes and optimizations. 264 | " 265 | " 266 | " Changes: 1.24 - Added compatibility with the latest version of 267 | " php.vim syntax file by Peter Hodge (https://www.vim.org/scripts/script.php?script_id=1571) 268 | " This fixes wrong indentation and ultra-slow indenting 269 | " on large php files... 270 | " - Fixed spelling in comments. 271 | " 272 | " 273 | " Changes: 1.23 - html tag was preceded by a "?>" it wasn't indented. 346 | " - Some other minor corrections and improvements. 347 | " 348 | " 349 | " Changes: 1.16 - Now starting and ending '*' of multiline '/* */' comments are aligned 350 | " on the '*' of the '/*' comment starter. 351 | " - Some code improvements that make indentation faster. 352 | " 353 | " Changes: 1.15 - Corrected some problems with the indentation of 354 | " multiline "array()" declarations. 355 | " 356 | " Changes: 1.14 - Added auto-formatting for comments (using the Vim option formatoptions=qroc). 357 | " - Added the script option PHP_BracesAtCodeLevel to 358 | " indent the '{' and '}' at the same level than the 359 | " code they contain. 360 | " 361 | " Changes: 1.13 - Some code cleaning and typo corrections (Thanks to 362 | " Emanuele Giaquinta for his patches) 363 | " 364 | " Changes: 1.12 - The bug involving searchpair() and utf-8 encoding in Vim 6.3 will 365 | " not make this script to hang but you'll have to be 366 | " careful to not write '/* */' comments with other '/*' 367 | " inside the comments else the indentation won't be correct. 368 | " NOTE: This is true only if you are using utf-8 and vim 6.3. 369 | " 370 | " Changes: 1.11 - If the "case" of a "switch" wasn't alone on its line 371 | " and if the "switch" was at col 0 (or at default indenting) 372 | " the lines following the "case" were not indented. 373 | " 374 | " Changes: 1.10 - Lines beginning by a single or double quote were 375 | " not indented in some cases. 376 | " 377 | " Changes: 1.09 - JavaScript code was not always directly indented. 378 | " 379 | " Changes: 1.08 - End comment tags '*/' are indented like start tags '/*'. 380 | " - When typing a multiline comment, '}' are indented 381 | " according to other commented '{'. 382 | " - Added a new option 'PHP_removeCRwhenUnix' to 383 | " automatically remove CR at end of lines when the file 384 | " format is Unix. 385 | " - Changed the file format of this very file to Unix. 386 | " - This version seems to correct several issues some people 387 | " had with 1.07. 388 | " 389 | " Changes: 1.07 - Added support for "Here document" tags: 390 | " - HereDoc end tags are indented properly. 391 | " - HereDoc content remains unchanged. 392 | " - All the code that is outside PHP delimiters remains 393 | " unchanged. 394 | " - New feature: The content of html tags is considered as PHP 395 | " and indented according to the surrounding PHP code. 396 | " - "else if" are detected as "elseif". 397 | " - Multiline /**/ are indented when the user types it but 398 | " remain unchanged when indenting from their beginning. 399 | " - Fixed indenting of // and # comments. 400 | " - php_sync_method option is set to 0 (fromstart). 401 | " This is required for complex PHP scripts else the indent 402 | " may fail. 403 | " - Files with non PHP code at the beginning could alter the indent 404 | " of the following PHP code. 405 | " - Other minor improvements and corrections. 406 | " 407 | " Changes: 1.06: - Switch block were no longer indented correctly... 408 | " - Added an option to use a default indenting instead of 0. 409 | " (whereas I still can't find any good reason to use it!) 410 | " - A problem with ^\s*);\= lines where ending a non '{}' 411 | " structure. 412 | " - Changed script local variable to be buffer local 413 | " variable instead. 414 | " 415 | " Changes: 1.05: - Lines containing "" and "?> ,=?>,=' 574 | let 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\>\)' 575 | let s:functionDeclPrefix = '\\%(\s\+&\='.s:PHP_validVariable.'\)\=\s*(' 576 | let s:functionDecl = s:functionDeclPrefix.'.*' 577 | let s:multilineFunctionDecl = s:functionDeclPrefix.s:endline 578 | let s:arrayDecl = '\\s*(.*' 579 | let s:multilineFunctionCall = s:PHP_validVariable.'\s*('.s:endline 580 | " Unstated line? 581 | " - an "else" at the end of line 582 | " - a s:blockstart (if while etc...) followed by anything but a ";" at 583 | " the end of line 584 | let s:unstated = '\%(^\s*'.s:blockstart.'.*)\|\%(//.*\)\@\)'.s:endline 585 | 586 | " Terminated line? 587 | " - a line terminated by a ";" optionally followed by a "?>" or "}" 588 | " - a HEREDOC starter line (the content of such block is never seen by this script) 589 | " - a "}" not followed by a "{" 590 | " - a goto's label 591 | 592 | let s:terminated = '\%(\%(;\%(\s*\%(?>\|}\)\)\=\|<<<\s*[''"]\=\a\w*[''"]\=$\|^\s*}\|^\s*'.s:PHP_validVariable.':\)'.s:endline.'\)' 593 | let s:PHP_startindenttag = '\)\@!\|]*>\%(.*<\/script>\)\@!' 594 | let s:matchStart = 'match\s*(\s*\$\?'.s:PHP_validVariable.'\s*)\s*{'. s:endline 595 | let s:structureHead = '^\s*\%(' . s:blockstart . '\)\|'. s:functionDecl . s:endline . '\|\\|' . s:matchStart 596 | 597 | 598 | let s:escapeDebugStops = 0 599 | function! DebugPrintReturn(scriptLine) 600 | 601 | if ! s:escapeDebugStops 602 | echo "debug:" . a:scriptLine 603 | let c = getchar() 604 | if c == "\" 605 | let s:escapeDebugStops = 1 606 | end 607 | endif 608 | 609 | endfunction 610 | 611 | function! GetLastRealCodeLNum(startline) " {{{ 612 | "Inspired from the function SkipJavaBlanksAndComments by Toby Allsopp for indent/java.vim 613 | 614 | let lnum = a:startline 615 | 616 | " DEBUG call DebugPrintReturn('565: started GetLastRealCodeLNum ' . lnum . ' --- lastline: ' . getline(lnum) ) 617 | " Used to indent html tag correctly 618 | if b:GetLastRealCodeLNum_ADD && b:GetLastRealCodeLNum_ADD == lnum + 1 619 | let lnum = b:GetLastRealCodeLNum_ADD 620 | endif 621 | 622 | while lnum > 1 623 | " DEBUG call DebugPrintReturn('587: in while' ) 624 | let lnum = prevnonblank(lnum) 625 | let lastline = getline(lnum) 626 | 627 | " if we are inside an html ' 1288 | let b:InPHPcode = 0 1289 | let b:InPHPcode_tofind = s:PHP_startindenttag 1290 | " Note that b:InPHPcode_and_script is still true so that the 1291 | " can be indented correctly 1292 | endif 1293 | endif " }}} 1294 | 1295 | 1296 | " Non PHP code is left as it is 1297 | if 1 > b:InPHPcode && !b:InPHPcode_and_script 1298 | " DEBUG call DebugPrintReturn(996 . ' ipc? ' . b:InPHPcode . ' ipcs? ' . b:InPHPcode_and_script) 1299 | return -1 1300 | endif 1301 | 1302 | " Align correctly multi // or # lines 1303 | " Indent successive // or # comment the same way the first is {{{ 1304 | let addSpecial = 0 1305 | if cline =~ '^\s*\%(//\|#\[\@!\|/\*.*\*/\s*$\)' 1306 | let addSpecial = b:PHP_outdentSLComments 1307 | if b:PHP_LastIndentedWasComment == 1 1308 | " DEBUG call DebugPrintReturn(1031) 1309 | return indent(real_PHP_lastindented) 1310 | endif 1311 | let b:PHP_LastIndentedWasComment = 1 1312 | else 1313 | let b:PHP_LastIndentedWasComment = 0 1314 | endif " }}} 1315 | 1316 | " Indent multiline /* comments correctly {{{ 1317 | 1318 | "if we are on the start of a MULTI * beginning comment or if the user is 1319 | "currently typing a /* beginning comment. 1320 | if b:PHP_InsideMultilineComment || b:UserIsTypingComment 1321 | if cline =~ '^\s*\*\%(\/\)\@!' 1322 | " if cline == '*' 1323 | if last_line =~ '^\s*/\*' 1324 | " if last_line == '/*' 1325 | " DEBUG call DebugPrintReturn(1048) 1326 | return indent(lnum) + 1 1327 | else 1328 | " DEBUG call DebugPrintReturn(1051) 1329 | return indent(lnum) 1330 | endif 1331 | else 1332 | let b:PHP_InsideMultilineComment = 0 1333 | endif 1334 | endif 1335 | 1336 | " If cline is the start of a _multiline_ /**/ comment 1337 | if !b:PHP_InsideMultilineComment && cline =~ '^\s*/\*\%(.*\*/\)\@!' 1338 | if getline(v:lnum + 1) !~ '^\s*\*' 1339 | " DEBUG call DebugPrintReturn(1062) 1340 | return -1 1341 | endif 1342 | let b:PHP_InsideMultilineComment = 1 1343 | endif " }}} 1344 | 1345 | " Some tags are always indented to col 1 1346 | 1347 | " Things always indented at col 1 (PHP delimiter: , Heredoc end) {{{ 1348 | " PHP start tags are always at col 1, useless to indent unless the end tag 1349 | " is on the same line 1350 | if cline =~# '^\s*' && b:PHP_outdentphpescape 1351 | " DEBUG call DebugPrintReturn(1135) 1352 | return 0 1353 | endif 1354 | 1355 | " PHP end tags are always at col 1, useless to indent unless if it's 1356 | " followed by a start tag on the same line 1357 | if cline =~ '^\s*?>' && cline !~# '' 1453 | " prevent optimized to work at next call XXX why ? 1454 | let b:PHP_CurrentIndentLevel = b:PHP_default_indenting 1455 | " DEBUG call DebugPrintReturn(1062) 1456 | return indent(FindTheIfOfAnElse(v:lnum, 1)) 1457 | elseif cline =~# s:defaultORcase 1458 | " DEBUG call DebugPrintReturn(1064) 1459 | " case and default need a special treatment 1460 | return FindTheSwitchIndent(v:lnum) + shiftwidth() * b:PHP_vintage_case_default_indent 1461 | elseif cline =~ '^\s*)\=\s*{' 1462 | let previous_line = last_line 1463 | let last_line_num = lnum 1464 | 1465 | " DEBUG call DebugPrintReturn(1099) 1466 | " let's find the indent of the block starter (if, while, for, etc...) 1467 | while last_line_num > 1 1468 | 1469 | if previous_line =~ terminated || previous_line =~ s:structureHead 1470 | 1471 | let ind = indent(last_line_num) 1472 | 1473 | " If the PHP_BracesAtCodeLevel is set then indent the '{' 1474 | if b:PHP_BracesAtCodeLevel 1475 | let ind = ind + shiftwidth() 1476 | endif 1477 | 1478 | " DEBUG call DebugPrintReturn(1083) 1479 | return ind 1480 | endif 1481 | 1482 | let last_line_num = GetLastRealCodeLNum(last_line_num - 1) 1483 | let previous_line = getline(last_line_num) 1484 | endwhile 1485 | elseif cline =~ '^\s*->' 1486 | return FindArrowIndent(lnum) 1487 | elseif last_line =~# unstated && cline !~ '^\s*);\='.endline 1488 | let ind = ind + shiftwidth() " we indent one level further when the preceding line is not stated 1489 | " DEBUG call DebugPrintReturn(1093) 1490 | return ind + addSpecial 1491 | 1492 | " If the last line is terminated by ';' or if it's a closing '}' 1493 | " We need to check if this isn't the end of a multilevel non '{}' 1494 | " structure such as: 1495 | " Exemple: 1496 | " if ($truc) 1497 | " echo 'truc'; 1498 | " 1499 | " OR 1500 | " 1501 | " if ($truc) 1502 | " while ($truc) { 1503 | " lkhlkh(); 1504 | " echo 'infinite loop\n'; 1505 | " } 1506 | " 1507 | " OR even (ADDED for version 1.17 - no modification required ) 1508 | " 1509 | " $thing = 1510 | " "something"; 1511 | elseif (ind != b:PHP_default_indenting || last_line =~ '^[)\]]' ) && last_line =~ terminated 1512 | " If we are here it means that the previous line is: 1513 | " - a *;$ line 1514 | " - a [beginning-blanck] } followed by anything but a { $ 1515 | let previous_line = last_line 1516 | let last_line_num = lnum 1517 | let LastLineClosed = 1 1518 | " The idea here is to check if the current line is after a non '{}' 1519 | " structure so we can indent it like the top of that structure. 1520 | " The top of that structure is characterized by a if (ff)$ style line 1521 | " preceded by a stated line. If there is no such structure then we 1522 | " just have to find two 'normal' lines following each other with the 1523 | " same indentation and with the first of these two lines terminated by 1524 | " a ; or by a }... 1525 | 1526 | let isSingleLineBlock = 0 1527 | while 1 1528 | " let's skip '{}' blocks 1529 | if ! isSingleLineBlock && previous_line =~ '^\s*}\|;\s*}'.endline 1530 | " find the opening '{' 1531 | 1532 | call cursor(last_line_num, 1) 1533 | if previous_line !~ '^}' 1534 | call search('}\|;\s*}'.endline, 'W') 1535 | end 1536 | let oldLastLine = last_line_num 1537 | let last_line_num = searchpair('{', '', '}', 'bW', 'Skippmatch()') 1538 | 1539 | " DEBUG call DebugPrintReturn("on line:" . line(".") . " { of } is on line " . last_line_num . ' } was on ' . oldLastLine) 1540 | " if the '{' is alone on the line, get the line before 1541 | if getline(last_line_num) =~ '^\s*{' 1542 | let last_line_num = GetLastRealCodeLNum(last_line_num - 1) 1543 | elseif oldLastLine == last_line_num 1544 | " if we're on a {}, then there was nothing to skip in the 1545 | " first place... 1546 | let isSingleLineBlock = 1 1547 | continue 1548 | endif 1549 | 1550 | let previous_line = getline(last_line_num) 1551 | 1552 | continue 1553 | else 1554 | let isSingleLineBlock = 0 1555 | " DEBUG call DebugPrintReturn(1230 . " previous_line: " . previous_line) 1556 | " At this point we know that the previous_line isn't a closing 1557 | " '}' so we can check if we really are in such a structure. 1558 | 1559 | " it's not a '}' but it could be an else alone... 1560 | if getline(last_line_num) =~# '^\s*else\%(if\)\=\>' 1561 | let last_line_num = FindTheIfOfAnElse(last_line_num, 0) 1562 | " re-run the loop (we could find a '}' again) 1563 | continue 1564 | endif 1565 | 1566 | " So now it's ok we can check :-) 1567 | " A good quality is to have confidence in oneself so to know 1568 | " if we really are in that structure lets test the indent of 1569 | " last_line_num and of last_line_num - 1! 1570 | " If those are == then we are almost done. 1571 | " 1572 | " This isn't sufficient, we need to test how the first of 1573 | " these 2 lines ends... 1574 | 1575 | " Remember the 'topest' line we found so far 1576 | let last_match = last_line_num 1577 | 1578 | let one_ahead_indent = indent(last_line_num) 1579 | let last_line_num = GetLastRealCodeLNum(last_line_num - 1) 1580 | let two_ahead_indent = indent(last_line_num) 1581 | let after_previous_line = previous_line 1582 | let previous_line = getline(last_line_num) 1583 | 1584 | 1585 | " DEBUG call DebugPrintReturn(1260 . " previous_line: " . previous_line) 1586 | " If we find a '{' or a case/default then we are inside that block so lets 1587 | " indent properly... Like the line following that block starter 1588 | if previous_line =~# s:defaultORcase.'\|{'.endline 1589 | " DEBUG call DebugPrintReturn(1264 . ' last_match: ' . last_match) 1590 | break 1591 | endif 1592 | 1593 | " The 3 lines below are not necessary for the script to work 1594 | " but it makes it work a little faster in some (rare) cases. 1595 | " We verify if we are at the top of a non '{}' struct. 1596 | if after_previous_line=~# '^\s*'.s:blockstart.'.*)'.endline && previous_line =~# '[;}]'.endline 1597 | " DEBUG call DebugPrintReturn(1272) 1598 | break 1599 | endif 1600 | 1601 | if one_ahead_indent == two_ahead_indent || last_line_num < 1 1602 | " So the previous line and the line before are at the same 1603 | " col. Now we just have to check if the line before is a ;$ or [}]$ ended line 1604 | " we always check the most ahead line of the 2 lines so 1605 | " it's useless to match ')$' since the lines couldn't have 1606 | " the same indent... 1607 | if previous_line =~# '\%(;\|^\s*}\)'.endline || last_line_num < 1 1608 | " DEBUG call DebugPrintReturn(1283 . " last_match: " . last_match . " - previous_line (".last_line_num .'): ' . previous_line) 1609 | break 1610 | endif 1611 | endif 1612 | endif 1613 | endwhile 1614 | 1615 | if indent(last_match) != ind 1616 | " let's use the indent of the last line matched by the algorithm above 1617 | let ind = indent(last_match) 1618 | let b:PHP_CurrentIndentLevel = b:PHP_default_indenting 1619 | 1620 | " DEBUG call DebugPrintReturn(1297 . " last match:" . last_match) 1621 | return ind + addSpecial 1622 | endif 1623 | " if nothing was done lets the old script continue 1624 | endif 1625 | 1626 | " previous to last line 1627 | if (last_line !~ '^\s*}\%(}}\)\@!') 1628 | let plinnum = GetLastRealCodeLNum(lnum - 1) 1629 | else 1630 | let plinnum = GetLastRealCodeLNum(FindOpenBracket(lnum, 1) - 1) 1631 | endif 1632 | 1633 | let AntepenultimateLine = getline(plinnum) 1634 | 1635 | let last_line = StripEndlineComments(last_line) 1636 | 1637 | if ind == b:PHP_default_indenting 1638 | if last_line =~ terminated && last_line !~# s:defaultORcase 1639 | let LastLineClosed = 1 1640 | endif 1641 | endif 1642 | 1643 | " Indent blocks enclosed by {} or () (default indenting) 1644 | if !LastLineClosed 1645 | 1646 | " this variable is going to be set when a "()," block was skipped 1647 | let openedparent = -1 1648 | 1649 | " the last line isn't a .*; or a }$ line 1650 | " Indent correctly multilevel and multiline '(.*)' things 1651 | 1652 | " if the last line is a [{(\[]$ or a multiline function call (or array 1653 | " declaration) with already one parameter on the opening ( line 1654 | if last_line =~# '[{(\[]'.endline || last_line =~? '\h\w*\s*(.*,$' && AntepenultimateLine !~ '[,(\[]'.endline && BalanceDirection(last_line) > 0 1655 | 1656 | let dontIndent = 0 1657 | " the last line contains a '{' with other meaningful characters 1658 | " before it but is not a block starter / function declaration. 1659 | " It should mean that it's a multi-line block declaration and that 1660 | " the previous line is already indented... 1661 | if last_line =~ '\S\+\s*{'.endline && last_line !~ '^\s*[)\]]\+\(\s*:\s*'.s:PHP_validVariable.'\)\=\s*{'.endline && last_line !~ s:structureHead 1662 | let dontIndent = 1 1663 | " DEBUG call DebugPrintReturn(1579 . ' dontIndentSet ' . (last_line =~ '\S\+\s*{'.endline) . '-' . (last_line !~ '^\s*[)\]]\+\(\s*:\s*'.s:PHP_validVariable.'\)\=\s*{'.endline ) . '-' . (last_line !~ s:structureHead)) 1664 | endif 1665 | 1666 | " DEBUG call DebugPrintReturn(1450. ' ' . dontIndent . ' lastline: ' . last_line . ' balance? ' . BalanceDirection(last_line) . ' structure head? ' . (last_line !~ s:structureHead) ) 1667 | " indent if we don't want braces at code level or if the last line 1668 | " is not a lonely '{' (default indent for the if block) 1669 | if !dontIndent && (!b:PHP_BracesAtCodeLevel || last_line !~# '^\s*{') 1670 | let ind = ind + shiftwidth() 1671 | " DEBUG call DebugPrintReturn(1454. ' +1 indent: '.ind) 1672 | endif 1673 | 1674 | if b:PHP_IndentFunctionCallParameters && last_line =~ s:multilineFunctionCall && last_line !~ s:structureHead && last_line !~ s:arrayDecl 1675 | let ind = ind + b:PHP_IndentFunctionCallParameters * shiftwidth() 1676 | endif 1677 | 1678 | if b:PHP_IndentFunctionDeclarationParameters && last_line =~ s:multilineFunctionDecl 1679 | let ind = ind + b:PHP_IndentFunctionDeclarationParameters * shiftwidth() 1680 | endif 1681 | 1682 | if b:PHP_BracesAtCodeLevel || b:PHP_vintage_case_default_indent == 1 1683 | " case and default are not indented inside blocks 1684 | let b:PHP_CurrentIndentLevel = ind 1685 | 1686 | " DEBUG call DebugPrintReturn(1299) 1687 | " return ind + addSpecial " commented out to fix #58. Couldn't 1688 | " find a proper reason to return here 1689 | endif 1690 | 1691 | " If the last line ends with a '),' then check if the 1692 | " ')' was opened on the same line, if not it means it closes a 1693 | " multiline '(.*)' thing and that the current line needs to be 1694 | " de-indented one time. 1695 | elseif last_line =~ '),'.endline && BalanceDirection(last_line) < 0 1696 | call cursor(lnum, 1) 1697 | call searchpos('),'.endline, 'cW') 1698 | " DEBUG call DebugPrintReturn(1373) 1699 | let openedparent = searchpair('(', '', ')', 'bW', 'Skippmatch()') 1700 | if openedparent != lnum 1701 | let ind = indent(openedparent) 1702 | endif 1703 | 1704 | " if the line before starts a block then we need to indent the 1705 | " current line. 1706 | elseif last_line =~ s:structureHead 1707 | let ind = ind + shiftwidth() 1708 | 1709 | " In all other cases if !LastLineClosed indent 1 level higher 1710 | " _only_ if the ante-penultimate line _is_ 'closed' or if it's a 1711 | " block starter 1712 | " 1713 | " IE: We test the line before the last one to check if we already 1714 | " were in this "list" 1715 | " 1716 | " we handle "use" block statement specifically for now... 1717 | 1718 | elseif AntepenultimateLine =~ '{'.endline && AntepenultimateLine !~? '^\s*use\>' && AntepenultimateLine !~? s:matchStart || AntepenultimateLine =~ terminated || AntepenultimateLine =~# s:defaultORcase 1719 | let ind = ind + shiftwidth() 1720 | " DEBUG call DebugPrintReturn(1422 . ' AntepenultimateLine: ' . AntepenultimateLine . ' lastline: ' . last_line . ' LastLineClosed: ' . LastLineClosed) 1721 | endif 1722 | 1723 | 1724 | " update last_line if necessary 1725 | if openedparent >= 0 1726 | let last_line = StripEndlineComments(getline(openedparent)) 1727 | endif 1728 | endif 1729 | 1730 | " If the current line closes a multiline function call or array def 1731 | if cline =~ '^\s*[)\]];\=' 1732 | call cursor(v:lnum, 1) 1733 | call searchpos('[)\]]', 'cW') 1734 | let matchedBlockChar = cline[col('.')-1] 1735 | " DEBUG call DebugPrintReturn(1662 .' ' . matchedBlockChar.s:blockCharsLUT[matchedBlockChar]) 1736 | let openedparent = searchpair('\M'.s:blockCharsLUT[matchedBlockChar], '', '\M'.matchedBlockChar, 'bW', 'Skippmatch()') 1737 | if openedparent != v:lnum 1738 | let ind = indent(openedparent) 1739 | endif 1740 | 1741 | " if the previous line begins with a -> then we need to remove one &sw 1742 | elseif last_line =~ '^\s*->' && last_line !~? s:structureHead && BalanceDirection(last_line) <= 0 1743 | " DEBUG call DebugPrintReturn(1621. ' -1 indent ') 1744 | let ind = ind - shiftwidth() 1745 | endif 1746 | 1747 | let b:PHP_CurrentIndentLevel = ind 1748 | " DEBUG call DebugPrintReturn(1538 . 'final indent: ' . ind . ' - addSpecial: ' . addSpecial) 1749 | return ind + addSpecial 1750 | endfunction 1751 | 1752 | " vim:ts=8:sw=4:sts=4:nosta:noet: 1753 | --------------------------------------------------------------------------------