]> git.pld-linux.org Git - packages/vim.git/blame - php.vim
- added __autoheader
[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
0ae4014d
AM
5" Last Change: 2005 February 10th
6" Version: 1.10
7"
8" Changes: 1.10 - Lines beginning by a single or double quote were
9" not indented in some cases.
10"
11" Changes: 1.09 - JavaScript code was not always directly indented.
a4c85cb5
AM
12"
13" Changes: 1.08 - End comment tags '*/' are indented like start tags '/*'.
14" - When typing a multiline comment, '}' are indented
15" according to other commented '{'.
16" - Added a new option 'PHP_removeCRwhenUnix' to
17" automatically remove CR at end of lines when the file
18" format is Unix.
19" - Changed the file format of this very file to Unix.
20" - This version seems to correct several issues some people
21" had with 1.07.
8fffc476
AM
22"
23" Changes: 1.07 - Added support for "Here document" tags:
24" - HereDoc end tags are indented properly.
25" - HereDoc content remains unchanged.
26" - All the code that is outside PHP delimiters remains
27" unchanged.
28" - New feature: The content of <script.*> html tags is considered as PHP
29" and indented according to the surrounding PHP code.
30" - "else if" are detected as "elseif".
31" - Multiline /**/ are indented when the user types it but
32" remain unchanged when indenting from their beginning.
33" - Fixed indenting of // and # comments.
34" - php_sync_method option is set to 0 (fromstart).
35" This is required for complex PHP scripts else the indent
36" may fail.
37" - Files with non PHP code at the beginning could alter the indent
38" of the following PHP code.
39" - Other minor improvements and corrections.
40"
8fffc476
AM
41" Changes: 1.06: - Switch block were no longer indented correctly...
42" - Added an option to use a default indenting instead of 0.
43" (whereas I still can't find any good reason to use it!)
44" - A problem with ^\s*);\= lines where ending a non '{}'
45" structure.
46" - Changed script local variable to be buffer local
47" variable instead.
48"
49" Changes: 1.05: - Lines containing "<?php ?>" and "?> <?php"
50" (start and end tag on the same line) are no
51" longer indented at col 1 but as normal code.
52"
8fffc476
AM
53" Changes: 1.04: - Strings containing "//" could break the indenting
54" algorithm.
55" - When a '{}' block was at col 1, the second line of the
56" block was not indented at all (because of a stupid
57" optimization coupled with a bug).
58"
59" Changes: 1.03: - Some indenting problems corrected: end of non '{}'
60" structures was not detected in some cases. The part of
61" code concerned have been re-written
62" - PHP start tags were not indented at col 1
63" - Wrong comment in the code have been corrected
64"
65" Changes: 1.02: - The bug I was talking about in version 1.01 (right below) has
66" been corrected :)
67" - Also corrected another bug that could occur in
68" some special cases.
69" - I removed the debug mode left in 1.01 that could
70" cause some Vim messages at loading if other script were
71" bugged.
72"
73" Changes: 1.01: - Some little bug corrections reguarding automatic optimized
74" mode that missed some tests and could break the indenting.
8fffc476
AM
75" - There is also a problem with complex non bracked structures, when several
76" else are following each other, the algorithm do not indent the way it
77" should.
78" That will be corrected in the next version.
79"
80" Changes: improvements with regard to the original version (0.5) by Miles Lott (whose this script was inspired):
81" - Commented part of code or non PHP code no longer break the
82" indent algorithm, the content of those parts are indented
83" separatly
84" - corrected a strange thing (a part of code was duplicated) ->
85" the last version couldn't work.
86" - Folds can be used without problem
87" - multilevel non bracked structures are indented (like
88" in C)
89" Exemple:
90" if (!isset($History_lst_sel))
91" if (!isset($blabla))
92" if (!isset($bloum)) {
93" $History_lst_sel=0;
94" } else
95" $foo="truc";
96" else $bla= "foo";
97" $command_hist = TRUE;
98"
99" - "array( 'blabla'," lines no longer break the indent of the
100" following lines
101" - the options php_noindent_switch and php_indent_shortopentags have been removed
102" (couldn't find any reason why one would want to use them)
103" - PHP open and close tags are always set to col 1 as for the
104" immediate following php code
105"
106" If you find a bug, please e-mail me at John.wellesz (AT) teaser (DOT) fr
107" with an example of code that break the algorithm.
108"
109"
110" Thanks a lot for using this script.
111"
112
113" NOTE: This script must be used with PHP syntax ON and with the php syntax
a4c85cb5 114" script by Lutz Eymers (http://www.isp.de/data/php.vim ) that's the script bundled with Gvim.
8fffc476
AM
115"
116" This script set the option php_sync_method of PHP syntax script to 0
117" (fromstart indenting method) in order to have an accurate syntax.
a4c85cb5
AM
118" If you are using very big PHP files (which is a bad idea) you will
119" experience slowings down while editing, if your code contains only PHP
120" code you can comment the line below.
121
122let php_sync_method = 0
123
8fffc476
AM
124"
125" In the case you have syntax errors in your script such as end of HereDoc
126" tags not at col 1 you'll have to indent your file 2 times (This script
127" will automatically put HereDoc end tags at col 1).
128"
129
a4c85cb5
AM
130" NOTE: If you are editing file in Unix file format and that (by accident)
131" there are '\r' before new lines, this script won't be able to proceed
132" correctly and will make many mistakes because it won't be able to match
133" '\s*$' correctly.
134" So you have to remove those useless characters first with a command like:
135"
136" :%s /\r$//g
137"
138" or simply 'let' the option PHP_removeCRwhenUnix to 1 and the script will
139" silently remove them when VIM load this script (at each bufread).
8fffc476 140
a4c85cb5
AM
141" Options: PHP_default_indenting = # of sw (default is 0), # of sw will be
142" added to the indent of each line of PHP code.
143"
144" Options: PHP_removeCRwhenUnix = 1 to make the script automatically remove CR
145" at end of lines (by default this option is unset), NOTE that you
146" MUST remove CR when the fileformat is UNIX else the indentation
147" won't be correct...
148
149if &fileformat == "unix" && exists("PHP_removeCRwhenUnix") && PHP_removeCRwhenUnix
150 let myul=&ul
151 silent! %s/\r$//g
152endif
8fffc476
AM
153
154if exists("PHP_default_indenting")
155 let b:PHP_default_indenting = PHP_default_indenting * &sw
156else
157 let b:PHP_default_indenting = 0
158endif
159" Only load this indent file when no other was loaded. But reset those state
a4c85cb5 160" variables
8fffc476
AM
161
162let b:PHP_lastindented = 0
163let b:PHP_indentbeforelast = 0
164let b:PHP_indentinghuge = 0
165let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
166let b:PHP_LastIndentedWasComment = 0
167" PHP code detect variables
168let b:InPHPcode = 0
169let b:InPHPcode_checked = 0
170let b:InPHPcode_and_script = 0
171let b:InPHPcode_tofind = ""
172let b:PHP_oldchangetick = b:changedtick
a4c85cb5 173let b:UserIsTypingComment = 0
8fffc476
AM
174
175if exists("b:did_indent")
176 finish
177endif
178
179let b:did_indent = 1
180setlocal nosmartindent
181
182setlocal nolisp
183setlocal indentexpr=GetPhpIndent()
a4c85cb5 184setlocal indentkeys=0{,0},0),:,!^F,o,O,e,*<Return>,=?>,=<?,=*/
8fffc476
AM
185
186" Only define the function once.
187if exists("*GetPhpIndent")
188 finish
189endif
190
191let s:endline= '\s*\%(//.*\|#.*\|/\*.*\*/\s*\)\=$'
192let s:PHP_startindenttag = '<?\%(.*?>\)\@!\|<script[^>]*>\%(.*<\/script>\)\@!'
193" setlocal debug=msg
194
195
196function! GetLastRealCodeLNum(startline) " {{{
197 "Inspired from the function SkipJavaBlanksAndComments by Toby Allsopp for indent/java.vim
198 let lnum = a:startline
199 let old_lnum = lnum
200
201 while lnum > 1
202 let lnum = prevnonblank(lnum)
203 let lastline = getline(lnum)
204
205 " if we are inside an html <script> we must skip ?> tags to indent
206 " everything as php
207 if b:InPHPcode_and_script && lastline =~ '?>\s*$'
208 let lnum = lnum - 1
209
210
211 elseif lastline =~ '^\s*\%(//\|#\|/\*.*\*/\s*$\)' " if line is under comment
212 let lnum = lnum - 1
213 elseif lastline =~ '\*/\s*$' " skip multiline comments
214 call cursor(lnum, 1)
215 call search('\*/\zs', 'W')
216 let lnum = searchpair('/\*\zs', '', '\*/\zs', 'bWr', '') " find the most outside /*
217
218 let lastline = getline(lnum)
219 if lastline =~ '^\s*/\*' " if line contains nothing but comment
220 let lnum = lnum - 1 " do the job again on the line before (a comment can hide another...)
221 else
222 break
223 endif
224
225
226 elseif lastline =~? '\%(//\s*\|?>.*\)\@<!<?\%(php\)\=\s*$\|^\s*<script\>' " skip non php code
227 " call cursor(lnum, 1)
228 " call search('<?\zs', 'W')
229 " let lnum = searchpair('?>\zs', '', '<?\zs', 'bW', 'getline(".") =~ "<?.*?>"') " find the most outside /*
230
231 " let lastline = getline(lnum)
232 while lastline !~ '\(<?.*\)\@<!?>' && lnum > 1
233 let lnum = lnum - 1
234 let lastline = getline(lnum)
235 endwhile
236 if lastline =~ '^\s*?>' " if line contains nothing but end tag
237 let lnum = lnum - 1
238 else
239 break " else there is something important before the ?>
240 endif
241
242
243 " Manage "here document" tags
244 elseif lastline =~? '^\a\w*;$' && lastline !~? s:notPhpHereDoc " match the end of a heredoc
245 let tofind=substitute( lastline, '\([^;]\+\);', '<<<\1$', '')
246 while getline(lnum) !~? tofind && lnum > 1
247 let lnum = lnum - 1
248 endwhile
249 else
250 break " if none of these were true then we are done
251 endif
252 endwhile
253
254 if lnum==1 && getline(lnum)!~ '<?'
255 let lnum=0
256 endif
257 return lnum
258endfunction
259" }}}
260
261function! Skippmatch() " {{{
262 " the slowest instruction of this script, remove it and the script is 3
263 " times faster but you may have troubles with '{' inside comments or strings
264 " that will break the indent algorithm...
265 let synname = synIDattr(synID(line("."), col("."), 0), "name")
a4c85cb5 266 if synname == "phpParent" || synname == "javaScriptBraces" || synname == "phpComment" && b:UserIsTypingComment
8fffc476 267 return 0
8fffc476
AM
268 else
269 return 1
8fffc476
AM
270 endif
271endfun
272" }}}
273
274function! FindOpenBracket(lnum) " {{{
275 call cursor(a:lnum, 1) " set the cursor to the start of the lnum line
276 return searchpair('{', '', '}', 'bW', 'Skippmatch()')
277endfun
278" }}}
279
280function! FindTheIfOfAnElse (lnum, StopAfterFirstPrevElse) " {{{
281" A very clever recoursive function created by me (John Wellesz) that find the "if" corresponding to an
282" "else". This function can easily be adapted for other languages :)
283
284 if getline(a:lnum) =~# '^\s*}\s*else\%(if\)\=\>'
285 let beforeelse = a:lnum " we do this so we can find the opened bracket to speed up the process
286 else
287 let beforeelse = GetLastRealCodeLNum(a:lnum - 1)
288 endif
289
290 if !s:level
291 let s:iftoskip = 0
292 endif
293
294 " If we found another "else" then it means we need to skip the next "if"
295 " we'll found. (since version 1.02)
296 if getline(beforeelse) =~# '^\s*\%(}\s*\)\=else\%(\s*if\)\@!\>'
297 let s:iftoskip = s:iftoskip + 1
298 endif
299
300 " A closing bracket? let skip the whole block to save some recursive calls
301 if getline(beforeelse) =~ '^\s*}' " .s:endline
302 let beforeelse = FindOpenBracket(beforeelse)
303
304 " Put us on the block starter
305 if getline(beforeelse) =~ '^\s*{'
306 let beforeelse = GetLastRealCodeLNum(beforeelse - 1)
307 endif
308 endif
309
310
311 if !s:iftoskip && a:StopAfterFirstPrevElse && getline(beforeelse) =~# '^\s*\%([}]\s*\)\=else\%(if\)\=\>'
312 return beforeelse
313 endif
a4c85cb5 314
8fffc476
AM
315 " if there was an else, then there is a if...
316 if getline(beforeelse) !~# '^\s*if\>' && beforeelse>1 || s:iftoskip && beforeelse>1
317
318 if s:iftoskip && getline(beforeelse) =~# '^\s*if\>'
319 let s:iftoskip = s:iftoskip - 1
320 endif
321
322 let s:level = s:level + 1
323 let beforeelse = FindTheIfOfAnElse(beforeelse, a:StopAfterFirstPrevElse)
324 endif
325
326 return beforeelse
327
328endfunction
329" }}}
330
331function! IslinePHP (lnum, tofind) " {{{
332 " This function asks to the syntax if the pattern 'tofind' on the line
333 " number 'lnum' is PHP code (very slow...).
334 let cline = getline(a:lnum)
335
336 if a:tofind==""
0ae4014d
AM
337 let tofind = "^\\s*[\"']*\s*\\zs\\S" " This correct the issue where lines beginning by a
338 " single or double quote were not indented in some cases.
8fffc476
AM
339 else
340 let tofind = a:tofind
341 endif
342
343 let tofind = tofind . '\c' " ignorecase
344
345 let coltotest = match (cline, tofind) + 1 "find the first non blank char in the current line
346
347 let synname = synIDattr(synID(a:lnum, coltotest, 0), "name") " ask to syntax what is its name
0ae4014d 348 "echo synname
8fffc476 349
0ae4014d
AM
350 " if matchstr(synname, '^...') == "php" || synname=="Delimiter" || synname =~? '^javaScript'
351 if synname =~ '^php' || synname=="Delimiter" || synname =~? '^javaScript'
8fffc476
AM
352 return synname
353 else
354 return ""
355 endif
356endfunction
357" }}}
358
359let s:notPhpHereDoc = '\%(break\|return\|continue\|exit\);'
360let s:blockstart = '\%(\%(\%(}\s*\)\=else\%(\s\+\)\=\)\=if\>\|while\>\|for\%(each\)\=\>\|declare\|||\|&&\>\)'
361
362function! GetPhpIndent()
363 "##############################################
364 "########### MAIN INDENT FUNCTION #############
365 "##############################################
366
367 " This detect if the user is currently typing text between each call
368 let UserIsEditing=0
369 if b:PHP_oldchangetick != b:changedtick
370 let b:PHP_oldchangetick = b:changedtick
371 let UserIsEditing=1
372 endif
373
8fffc476
AM
374 if b:PHP_default_indenting
375 let b:PHP_default_indenting = g:PHP_default_indenting * &sw
376 endif
377
378 let cline = getline(v:lnum) " current line
379
380 " Let's detect if we are indenting just one line or more than 3 lines
381 " in the last case we can slightly optimize our algorithm
382 if !b:PHP_indentinghuge && b:PHP_lastindented > b:PHP_indentbeforelast
383 if b:PHP_indentbeforelast
384 let b:PHP_indentinghuge = 1
385 echom 'Large indenting detected, speed optimizations engaged'
386 endif
387 let b:PHP_indentbeforelast = b:PHP_lastindented
388 endif
389
390 " If the line we are indenting isn't directly under the previous non-blank
391 " line of the file then deactivate the optimization procedures and reset
392 " status variable (we restart for scratch)
393 if b:InPHPcode_checked && prevnonblank(v:lnum - 1) != b:PHP_lastindented
394 if b:PHP_indentinghuge
395 echom 'Large indenting deactivated'
396 let b:PHP_indentinghuge = 0
397 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
398 endif
399 let b:PHP_lastindented = v:lnum
400 let b:PHP_LastIndentedWasComment=0
401 let b:PHP_indentbeforelast = 0
402
8fffc476
AM
403 let b:InPHPcode = 0
404 let b:InPHPcode_checked = 0
405 let b:InPHPcode_and_script = 0
406 let b:InPHPcode_tofind = ""
407
408 elseif v:lnum > b:PHP_lastindented " we are indenting line in > order (we can rely on the line before)
409 let real_PHP_lastindented = b:PHP_lastindented
410 let b:PHP_lastindented = v:lnum
411 endif
412
413 " We must detect if we are in PHPCODE or not, but one time only, then
414 " we will detect php end and start tags, comments /**/ and HereDoc
415 " tags
416
417 if !b:InPHPcode_checked " {{{ One time check
418 let b:InPHPcode_checked = 1
419
420 let synname = IslinePHP (prevnonblank(v:lnum), "") " the line could be blank (if the user presses 'return')
421
422 if synname!=""
423 if synname != "phpHereDoc"
424 let b:InPHPcode = 1
425 let b:InPHPcode_tofind = ""
0ae4014d 426
a4c85cb5
AM
427 if synname == "phpComment"
428 let b:UserIsTypingComment = 1
429 else
430 let b:UserIsTypingComment = 0
431 endif
0ae4014d
AM
432
433 if synname =~? '^javaScript'
434 let b:InPHPcode_and_script = 1
435 endif
436
8fffc476
AM
437 else
438 let b:InPHPcode = 0
a4c85cb5 439 let b:UserIsTypingComment = 0
8fffc476
AM
440
441 let lnum = v:lnum - 1
a4c85cb5 442 while getline(lnum) !~? '<<<\a\w*$' && lnum > 1
8fffc476
AM
443 let lnum = lnum - 1
444 endwhile
445
446 let b:InPHPcode_tofind = substitute( getline(lnum), '^.*<<<\(\a\w*\)\c', '^\\s*\1;$', '')
447 endif
0ae4014d 448 else " IslinePHP returned "" => we are not in PHP or Javascript
8fffc476 449 let b:InPHPcode = 0
a4c85cb5 450 let b:UserIsTypingComment = 0
8fffc476
AM
451 " Then we have to find a php start tag...
452 let b:InPHPcode_tofind = '<?\%(.*?>\)\@!\|<script.*>'
453 endif
454 endif "!b:InPHPcode_checked }}}
455
456 " Now we know where we are so we can verify the line right above the
457 " current one to see if we have to stop or restart php indenting
0ae4014d 458
8fffc476
AM
459 " Test if we are indenting PHP code {{{
460 " Find an executable php code line above the current line.
461 let lnum = prevnonblank(v:lnum - 1)
462 let last_line = getline(lnum)
463
464 " If we aren't in php code, then there is something we have to find
465 if b:InPHPcode_tofind!=""
466 if cline =~? b:InPHPcode_tofind
467 let b:InPHPcode = 1
468 let b:InPHPcode_tofind = ""
a4c85cb5
AM
469 let b:UserIsTypingComment = 0
470 if cline =~ '\*/' " End comment tags must be indented like start comment tags
471 call cursor(v:lnum, 1)
472 call search('\*/\zs', 'W')
473 let lnum = searchpair('/\*\zs', '', '\*/\zs', 'bWr', '') " find the most outside /*
474 return indent(lnum)
8fffc476
AM
475 elseif cline =~? '<script\>' " a more accurate test is useless since there isn't any other possibility
476 let b:InPHPcode_and_script = 1
477 endif
478 endif
479 endif
480
481 " ### If we are in PHP code, we test the line before to see if we have to stop indenting
482
483 if b:InPHPcode
484
485 " Was last line containing a PHP end tag ?
486 if !b:InPHPcode_and_script && last_line =~ '\%(<?.*\)\@<!?>\%(.*<?\)\@!' && IslinePHP(lnum, '?>')=="Delimiter"
487 if cline !~? s:PHP_startindenttag
488 let b:InPHPcode = 0
489 let b:InPHPcode_tofind = s:PHP_startindenttag
490 elseif cline =~? '<script\>'
491 let b:InPHPcode_and_script = 1
492 endif
493
494 " Was last line the start of a HereDoc ?
495 elseif last_line =~? '<<<\a\w*$'
0ae4014d 496 " \&& IslinePHP(lnum, '\a\w*$')=="Delimiter"
8fffc476
AM
497 let b:InPHPcode = 0
498 let b:InPHPcode_tofind = substitute( last_line, '^.*<<<\(\a\w*\)\c', '^\\s*\1;$', '')
499
500 " Skip /* \n+ */ comments execept when the user is currently
501 " writting them
502 elseif !UserIsEditing && cline =~ '^\s*/\*\%(.*\*/\)\@!'
0ae4014d 503 " \ && IslinePHP(v:lnum, '/\*')=="phpComment"
8fffc476
AM
504 let b:InPHPcode = 0
505 let b:InPHPcode_tofind = '\*/'
506
507 " is current line the end of a HTML script ? (we indent script the
508 " same as php code)
509 elseif cline =~? '^\s*</script>'
510 let b:InPHPcode = 0
511 " let b:InPHPcode_and_script = 0
512 let b:InPHPcode_tofind = s:PHP_startindenttag
513 endif
514 endif " }}}
515
516 " Non PHP code is let as it is
517 if !b:InPHPcode && !b:InPHPcode_and_script
518 return -1
519 elseif !b:InPHPcode
520 let b:InPHPcode_and_script = 0
521 endif
522
523 " Align correctly multi // or # lines
524
525 " Indent successive // or # comment the same way the first is {{{
526 if cline =~ '^\s*\%(//\|#\|/\*.*\*/\s*$\)'
527 if b:PHP_LastIndentedWasComment == 1
528 return indent(real_PHP_lastindented) " line replaced in 1.02
529 endif
530 let b:PHP_LastIndentedWasComment = 1
531 else
532 let b:PHP_LastIndentedWasComment = 0
533 endif
534 " }}}
535
536 " Some tags are always indented to col 1
537
538 " Things always indented at col 1 (PHP delimiter: <?, ?>, Heredoc end) {{{
539 " PHP start tags are always at col 1, useless to indent unless the end tag
540 " is on the same line
541 if cline =~# '^\s*<?' && cline !~ '?>' " Added the ^\s* part in version 1.03
542 return 0
543 endif
544
545 " PHP end tags are always at col 1, useless to indent unless if it's
546 " followed by a start tag on the same line
547 if cline =~ '^\s*?>' && cline !~# '<?'
548 return 0
549 endif
550
551 " put HereDoc end tags at start of lines
552 if cline =~? '^\s*\a\w*;$' && cline !~? s:notPhpHereDoc
553 return 0
554 endif
555 " }}}
556
557 let s:level = 0
558
559 " Find an executable php code line above the current line.
560 let lnum = GetLastRealCodeLNum(v:lnum - 1)
561 let last_line = getline(lnum) " last line
562 let ind = indent(lnum) " by default
563 let endline= s:endline
564
565 if ind==0 && b:PHP_default_indenting
566 let ind = b:PHP_default_indenting
567 endif
568
569 " Hit the start of the file, use default indent.
570 if lnum == 0
571 return b:PHP_default_indenting
572 endif
573
574 " if the last line is a stated line and it's not indented then why should
575 " we indent this one??
576 " if optimized mode is active and nor current or previous line are an 'else'
577 " or the end of a possible bracketless thing then indent the same as the previous
578 " line
579 if last_line =~ '[;}]'.endline
580 if ind==b:PHP_default_indenting
581 return b:PHP_default_indenting
582 elseif b:PHP_indentinghuge && ind==b:PHP_CurrentIndentLevel && cline !~# '^\s*\%(else\|\%(case\|default\).*:\|[})];\=\)' && last_line !~# '^\s*\%(\%(}\s*\)\=else\)' && getline(GetLastRealCodeLNum(lnum - 1))=~';'.endline
583 return b:PHP_CurrentIndentLevel
584 endif
585 endif
586
587 " Search the matching open bracket (with searchpair()) and set the indent of cline
588 " to the indent of the matching line.
589 if cline =~ '^\s*}\%(}}\)\@!'
590 let ind = indent(FindOpenBracket(v:lnum))
591 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
592 return ind
593 endif
594
a4c85cb5
AM
595 " While editing check for end of comment and indent it like its beginning
596 if UserIsEditing && cline =~ '\*/' " End comment tags must be indented like start comment tags
597 call cursor(v:lnum, 1)
598 call search('\*/\zs', 'W')
599 let lnum = searchpair('/\*\zs', '', '\*/\zs', 'bWr', '') " find the most outside /*
600 return indent(lnum)
601 endif
0ae4014d 602
8fffc476
AM
603 let LastLineClosed = 0 " used to prevent redundant tests in the last part of the script
604
605 let unstated='\%(^\s*'.s:blockstart.'.*)\|\%(//.*\)\@<!\<e'.'lse\>\)'.endline
606 " What is an unstated line?
607 " - an "else" at the end of line
608 " - a s:blockstart (if while etc...) followed by anything and a ")" at
609 " the end of line
610
611 " if the current line is an 'else' starting line
612 " (to match an 'else' preceded by a '}' is irrelevant and futile - see
613 " code above)
614 if ind != b:PHP_default_indenting && cline =~# '^\s*else\%(if\)\=\>'
615 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting " prevent optimized to work at next call
616 return indent(FindTheIfOfAnElse(v:lnum, 1))
617 elseif last_line =~# unstated && cline !~ '^\s*{\|^\s*);\='.endline
618 let ind = ind + &sw
619 return ind
620
621 " If the last line is terminated by ';' or if it's a closing '}'
622 " We need to check if this isn't the end of a multilevel non '{}'
623 " structure such as:
624 " Exemple:
625 " if ($truc)
626 " echo 'truc';
627 "
628 " OR
629 "
630 " if ($truc)
631 " while ($truc) {
632 " lkhlkh();
633 " echo 'infinite loop\n';
634 " }
635 elseif ind != b:PHP_default_indenting && last_line =~ ';'.endline.'\|^\s*}\%(.*{'. endline.'\)\@!'
636 " If we are here it means that the previous line is:
637 " - a *;$ line
638 " - a [beginning-blanck] } followed by anything but a { $
639 let previous_line = last_line
640 let last_line_num = lnum
641 let LastLineClosed = 1
642 " The idea here is to check if the current line is after a non '{}'
643 " structure so we can indent it like the top of that structure.
644 " The top of that structure is caracterized by a if (ff)$ style line
645 " preceded by a stated line. If there is no such structure then we
646 " just have to find two 'normal' lines following each other with the
647 " same indentation and with the first of these two lines terminated by
648 " a ; or by a }...
649
650 while 1
651 " let's skip '{}' blocks
652 if previous_line =~ '^\s*}'
653 " find the openning '{'
654 let last_line_num = FindOpenBracket(last_line_num)
655
656 " if the '{' is alone on the line get the line before
657 if getline(last_line_num) =~ '^\s*{'
658 let last_line_num = GetLastRealCodeLNum(last_line_num - 1)
659 endif
660
661 let previous_line = getline(last_line_num)
662
663 continue
664 else
665 " At this point we know that the previous_line isn't a closing
666 " '}' so we can check if we really are in such a structure.
667
668 " it's not a '}' but it could be an else alone...
669 if getline(last_line_num) =~# '^\s*else\%(if\)\=\>'
670 let last_line_num = FindTheIfOfAnElse(last_line_num, 0)
671 continue " re-run the loop (we could find a '}' again)
672 endif
673
674 " So now it's ok we can check :-)
675 " A good quality is to have confidence in oneself so to know
676 " if yes or no we are in that struct lets test the indent of
677 " last_line_num and of last_line_num - 1!
678 " If those are == then we are almost done.
679 "
680 " That isn't sufficient, we need to test how the first of the
681 " 2 lines is ended...
682
683 " Note the indenting of the line we are checking
684
685 let last_match = last_line_num " remember the 'topest' line we found so far
686
687 let one_ahead_indent = indent(last_line_num)
688 let last_line_num = GetLastRealCodeLNum(last_line_num - 1)
689 let two_ahead_indent = indent(last_line_num)
690 let after_previous_line = previous_line
691 let previous_line = getline(last_line_num)
692
693
694 " If we find a '{' or a case/default then we are inside that block so lets
695 " indent properly... Like the line following that block starter
696 if previous_line =~# '^\s*\%(case\|default\).*:\|{'.endline
697 break
698 endif
699
700 " The 3 lines below are not necessary for the script to work
701 " but it makes it work a little more faster in some (rare) cases.
702 " We verify if we are at the top of a non '{}' struct.
703 if after_previous_line=~# '^\s*'.s:blockstart.'.*)'.endline && previous_line =~# '[;}]'.endline
704 break
705 endif
706
707 if one_ahead_indent == two_ahead_indent || last_line_num < 1
708 " So the previous line and the line before are at the same
709 " col. Now we just have to check if the line before is a ;$ or [}]$ ended line
710 " we always check the most ahead line of the 2 lines so
711 " it's useless to match ')$' since the lines couldn't have
712 " the same indent...
713 if previous_line =~# '[;}]'.endline || last_line_num < 1
714 break
715 endif
716 endif
717 endif
718 endwhile
719
720 if indent(last_match) != ind " if nothing was done lets the old script continue
721 let ind = indent(last_match) " let's use the indent of the last line matched by the alhorithm above
722 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting "line added in version 1.02 to prevent optimized mode
723 " from acting in some special cases
724 return ind
725 endif
726 endif
727
728
729 let plinnum = GetLastRealCodeLNum(lnum - 1)
730 let pline = getline(plinnum) " previous to last line
731
732 " REMOVE comments at end of line before treatment
733 " the first par of the regex removes // from the end of line when they are
734 " followed by a number of '"' which is a multiple of 2. The second part
735 " removes // that are not followed by any '"'
736 " Sorry for this unreadable thing...
737 let last_line = substitute(last_line,"\\(//\\|#\\)\\(\\(\\([^\"']*\\([\"']\\)[^\"']*\\5\\)\\+[^\"']*$\\)\\|\\([^\"']*$\\)\\)",'','')
738
739 " Indent blocks enclosed by {} or () (default indenting)
740 if !LastLineClosed " the last line isn't a .*; or a }$ line
741 " if the last line is a [{(]$ or a multiline function call (or array
742 " declaration) with already one parameter on the opening ( line
743 if last_line =~# '[{(]'.endline || last_line =~? '\h\w*\s*(.*,$' && pline !~ '[,(]'.endline
744 let ind = ind + &sw
745 if cline !~# '^\s*\%(default\|case\).*:' " case and default are not indented inside blocks
746 let b:PHP_CurrentIndentLevel = ind
747 return ind
748 endif
749 endif
750 endif
751
752 " If the current line closes a multiline function call or array def
753 if cline =~ '^\s*);\='
754 let ind = ind - &sw
755 elseif cline =~# '^\s*\%(default\|case\).*:'
756 let ind = ind - &sw
757 endif
758
759 if last_line =~# '^\s*\%(default\|case\).*:'
760 let ind = ind + &sw
761 endif
762
763 let b:PHP_CurrentIndentLevel = ind
764 return ind
765endfunction
766
767" vim: set ts=4 sw=4:
a4c85cb5 768" vim: set ff=unix:
This page took 0.114283 seconds and 4 git commands to generate.