summaryrefslogtreecommitdiffstats
path: root/indent/php.vim
diff options
context:
space:
mode:
authorAdam Stankiewicz <sheerun@sher.pl>2013-09-12 16:33:12 +0200
committerAdam Stankiewicz <sheerun@sher.pl>2013-09-12 16:33:12 +0200
commitd96dc724d442bbc9788815ab3da09d9fff0555a9 (patch)
treef4b1859aa45a28cd420c7285006a4398726ff18a /indent/php.vim
parentd4eca3f2eb6c8496261ed252596d6813b9eb8a04 (diff)
downloadvim-polyglot-d96dc724d442bbc9788815ab3da09d9fff0555a9.tar.gz
vim-polyglot-d96dc724d442bbc9788815ab3da09d9fff0555a9.zip
Add extended php support
Diffstat (limited to 'indent/php.vim')
-rw-r--r--indent/php.vim1269
1 files changed, 1269 insertions, 0 deletions
diff --git a/indent/php.vim b/indent/php.vim
new file mode 100644
index 00000000..6286c6b3
--- /dev/null
+++ b/indent/php.vim
@@ -0,0 +1,1269 @@
+" Vim indent file
+" Language: PHP
+" Author: John Wellesz <John.wellesz (AT) teaser (DOT) fr>
+" URL: http://www.2072productions.com/vim/indent/php.vim
+" Last Change: 2010 July 26th
+" Newsletter: http://www.2072productions.com/?to=php-indent-for-vim-newsletter.php
+" Version: 1.33
+"
+"
+" Changes: 1.33 - Rewrote Switch(){case:default:} handling from
+" scratch in a simpler more logical and infallible way...
+" - Removed PHP_ANSI_indenting which is no longer
+" needed.
+"
+"
+" Changes: 1.32b - Added PHP_ANSI_indenting and PHP_outdentphpescape
+" options details to VIm documentation (:help php-indent).
+"
+"
+" Changes: 1.32 - Added a new option: PHP_ANSI_indenting
+"
+"
+" Changes: 1.31a - Added a new option: PHP_outdentphpescape to indent
+" PHP tags as the surrounding code.
+"
+" Changes: 1.30 - Fixed empty case/default indentation again :/
+" - The ResetOptions() function will be called each time
+" the ftplugin calls this script, previously it was
+" executed on BufWinEnter and Syntax events.
+"
+"
+" Changes: 1.29 - Fixed php file detection for ResetOptions() used for
+" comments formatting. It now uses the same tests as
+" filetype.vim. ResetOptions() will be correctly
+" called for *.phtml, *.ctp and *.inc files.
+"
+"
+" Changes: 1.28 - End HEREDOC delimiters were not considered as such
+" if they were not followed by a ';'.
+" - Added support for NOWDOC tags ($foo = <<<'bar')
+"
+"
+" Changes: 1.27 - if a "case" was preceded by another "case" on the
+" previous line, the second "case" was indented incorrectly.
+"
+" Changes: 1.26 - '/*' character sequences found on a line
+" starting by a '#' were not dismissed by the indenting algorithm
+" and could cause indentation problem in some cases.
+"
+"
+" Changes: 1.25 - Fix some indentation errors on multi line conditions
+" and multi line statements.
+" - Fix when array indenting is broken and a closing
+" ');' is placed at the start of the line, following
+" lines will be indented correctly.
+" - New option: PHP_vintage_case_default_indent (default off)
+" - Minor fixes and optimizations.
+"
+"
+" Changes: 1.24 - Added compatibility with the latest version of
+" php.vim syntax file by Peter Hodge (http://www.vim.org/scripts/script.php?script_id=1571)
+" This fixes wrong indentation and ultra-slow indenting
+" on large php files...
+" - Fixed spelling in comments.
+"
+"
+" Changes: 1.23 - <script> html tags are now correctly indented the same
+" way their content is.
+" - <?.*?> (on a single line) PHP declarations are now
+" always considered as non-PHP code and let untouched.
+"
+" Changes: 1.22 - PHPDoc comments are now indented according to the
+" surrounding code.
+" - This is also true for '/* */' multi-line comments
+" when the second line begins by a '*'.
+" - Single line '/* */' comments are also indented.
+"
+"
+" Changes: 1.21 - 'try' and 'catch' were not registered as block starters so the '{'
+" after a 'try' or 'catch' could be wrongly indented...
+" (thanks to Gert Muller for finding this issue)
+"
+" Changes: 1.20 - Line beginning by a single or double quote followed
+" by a space would cause problems... this was related
+" to the bug correction of version 1.10 - Thanks to
+" David Fishburn for finding this (he was lucky).
+" - Changed the way this script set the 'formatoptions'
+" setting, now it uses '-=' and '+='
+" - New option: PHP_autoformatcomment (defaults to 1),
+" if set to 0 the 'formatoptions' setting will not be
+" altered.
+" - When PHP_autoformatcomment is not 0, the 'comments'
+" setting is set to the type of comments that PHP
+" supports.
+"
+" Changes: 1.19 - Indentation of '*/' delimiter of '/**/' won't be broken by
+" strings or '//' comments containing the "/*" character sequence.
+"
+" Changes: 1.182 - I Forgot to register 'interface' and 'abstract' as block starters so the '{'
+" after them could be wrongly indented...
+"
+" Changes: 1.181 - I Forgot to register 'class' as a block starter so the '{'
+" after a 'class' could be wrongly indented...
+"
+" Changes: 1.18 - No more problems with Vim 6.3 and UTF-8.
+" - Opening braces "{" are always indented according to their block starter.
+"
+" Instead of:
+"
+" if( $test
+" && $test2 )
+" {
+" }
+"
+" You have:
+"
+" if( $test
+" && $test2 )
+" {
+" }
+"
+"
+" Changes: 1.17 - Now following parts of split lines are indented:
+"
+" Instead of:
+"
+" $foo=
+" "foo"
+" ."foo";
+"
+" You have:
+"
+" $foo=
+" "foo"
+" ."foo";
+"
+" - If a "case : break;" was declared on a single line, the
+" following "case" was not indented correctly.
+" - If a </script> html tag was preceded by a "?>" it wasn't indented.
+" - Some other minor corrections and improvements.
+"
+"
+" Changes: 1.16 - Now starting and ending '*' of multiline '/* */' comments are aligned
+" on the '*' of the '/*' comment starter.
+" - Some code improvements that make indentation faster.
+"
+" Changes: 1.15 - Corrected some problems with the indentation of
+" multiline "array()" declarations.
+"
+" Changes: 1.14 - Added auto-formatting for comments (using the Vim option formatoptions=qroc).
+" - Added the script option PHP_BracesAtCodeLevel to
+" indent the '{' and '}' at the same level than the
+" code they contain.
+"
+" Changes: 1.13 - Some code cleaning and typo corrections (Thanks to
+" Emanuele Giaquinta for his patches)
+"
+" Changes: 1.12 - The bug involving searchpair() and utf-8 encoding in Vim 6.3 will
+" not make this script to hang but you'll have to be
+" careful to not write '/* */' comments with other '/*'
+" inside the comments else the indentation won't be correct.
+" NOTE: This is true only if you are using utf-8 and vim 6.3.
+"
+" Changes: 1.11 - If the "case" of a "switch" wasn't alone on its line
+" and if the "switch" was at col 0 (or at default indenting)
+" the lines following the "case" were not indented.
+"
+" Changes: 1.10 - Lines beginning by a single or double quote were
+" not indented in some cases.
+"
+" Changes: 1.09 - JavaScript code was not always directly indented.
+"
+" Changes: 1.08 - End comment tags '*/' are indented like start tags '/*'.
+" - When typing a multiline comment, '}' are indented
+" according to other commented '{'.
+" - Added a new option 'PHP_removeCRwhenUnix' to
+" automatically remove CR at end of lines when the file
+" format is Unix.
+" - Changed the file format of this very file to Unix.
+" - This version seems to correct several issues some people
+" had with 1.07.
+"
+" Changes: 1.07 - Added support for "Here document" tags:
+" - HereDoc end tags are indented properly.
+" - HereDoc content remains unchanged.
+" - All the code that is outside PHP delimiters remains
+" unchanged.
+" - New feature: The content of <script.*> html tags is considered as PHP
+" and indented according to the surrounding PHP code.
+" - "else if" are detected as "elseif".
+" - Multiline /**/ are indented when the user types it but
+" remain unchanged when indenting from their beginning.
+" - Fixed indenting of // and # comments.
+" - php_sync_method option is set to 0 (fromstart).
+" This is required for complex PHP scripts else the indent
+" may fail.
+" - Files with non PHP code at the beginning could alter the indent
+" of the following PHP code.
+" - Other minor improvements and corrections.
+"
+" Changes: 1.06: - Switch block were no longer indented correctly...
+" - Added an option to use a default indenting instead of 0.
+" (whereas I still can't find any good reason to use it!)
+" - A problem with ^\s*);\= lines where ending a non '{}'
+" structure.
+" - Changed script local variable to be buffer local
+" variable instead.
+"
+" Changes: 1.05: - Lines containing "<?php ?>" and "?> <?php"
+" (start and end tag on the same line) are no
+" longer indented at col 1 but as normal code.
+"
+" Changes: 1.04: - Strings containing "//" could break the indenting
+" algorithm.
+" - When a '{}' block was at col 1, the second line of the
+" block was not indented at all (because of a stupid
+" optimization coupled with a bug).
+"
+" Changes: 1.03: - Some indenting problems corrected: end of non '{}'
+" structures was not detected in some cases. The part of
+" code concerned have been re-written
+" - PHP start tags were not indented at col 1
+" - Wrong comment in the code have been corrected
+"
+" Changes: 1.02: - The bug I was talking about in version 1.01 (right below) has
+" been corrected :)
+" - Also corrected another bug that could occur in
+" some special cases.
+" - I removed the debug mode left in 1.01 that could
+" cause some Vim messages at loading if other script were
+" bugged.
+"
+" Changes: 1.01: - Some little bug corrections regarding automatic optimized
+" mode that missed some tests and could break the indenting.
+" - There is also a problem with complex non bracketed structures, when several
+" else are following each other, the algorithm do not indent the way it
+" should.
+" That will be corrected in the next version.
+"
+" If you find a bug, please e-mail me at John.wellesz (AT) teaser (DOT) fr
+" with an example of code that breaks the algorithm.
+"
+"
+" Thanks a lot for using this script.
+"
+
+" NOTE: This script must be used with PHP syntax ON and with the php syntax
+" script by Lutz Eymers (http://www.isp.de/data/php.vim ) or with the
+" script by Peter Hodge (http://www.vim.org/scripts/script.php?script_id=1571 )
+" the later is bundled by default with Vim 7.
+"
+"
+" In the case you have syntax errors in your script such as HereDoc end
+" identifiers not at col 1 you'll have to indent your file 2 times (This
+" script will automatically put HereDoc end identifiers at col 1 if
+" they are followed by a ';').
+"
+
+" NOTE: If you are editing files in Unix file format and that (by accident)
+" there are '\r' before new lines, this script won't be able to proceed
+" correctly and will make many mistakes because it won't be able to match
+" '\s*$' correctly.
+" So you have to remove those useless characters first with a command like:
+"
+" :%s /\r$//g
+"
+" or simply 'let' the option PHP_removeCRwhenUnix to 1 and the script will
+" silently remove them when VIM load this script (at each bufread).
+"
+"
+" Options: PHP_autoformatcomment = 0 to not enable autoformating of comment by
+" default, if set to 0, this script will let the 'formatoptions' setting intact.
+"
+" Options: PHP_default_indenting = # of sw (default is 0), # of sw will be
+" added to the indent of each line of PHP code.
+"
+" Options: PHP_removeCRwhenUnix = 1 to make the script automatically remove CR
+" at end of lines (by default this option is unset), NOTE that you
+" MUST remove CR when the fileformat is UNIX else the indentation
+" won't be correct!
+"
+" Options: PHP_BracesAtCodeLevel = 1 to indent the '{' and '}' at the same
+" level than the code they contain.
+" Exemple:
+" Instead of:
+" if ($foo)
+" {
+" foo();
+" }
+"
+" You will write:
+" if ($foo)
+" {
+" foo();
+" }
+"
+" NOTE: The script will be a bit slower if you use this option because
+" some optimizations won't be available.
+"
+"
+" Options: PHP_outdentphpescape = 0 (defaults to 1) to indent PHP tags as the surrounding code.
+"
+" Options: PHP_vintage_case_default_indent = 1 (defaults to 0) to add a meaningless indent
+" befaore 'case:' and 'default":' statement in switch blocks.
+"
+"
+" Remove all the comments from this file:
+" :%s /^\s*".*\({{{\|xxx\)\@<!\n\c//g
+" }}}
+
+" The 4 following lines prevent this script from being loaded several times per buffer.
+" They also prevent the load of different indent scripts for PHP at the same time.
+if exists("b:did_indent")
+ finish
+endif
+let b:did_indent = 1
+
+" This script set the option php_sync_method of PHP syntax script to 0
+" (fromstart indenting method) in order to have an accurate syntax.
+" If you are using very big PHP files (which is a bad idea) you will
+" experience slowings down while editing, if your code contains only PHP
+" code you can comment the line below.
+
+let php_sync_method = 0
+
+
+" Apply PHP_default_indenting option
+if exists("PHP_default_indenting")
+ let b:PHP_default_indenting = PHP_default_indenting * &sw
+else
+ let b:PHP_default_indenting = 0
+endif
+
+if exists("PHP_BracesAtCodeLevel")
+ let b:PHP_BracesAtCodeLevel = PHP_BracesAtCodeLevel
+else
+ let b:PHP_BracesAtCodeLevel = 0
+endif
+
+
+if exists("PHP_autoformatcomment")
+ let b:PHP_autoformatcomment = PHP_autoformatcomment
+else
+ let b:PHP_autoformatcomment = 1
+endif
+
+if exists("PHP_outdentphpescape")
+ let b:PHP_outdentphpescape = PHP_outdentphpescape
+else
+ let b:PHP_outdentphpescape = 1
+endif
+
+
+if exists("PHP_vintage_case_default_indent") && PHP_vintage_case_default_indent
+ let b:PHP_vintage_case_default_indent = 1
+else
+ let b:PHP_vintage_case_default_indent = 0
+endif
+
+
+
+let b:PHP_lastindented = 0
+let b:PHP_indentbeforelast = 0
+let b:PHP_indentinghuge = 0
+let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
+let b:PHP_LastIndentedWasComment = 0
+let b:PHP_InsideMultilineComment = 0
+" PHP code detect variables
+let b:InPHPcode = 0
+let b:InPHPcode_checked = 0
+let b:InPHPcode_and_script = 0
+let b:InPHPcode_tofind = ""
+let b:PHP_oldchangetick = b:changedtick
+let b:UserIsTypingComment = 0
+let b:optionsset = 0
+
+" The 4 options belows are overridden by indentexpr so they are always off
+" anyway...
+setlocal nosmartindent
+setlocal noautoindent
+setlocal nocindent
+" autoindent must be on, so the line below is also useless...
+setlocal nolisp
+
+setlocal indentexpr=GetPhpIndent()
+setlocal indentkeys=0{,0},0),:,!^F,o,O,e,*<Return>,=?>,=<?,=*/
+
+
+
+let s:searchpairflags = 'bWr'
+
+" Clean CR when the file is in Unix format
+if &fileformat == "unix" && exists("PHP_removeCRwhenUnix") && PHP_removeCRwhenUnix
+ silent! %s/\r$//g
+endif
+
+" Only define the functions once per Vim session.
+if exists("*GetPhpIndent")
+ call ResetPhpOptions()
+ finish " XXX -- comment this line for easy dev
+endif
+
+let s:endline= '\s*\%(//.*\|#.*\|/\*.*\*/\s*\)\=$'
+let s:PHP_startindenttag = '<?\%(.*?>\)\@!\|<script[^>]*>\%(.*<\/script>\)\@!'
+"setlocal debug=msg " XXX -- do not comment this line when modifying this file
+
+
+function! GetLastRealCodeLNum(startline) " {{{
+ "Inspired from the function SkipJavaBlanksAndComments by Toby Allsopp for indent/java.vim
+
+ let lnum = a:startline
+
+ " Used to indent <script.*> html tag correctly
+ if b:GetLastRealCodeLNum_ADD && b:GetLastRealCodeLNum_ADD == lnum + 1
+ let lnum = b:GetLastRealCodeLNum_ADD
+ endif
+
+ let old_lnum = lnum
+
+ while lnum > 1
+ let lnum = prevnonblank(lnum)
+ let lastline = getline(lnum)
+
+ " if we are inside an html <script> we must skip ?> tags to indent
+ " everything as php
+ if b:InPHPcode_and_script && lastline =~ '?>\s*$'
+ let lnum = lnum - 1
+ elseif lastline =~ '^\s*?>.*<?\%(php\)\=\s*$'
+ let lnum = lnum - 1
+ elseif lastline =~ '^\s*\%(//\|#\|/\*.*\*/\s*$\)'
+ " if line is under comment
+ let lnum = lnum - 1
+ elseif lastline =~ '\*/\s*$'
+ " skip multiline comments
+ call cursor(lnum, 1)
+ if lastline !~ '^\*/'
+ call search('\*/', 'W')
+ " position the cursor on the first */
+ endif
+ let lnum = searchpair('/\*', '', '\*/', s:searchpairflags, 'Skippmatch2()')
+ " find the most outside /*
+
+ let lastline = getline(lnum)
+ if lastline =~ '^\s*/\*'
+ " if line contains nothing but comment
+ " do the job again on the line before (a comment can hide another...)
+ let lnum = lnum - 1
+ else
+ break
+ endif
+
+
+ elseif lastline =~? '\%(//\s*\|?>.*\)\@<!<?\%(php\)\=\s*$\|^\s*<script\>'
+ " skip non php code
+
+ while lastline !~ '\(<?.*\)\@<!?>' && lnum > 1
+ let lnum = lnum - 1
+ let lastline = getline(lnum)
+ endwhile
+ if lastline =~ '^\s*?>'
+ " if line contains nothing but end tag
+ let lnum = lnum - 1
+ else
+ break
+ " else there is something important before the ?>
+ endif
+
+
+ " Manage "here document" tags
+ elseif lastline =~? '^\a\w*;\=$' && lastline !~? s:notPhpHereDoc
+ " match the end of a heredoc
+ let tofind=substitute( lastline, '\(\a\w*\);\=', '<<<''\\=\1''\\=$', '')
+ while getline(lnum) !~? tofind && lnum > 1
+ let lnum = lnum - 1
+ endwhile
+ else
+ " if none of these were true then we are done
+ break
+ endif
+ endwhile
+
+ if lnum==1 && getline(lnum) !~ '<?'
+ let lnum=0
+ endif
+
+ " This is to handle correctly end of script tags; to return the real last php
+ " code line else a '?>' could be returned has last_line
+ if b:InPHPcode_and_script && !b:InPHPcode
+ let b:InPHPcode_and_script = 0
+ endif
+
+ "echom lnum
+ "call getchar()
+
+
+ return lnum
+endfunction " }}}
+
+function! Skippmatch2()
+
+ let line = getline(".")
+
+ if line =~ '\%(".*\)\@<=/\*\%(.*"\)\@=' || line =~ '\%(\%(//\|#\).*\)\@<=/\*'
+ return 1
+ else
+ return 0
+ endif
+endfun
+
+function! Skippmatch() " {{{
+ " the slowest instruction of this script, remove it and the script is 3
+ " times faster but you may have troubles with '{' inside comments or strings
+ " that will break the indent algorithm...
+ let synname = synIDattr(synID(line("."), col("."), 0), "name")
+ if synname == "Delimiter" || synname == "phpRegionDelimiter" || synname =~# "^phpParent" || synname == "phpArrayParens" || synname =~# '^php\%(Block\|Brace\)' || synname == "javaScriptBraces" || synname =~# "^phpComment" && b:UserIsTypingComment
+ return 0
+ else
+" echo "\"" . synname . "\" " . getline(line("."));
+" call getchar()
+ return 1
+ endif
+endfun " }}}
+
+function! FindOpenBracket(lnum) " {{{
+ " set the cursor to the start of the lnum line
+ call cursor(a:lnum, 1)
+ return searchpair('{', '', '}', 'bW', 'Skippmatch()')
+endfun " }}}
+
+function! FindTheIfOfAnElse (lnum, StopAfterFirstPrevElse) " {{{
+ " A very clever recoursive function created by me (John Wellesz) that find the "if" corresponding to an
+ " "else". This function can easily be adapted for other languages :)
+ " 2010-07-25 -- Wow! it seems I was very proud of myself, I wouldn't write
+ " such a comment nowadays.
+
+ if getline(a:lnum) =~# '^\s*}\s*else\%(if\)\=\>'
+ " we do this so we can find the opened bracket to speed up the process
+ let beforeelse = a:lnum
+ else
+ let beforeelse = GetLastRealCodeLNum(a:lnum - 1)
+ endif
+
+ if !s:level
+ let s:iftoskip = 0
+ endif
+
+ " If we've found another "else" then it means we need to skip the next "if"
+ " we'll find.
+ if getline(beforeelse) =~# '^\s*\%(}\s*\)\=else\%(\s*if\)\@!\>'
+ let s:iftoskip = s:iftoskip + 1
+ endif
+
+ " A closing bracket? let skip the whole block to save some recursive calls
+ if getline(beforeelse) =~ '^\s*}'
+ let beforeelse = FindOpenBracket(beforeelse)
+
+ " Put us on the block starter
+ if getline(beforeelse) =~ '^\s*{'
+ let beforeelse = GetLastRealCodeLNum(beforeelse - 1)
+ endif
+ endif
+
+
+ " sometimes it's not useful to find the very first if of a long if elseif
+ " chain. The previous elseif will be enough
+ if !s:iftoskip && a:StopAfterFirstPrevElse && getline(beforeelse) =~# '^\s*\%([}]\s*\)\=else\%(if\)\=\>'
+ return beforeelse
+ endif
+
+ " if there was an else, then there is a if...
+ if getline(beforeelse) !~# '^\s*if\>' && beforeelse>1 || s:iftoskip && beforeelse>1
+
+ if s:iftoskip && getline(beforeelse) =~# '^\s*if\>'
+ let s:iftoskip = s:iftoskip - 1
+ endif
+
+ let s:level = s:level + 1
+ let beforeelse = FindTheIfOfAnElse(beforeelse, a:StopAfterFirstPrevElse)
+ endif
+
+ return beforeelse
+
+endfunction " }}}
+
+let s:defaultORcase = '^\s*\%(default\|case\).*:'
+
+function! FindTheSwitchIndent (lnum) " {{{
+ " Yes that's right, another very clever recursive function by the
+ " author of the famous FindTheIfOfAnElse()
+
+
+ let test = GetLastRealCodeLNum(a:lnum - 1)
+
+ if test <= 1
+ return indent(1) - &sw * b:PHP_vintage_case_default_indent
+ end
+
+ " A closing bracket? let skip the whole block to save some recursive calls
+ if getline(test) =~ '^\s*}'
+ let test = FindOpenBracket(test)
+
+ " Put us on the line above the block starter since if it's a switch,
+ " it's not the one we want.
+ if getline(test) =~ '^\s*{'
+ let test = GetLastRealCodeLNum(GetLastRealCodeLNum(test - 1) - 1)
+ endif
+ endif
+
+ " did we find it?
+ if getline(test) =~# '^\s*switch\>'
+ return indent(test)
+ elseif getline(test) =~# s:defaultORcase
+ return indent(test) - &sw * b:PHP_vintage_case_default_indent
+ else
+ return FindTheSwitchIndent(test)
+ endif
+
+endfunction "}}}
+
+
+function! IslinePHP (lnum, tofind) " {{{
+ " This function asks to the syntax if the pattern 'tofind' on the line
+ " number 'lnum' is PHP code (very slow...).
+ let cline = getline(a:lnum)
+
+ if a:tofind==""
+ " This correct the issue where lines beginning by a
+ " single or double quote were not indented in some cases.
+ let tofind = "^\\s*[\"']*\\s*\\zs\\S"
+ else
+ let tofind = a:tofind
+ endif
+
+ " ignore case
+ let tofind = tofind . '\c'
+
+ "find the first non blank char in the current line
+ let coltotest = match (cline, tofind) + 1
+
+ " ask to syntax what is its name
+ let synname = synIDattr(synID(a:lnum, coltotest, 0), "name")
+
+" echom synname
+ " if matchstr(synname, '^...') == "php" || synname=="Delimiter" || synname =~? '^javaScript'
+ if synname =~ '^php' || synname=="Delimiter" || synname =~? '^javaScript'
+ return synname
+ else
+ return ""
+ endif
+endfunction " }}}
+
+let s:notPhpHereDoc = '\%(break\|return\|continue\|exit\|else\)'
+let s:blockstart = '\%(\%(\%(}\s*\)\=else\%(\s\+\)\=\)\=if\>\|else\>\|while\>\|switch\>\|case\>\|default\>\|for\%(each\)\=\>\|declare\>\|class\>\|interface\>\|abstract\>\|try\>\|catch\>\)'
+
+" make sure the options needed for this script to work correctly are set here
+" for the last time. They could have been overridden by any 'onevent'
+" associated setting file...
+let s:autoresetoptions = 0
+if ! s:autoresetoptions
+ "au BufWinEnter,Syntax *.php,*.php\d,*.phtml,*.ctp,*.inc call ResetPhpOptions()
+ let s:autoresetoptions = 1
+endif
+
+function! ResetPhpOptions()
+ if ! b:optionsset && &filetype == "php"
+ if b:PHP_autoformatcomment
+
+ " Set the comment setting to something correct for PHP
+ setlocal comments=s1:/*,mb:*,ex:*/,://,:#
+
+ " disable Auto-wrap of text
+ setlocal formatoptions-=t
+ " Allow formatting of comments with "gq"
+ setlocal formatoptions+=q
+ " Insert comment leader after hitting <Enter>
+ setlocal formatoptions+=r
+ " Insert comment leader after hitting o or O in normal mode
+ setlocal formatoptions+=o
+ " Uses trailing white spaces to detect paragraphs
+ setlocal formatoptions+=w
+ " Autowrap comments using textwidth
+ setlocal formatoptions+=c
+ " Do not wrap if you modify a line after textwidth
+ setlocal formatoptions+=b
+ endif
+ let b:optionsset = 1
+ endif
+endfunc
+
+call ResetPhpOptions()
+
+function! GetPhpIndent()
+ "##############################################
+ "########### MAIN INDENT FUNCTION #############
+ "##############################################
+
+ " variable added on 2005-01-15 to make <script> tags really indent correctly (not pretty at all :-/ )
+ let b:GetLastRealCodeLNum_ADD = 0
+
+ " This detect if the user is currently typing text between each call
+ let UserIsEditing=0
+ if b:PHP_oldchangetick != b:changedtick
+ let b:PHP_oldchangetick = b:changedtick
+ let UserIsEditing=1
+ endif
+
+ if b:PHP_default_indenting
+ let b:PHP_default_indenting = g:PHP_default_indenting * &sw
+ endif
+
+ " current line
+ let cline = getline(v:lnum)
+
+ " Let's detect if we are indenting just one line or more than 3 lines
+ " in the last case we can slightly optimize our algorithm (by trusting
+ " what is above the current line)
+ if !b:PHP_indentinghuge && b:PHP_lastindented > b:PHP_indentbeforelast
+ if b:PHP_indentbeforelast
+ let b:PHP_indentinghuge = 1
+ echom 'Large indenting detected, speed optimizations engaged (v1.33)'
+ endif
+ let b:PHP_indentbeforelast = b:PHP_lastindented
+ endif
+
+ " If the line we are indenting isn't directly under the previous non-blank
+ " line of the file then deactivate the optimization procedures and reset
+ " status variable (we restart from scratch)
+ if b:InPHPcode_checked && prevnonblank(v:lnum - 1) != b:PHP_lastindented
+ if b:PHP_indentinghuge
+ echom 'Large indenting deactivated'
+ let b:PHP_indentinghuge = 0
+ let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
+ endif
+ let b:PHP_lastindented = v:lnum
+ let b:PHP_LastIndentedWasComment=0
+ let b:PHP_InsideMultilineComment=0
+ let b:PHP_indentbeforelast = 0
+
+ let b:InPHPcode = 0
+ let b:InPHPcode_checked = 0
+ let b:InPHPcode_and_script = 0
+ let b:InPHPcode_tofind = ""
+
+ elseif v:lnum > b:PHP_lastindented
+ " we are indenting line in > order (we can rely on the line before)
+ let real_PHP_lastindented = b:PHP_lastindented
+ let b:PHP_lastindented = v:lnum
+ endif
+
+ " We must detect if we are in PHPCODE or not, but one time only, then
+ " we will detect php end and start tags, comments /**/ and HereDoc
+ " tags
+
+ if !b:InPHPcode_checked " {{{ One time check
+ let b:InPHPcode_checked = 1
+
+ let synname = ""
+ if cline !~ '<?.*?>'
+ " the line could be blank (if the user presses 'return' so we use
+ " prevnonblank()) We ask to Syntax
+ let synname = IslinePHP (prevnonblank(v:lnum), "")
+ endif
+
+ if synname!=""
+ if synname != "phpHereDoc" && synname != "phpHereDocDelimiter"
+ let b:InPHPcode = 1
+ let b:InPHPcode_tofind = ""
+
+ if synname =~# "^phpComment"
+ let b:UserIsTypingComment = 1
+ else
+ let b:UserIsTypingComment = 0
+ endif
+
+ if synname =~? '^javaScript'
+ let b:InPHPcode_and_script = 1
+ endif
+
+ else
+ "We are inside an "HereDoc"
+ let b:InPHPcode = 0
+ let b:UserIsTypingComment = 0
+
+ let lnum = v:lnum - 1
+ while getline(lnum) !~? '<<<''\=\a\w*''\=$' && lnum > 1
+ let lnum = lnum - 1
+ endwhile
+
+ let b:InPHPcode_tofind = substitute( getline(lnum), '^.*<<<''\=\(\a\w*\)''\=$', '^\\s*\1;\\=$', '')
+ endif
+ else
+ " IslinePHP returned "" => we are not in PHP or Javascript
+ let b:InPHPcode = 0
+ let b:UserIsTypingComment = 0
+ " Then we have to find a php start tag...
+ let b:InPHPcode_tofind = '<?\%(.*?>\)\@!\|<script.*>'
+ endif
+ endif "!b:InPHPcode_checked }}}
+
+ " Now we know where we are so we can verify the line right above the
+ " current one to see if we have to stop or restart php indenting
+
+ " Test if we are indenting PHP code {{{
+ " Find an executable php code line above the current line.
+ let lnum = prevnonblank(v:lnum - 1)
+ let last_line = getline(lnum)
+
+ " If we aren't in php code, then there is something we have to find
+ if b:InPHPcode_tofind!=""
+ if cline =~? b:InPHPcode_tofind
+ let b:InPHPcode = 1
+ let b:InPHPcode_tofind = ""
+ let b:UserIsTypingComment = 0
+ if cline =~ '\*/'
+ " End comment tags must be indented like start comment tags
+ call cursor(v:lnum, 1)
+ if cline !~ '^\*/'
+ call search('\*/', 'W')
+ endif
+ " find the most outside /*
+ let lnum = searchpair('/\*', '', '\*/', s:searchpairflags, 'Skippmatch2()')
+
+ let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
+
+ " prevent a problem if multiline /**/ comment are surrounded by
+ " other types of comments
+ let b:PHP_LastIndentedWasComment = 0
+
+ if cline =~ '^\s*\*/'
+ return indent(lnum) + 1
+ else
+ return indent(lnum)
+ endif
+
+ elseif cline =~? '<script\>'
+ " a more accurate test is useless since there isn't any other possibility
+ let b:InPHPcode_and_script = 1
+ " this will make GetLastRealCodeLNum to add one line to its
+ " given argument so it can detect the <script> easily (that is
+ " simpler/quicker than using a regex...)
+ let b:GetLastRealCodeLNum_ADD = v:lnum
+ endif
+ endif
+ endif
+
+ " ### If we are in PHP code, we test the line before to see if we have to stop indenting
+ if b:InPHPcode
+
+ " Was last line containing a PHP end tag ?
+ if !b:InPHPcode_and_script && last_line =~ '\%(<?.*\)\@<!?>\%(.*<?\)\@!' && IslinePHP(lnum, '?>')=~"Delimiter"
+ if cline !~? s:PHP_startindenttag
+ let b:InPHPcode = 0
+ let b:InPHPcode_tofind = s:PHP_startindenttag
+ elseif cline =~? '<script\>'
+ let b:InPHPcode_and_script = 1
+ endif
+
+ " Was last line the start of a HereDoc ?
+ elseif last_line =~? '<<<''\=\a\w*''\=$'
+ let b:InPHPcode = 0
+ let b:InPHPcode_tofind = substitute( last_line, '^.*<<<''\=\(\a\w*\)''\=$', '^\\s*\1;\\=$', '')
+
+ " Skip /* \n+ */ comments except when the user is currently
+ " writing them or when it is a comment (ie: not a code put in comment)
+ elseif !UserIsEditing && cline =~ '^\s*/\*\%(.*\*/\)\@!' && getline(v:lnum + 1) !~ '^\s*\*'
+ let b:InPHPcode = 0
+ let b:InPHPcode_tofind = '\*/'
+
+ " is current line the end of a HTML script ? (we indent scripts the
+ " same as php code)
+ elseif cline =~? '^\s*</script>'
+ let b:InPHPcode = 0
+ let b:InPHPcode_tofind = s:PHP_startindenttag
+ " Note that b:InPHPcode_and_script is still true so that the
+ " </script> can be indented correctly
+ endif
+ endif " }}}
+
+
+ " Non PHP code is let as it is
+ if !b:InPHPcode && !b:InPHPcode_and_script
+ return -1
+ endif
+
+ " Align correctly multi // or # lines
+ " Indent successive // or # comment the same way the first is {{{
+ if cline =~ '^\s*\%(//\|#\|/\*.*\*/\s*$\)'
+ if b:PHP_LastIndentedWasComment == 1
+ return indent(real_PHP_lastindented)
+ endif
+ let b:PHP_LastIndentedWasComment = 1
+ else
+ let b:PHP_LastIndentedWasComment = 0
+ endif " }}}
+
+ " Indent multiline /* comments correctly {{{
+
+ "if we are on the start of a MULTI * beginning comment or if the user is
+ "currently typing a /* beginning comment.
+ if b:PHP_InsideMultilineComment || b:UserIsTypingComment
+ if cline =~ '^\s*\*\%(\/\)\@!'
+ " if cline == '*'
+ if last_line =~ '^\s*/\*'
+ " if last_line == '/*'
+ return indent(lnum) + 1
+ else
+ return indent(lnum)
+ endif
+ else
+ let b:PHP_InsideMultilineComment = 0
+ endif
+ endif
+
+ if !b:PHP_InsideMultilineComment && cline =~ '^\s*/\*' && cline !~ '\*/\s*$'
+ " if cline == '/*' and doesn't end with '*/'
+ if getline(v:lnum + 1) !~ '^\s*\*'
+ return -1
+ endif
+ let b:PHP_InsideMultilineComment = 1
+ endif " }}}
+
+ " Some tags are always indented to col 1
+
+ " Things always indented at col 1 (PHP delimiter: <?, ?>, Heredoc end) {{{
+ " PHP start tags are always at col 1, useless to indent unless the end tag
+ " is on the same line
+ if cline =~# '^\s*<?' && cline !~ '?>' && b:PHP_outdentphpescape
+ return 0
+ endif
+
+ " PHP end tags are always at col 1, useless to indent unless if it's
+ " followed by a start tag on the same line
+ if cline =~ '^\s*?>' && cline !~# '<?' && b:PHP_outdentphpescape
+ return 0
+ endif
+
+ " put HereDoc end tags at start of lines
+ if cline =~? '^\s*\a\w*;$\|^\a\w*$' && cline !~? s:notPhpHereDoc
+ return 0
+ endif " }}}
+
+ let s:level = 0
+
+ " Find an executable php code line above the current line.
+ let lnum = GetLastRealCodeLNum(v:lnum - 1)
+
+ " last line
+ let last_line = getline(lnum)
+ " by default
+ let ind = indent(lnum)
+ let endline= s:endline
+
+ if ind==0 && b:PHP_default_indenting
+ let ind = b:PHP_default_indenting
+ endif
+
+ " Hit the start of the file, use default indent.
+ if lnum == 0
+ return b:PHP_default_indenting
+ endif
+
+
+ " Search the matching open bracket (with searchpair()) and set the indent of cline
+ " to the indent of the matching line. (unless it's a VIm folding end tag)
+ if cline =~ '^\s*}\%(}}\)\@!'
+ let ind = indent(FindOpenBracket(v:lnum))
+ let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
+ return ind
+ endif
+
+ " Check for end of comment and indent it like its beginning
+ if cline =~ '^\s*\*/'
+ " End comment tags must be indented like start comment tags
+ call cursor(v:lnum, 1)
+ if cline !~ '^\*/'
+ call search('\*/', 'W')
+ endif
+ " find the most outside /*
+ let lnum = searchpair('/\*', '', '\*/', s:searchpairflags, 'Skippmatch2()')
+
+ let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
+
+ if cline =~ '^\s*\*/'
+ return indent(lnum) + 1
+ else
+ return indent(lnum)
+ endif
+ endif
+
+
+ " if the last line is a stated line and it's not indented then why should
+ " we indent this one??
+ " Do not do this if the last line is a ')' because array indentation can
+ " fail... and defaultORcase can be at col 0.
+ " if optimized mode is active and nor current or previous line are an 'else'
+ " or the end of a possible bracketless thing then indent the same as the previous
+ " line
+ if last_line =~ '[;}]'.endline && last_line !~ '^)' && last_line !~# s:defaultORcase " Added && last_line !~ '^)' on 2007-12-30
+ if ind==b:PHP_default_indenting
+ " if no indentation for the previous line
+ return b:PHP_default_indenting
+ elseif b:PHP_indentinghuge && ind==b:PHP_CurrentIndentLevel && cline !~# '^\s*\%(else\|\%(case\|default\).*:\|[})];\=\)' && last_line !~# '^\s*\%(\%(}\s*\)\=else\)' && getline(GetLastRealCodeLNum(lnum - 1))=~';'.endline
+ return b:PHP_CurrentIndentLevel
+ endif
+ endif
+
+ " used to prevent redundant tests in the last part of the script
+ let LastLineClosed = 0
+
+ let terminated = '\%(;\%(\s*?>\)\=\|<<<''\=\a\w*''\=$\|^\s*}\)'.endline
+ " What is a terminated line?
+ " - a line terminated by a ";" optionally followed by a "?>"
+ " - a HEREDOC starter line (the content of such block is never seen by this script)
+ " - a "}" not followed by a "{"
+
+ let unstated = '\%(^\s*'.s:blockstart.'.*)\|\%(//.*\)\@<!\<e'.'lse\>\)'.endline
+ " What is an unstated line?
+ " - an "else" at the end of line
+ " - a s:blockstart (if while etc...) followed by anything but a ";" at
+ " the end of line
+
+ " if the current line is an 'else' starting line
+ " (to match an 'else' preceded by a '}' is irrelevant and futile - see
+ " code above)
+ if ind != b:PHP_default_indenting && cline =~# '^\s*else\%(if\)\=\>'
+ " prevent optimized to work at next call XXX why ?
+ let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
+ return indent(FindTheIfOfAnElse(v:lnum, 1))
+ elseif cline =~# s:defaultORcase
+ " case and default need a special treatment
+ return FindTheSwitchIndent(v:lnum) + &sw * b:PHP_vintage_case_default_indent
+ elseif cline =~ '^\s*)\=\s*{'
+ let previous_line = last_line
+ let last_line_num = lnum
+
+ " let's find the indent of the block starter (if, while, for, etc...)
+ while last_line_num > 1
+
+ if previous_line =~ '^\s*\%(' . s:blockstart . '\|\%([a-zA-Z]\s*\)*function\)'
+
+ let ind = indent(last_line_num)
+
+ " If the PHP_BracesAtCodeLevel is set then indent the '{'
+ if b:PHP_BracesAtCodeLevel
+ let ind = ind + &sw
+ endif
+
+ return ind
+ endif
+
+ let last_line_num = last_line_num - 1
+ let previous_line = getline(last_line_num)
+ endwhile
+
+ elseif last_line =~# unstated && cline !~ '^\s*);\='.endline
+ let ind = ind + &sw " we indent one level further when the preceding line is not stated
+ "echo "42"
+ "call getchar()
+ return ind
+
+ " If the last line is terminated by ';' or if it's a closing '}'
+ " We need to check if this isn't the end of a multilevel non '{}'
+ " structure such as:
+ " Exemple:
+ " if ($truc)
+ " echo 'truc';
+ "
+ " OR
+ "
+ " if ($truc)
+ " while ($truc) {
+ " lkhlkh();
+ " echo 'infinite loop\n';
+ " }
+ "
+ " OR even (ADDED for version 1.17 - no modification required )
+ "
+ " $thing =
+ " "something";
+ elseif (ind != b:PHP_default_indenting || last_line =~ '^)' ) && last_line =~ terminated " Added || last_line =~ '^)' on 2007-12-30 (array indenting problem broke other things)
+ " If we are here it means that the previous line is:
+ " - a *;$ line
+ " - a [beginning-blanck] } followed by anything but a { $
+ let previous_line = last_line
+ let last_line_num = lnum
+ let LastLineClosed = 1
+ " The idea here is to check if the current line is after a non '{}'
+ " structure so we can indent it like the top of that structure.
+ " The top of that structure is characterized by a if (ff)$ style line
+ " preceded by a stated line. If there is no such structure then we
+ " just have to find two 'normal' lines following each other with the
+ " same indentation and with the first of these two lines terminated by
+ " a ; or by a }...
+
+ while 1
+ " let's skip '{}' blocks
+ if previous_line =~ '^\s*}'
+ " find the opening '{'
+ let last_line_num = FindOpenBracket(last_line_num)
+
+ " if the '{' is alone on the line get the line before
+ if getline(last_line_num) =~ '^\s*{'
+ let last_line_num = GetLastRealCodeLNum(last_line_num - 1)
+ endif
+
+ let previous_line = getline(last_line_num)
+
+ continue
+ else
+ " At this point we know that the previous_line isn't a closing
+ " '}' so we can check if we really are in such a structure.
+
+ " it's not a '}' but it could be an else alone...
+ if getline(last_line_num) =~# '^\s*else\%(if\)\=\>'
+ let last_line_num = FindTheIfOfAnElse(last_line_num, 0)
+ " re-run the loop (we could find a '}' again)
+ continue
+ endif
+
+ " So now it's ok we can check :-)
+ " A good quality is to have confidence in oneself so to know
+ " if yes or no we are in that struct lets test the indent of
+ " last_line_num and of last_line_num - 1!
+ " If those are == then we are almost done.
+ "
+ " That isn't sufficient, we need to test how the first of
+ " these 2 lines ends...
+
+ " Remember the 'topest' line we found so far
+ let last_match = last_line_num
+
+ let one_ahead_indent = indent(last_line_num)
+ let last_line_num = GetLastRealCodeLNum(last_line_num - 1)
+ let two_ahead_indent = indent(last_line_num)
+ let after_previous_line = previous_line
+ let previous_line = getline(last_line_num)
+
+
+ " If we find a '{' or a case/default then we are inside that block so lets
+ " indent properly... Like the line following that block starter
+ if previous_line =~# s:defaultORcase.'\|{'.endline
+ break
+ endif
+
+ " The 3 lines below are not necessary for the script to work
+ " but it makes it work a little more faster in some (rare) cases.
+ " We verify if we are at the top of a non '{}' struct.
+ if after_previous_line=~# '^\s*'.s:blockstart.'.*)'.endline && previous_line =~# '[;}]'.endline
+ break
+ endif
+
+ if one_ahead_indent == two_ahead_indent || last_line_num < 1
+ " So the previous line and the line before are at the same
+ " col. Now we just have to check if the line before is a ;$ or [}]$ ended line
+ " we always check the most ahead line of the 2 lines so
+ " it's useless to match ')$' since the lines couldn't have
+ " the same indent...
+ if previous_line =~# '\%(;\|^\s*}\)'.endline || last_line_num < 1
+ break
+ endif
+ endif
+ endif
+ endwhile
+
+ if indent(last_match) != ind
+ " let's use the indent of the last line matched by the algorithm above
+ let ind = indent(last_match)
+ " line added in version 1.02 to prevent optimized mode
+ " from acting in some special cases
+ let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
+
+ return ind
+ endif
+ " if nothing was done lets the old script continue
+ endif
+
+ let plinnum = GetLastRealCodeLNum(lnum - 1)
+ " previous to last line
+ let AntepenultimateLine = getline(plinnum)
+
+ " REMOVE comments at end of line before treatment
+ " the first part of the regex removes // from the end of line when they are
+ " followed by a number of '"' which is a multiple of 2. The second part
+ " removes // that are not followed by any '"'
+ " Sorry for this unreadable thing...
+ let last_line = substitute(last_line,"\\(//\\|#\\)\\(\\(\\([^\"']*\\([\"']\\)[^\"']*\\5\\)\\+[^\"']*$\\)\\|\\([^\"']*$\\)\\)",'','')
+
+
+ if ind == b:PHP_default_indenting
+ if last_line =~ terminated
+ let LastLineClosed = 1
+ endif
+ endif
+
+ " Indent blocks enclosed by {} or () (default indenting)
+ if !LastLineClosed
+ "echo "start"
+ "call getchar()
+
+ " the last line isn't a .*; or a }$ line
+ " Indent correctly multilevel and multiline '(.*)' things
+
+ " if the last line is a [{(]$ or a multiline function call (or array
+ " declaration) with already one parameter on the opening ( line
+ if last_line =~# '[{(]'.endline || last_line =~? '\h\w*\s*(.*,$' && AntepenultimateLine !~ '[,(]'.endline
+
+ if !b:PHP_BracesAtCodeLevel || last_line !~# '^\s*{'
+ let ind = ind + &sw
+ endif
+
+ " echo "43"
+ " call getchar()
+ if b:PHP_BracesAtCodeLevel || b:PHP_vintage_case_default_indent == 1
+ " case and default are not indented inside blocks
+ let b:PHP_CurrentIndentLevel = ind
+
+ return ind
+ endif
+
+ " If the last line isn't empty and ends with a '),' then check if the
+ " ')' was opened on the same line, if not it means it closes a
+ " multiline '(.*)' thing and that the current line need to be
+ " de-indented one time.
+ elseif last_line =~ '\S\+\s*),'.endline
+ call cursor(lnum, 1)
+ call search('),'.endline, 'W')
+ let openedparent = searchpair('(', '', ')', 'bW', 'Skippmatch()')
+ if openedparent != lnum
+ let ind = indent(openedparent)
+ endif
+
+ " if the line before starts a block then we need to indent the
+ " current line.
+ elseif last_line =~ '^\s*'.s:blockstart
+ let ind = ind + &sw
+
+ "echo cline. " --test 5-- " . ind
+ "call getchar()
+
+ " In all other cases if the last line isn't terminated indent 1
+ " level higher but only if the last line wasn't already indented
+ " for the same "code event"/reason. IE: if the antepenultimate line is terminated.
+ "
+ " 2nd explanation:
+ " - Test if the antepenultimate line is terminated or is
+ " a default/case if yes indent else let since it must have
+ " been indented correctly already
+
+ "elseif cline !~ '^\s*{' && AntepenultimateLine =~ '\%(;\%(\s*?>\)\=\|<<<\a\w*\|{\|^\s*'.s:blockstart.'.*)\)'.endline.'\|^\s*}\|'.s:defaultORcase
+ elseif AntepenultimateLine =~ '\%(;\%(\s*?>\)\=\|<<<''\=\a\w*''\=$\|^\s*}\|{\)'.endline . '\|' . s:defaultORcase
+ let ind = ind + &sw
+ "echo pline. " --test 2-- " . ind
+ "call getchar()
+ endif
+
+ endif
+
+ "echo "end"
+ "call getchar()
+ " If the current line closes a multiline function call or array def
+ if cline =~ '^\s*);\='
+ let ind = ind - &sw
+ endif
+
+ let b:PHP_CurrentIndentLevel = ind
+ return ind
+endfunction
+
+" vim: set ts=8 sw=4 sts=4: