]> git.pld-linux.org Git - packages/vim.git/blame - php.vim
- up to 6.4.001 (but some todo issues left)
[packages/vim.git] / php.vim
CommitLineData
8fffc476
AM
1" Vim indent file
2" Language: PHP
3" Author: John Wellesz <John.wellesz (AT) teaser (DOT) fr>
4" URL: http://www.2072productions.com/vim/indent/php.vim
b2707e99
AM
5" Last Change: 2005 September 17th
6" Version: 1.181
7"
8"
9" Changes: 1.181 - I Forgot to register 'class' as a block starter so the '{'
10" after a 'class' could be wrongly indented...
11"
12" Changes: 1.18 - No more problems with Vim 6.3 and UTF-8.
13" - Opening braces "{" are always indented according to their block starter.
14"
15" Instead of:
16"
17" if( $test
18" && $test2 )
19" {
20" }
21"
22" You have:
23"
24" if( $test
25" && $test2 )
26" {
27" }
99df3f68
AM
28"
29"
30" Changes: 1.17 - Now following parts of split lines are indented:
31" Instead of:
32" $foo=
33" "foo"
34" ."foo";
35"
36" You have:
37" $foo=
38" "foo"
39" ."foo";
40"
41" - If a "case : break;" was declared on a single line, the
42" following "case" was not indented correctly.
43" - If a </script> html tag was preceded by a "?>" it wasn't indented.
44" - Some other minor corrections and improvements.
45"
46"
47" Changes: 1.16 - Now starting and ending '*' of multiline '/* */' comments are aligned
48" on the '*' of the '/*' comment starter.
49" - Some code improvements that make indentation faster.
50"
51" Changes: 1.15 - Corrected some problems with the indentation of
52" multiline "array()" declarations.
53"
54" Changes: 1.14 - Added auto-formatting for comments (using the Vim option formatoptions=qroc).
55" - Added the script option PHP_BracesAtCodeLevel to
56" indent the '{' and '}' at the same level than the
57" code they contain.
58"
59" Changes: 1.13 - Some code cleaning and typo corrections (Thanks to
60" Emanuele Giaquinta for his patches)
1d607244
AM
61"
62" Changes: 1.12 - The bug involving searchpair() and utf-8 encoding in Vim 6.3 will
63" not make this script to hang but you'll have to be
64" careful to not write '/* */' comments with other '/*'
65" inside the comments else the indentation won't be correct.
66" NOTE: This is true only if you are using utf-8 and vim 6.3.
67"
68" Changes: 1.11 - If the "case" of a "switch" wasn't alone on its line
69" and if the "switch" was at col 0 (or at default indenting)
70" the lines following the "case" were not indented.
0ae4014d
AM
71"
72" Changes: 1.10 - Lines beginning by a single or double quote were
73" not indented in some cases.
74"
75" Changes: 1.09 - JavaScript code was not always directly indented.
a4c85cb5
AM
76"
77" Changes: 1.08 - End comment tags '*/' are indented like start tags '/*'.
78" - When typing a multiline comment, '}' are indented
79" according to other commented '{'.
80" - Added a new option 'PHP_removeCRwhenUnix' to
81" automatically remove CR at end of lines when the file
82" format is Unix.
83" - Changed the file format of this very file to Unix.
84" - This version seems to correct several issues some people
85" had with 1.07.
8fffc476
AM
86"
87" Changes: 1.07 - Added support for "Here document" tags:
88" - HereDoc end tags are indented properly.
89" - HereDoc content remains unchanged.
90" - All the code that is outside PHP delimiters remains
91" unchanged.
92" - New feature: The content of <script.*> html tags is considered as PHP
93" and indented according to the surrounding PHP code.
94" - "else if" are detected as "elseif".
95" - Multiline /**/ are indented when the user types it but
96" remain unchanged when indenting from their beginning.
97" - Fixed indenting of // and # comments.
98" - php_sync_method option is set to 0 (fromstart).
99" This is required for complex PHP scripts else the indent
100" may fail.
101" - Files with non PHP code at the beginning could alter the indent
102" of the following PHP code.
103" - Other minor improvements and corrections.
104"
8fffc476
AM
105" Changes: 1.06: - Switch block were no longer indented correctly...
106" - Added an option to use a default indenting instead of 0.
107" (whereas I still can't find any good reason to use it!)
108" - A problem with ^\s*);\= lines where ending a non '{}'
109" structure.
110" - Changed script local variable to be buffer local
111" variable instead.
112"
113" Changes: 1.05: - Lines containing "<?php ?>" and "?> <?php"
114" (start and end tag on the same line) are no
115" longer indented at col 1 but as normal code.
116"
8fffc476
AM
117" Changes: 1.04: - Strings containing "//" could break the indenting
118" algorithm.
119" - When a '{}' block was at col 1, the second line of the
120" block was not indented at all (because of a stupid
121" optimization coupled with a bug).
122"
123" Changes: 1.03: - Some indenting problems corrected: end of non '{}'
124" structures was not detected in some cases. The part of
125" code concerned have been re-written
126" - PHP start tags were not indented at col 1
127" - Wrong comment in the code have been corrected
128"
129" Changes: 1.02: - The bug I was talking about in version 1.01 (right below) has
130" been corrected :)
131" - Also corrected another bug that could occur in
132" some special cases.
133" - I removed the debug mode left in 1.01 that could
134" cause some Vim messages at loading if other script were
135" bugged.
136"
137" Changes: 1.01: - Some little bug corrections reguarding automatic optimized
138" mode that missed some tests and could break the indenting.
8fffc476
AM
139" - There is also a problem with complex non bracked structures, when several
140" else are following each other, the algorithm do not indent the way it
141" should.
142" That will be corrected in the next version.
143"
8fffc476
AM
144" If you find a bug, please e-mail me at John.wellesz (AT) teaser (DOT) fr
145" with an example of code that break the algorithm.
146"
147"
148" Thanks a lot for using this script.
149"
150
151" NOTE: This script must be used with PHP syntax ON and with the php syntax
a4c85cb5 152" script by Lutz Eymers (http://www.isp.de/data/php.vim ) that's the script bundled with Gvim.
8fffc476 153"
8fffc476
AM
154"
155" In the case you have syntax errors in your script such as end of HereDoc
156" tags not at col 1 you'll have to indent your file 2 times (This script
157" will automatically put HereDoc end tags at col 1).
158"
159
a4c85cb5
AM
160" NOTE: If you are editing file in Unix file format and that (by accident)
161" there are '\r' before new lines, this script won't be able to proceed
162" correctly and will make many mistakes because it won't be able to match
163" '\s*$' correctly.
164" So you have to remove those useless characters first with a command like:
165"
166" :%s /\r$//g
167"
168" or simply 'let' the option PHP_removeCRwhenUnix to 1 and the script will
169" silently remove them when VIM load this script (at each bufread).
8fffc476 170
a4c85cb5
AM
171" Options: PHP_default_indenting = # of sw (default is 0), # of sw will be
172" added to the indent of each line of PHP code.
173"
174" Options: PHP_removeCRwhenUnix = 1 to make the script automatically remove CR
175" at end of lines (by default this option is unset), NOTE that you
176" MUST remove CR when the fileformat is UNIX else the indentation
177" won't be correct...
99df3f68
AM
178"
179" Options: PHP_BracesAtCodeLevel = 1 to indent the '{' and '}' at the same
180" level than the code they contain.
181" Exemple:
182" Instead of:
183" if ($foo)
184" {
185" foo();
186" }
187"
188" You will write:
189" if ($foo)
190" {
191" foo();
192" }
193"
194" NOTE: The script will be a bit slower if you use this option because
195" some optimizations won't be available.
a4c85cb5 196
1d607244 197
99df3f68
AM
198" The 4 following lines prevent this script from being loaded several times per buffer.
199" They also prevent the load of different indent scripts for PHP at the same time.
200if exists("b:did_indent")
201 finish
1d607244 202endif
99df3f68 203let b:did_indent = 1
1d607244 204
99df3f68
AM
205" This script set the option php_sync_method of PHP syntax script to 0
206" (fromstart indenting method) in order to have an accurate syntax.
207" If you are using very big PHP files (which is a bad idea) you will
208" experience slowings down while editing, if your code contains only PHP
209" code you can comment the line below.
1d607244 210
99df3f68 211let php_sync_method = 0
8fffc476 212
99df3f68
AM
213
214" Apply PHP_default_indenting option
8fffc476
AM
215if exists("PHP_default_indenting")
216 let b:PHP_default_indenting = PHP_default_indenting * &sw
217else
218 let b:PHP_default_indenting = 0
219endif
99df3f68
AM
220
221if exists("PHP_BracesAtCodeLevel")
222 let b:PHP_BracesAtCodeLevel = PHP_BracesAtCodeLevel
223else
224 let b:PHP_BracesAtCodeLevel = 0
225endif
226
8fffc476
AM
227
228let b:PHP_lastindented = 0
229let b:PHP_indentbeforelast = 0
230let b:PHP_indentinghuge = 0
231let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
232let b:PHP_LastIndentedWasComment = 0
99df3f68 233let b:PHP_InsideMultilineComment = 0
8fffc476
AM
234" PHP code detect variables
235let b:InPHPcode = 0
236let b:InPHPcode_checked = 0
237let b:InPHPcode_and_script = 0
238let b:InPHPcode_tofind = ""
239let b:PHP_oldchangetick = b:changedtick
a4c85cb5 240let b:UserIsTypingComment = 0
99df3f68 241let b:optionsset = 0
8fffc476 242
99df3f68
AM
243" The 4 options belows are overriden by indentexpr so they are always off
244" anyway...
1d607244 245setlocal nosmartindent
99df3f68 246setlocal noautoindent
1d607244 247setlocal nocindent
99df3f68 248setlocal nolisp " autoindent must be on, so this line is also useless...
1d607244 249
8fffc476 250setlocal indentexpr=GetPhpIndent()
a4c85cb5 251setlocal indentkeys=0{,0},0),:,!^F,o,O,e,*<Return>,=?>,=<?,=*/
8fffc476 252
99df3f68 253
b2707e99
AM
254
255let s:searchpairflags = 'bWr'
99df3f68
AM
256
257" Clean CR when the file is in Unix format
258if &fileformat == "unix" && exists("PHP_removeCRwhenUnix") && PHP_removeCRwhenUnix
259 silent! %s/\r$//g
260endif
261
262" Only define the functions once per Vim session.
8fffc476 263if exists("*GetPhpIndent")
1d607244 264 finish " XXX
8fffc476
AM
265endif
266
267let s:endline= '\s*\%(//.*\|#.*\|/\*.*\*/\s*\)\=$'
268let s:PHP_startindenttag = '<?\%(.*?>\)\@!\|<script[^>]*>\%(.*<\/script>\)\@!'
1d607244 269"setlocal debug=msg " XXX
8fffc476
AM
270
271
272function! GetLastRealCodeLNum(startline) " {{{
273 "Inspired from the function SkipJavaBlanksAndComments by Toby Allsopp for indent/java.vim
274 let lnum = a:startline
275 let old_lnum = lnum
276
277 while lnum > 1
278 let lnum = prevnonblank(lnum)
279 let lastline = getline(lnum)
280
281 " if we are inside an html <script> we must skip ?> tags to indent
282 " everything as php
283 if b:InPHPcode_and_script && lastline =~ '?>\s*$'
284 let lnum = lnum - 1
99df3f68
AM
285 elseif lastline =~ '^\s*?>.*<?\%(php\)\=\s*$'
286 let lnum = lnum - 1
8fffc476
AM
287 elseif lastline =~ '^\s*\%(//\|#\|/\*.*\*/\s*$\)' " if line is under comment
288 let lnum = lnum - 1
289 elseif lastline =~ '\*/\s*$' " skip multiline comments
290 call cursor(lnum, 1)
b2707e99
AM
291 if lastline !~ '^\*/'
292 call search('\*/', 'W') " positition the cursor on the first */
293 endif
294 let lnum = searchpair('/\*', '', '\*/', s:searchpairflags) " find the most outside /*
1d607244
AM
295 "echo 'lnum skipnonphp= ' . lnum
296 "call getchar()
8fffc476
AM
297
298 let lastline = getline(lnum)
299 if lastline =~ '^\s*/\*' " if line contains nothing but comment
300 let lnum = lnum - 1 " do the job again on the line before (a comment can hide another...)
301 else
302 break
303 endif
304
305
306 elseif lastline =~? '\%(//\s*\|?>.*\)\@<!<?\%(php\)\=\s*$\|^\s*<script\>' " skip non php code
307 " call cursor(lnum, 1)
1d607244
AM
308 " call search('<?', 'W')
309 " let lnum = searchpair('?>', '', '<?\zs', 'bW', 'getline(".") =~ "<?.*?>"')
8fffc476
AM
310
311 " let lastline = getline(lnum)
312 while lastline !~ '\(<?.*\)\@<!?>' && lnum > 1
313 let lnum = lnum - 1
314 let lastline = getline(lnum)
315 endwhile
316 if lastline =~ '^\s*?>' " if line contains nothing but end tag
317 let lnum = lnum - 1
318 else
319 break " else there is something important before the ?>
320 endif
321
322
323 " Manage "here document" tags
324 elseif lastline =~? '^\a\w*;$' && lastline !~? s:notPhpHereDoc " match the end of a heredoc
325 let tofind=substitute( lastline, '\([^;]\+\);', '<<<\1$', '')
326 while getline(lnum) !~? tofind && lnum > 1
327 let lnum = lnum - 1
328 endwhile
329 else
330 break " if none of these were true then we are done
331 endif
332 endwhile
333
334 if lnum==1 && getline(lnum)!~ '<?'
335 let lnum=0
336 endif
99df3f68
AM
337
338 " This is to handle correctly end of script tags; to return the real last php
339 " code line else a '?>' could be returned has last_line
340 if b:InPHPcode_and_script && !b:InPHPcode
341 let b:InPHPcode_and_script = 0
342 endif
8fffc476
AM
343 return lnum
344endfunction
345" }}}
346
347function! Skippmatch() " {{{
348 " the slowest instruction of this script, remove it and the script is 3
349 " times faster but you may have troubles with '{' inside comments or strings
350 " that will break the indent algorithm...
351 let synname = synIDattr(synID(line("."), col("."), 0), "name")
99df3f68 352 if synname == "Delimiter" || synname == "phpParent" || synname == "javaScriptBraces" || synname == "phpComment" && b:UserIsTypingComment
8fffc476 353 return 0
8fffc476
AM
354 else
355 return 1
8fffc476
AM
356 endif
357endfun
358" }}}
359
360function! FindOpenBracket(lnum) " {{{
361 call cursor(a:lnum, 1) " set the cursor to the start of the lnum line
362 return searchpair('{', '', '}', 'bW', 'Skippmatch()')
363endfun
364" }}}
365
366function! FindTheIfOfAnElse (lnum, StopAfterFirstPrevElse) " {{{
367" A very clever recoursive function created by me (John Wellesz) that find the "if" corresponding to an
368" "else". This function can easily be adapted for other languages :)
369
370 if getline(a:lnum) =~# '^\s*}\s*else\%(if\)\=\>'
371 let beforeelse = a:lnum " we do this so we can find the opened bracket to speed up the process
372 else
373 let beforeelse = GetLastRealCodeLNum(a:lnum - 1)
374 endif
375
376 if !s:level
377 let s:iftoskip = 0
378 endif
379
380 " If we found another "else" then it means we need to skip the next "if"
381 " we'll found. (since version 1.02)
382 if getline(beforeelse) =~# '^\s*\%(}\s*\)\=else\%(\s*if\)\@!\>'
383 let s:iftoskip = s:iftoskip + 1
384 endif
385
386 " A closing bracket? let skip the whole block to save some recursive calls
99df3f68 387 if getline(beforeelse) =~ '^\s*}'
8fffc476
AM
388 let beforeelse = FindOpenBracket(beforeelse)
389
390 " Put us on the block starter
391 if getline(beforeelse) =~ '^\s*{'
392 let beforeelse = GetLastRealCodeLNum(beforeelse - 1)
393 endif
394 endif
395
396
397 if !s:iftoskip && a:StopAfterFirstPrevElse && getline(beforeelse) =~# '^\s*\%([}]\s*\)\=else\%(if\)\=\>'
398 return beforeelse
399 endif
a4c85cb5 400
8fffc476
AM
401 " if there was an else, then there is a if...
402 if getline(beforeelse) !~# '^\s*if\>' && beforeelse>1 || s:iftoskip && beforeelse>1
403
404 if s:iftoskip && getline(beforeelse) =~# '^\s*if\>'
405 let s:iftoskip = s:iftoskip - 1
406 endif
407
408 let s:level = s:level + 1
409 let beforeelse = FindTheIfOfAnElse(beforeelse, a:StopAfterFirstPrevElse)
410 endif
411
412 return beforeelse
413
414endfunction
415" }}}
416
417function! IslinePHP (lnum, tofind) " {{{
418 " This function asks to the syntax if the pattern 'tofind' on the line
419 " number 'lnum' is PHP code (very slow...).
420 let cline = getline(a:lnum)
421
422 if a:tofind==""
0ae4014d
AM
423 let tofind = "^\\s*[\"']*\s*\\zs\\S" " This correct the issue where lines beginning by a
424 " single or double quote were not indented in some cases.
8fffc476
AM
425 else
426 let tofind = a:tofind
427 endif
428
429 let tofind = tofind . '\c' " ignorecase
430
431 let coltotest = match (cline, tofind) + 1 "find the first non blank char in the current line
432
433 let synname = synIDattr(synID(a:lnum, coltotest, 0), "name") " ask to syntax what is its name
0ae4014d 434 "echo synname
8fffc476 435
0ae4014d
AM
436 " if matchstr(synname, '^...') == "php" || synname=="Delimiter" || synname =~? '^javaScript'
437 if synname =~ '^php' || synname=="Delimiter" || synname =~? '^javaScript'
8fffc476
AM
438 return synname
439 else
440 return ""
441 endif
442endfunction
443" }}}
444
445let s:notPhpHereDoc = '\%(break\|return\|continue\|exit\);'
b2707e99 446let s:blockstart = '\%(\%(\%(}\s*\)\=else\%(\s\+\)\=\)\=if\>\|else\>\|while\>\|switch\>\|for\%(each\)\=\>\|declare\>\|class\>\|[|&]\)'
99df3f68
AM
447
448" make sure the options needed for this script to work correctly are set here
449" for the last time. They could have been overriden by any 'onevent'
450" associated setting file...
451let s:autorestoptions = 0
452if ! s:autorestoptions
453 au BufWinEnter,Syntax *.php,*.php3,*.php4,*.php5 call ResetOptions()
454 let s:autorestoptions = 1
455endif
456
457function! ResetOptions()
458 if ! b:optionsset
459 setlocal formatoptions=qroc
460 let b:optionsset = 1
461 endif
462endfunc
8fffc476
AM
463
464function! GetPhpIndent()
465 "##############################################
466 "########### MAIN INDENT FUNCTION #############
467 "##############################################
468
469 " This detect if the user is currently typing text between each call
470 let UserIsEditing=0
471 if b:PHP_oldchangetick != b:changedtick
472 let b:PHP_oldchangetick = b:changedtick
473 let UserIsEditing=1
474 endif
475
8fffc476
AM
476 if b:PHP_default_indenting
477 let b:PHP_default_indenting = g:PHP_default_indenting * &sw
478 endif
479
480 let cline = getline(v:lnum) " current line
481
482 " Let's detect if we are indenting just one line or more than 3 lines
483 " in the last case we can slightly optimize our algorithm
484 if !b:PHP_indentinghuge && b:PHP_lastindented > b:PHP_indentbeforelast
485 if b:PHP_indentbeforelast
486 let b:PHP_indentinghuge = 1
487 echom 'Large indenting detected, speed optimizations engaged'
488 endif
489 let b:PHP_indentbeforelast = b:PHP_lastindented
490 endif
491
492 " If the line we are indenting isn't directly under the previous non-blank
493 " line of the file then deactivate the optimization procedures and reset
494 " status variable (we restart for scratch)
495 if b:InPHPcode_checked && prevnonblank(v:lnum - 1) != b:PHP_lastindented
496 if b:PHP_indentinghuge
497 echom 'Large indenting deactivated'
498 let b:PHP_indentinghuge = 0
499 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
500 endif
501 let b:PHP_lastindented = v:lnum
502 let b:PHP_LastIndentedWasComment=0
99df3f68 503 let b:PHP_InsideMultilineComment=0
8fffc476
AM
504 let b:PHP_indentbeforelast = 0
505
8fffc476
AM
506 let b:InPHPcode = 0
507 let b:InPHPcode_checked = 0
508 let b:InPHPcode_and_script = 0
509 let b:InPHPcode_tofind = ""
510
511 elseif v:lnum > b:PHP_lastindented " we are indenting line in > order (we can rely on the line before)
512 let real_PHP_lastindented = b:PHP_lastindented
513 let b:PHP_lastindented = v:lnum
514 endif
515
516 " We must detect if we are in PHPCODE or not, but one time only, then
517 " we will detect php end and start tags, comments /**/ and HereDoc
518 " tags
519
520 if !b:InPHPcode_checked " {{{ One time check
521 let b:InPHPcode_checked = 1
522
523 let synname = IslinePHP (prevnonblank(v:lnum), "") " the line could be blank (if the user presses 'return')
524
525 if synname!=""
526 if synname != "phpHereDoc"
527 let b:InPHPcode = 1
528 let b:InPHPcode_tofind = ""
0ae4014d 529
a4c85cb5
AM
530 if synname == "phpComment"
531 let b:UserIsTypingComment = 1
532 else
533 let b:UserIsTypingComment = 0
534 endif
0ae4014d
AM
535
536 if synname =~? '^javaScript'
537 let b:InPHPcode_and_script = 1
538 endif
539
8fffc476
AM
540 else
541 let b:InPHPcode = 0
a4c85cb5 542 let b:UserIsTypingComment = 0
8fffc476
AM
543
544 let lnum = v:lnum - 1
a4c85cb5 545 while getline(lnum) !~? '<<<\a\w*$' && lnum > 1
8fffc476
AM
546 let lnum = lnum - 1
547 endwhile
548
549 let b:InPHPcode_tofind = substitute( getline(lnum), '^.*<<<\(\a\w*\)\c', '^\\s*\1;$', '')
550 endif
0ae4014d 551 else " IslinePHP returned "" => we are not in PHP or Javascript
8fffc476 552 let b:InPHPcode = 0
a4c85cb5 553 let b:UserIsTypingComment = 0
8fffc476
AM
554 " Then we have to find a php start tag...
555 let b:InPHPcode_tofind = '<?\%(.*?>\)\@!\|<script.*>'
556 endif
557 endif "!b:InPHPcode_checked }}}
558
559 " Now we know where we are so we can verify the line right above the
560 " current one to see if we have to stop or restart php indenting
0ae4014d 561
8fffc476
AM
562 " Test if we are indenting PHP code {{{
563 " Find an executable php code line above the current line.
564 let lnum = prevnonblank(v:lnum - 1)
565 let last_line = getline(lnum)
566
567 " If we aren't in php code, then there is something we have to find
568 if b:InPHPcode_tofind!=""
569 if cline =~? b:InPHPcode_tofind
570 let b:InPHPcode = 1
571 let b:InPHPcode_tofind = ""
a4c85cb5
AM
572 let b:UserIsTypingComment = 0
573 if cline =~ '\*/' " End comment tags must be indented like start comment tags
574 call cursor(v:lnum, 1)
b2707e99
AM
575 if cline !~ '^\*/'
576 call search('\*/', 'W')
577 endif
578 let lnum = searchpair('/\*', '', '\*/', s:searchpairflags) " find the most outside /*
99df3f68
AM
579
580 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
581 let b:PHP_LastIndentedWasComment = 0 " prevent a problem if multiline /**/ comment are surounded by
582 " other types of comments
583
584 if cline =~ '^\s*\*/'
585 return indent(lnum) + 1
586 else
587 return indent(lnum)
588 endif
589
8fffc476
AM
590 elseif cline =~? '<script\>' " a more accurate test is useless since there isn't any other possibility
591 let b:InPHPcode_and_script = 1
592 endif
593 endif
594 endif
595
596 " ### If we are in PHP code, we test the line before to see if we have to stop indenting
597
598 if b:InPHPcode
599
600 " Was last line containing a PHP end tag ?
601 if !b:InPHPcode_and_script && last_line =~ '\%(<?.*\)\@<!?>\%(.*<?\)\@!' && IslinePHP(lnum, '?>')=="Delimiter"
602 if cline !~? s:PHP_startindenttag
603 let b:InPHPcode = 0
604 let b:InPHPcode_tofind = s:PHP_startindenttag
605 elseif cline =~? '<script\>'
606 let b:InPHPcode_and_script = 1
607 endif
608
609 " Was last line the start of a HereDoc ?
610 elseif last_line =~? '<<<\a\w*$'
0ae4014d 611 " \&& IslinePHP(lnum, '\a\w*$')=="Delimiter"
8fffc476
AM
612 let b:InPHPcode = 0
613 let b:InPHPcode_tofind = substitute( last_line, '^.*<<<\(\a\w*\)\c', '^\\s*\1;$', '')
614
615 " Skip /* \n+ */ comments execept when the user is currently
616 " writting them
b2707e99 617 elseif !UserIsEditing && cline =~ '^\s*/\*\%(.*\*/\)\@!' && getline(v:lnum + 1) !~ '^\s*\*'
8fffc476
AM
618 let b:InPHPcode = 0
619 let b:InPHPcode_tofind = '\*/'
620
621 " is current line the end of a HTML script ? (we indent script the
622 " same as php code)
623 elseif cline =~? '^\s*</script>'
624 let b:InPHPcode = 0
8fffc476
AM
625 let b:InPHPcode_tofind = s:PHP_startindenttag
626 endif
627 endif " }}}
628
629 " Non PHP code is let as it is
630 if !b:InPHPcode && !b:InPHPcode_and_script
631 return -1
99df3f68
AM
632 "elseif !b:InPHPcode
633 " let b:InPHPcode_and_script = 0 " now it is GetLastRealCodeLNum that resets this variable
8fffc476
AM
634 endif
635
636 " Align correctly multi // or # lines
637
638 " Indent successive // or # comment the same way the first is {{{
639 if cline =~ '^\s*\%(//\|#\|/\*.*\*/\s*$\)'
640 if b:PHP_LastIndentedWasComment == 1
641 return indent(real_PHP_lastindented) " line replaced in 1.02
642 endif
643 let b:PHP_LastIndentedWasComment = 1
644 else
645 let b:PHP_LastIndentedWasComment = 0
646 endif
647 " }}}
99df3f68
AM
648
649 " Indent multiline /* comments correctly {{{
650
651 "if we are on the start of a MULTI * beginning comment or if the user is
652 "currently typing a /* beginning comment.
653
654 if b:PHP_InsideMultilineComment || b:UserIsTypingComment
655 if cline =~ '^\s*\*\%(\/\)\@!' " if cline == '*'
656 if last_line =~ '^\s*/\*' " if last_line == '/*'
657 return indent(lnum) + 1
658 else
659 return indent(lnum)
660 endif
661 else
662 let b:PHP_InsideMultilineComment = 0
663 endif
664 endif
665
666 if !b:PHP_InsideMultilineComment && cline =~ '^\s*/\*' " if cline == '/*'
667 let b:PHP_InsideMultilineComment = 1
668 return -1
669 endif
670 " }}}
8fffc476
AM
671
672 " Some tags are always indented to col 1
673
674 " Things always indented at col 1 (PHP delimiter: <?, ?>, Heredoc end) {{{
675 " PHP start tags are always at col 1, useless to indent unless the end tag
676 " is on the same line
677 if cline =~# '^\s*<?' && cline !~ '?>' " Added the ^\s* part in version 1.03
678 return 0
679 endif
680
681 " PHP end tags are always at col 1, useless to indent unless if it's
682 " followed by a start tag on the same line
683 if cline =~ '^\s*?>' && cline !~# '<?'
684 return 0
685 endif
686
687 " put HereDoc end tags at start of lines
688 if cline =~? '^\s*\a\w*;$' && cline !~? s:notPhpHereDoc
689 return 0
690 endif
691 " }}}
692
693 let s:level = 0
694
695 " Find an executable php code line above the current line.
696 let lnum = GetLastRealCodeLNum(v:lnum - 1)
697 let last_line = getline(lnum) " last line
698 let ind = indent(lnum) " by default
699 let endline= s:endline
700
701 if ind==0 && b:PHP_default_indenting
702 let ind = b:PHP_default_indenting
703 endif
704
705 " Hit the start of the file, use default indent.
706 if lnum == 0
707 return b:PHP_default_indenting
708 endif
709
8fffc476
AM
710
711 " Search the matching open bracket (with searchpair()) and set the indent of cline
712 " to the indent of the matching line.
713 if cline =~ '^\s*}\%(}}\)\@!'
714 let ind = indent(FindOpenBracket(v:lnum))
715 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
716 return ind
717 endif
718
99df3f68
AM
719 " Check for end of comment and indent it like its beginning
720 if cline =~ '^\s*\*/' " End comment tags must be indented like start comment tags
a4c85cb5 721 call cursor(v:lnum, 1)
b2707e99
AM
722 if cline !~ '^\*/'
723 call search('\*/', 'W')
724 endif
725 let lnum = searchpair('/\*', '', '\*/', s:searchpairflags) " find the most outside /*
726 "echo 'Searchpair returned: ' . lnum
727 "call getchar()
99df3f68
AM
728
729 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
730
731 if cline =~ '^\s*\*/'
732 return indent(lnum) + 1
733 else
734 return indent(lnum)
735 endif
736 endif
737
738 let defaultORcase = '^\s*\%(default\|case\).*:'
739
740 " if the last line is a stated line and it's not indented then why should
741 " we indent this one??
742 " if optimized mode is active and nor current or previous line are an 'else'
743 " or the end of a possible bracketless thing then indent the same as the previous
744 " line
745 if last_line =~ '[;}]'.endline && last_line !~# defaultORcase
746 if ind==b:PHP_default_indenting " if no indentation for the previous line
747 return b:PHP_default_indenting
748 elseif b:PHP_indentinghuge && ind==b:PHP_CurrentIndentLevel && cline !~# '^\s*\%(else\|\%(case\|default\).*:\|[})];\=\)' && last_line !~# '^\s*\%(\%(}\s*\)\=else\)' && getline(GetLastRealCodeLNum(lnum - 1))=~';'.endline
749 return b:PHP_CurrentIndentLevel
750 endif
a4c85cb5 751 endif
0ae4014d 752
8fffc476
AM
753 let LastLineClosed = 0 " used to prevent redundant tests in the last part of the script
754
99df3f68
AM
755 let terminated = '\%(;\%(\s*?>\)\=\|<<<\a\w*\|}\)'.endline
756 " What is a terminated line?
757 " - a line terminated by a ";" optionaly followed by a "?>"
758 " - a HEREDOC starter line (the content of such block is never seen by this script)
759 " - a "}" not followed by a "{"
760
761 let unstated = '\%(^\s*'.s:blockstart.'.*)\|\%(//.*\)\@<!\<e'.'lse\>\)'.endline
8fffc476
AM
762 " What is an unstated line?
763 " - an "else" at the end of line
764 " - a s:blockstart (if while etc...) followed by anything and a ")" at
765 " the end of line
766
767 " if the current line is an 'else' starting line
768 " (to match an 'else' preceded by a '}' is irrelevant and futile - see
769 " code above)
770 if ind != b:PHP_default_indenting && cline =~# '^\s*else\%(if\)\=\>'
771 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting " prevent optimized to work at next call
772 return indent(FindTheIfOfAnElse(v:lnum, 1))
b2707e99
AM
773 elseif cline =~ '^\s*{'
774 let previous_line = last_line
775 let last_line_num = lnum
776
777 while last_line_num > 1
778
779 if previous_line =~ '^\s*\%(' . s:blockstart . '\|\%([a-zA-Z]\s*\)*function\)' && previous_line !~ '^\s*[|&]'
780 "echo '{ detected and aligned to ' . last_line_num . ' ('.previous_line.')'
781 "call getchar()
782
783 let ind = indent(last_line_num)
784
785 " If the PHP_BracesAtCodeLevel is set then indent the '{'
786 if b:PHP_BracesAtCodeLevel " XXX mod {
787 let ind = ind + &sw
788 endif
789
790 return ind
791 endif
792
793 let last_line_num = last_line_num - 1
794 let previous_line = getline(last_line_num)
795 endwhile
796
8fffc476
AM
797 elseif last_line =~# unstated && cline !~ '^\s*{\|^\s*);\='.endline
798 let ind = ind + &sw
799 return ind
800
801 " If the last line is terminated by ';' or if it's a closing '}'
802 " We need to check if this isn't the end of a multilevel non '{}'
803 " structure such as:
804 " Exemple:
805 " if ($truc)
806 " echo 'truc';
807 "
808 " OR
809 "
810 " if ($truc)
811 " while ($truc) {
812 " lkhlkh();
813 " echo 'infinite loop\n';
814 " }
99df3f68
AM
815 "
816 " OR even (ADDED for version 1.17 - no modification required )
817 "
818 " $thing =
819 " "something";
820 elseif ind != b:PHP_default_indenting && last_line =~ terminated
8fffc476
AM
821 " If we are here it means that the previous line is:
822 " - a *;$ line
823 " - a [beginning-blanck] } followed by anything but a { $
824 let previous_line = last_line
825 let last_line_num = lnum
826 let LastLineClosed = 1
827 " The idea here is to check if the current line is after a non '{}'
828 " structure so we can indent it like the top of that structure.
829 " The top of that structure is caracterized by a if (ff)$ style line
830 " preceded by a stated line. If there is no such structure then we
831 " just have to find two 'normal' lines following each other with the
832 " same indentation and with the first of these two lines terminated by
833 " a ; or by a }...
834
835 while 1
836 " let's skip '{}' blocks
837 if previous_line =~ '^\s*}'
838 " find the openning '{'
839 let last_line_num = FindOpenBracket(last_line_num)
840
841 " if the '{' is alone on the line get the line before
842 if getline(last_line_num) =~ '^\s*{'
843 let last_line_num = GetLastRealCodeLNum(last_line_num - 1)
844 endif
845
846 let previous_line = getline(last_line_num)
847
848 continue
849 else
850 " At this point we know that the previous_line isn't a closing
851 " '}' so we can check if we really are in such a structure.
852
853 " it's not a '}' but it could be an else alone...
854 if getline(last_line_num) =~# '^\s*else\%(if\)\=\>'
855 let last_line_num = FindTheIfOfAnElse(last_line_num, 0)
856 continue " re-run the loop (we could find a '}' again)
857 endif
858
859 " So now it's ok we can check :-)
860 " A good quality is to have confidence in oneself so to know
861 " if yes or no we are in that struct lets test the indent of
862 " last_line_num and of last_line_num - 1!
863 " If those are == then we are almost done.
864 "
865 " That isn't sufficient, we need to test how the first of the
866 " 2 lines is ended...
867
868 " Note the indenting of the line we are checking
869
870 let last_match = last_line_num " remember the 'topest' line we found so far
871
872 let one_ahead_indent = indent(last_line_num)
873 let last_line_num = GetLastRealCodeLNum(last_line_num - 1)
874 let two_ahead_indent = indent(last_line_num)
875 let after_previous_line = previous_line
876 let previous_line = getline(last_line_num)
877
878
879 " If we find a '{' or a case/default then we are inside that block so lets
880 " indent properly... Like the line following that block starter
99df3f68 881 if previous_line =~# defaultORcase.'\|{'.endline
8fffc476
AM
882 break
883 endif
884
885 " The 3 lines below are not necessary for the script to work
886 " but it makes it work a little more faster in some (rare) cases.
887 " We verify if we are at the top of a non '{}' struct.
888 if after_previous_line=~# '^\s*'.s:blockstart.'.*)'.endline && previous_line =~# '[;}]'.endline
889 break
890 endif
891
892 if one_ahead_indent == two_ahead_indent || last_line_num < 1
893 " So the previous line and the line before are at the same
894 " col. Now we just have to check if the line before is a ;$ or [}]$ ended line
895 " we always check the most ahead line of the 2 lines so
896 " it's useless to match ')$' since the lines couldn't have
897 " the same indent...
898 if previous_line =~# '[;}]'.endline || last_line_num < 1
899 break
900 endif
901 endif
902 endif
903 endwhile
904
905 if indent(last_match) != ind " if nothing was done lets the old script continue
906 let ind = indent(last_match) " let's use the indent of the last line matched by the alhorithm above
99df3f68 907 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting " line added in version 1.02 to prevent optimized mode
8fffc476 908 " from acting in some special cases
99df3f68
AM
909
910 " case and default are indented 1 level below
911 if cline =~# defaultORcase
912 let ind = ind - &sw
913 endif
8fffc476
AM
914 return ind
915 endif
916 endif
917
8fffc476
AM
918 let plinnum = GetLastRealCodeLNum(lnum - 1)
919 let pline = getline(plinnum) " previous to last line
920
921 " REMOVE comments at end of line before treatment
1d607244 922 " the first part of the regex removes // from the end of line when they are
8fffc476
AM
923 " followed by a number of '"' which is a multiple of 2. The second part
924 " removes // that are not followed by any '"'
925 " Sorry for this unreadable thing...
926 let last_line = substitute(last_line,"\\(//\\|#\\)\\(\\(\\([^\"']*\\([\"']\\)[^\"']*\\5\\)\\+[^\"']*$\\)\\|\\([^\"']*$\\)\\)",'','')
927
99df3f68
AM
928
929 if ind == b:PHP_default_indenting
930 if last_line =~ terminated
931 let LastLineClosed = 1
932 endif
933 endif
934
8fffc476
AM
935 " Indent blocks enclosed by {} or () (default indenting)
936 if !LastLineClosed " the last line isn't a .*; or a }$ line
99df3f68
AM
937 " Indent correctly multilevel and multiline '(.*)' things
938
8fffc476
AM
939 " if the last line is a [{(]$ or a multiline function call (or array
940 " declaration) with already one parameter on the opening ( line
941 if last_line =~# '[{(]'.endline || last_line =~? '\h\w*\s*(.*,$' && pline !~ '[,(]'.endline
99df3f68
AM
942
943 if !b:PHP_BracesAtCodeLevel || last_line !~# '^\s*{' " XXX mod {
944 let ind = ind + &sw
945 endif
946
947 if b:PHP_BracesAtCodeLevel || cline !~# defaultORcase " XXX mod (2) {
948 " case and default are not indented inside blocks
8fffc476
AM
949 let b:PHP_CurrentIndentLevel = ind
950 return ind
951 endif
99df3f68
AM
952
953 " If the last line isn't empty and ends with a '),' then check if the
954 " ')' was oppened on the same line, if not it means it closes a
955 " multiline '(.*)' thing and that the current line need to be
956 " de-indented one time.
957 elseif last_line =~ '\S\+\s*),'.endline
958 call cursor(lnum, 1)
959 call search('),'.endline, 'W')
960 let openedparent = searchpair('(', '', ')', 'bW', 'Skippmatch()')
961 if openedparent != lnum
962 let ind = indent(openedparent)
963 endif
964
965 " In all other cases if the last line isn't terminated indent 1
966 " level higher but only if the line before the last line wasn't
967 " indented for the same reason.
968
969 elseif cline !~ '^\s*{' && pline =~ '\%(;\%(\s*?>\)\=\|<<<\a\w*\|{\|^\s*'.s:blockstart.'\s*(.*)\)'.endline.'\|^\s*}\|'.defaultORcase
970
971 let ind = ind + &sw
972
973 endif
99df3f68
AM
974
975 elseif last_line =~# defaultORcase
976 let ind = ind + &sw
8fffc476
AM
977 endif
978
99df3f68 979 " If the current line closes a multiline function call or array def XXX
8fffc476
AM
980 if cline =~ '^\s*);\='
981 let ind = ind - &sw
99df3f68
AM
982 " CASE and DEFAULT are indented at the same level than the SWITCH
983 elseif cline =~# defaultORcase
8fffc476 984 let ind = ind - &sw
99df3f68 985
8fffc476
AM
986 endif
987
988 let b:PHP_CurrentIndentLevel = ind
989 return ind
990endfunction
991
992" vim: set ts=4 sw=4:
a4c85cb5 993" vim: set ff=unix:
This page took 0.203234 seconds and 4 git commands to generate.