diff options
| author | Adam Stankiewicz <sheerun@sher.pl> | 2013-09-12 16:33:12 +0200 | 
|---|---|---|
| committer | Adam Stankiewicz <sheerun@sher.pl> | 2013-09-12 16:33:12 +0200 | 
| commit | d96dc724d442bbc9788815ab3da09d9fff0555a9 (patch) | |
| tree | f4b1859aa45a28cd420c7285006a4398726ff18a /indent | |
| parent | d4eca3f2eb6c8496261ed252596d6813b9eb8a04 (diff) | |
| download | vim-polyglot-d96dc724d442bbc9788815ab3da09d9fff0555a9.tar.gz vim-polyglot-d96dc724d442bbc9788815ab3da09d9fff0555a9.zip | |
Add extended php support
Diffstat (limited to 'indent')
| -rw-r--r-- | indent/php.vim | 1269 | 
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: | 
