home *** CD-ROM | disk | FTP | other *** search
/ vim.ftp.fu-berlin.de / 2015-02-03.vim.ftp.fu-berlin.de.tar / vim.ftp.fu-berlin.de / runtime / indent / php.vim < prev    next >
Encoding:
Text File  |  2010-08-15  |  18.2 KB  |  734 lines

  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:    2010 Jully 26th
  6. " Newsletter:    http://www.2072productions.com/?to=php-indent-for-vim-newsletter.php
  7. " Version:    1.33
  8. "
  9. "
  10. "  If you find a bug, please report it on GitHub:
  11. "    http://github.com/2072/PHP-Indenting-for-VIm/issues
  12. "  with an example of code that breaks the algorithm.
  13. "
  14. "
  15. "    Thanks a lot for using this script.
  16. "
  17. "
  18. " NOTE: This script must be used with PHP syntax ON and with the php syntax
  19. "    script by Lutz Eymers (http://www.ipdienste.net/data/php.vim ) or with the
  20. "    script by Peter Hodge (http://www.vim.org/scripts/script.php?script_id=1571 )
  21. "    the later is bunbdled by default with Vim 7.
  22. "
  23. "
  24. "    In the case you have syntax errors in your script such as HereDoc end
  25. "    identifiers not at col 1 you'll have to indent your file 2 times (This
  26. "    script will automatically put HereDoc end identifiers at col 1 if
  27. "    they are followed by a ';').
  28. "
  29. "
  30. " NOTE: If you are editing files in Unix file format and that (by accident)
  31. "    there are '\r' before new lines, this script won't be able to proceed
  32. "    correctly and will make many mistakes because it won't be able to match
  33. "    '\s*$' correctly.
  34. "    So you have to remove those useless characters first with a command like:
  35. "
  36. "    :%s /\r$//g
  37. "
  38. "    or simply 'let' the option PHP_removeCRwhenUnix to 1 and the script will
  39. "    silently remove them when VIM load this script (at each bufread).
  40. "
  41. " Options: See :help php-indent for available options.
  42.  
  43.  
  44. if exists("b:did_indent")
  45.     finish
  46. endif
  47. let b:did_indent = 1
  48.  
  49.  
  50. let php_sync_method = 0
  51.  
  52.  
  53. if exists("PHP_default_indenting")
  54.     let b:PHP_default_indenting = PHP_default_indenting * &sw
  55. else
  56.     let b:PHP_default_indenting = 0
  57. endif
  58.  
  59. if exists("PHP_BracesAtCodeLevel")
  60.     let b:PHP_BracesAtCodeLevel = PHP_BracesAtCodeLevel
  61. else
  62.     let b:PHP_BracesAtCodeLevel = 0
  63. endif
  64.  
  65.  
  66. if exists("PHP_autoformatcomment")
  67.     let b:PHP_autoformatcomment = PHP_autoformatcomment
  68. else
  69.     let b:PHP_autoformatcomment = 1
  70. endif
  71.  
  72. if exists("PHP_outdentphpescape")
  73.     let b:PHP_outdentphpescape = PHP_outdentphpescape
  74. else
  75.     let b:PHP_outdentphpescape = 1
  76. endif
  77.  
  78.  
  79. if exists("PHP_vintage_case_default_indent") && PHP_vintage_case_default_indent
  80.     let b:PHP_vintage_case_default_indent = 1
  81. else
  82.     let b:PHP_vintage_case_default_indent = 0
  83. endif
  84.  
  85.  
  86.  
  87. let b:PHP_lastindented = 0
  88. let b:PHP_indentbeforelast = 0
  89. let b:PHP_indentinghuge = 0
  90. let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
  91. let b:PHP_LastIndentedWasComment = 0
  92. let b:PHP_InsideMultilineComment = 0
  93. let b:InPHPcode = 0
  94. let b:InPHPcode_checked = 0
  95. let b:InPHPcode_and_script = 0
  96. let b:InPHPcode_tofind = ""
  97. let b:PHP_oldchangetick = b:changedtick
  98. let b:UserIsTypingComment = 0
  99. let b:optionsset = 0
  100.  
  101. setlocal nosmartindent
  102. setlocal noautoindent
  103. setlocal nocindent
  104. setlocal nolisp
  105.  
  106. setlocal indentexpr=GetPhpIndent()
  107. setlocal indentkeys=0{,0},0),:,!^F,o,O,e,*<Return>,=?>,=<?,=*/
  108.  
  109.  
  110.  
  111. let s:searchpairflags = 'bWr'
  112.  
  113. if &fileformat == "unix" && exists("PHP_removeCRwhenUnix") && PHP_removeCRwhenUnix
  114.     silent! %s/\r$//g
  115. endif
  116.  
  117. if exists("*GetPhpIndent")
  118.     call ResetPhpOptions()
  119.     finish
  120. endif
  121.  
  122. let s:endline= '\s*\%(//.*\|#.*\|/\*.*\*/\s*\)\=$'
  123. let s:PHP_startindenttag = '<?\%(.*?>\)\@!\|<script[^>]*>\%(.*<\/script>\)\@!'
  124.  
  125.  
  126. function! GetLastRealCodeLNum(startline) " {{{
  127.  
  128.     let lnum = a:startline
  129.  
  130.     if b:GetLastRealCodeLNum_ADD && b:GetLastRealCodeLNum_ADD == lnum + 1
  131.     let lnum = b:GetLastRealCodeLNum_ADD
  132.     endif
  133.  
  134.     let old_lnum = lnum
  135.  
  136.     while lnum > 1
  137.     let lnum = prevnonblank(lnum)
  138.     let lastline = getline(lnum)
  139.  
  140.     if b:InPHPcode_and_script && lastline =~ '?>\s*$'
  141.         let lnum = lnum - 1
  142.     elseif lastline =~ '^\s*?>.*<?\%(php\)\=\s*$'
  143.         let lnum = lnum - 1
  144.     elseif lastline =~ '^\s*\%(//\|#\|/\*.*\*/\s*$\)'
  145.         let lnum = lnum - 1
  146.     elseif lastline =~ '\*/\s*$'
  147.         call cursor(lnum, 1)
  148.         if lastline !~ '^\*/'
  149.         call search('\*/', 'W')
  150.         endif
  151.         let lnum = searchpair('/\*', '', '\*/', s:searchpairflags, 'Skippmatch2()')
  152.  
  153.         let lastline = getline(lnum)
  154.         if lastline =~ '^\s*/\*'
  155.         let lnum = lnum - 1
  156.         else
  157.         break
  158.         endif
  159.  
  160.  
  161.     elseif lastline =~? '\%(//\s*\|?>.*\)\@<!<?\%(php\)\=\s*$\|^\s*<script\>'
  162.  
  163.         while lastline !~ '\(<?.*\)\@<!?>' && lnum > 1
  164.         let lnum = lnum - 1
  165.         let lastline = getline(lnum)
  166.         endwhile
  167.         if lastline =~ '^\s*?>'
  168.         let lnum = lnum - 1
  169.         else
  170.         break
  171.         endif
  172.  
  173.  
  174.     elseif lastline =~? '^\a\w*;\=$' && lastline !~? s:notPhpHereDoc
  175.         let tofind=substitute( lastline, '\(\a\w*\);\=', '<<<''\\=\1''\\=$', '')
  176.         while getline(lnum) !~? tofind && lnum > 1
  177.         let lnum = lnum - 1
  178.         endwhile
  179.     else
  180.         break
  181.     endif
  182.     endwhile
  183.  
  184.     if lnum==1 && getline(lnum) !~ '<?'
  185.     let lnum=0
  186.     endif
  187.  
  188.     if b:InPHPcode_and_script && !b:InPHPcode
  189.     let b:InPHPcode_and_script = 0
  190.     endif
  191.  
  192.  
  193.  
  194.     return lnum
  195. endfunction " }}}
  196.  
  197. function! Skippmatch2()
  198.  
  199.     let line = getline(".")
  200.  
  201.    if line =~ '\%(".*\)\@<=/\*\%(.*"\)\@=' || line =~ '\%(\%(//\|#\).*\)\@<=/\*'
  202.        return 1
  203.    else
  204.        return 0
  205.    endif
  206. endfun
  207.  
  208. function! Skippmatch()    " {{{
  209.     let synname = synIDattr(synID(line("."), col("."), 0), "name")
  210.     if synname == "Delimiter" || synname == "phpRegionDelimiter" || synname =~# "^phpParent" || synname == "phpArrayParens" || synname =~# '^php\%(Block\|Brace\)' || synname == "javaScriptBraces" || synname =~# "^phpComment" && b:UserIsTypingComment
  211.     return 0
  212.     else
  213.     return 1
  214.     endif
  215. endfun " }}}
  216.  
  217. function! FindOpenBracket(lnum) " {{{
  218.     call cursor(a:lnum, 1)
  219.     return searchpair('{', '', '}', 'bW', 'Skippmatch()')
  220. endfun " }}}
  221.  
  222. function! FindTheIfOfAnElse (lnum, StopAfterFirstPrevElse) " {{{
  223.  
  224.     if getline(a:lnum) =~# '^\s*}\s*else\%(if\)\=\>'
  225.     let beforeelse = a:lnum
  226.     else
  227.     let beforeelse = GetLastRealCodeLNum(a:lnum - 1)
  228.     endif
  229.  
  230.     if !s:level
  231.     let s:iftoskip = 0
  232.     endif
  233.  
  234.     if getline(beforeelse) =~# '^\s*\%(}\s*\)\=else\%(\s*if\)\@!\>'
  235.     let s:iftoskip = s:iftoskip + 1
  236.     endif
  237.  
  238.     if getline(beforeelse) =~ '^\s*}'
  239.     let beforeelse = FindOpenBracket(beforeelse)
  240.  
  241.     if getline(beforeelse) =~ '^\s*{'
  242.         let beforeelse = GetLastRealCodeLNum(beforeelse - 1)
  243.     endif
  244.     endif
  245.  
  246.  
  247.     if !s:iftoskip && a:StopAfterFirstPrevElse && getline(beforeelse) =~# '^\s*\%([}]\s*\)\=else\%(if\)\=\>'
  248.     return beforeelse
  249.     endif
  250.  
  251.     if getline(beforeelse) !~# '^\s*if\>' && beforeelse>1 || s:iftoskip && beforeelse>1
  252.  
  253.     if s:iftoskip && getline(beforeelse) =~# '^\s*if\>'
  254.         let s:iftoskip = s:iftoskip - 1
  255.     endif
  256.  
  257.     let s:level =  s:level + 1
  258.     let beforeelse = FindTheIfOfAnElse(beforeelse, a:StopAfterFirstPrevElse)
  259.     endif
  260.  
  261.     return beforeelse
  262.  
  263. endfunction " }}}
  264.  
  265. let s:defaultORcase = '^\s*\%(default\|case\).*:'
  266.  
  267. function! FindTheSwitchIndent (lnum) " {{{
  268.  
  269.  
  270.     let test = GetLastRealCodeLNum(a:lnum - 1)
  271.  
  272.     if test <= 1
  273.     return indent(1) - &sw * b:PHP_vintage_case_default_indent
  274.     end
  275.  
  276.     if getline(test) =~ '^\s*}'
  277.     let test = FindOpenBracket(test)
  278.  
  279.     if getline(test) =~ '^\s*{'
  280.         let test = GetLastRealCodeLNum(GetLastRealCodeLNum(test - 1) - 1)
  281.     endif
  282.     endif
  283.  
  284.     if getline(test) =~# '^\s*switch\>'
  285.     return indent(test)
  286.     elseif getline(test) =~# s:defaultORcase
  287.     return indent(test) - &sw * b:PHP_vintage_case_default_indent
  288.     else
  289.     return FindTheSwitchIndent(test)
  290.     endif
  291.  
  292. endfunction "}}}
  293.  
  294.  
  295. function! IslinePHP (lnum, tofind) " {{{
  296.     let cline = getline(a:lnum)
  297.  
  298.     if a:tofind==""
  299.     let tofind = "^\\s*[\"']*\\s*\\zs\\S"
  300.     else
  301.     let tofind = a:tofind
  302.     endif
  303.  
  304.     let tofind = tofind . '\c'
  305.  
  306.     let coltotest = match (cline, tofind) + 1
  307.  
  308.     let synname = synIDattr(synID(a:lnum, coltotest, 0), "name")
  309.  
  310.     if synname =~ '^php' || synname=="Delimiter" || synname =~? '^javaScript'
  311.     return synname
  312.     else
  313.     return ""
  314.     endif
  315. endfunction " }}}
  316.  
  317. let s:notPhpHereDoc = '\%(break\|return\|continue\|exit\|else\)'
  318. let s:blockstart = '\%(\%(\%(}\s*\)\=else\%(\s\+\)\=\)\=if\>\|else\>\|while\>\|switch\>\|case\>\|default\>\|for\%(each\)\=\>\|declare\>\|class\>\|interface\>\|abstract\>\|try\>\|catch\>\)'
  319.  
  320. let s:autoresetoptions = 0
  321. if ! s:autoresetoptions
  322.     let s:autoresetoptions = 1
  323. endif
  324.  
  325. function! ResetPhpOptions()
  326.     if ! b:optionsset && &filetype == "php"
  327.     if b:PHP_autoformatcomment
  328.  
  329.         setlocal comments=s1:/*,mb:*,ex:*/,://,:#
  330.  
  331.         setlocal formatoptions-=t
  332.         setlocal formatoptions+=q
  333.         setlocal formatoptions+=r
  334.         setlocal formatoptions+=o
  335.         setlocal formatoptions+=w
  336.         setlocal formatoptions+=c
  337.         setlocal formatoptions+=b
  338.     endif
  339.     let b:optionsset = 1
  340.     endif
  341. endfunc
  342.  
  343. call ResetPhpOptions()
  344.  
  345. function! GetPhpIndent()
  346.  
  347.     let b:GetLastRealCodeLNum_ADD = 0
  348.  
  349.     let UserIsEditing=0
  350.     if    b:PHP_oldchangetick != b:changedtick
  351.     let b:PHP_oldchangetick = b:changedtick
  352.     let UserIsEditing=1
  353.     endif
  354.  
  355.     if b:PHP_default_indenting
  356.     let b:PHP_default_indenting = g:PHP_default_indenting * &sw
  357.     endif
  358.  
  359.     let cline = getline(v:lnum)
  360.  
  361.     if !b:PHP_indentinghuge && b:PHP_lastindented > b:PHP_indentbeforelast
  362.     if b:PHP_indentbeforelast
  363.         let b:PHP_indentinghuge = 1
  364.         echom 'Large indenting detected, speed optimizations engaged (v1.33)'
  365.     endif
  366.     let b:PHP_indentbeforelast = b:PHP_lastindented
  367.     endif
  368.  
  369.     if b:InPHPcode_checked && prevnonblank(v:lnum - 1) != b:PHP_lastindented
  370.     if b:PHP_indentinghuge
  371.         echom 'Large indenting deactivated'
  372.         let b:PHP_indentinghuge = 0
  373.         let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
  374.     endif
  375.     let b:PHP_lastindented = v:lnum
  376.     let b:PHP_LastIndentedWasComment=0
  377.     let b:PHP_InsideMultilineComment=0
  378.     let b:PHP_indentbeforelast = 0
  379.  
  380.     let b:InPHPcode = 0
  381.     let b:InPHPcode_checked = 0
  382.     let b:InPHPcode_and_script = 0
  383.     let b:InPHPcode_tofind = ""
  384.  
  385.     elseif v:lnum > b:PHP_lastindented
  386.     let real_PHP_lastindented = b:PHP_lastindented
  387.     let b:PHP_lastindented = v:lnum
  388.     endif
  389.  
  390.  
  391.     if !b:InPHPcode_checked " {{{ One time check
  392.     let b:InPHPcode_checked = 1
  393.  
  394.     let synname = ""
  395.     if cline !~ '<?.*?>'
  396.         let synname = IslinePHP (prevnonblank(v:lnum), "")
  397.     endif
  398.  
  399.     if synname!=""
  400.         if synname != "phpHereDoc" && synname != "phpHereDocDelimiter"
  401.         let b:InPHPcode = 1
  402.         let b:InPHPcode_tofind = ""
  403.  
  404.         if synname =~# "^phpComment"
  405.             let b:UserIsTypingComment = 1
  406.         else
  407.             let b:UserIsTypingComment = 0
  408.         endif
  409.  
  410.         if synname =~? '^javaScript'
  411.             let b:InPHPcode_and_script = 1
  412.         endif
  413.  
  414.         else
  415.         let b:InPHPcode = 0
  416.         let b:UserIsTypingComment = 0
  417.  
  418.         let lnum = v:lnum - 1
  419.         while getline(lnum) !~? '<<<''\=\a\w*''\=$' && lnum > 1
  420.             let lnum = lnum - 1
  421.         endwhile
  422.  
  423.         let b:InPHPcode_tofind = substitute( getline(lnum), '^.*<<<''\=\(\a\w*\)''\=$', '^\\s*\1;\\=$', '')
  424.         endif
  425.     else
  426.         let b:InPHPcode = 0
  427.         let b:UserIsTypingComment = 0
  428.         let b:InPHPcode_tofind = '<?\%(.*?>\)\@!\|<script.*>'
  429.     endif
  430.     endif "!b:InPHPcode_checked }}}
  431.  
  432.  
  433.     " Test if we are indenting PHP code {{{
  434.     let lnum = prevnonblank(v:lnum - 1)
  435.     let last_line = getline(lnum)
  436.  
  437.     if b:InPHPcode_tofind!=""
  438.     if cline =~? b:InPHPcode_tofind
  439.         let b:InPHPcode = 1
  440.         let b:InPHPcode_tofind = ""
  441.         let b:UserIsTypingComment = 0
  442.         if cline =~ '\*/'
  443.         call cursor(v:lnum, 1)
  444.         if cline !~ '^\*/'
  445.             call search('\*/', 'W')
  446.         endif
  447.         let lnum = searchpair('/\*', '', '\*/', s:searchpairflags, 'Skippmatch2()')
  448.  
  449.         let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
  450.  
  451.         let b:PHP_LastIndentedWasComment = 0
  452.  
  453.         if cline =~ '^\s*\*/'
  454.             return indent(lnum) + 1
  455.         else
  456.             return indent(lnum)
  457.         endif
  458.  
  459.         elseif cline =~? '<script\>'
  460.         let b:InPHPcode_and_script = 1
  461.         let b:GetLastRealCodeLNum_ADD = v:lnum
  462.         endif
  463.     endif
  464.     endif
  465.  
  466.     if b:InPHPcode
  467.  
  468.     if !b:InPHPcode_and_script && last_line =~ '\%(<?.*\)\@<!?>\%(.*<?\)\@!' && IslinePHP(lnum, '?>')=~"Delimiter"
  469.         if cline !~? s:PHP_startindenttag
  470.         let b:InPHPcode = 0
  471.         let b:InPHPcode_tofind = s:PHP_startindenttag
  472.         elseif cline =~? '<script\>'
  473.         let b:InPHPcode_and_script = 1
  474.         endif
  475.  
  476.     elseif last_line =~? '<<<''\=\a\w*''\=$'
  477.         let b:InPHPcode = 0
  478.         let b:InPHPcode_tofind = substitute( last_line, '^.*<<<''\=\(\a\w*\)''\=$', '^\\s*\1;\\=$', '')
  479.  
  480.     elseif !UserIsEditing && cline =~ '^\s*/\*\%(.*\*/\)\@!' && getline(v:lnum + 1) !~ '^\s*\*'
  481.         let b:InPHPcode = 0
  482.         let b:InPHPcode_tofind = '\*/'
  483.  
  484.     elseif cline =~? '^\s*</script>'
  485.         let b:InPHPcode = 0
  486.         let b:InPHPcode_tofind = s:PHP_startindenttag
  487.     endif
  488.     endif " }}}
  489.  
  490.  
  491.     if !b:InPHPcode && !b:InPHPcode_and_script
  492.     return -1
  493.     endif
  494.  
  495.     " Indent successive // or # comment the same way the first is {{{
  496.     if cline =~ '^\s*\%(//\|#\|/\*.*\*/\s*$\)'
  497.     if b:PHP_LastIndentedWasComment == 1
  498.         return indent(real_PHP_lastindented)
  499.     endif
  500.     let b:PHP_LastIndentedWasComment = 1
  501.     else
  502.     let b:PHP_LastIndentedWasComment = 0
  503.     endif " }}}
  504.  
  505.     " Indent multiline /* comments correctly {{{
  506.  
  507.     if b:PHP_InsideMultilineComment || b:UserIsTypingComment
  508.     if cline =~ '^\s*\*\%(\/\)\@!'
  509.         if last_line =~ '^\s*/\*'
  510.         return indent(lnum) + 1
  511.         else
  512.         return indent(lnum)
  513.         endif
  514.     else
  515.         let b:PHP_InsideMultilineComment = 0
  516.     endif
  517.     endif
  518.  
  519.     if !b:PHP_InsideMultilineComment && cline =~ '^\s*/\*' && cline !~ '\*/\s*$'
  520.     if getline(v:lnum + 1) !~ '^\s*\*'
  521.         return -1
  522.     endif
  523.     let b:PHP_InsideMultilineComment = 1
  524.     endif " }}}
  525.  
  526.  
  527.     " Things always indented at col 1 (PHP delimiter: <?, ?>, Heredoc end) {{{
  528.     if cline =~# '^\s*<?' && cline !~ '?>' && b:PHP_outdentphpescape
  529.     return 0
  530.     endif
  531.  
  532.     if    cline =~ '^\s*?>' && cline !~# '<?' && b:PHP_outdentphpescape
  533.     return 0
  534.     endif
  535.  
  536.     if cline =~? '^\s*\a\w*;$\|^\a\w*$' && cline !~? s:notPhpHereDoc
  537.     return 0
  538.     endif " }}}
  539.  
  540.     let s:level = 0
  541.  
  542.     let lnum = GetLastRealCodeLNum(v:lnum - 1)
  543.  
  544.     let last_line = getline(lnum)
  545.     let ind = indent(lnum)
  546.     let endline= s:endline
  547.  
  548.     if ind==0 && b:PHP_default_indenting
  549.     let ind = b:PHP_default_indenting
  550.     endif
  551.  
  552.     if lnum == 0
  553.     return b:PHP_default_indenting
  554.     endif
  555.  
  556.  
  557.     if cline =~ '^\s*}\%(}}\)\@!'
  558.     let ind = indent(FindOpenBracket(v:lnum))
  559.     let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
  560.     return ind
  561.     endif
  562.  
  563.     if cline =~ '^\s*\*/'
  564.     call cursor(v:lnum, 1)
  565.     if cline !~ '^\*/'
  566.         call search('\*/', 'W')
  567.     endif
  568.     let lnum = searchpair('/\*', '', '\*/', s:searchpairflags, 'Skippmatch2()')
  569.  
  570.     let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
  571.  
  572.     if cline =~ '^\s*\*/'
  573.         return indent(lnum) + 1
  574.     else
  575.         return indent(lnum)
  576.     endif
  577.     endif
  578.  
  579.  
  580.     if last_line =~ '[;}]'.endline && last_line !~ '^)' && last_line !~# s:defaultORcase
  581.     if ind==b:PHP_default_indenting
  582.         return b:PHP_default_indenting
  583.     elseif b:PHP_indentinghuge && ind==b:PHP_CurrentIndentLevel && cline !~# '^\s*\%(else\|\%(case\|default\).*:\|[})];\=\)' && last_line !~# '^\s*\%(\%(}\s*\)\=else\)' && getline(GetLastRealCodeLNum(lnum - 1))=~';'.endline
  584.         return b:PHP_CurrentIndentLevel
  585.     endif
  586.     endif
  587.  
  588.     let LastLineClosed = 0
  589.  
  590.     let terminated = '\%(;\%(\s*?>\)\=\|<<<''\=\a\w*''\=$\|^\s*}\)'.endline
  591.  
  592.     let unstated   = '\%(^\s*'.s:blockstart.'.*)\|\%(//.*\)\@<!\<e'.'lse\>\)'.endline
  593.  
  594.     if ind != b:PHP_default_indenting && cline =~# '^\s*else\%(if\)\=\>'
  595.     let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
  596.     return indent(FindTheIfOfAnElse(v:lnum, 1))
  597.     elseif cline =~# s:defaultORcase
  598.     return FindTheSwitchIndent(v:lnum) + &sw * b:PHP_vintage_case_default_indent
  599.     elseif cline =~ '^\s*)\=\s*{'
  600.     let previous_line = last_line
  601.     let last_line_num = lnum
  602.  
  603.     while last_line_num > 1
  604.  
  605.         if previous_line =~ '^\s*\%(' . s:blockstart . '\|\%([a-zA-Z]\s*\)*function\)'
  606.  
  607.         let ind = indent(last_line_num)
  608.  
  609.         if  b:PHP_BracesAtCodeLevel
  610.             let ind = ind + &sw
  611.         endif
  612.  
  613.         return ind
  614.         endif
  615.  
  616.         let last_line_num = last_line_num - 1
  617.         let previous_line = getline(last_line_num)
  618.     endwhile
  619.  
  620.     elseif last_line =~# unstated && cline !~ '^\s*);\='.endline
  621.     let ind = ind + &sw
  622.     return ind
  623.  
  624.     elseif (ind != b:PHP_default_indenting || last_line =~ '^)' ) && last_line =~ terminated
  625.     let previous_line = last_line
  626.     let last_line_num = lnum
  627.     let LastLineClosed = 1
  628.  
  629.     while 1
  630.         if previous_line =~ '^\s*}'
  631.         let last_line_num = FindOpenBracket(last_line_num)
  632.  
  633.         if getline(last_line_num) =~ '^\s*{'
  634.             let last_line_num = GetLastRealCodeLNum(last_line_num - 1)
  635.         endif
  636.  
  637.         let previous_line = getline(last_line_num)
  638.  
  639.         continue
  640.         else
  641.  
  642.         if getline(last_line_num) =~# '^\s*else\%(if\)\=\>'
  643.             let last_line_num = FindTheIfOfAnElse(last_line_num, 0)
  644.             continue
  645.         endif
  646.  
  647.  
  648.         let last_match = last_line_num
  649.  
  650.         let one_ahead_indent = indent(last_line_num)
  651.         let last_line_num = GetLastRealCodeLNum(last_line_num - 1)
  652.         let two_ahead_indent = indent(last_line_num)
  653.         let after_previous_line = previous_line
  654.         let previous_line = getline(last_line_num)
  655.  
  656.  
  657.         if previous_line =~# s:defaultORcase.'\|{'.endline
  658.             break
  659.         endif
  660.  
  661.         if after_previous_line=~# '^\s*'.s:blockstart.'.*)'.endline && previous_line =~# '[;}]'.endline
  662.             break
  663.         endif
  664.  
  665.         if one_ahead_indent == two_ahead_indent || last_line_num < 1
  666.             if previous_line =~# '\%(;\|^\s*}\)'.endline || last_line_num < 1
  667.             break
  668.             endif
  669.         endif
  670.         endif
  671.     endwhile
  672.  
  673.     if indent(last_match) != ind
  674.         let ind = indent(last_match)
  675.         let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
  676.  
  677.         return ind
  678.     endif
  679.     endif
  680.  
  681.     let plinnum = GetLastRealCodeLNum(lnum - 1)
  682.     let AntepenultimateLine = getline(plinnum)
  683.  
  684.     let last_line = substitute(last_line,"\\(//\\|#\\)\\(\\(\\([^\"']*\\([\"']\\)[^\"']*\\5\\)\\+[^\"']*$\\)\\|\\([^\"']*$\\)\\)",'','')
  685.  
  686.  
  687.     if ind == b:PHP_default_indenting
  688.     if last_line =~ terminated
  689.         let LastLineClosed = 1
  690.     endif
  691.     endif
  692.  
  693.     if !LastLineClosed
  694.  
  695.  
  696.     if last_line =~# '[{(]'.endline || last_line =~? '\h\w*\s*(.*,$' && AntepenultimateLine !~ '[,(]'.endline
  697.  
  698.         if !b:PHP_BracesAtCodeLevel || last_line !~# '^\s*{'
  699.         let ind = ind + &sw
  700.         endif
  701.  
  702.         if b:PHP_BracesAtCodeLevel || b:PHP_vintage_case_default_indent == 1
  703.         let b:PHP_CurrentIndentLevel = ind
  704.  
  705.         return ind
  706.         endif
  707.  
  708.     elseif last_line =~ '\S\+\s*),'.endline
  709.         call cursor(lnum, 1)
  710.         call search('),'.endline, 'W')
  711.         let openedparent = searchpair('(', '', ')', 'bW', 'Skippmatch()')
  712.         if openedparent != lnum
  713.         let ind = indent(openedparent)
  714.         endif
  715.     
  716.     elseif last_line =~ '^\s*'.s:blockstart
  717.         let ind = ind + &sw
  718.  
  719.  
  720.  
  721.     elseif AntepenultimateLine =~ '\%(;\%(\s*?>\)\=\|<<<''\=\a\w*''\=$\|^\s*}\|{\)'.endline . '\|' . s:defaultORcase
  722.         let ind = ind + &sw
  723.     endif
  724.  
  725.     endif
  726.  
  727.     if cline =~  '^\s*);\='
  728.     let ind = ind - &sw
  729.     endif
  730.  
  731.     let b:PHP_CurrentIndentLevel = ind
  732.     return ind
  733. endfunction
  734.