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