comparison runtime/indent/php.vim @ 532:7052f11a3dc9

updated for version 7.0150
author vimboss
date Sun, 25 Sep 2005 22:16:38 +0000
parents 66080ac5dab7
children 862863033fdd
comparison
equal deleted inserted replaced
531:da9142bd190a 532:7052f11a3dc9
1 " Vim indent file 1 " Vim indent file
2 " Language: PHP 2 " Language: PHP
3 " Author: John Wellesz <John.wellesz (AT) teaser (DOT) fr> 3 " Author: John Wellesz <John.wellesz (AT) teaser (DOT) fr>
4 " URL: http://www.2072productions.com/vim/indent/php.vim 4 " URL: http://www.2072productions.com/vim/indent/php.vim
5 " Last Change: 2005 Aug 15 5 " Last Change: 2005 September 22th
6 " Version: 1.17 6 " Version: 1.181
7 " 7 "
8 " For a complete change log and lots of comments in the code, download the script on 8 " The change log and all the comments have been removed from this file.
9 "
10 " For a complete change log and fully commented code, download the script on
9 " 2072productions.com at the URI provided above. 11 " 2072productions.com at the URI provided above.
10 " 12 "
11 " 13 "
12 "
13 " If you find a bug, please e-mail me at John.wellesz (AT) teaser (DOT) fr 14 " If you find a bug, please e-mail me at John.wellesz (AT) teaser (DOT) fr
14 " with an example of code that break the algorithm. 15 " with an example of code that breaks the algorithm.
15 "
16 "
17 " Thanks a lot for using this script.
18 " 16 "
19 " 17 "
20 " NOTE: This script must be used with PHP syntax ON and with the php syntax 18 " NOTE: This script must be used with PHP syntax ON and with the php syntax
21 " script by Lutz Eymers (http://www.isp.de/data/php.vim ) that's the script bundled with Gvim. 19 " script by Lutz Eymers (http://www.isp.de/data/php.vim ) that's the script bundled with Gvim.
22 " 20 "
23 " 21 "
24 " In the case you have syntax errors in your script such as end of HereDoc 22 " In the case you have syntax errors in your script such as end of HereDoc
25 " tags not at col 1 you'll have to indent your file 2 times (This script 23 " tags not at col 1 you'll have to indent your file 2 times (This script
26 " will automatically put HereDoc end tags at col 1). 24 " will automatically put HereDoc end tags at col 1).
27 " 25 "
28 "
29 " NOTE: If you are editing file in Unix file format and that (by accident) 26 " NOTE: If you are editing file in Unix file format and that (by accident)
30 " there are '\r' before new lines, this script won't be able to proceed 27 " there are '\r' before new lines, this script won't be able to proceed
31 " correctly and will make many mistakes because it won't be able to match 28 " correctly and will make many mistakes because it won't be able to match
32 " '\s*$' correctly. 29 " '\s*$' correctly.
33 " So you have to remove those useless characters first with a command like: 30 " So you have to remove those useless characters first with a command like:
36 " 33 "
37 " or simply 'let' the option PHP_removeCRwhenUnix to 1 and the script will 34 " or simply 'let' the option PHP_removeCRwhenUnix to 1 and the script will
38 " silently remove them when VIM load this script (at each bufread). 35 " silently remove them when VIM load this script (at each bufread).
39 36
40 " Options: PHP_default_indenting = # of sw (default is 0), # of sw will be 37 " Options: PHP_default_indenting = # of sw (default is 0), # of sw will be
41 " added to the indent of each line of PHP code. 38 " added to the indent of each line of PHP code.
42 " 39 "
43 " Options: PHP_removeCRwhenUnix = 1 to make the script automatically remove CR 40 " Options: PHP_removeCRwhenUnix = 1 to make the script automatically remove CR
44 " at end of lines (by default this option is unset), NOTE that you 41 " at end of lines (by default this option is unset), NOTE that you
45 " MUST remove CR when the fileformat is UNIX else the indentation 42 " MUST remove CR when the fileformat is UNIX else the indentation
46 " won't be correct... 43 " won't be correct...
47 " 44 "
48 " Options: PHP_BracesAtCodeLevel = 1 to indent the '{' and '}' at the same 45 " Options: PHP_BracesAtCodeLevel = 1 to indent the '{' and '}' at the same
49 " level than the code they contain. 46 " level than the code they contain.
50 " Exemple: 47 " Exemple:
51 " Instead of: 48 " Instead of:
52 " if ($foo) 49 " if ($foo)
50 " {
51 " foo();
52 " }
53 "
54 " You will write:
55 " if ($foo)
53 " { 56 " {
54 " foo(); 57 " foo();
55 " } 58 " }
56 " 59 "
57 " You will write: 60 " NOTE: The script will be a bit slower if you use this option because
58 " if ($foo) 61 " some optimizations won't be available.
59 " {
60 " foo();
61 " }
62 "
63 " NOTE: The script will be a bit slower if you use this option because
64 " some optimizations won't be available.
65 62
66 63
67 if exists("b:did_indent") 64 if exists("b:did_indent")
68 finish 65 finish
69 endif 66 endif
70 let b:did_indent = 1 67 let b:did_indent = 1
71 68
72 " This script set the option php_sync_method of PHP syntax script to 0
73 " (fromstart indenting method) in order to have an accurate syntax.
74 " If you are using very big PHP files (which is a bad idea) you will
75 " experience slowings down while editing, if your code contains only PHP
76 " code you can comment the line below.
77 69
78 let php_sync_method = 0 70 let php_sync_method = 0
79 71
80 72
81 if exists("PHP_default_indenting") 73 if exists("PHP_default_indenting")
82 let b:PHP_default_indenting = PHP_default_indenting * &sw 74 let b:PHP_default_indenting = PHP_default_indenting * &sw
83 else 75 else
84 let b:PHP_default_indenting = 0 76 let b:PHP_default_indenting = 0
85 endif 77 endif
86 78
87 if exists("PHP_BracesAtCodeLevel") 79 if exists("PHP_BracesAtCodeLevel")
88 let b:PHP_BracesAtCodeLevel = PHP_BracesAtCodeLevel 80 let b:PHP_BracesAtCodeLevel = PHP_BracesAtCodeLevel
89 else 81 else
90 let b:PHP_BracesAtCodeLevel = 0 82 let b:PHP_BracesAtCodeLevel = 0
91 endif 83 endif
92 84
93 85
94 let b:PHP_lastindented = 0 86 let b:PHP_lastindented = 0
95 let b:PHP_indentbeforelast = 0 87 let b:PHP_indentbeforelast = 0
106 let b:optionsset = 0 98 let b:optionsset = 0
107 99
108 setlocal nosmartindent 100 setlocal nosmartindent
109 setlocal noautoindent 101 setlocal noautoindent
110 setlocal nocindent 102 setlocal nocindent
111 setlocal nolisp " autoindent must be on, so this line is also useless... 103 setlocal nolisp
112 104
113 setlocal indentexpr=GetPhpIndent() 105 setlocal indentexpr=GetPhpIndent()
114 setlocal indentkeys=0{,0},0),:,!^F,o,O,e,*<Return>,=?>,=<?,=*/ 106 setlocal indentkeys=0{,0},0),:,!^F,o,O,e,*<Return>,=?>,=<?,=*/
115 107
116 108
117 if version <= 603 && &encoding == 'utf-8' 109
118 let s:searchpairflags = 'bW' 110 let s:searchpairflags = 'bWr'
119 else 111
120 let s:searchpairflags = 'bWr' 112 if &fileformat == "unix" && exists("PHP_removeCRwhenUnix") && PHP_removeCRwhenUnix
113 silent! %s/\r$//g
121 endif 114 endif
122 115
123 if &fileformat == "unix" && exists("PHP_removeCRwhenUnix") && PHP_removeCRwhenUnix
124 silent! %s/\r$//g
125 endif
126
127 if exists("*GetPhpIndent") 116 if exists("*GetPhpIndent")
128 finish " XXX 117 finish " XXX
129 endif 118 endif
130 119
131 let s:endline= '\s*\%(//.*\|#.*\|/\*.*\*/\s*\)\=$' 120 let s:endline= '\s*\%(//.*\|#.*\|/\*.*\*/\s*\)\=$'
132 let s:PHP_startindenttag = '<?\%(.*?>\)\@!\|<script[^>]*>\%(.*<\/script>\)\@!' 121 let s:PHP_startindenttag = '<?\%(.*?>\)\@!\|<script[^>]*>\%(.*<\/script>\)\@!'
133 "setlocal debug=msg " XXX 122 "setlocal debug=msg " XXX
134 123
135 124
136 function! GetLastRealCodeLNum(startline) " {{{ 125 function! GetLastRealCodeLNum(startline) " {{{
137 "Inspired from the function SkipJavaBlanksAndComments by Toby Allsopp for indent/java.vim 126 let lnum = a:startline
138 let lnum = a:startline 127 let old_lnum = lnum
139 let old_lnum = lnum 128
140 129 while lnum > 1
141 while lnum > 1 130 let lnum = prevnonblank(lnum)
142 let lnum = prevnonblank(lnum) 131 let lastline = getline(lnum)
132
133 if b:InPHPcode_and_script && lastline =~ '?>\s*$'
134 let lnum = lnum - 1
135 elseif lastline =~ '^\s*?>.*<?\%(php\)\=\s*$'
136 let lnum = lnum - 1
137 elseif lastline =~ '^\s*\%(//\|#\|/\*.*\*/\s*$\)'
138 let lnum = lnum - 1
139 elseif lastline =~ '\*/\s*$'
140 call cursor(lnum, 1)
141 if lastline !~ '^\*/'
142 call search('\*/', 'W')
143 endif
144 let lnum = searchpair('/\*', '', '\*/', s:searchpairflags)
145
146 let lastline = getline(lnum)
147 if lastline =~ '^\s*/\*'
148 let lnum = lnum - 1
149 else
150 break
151 endif
152
153
154 elseif lastline =~? '\%(//\s*\|?>.*\)\@<!<?\%(php\)\=\s*$\|^\s*<script\>'
155
156 while lastline !~ '\(<?.*\)\@<!?>' && lnum > 1
157 let lnum = lnum - 1
143 let lastline = getline(lnum) 158 let lastline = getline(lnum)
144 159 endwhile
145 if b:InPHPcode_and_script && lastline =~ '?>\s*$' 160 if lastline =~ '^\s*?>'
146 let lnum = lnum - 1 161 let lnum = lnum - 1
147 elseif lastline =~ '^\s*?>.*<?\%(php\)\=\s*$' 162 else
148 let lnum = lnum - 1 163 break
149 elseif lastline =~ '^\s*\%(//\|#\|/\*.*\*/\s*$\)' " if line is under comment 164 endif
150 let lnum = lnum - 1 165
151 elseif lastline =~ '\*/\s*$' " skip multiline comments 166
152 call cursor(lnum, 1) 167 elseif lastline =~? '^\a\w*;$' && lastline !~? s:notPhpHereDoc
153 call search('\*/\zs', 'W') " positition the cursor after the first */ 168 let tofind=substitute( lastline, '\([^;]\+\);', '<<<\1$', '')
154 let lnum = searchpair('/\*', '', '\*/\zs', s:searchpairflags) " find the most outside /* 169 while getline(lnum) !~? tofind && lnum > 1
155 170 let lnum = lnum - 1
156 let lastline = getline(lnum) 171 endwhile
157 if lastline =~ '^\s*/\*' " if line contains nothing but comment 172 else
158 let lnum = lnum - 1 " do the job again on the line before (a comment can hide another...) 173 break
159 else 174 endif
160 break 175 endwhile
161 endif 176
162 177 if lnum==1 && getline(lnum)!~ '<?'
163 178 let lnum=0
164 elseif lastline =~? '\%(//\s*\|?>.*\)\@<!<?\%(php\)\=\s*$\|^\s*<script\>' " skip non php code 179 endif
165 180
166 while lastline !~ '\(<?.*\)\@<!?>' && lnum > 1 181 if b:InPHPcode_and_script && !b:InPHPcode
167 let lnum = lnum - 1 182 let b:InPHPcode_and_script = 0
168 let lastline = getline(lnum) 183 endif
169 endwhile 184 return lnum
170 if lastline =~ '^\s*?>' " if line contains nothing but end tag 185 endfunction " }}}
171 let lnum = lnum - 1
172 else
173 break " else there is something important before the ?>
174 endif
175
176
177 elseif lastline =~? '^\a\w*;$' && lastline !~? s:notPhpHereDoc " match the end of a heredoc
178 let tofind=substitute( lastline, '\([^;]\+\);', '<<<\1$', '')
179 while getline(lnum) !~? tofind && lnum > 1
180 let lnum = lnum - 1
181 endwhile
182 else
183 break " if none of these were true then we are done
184 endif
185 endwhile
186
187 if lnum==1 && getline(lnum)!~ '<?'
188 let lnum=0
189 endif
190
191 if b:InPHPcode_and_script && !b:InPHPcode
192 let b:InPHPcode_and_script = 0
193 endif
194 return lnum
195 endfunction
196 " }}}
197 186
198 function! Skippmatch() " {{{ 187 function! Skippmatch() " {{{
199 let synname = synIDattr(synID(line("."), col("."), 0), "name") 188 let synname = synIDattr(synID(line("."), col("."), 0), "name")
200 if synname == "Delimiter" || synname == "phpParent" || synname == "javaScriptBraces" || synname == "phpComment" && b:UserIsTypingComment 189 if synname == "Delimiter" || synname == "phpParent" || synname == "javaScriptBraces" || synname == "phpComment" && b:UserIsTypingComment
201 return 0 190 return 0
202 else 191 else
203 return 1 192 return 1
204 endif 193 endif
205 endfun 194 endfun " }}}
206 " }}}
207 195
208 function! FindOpenBracket(lnum) " {{{ 196 function! FindOpenBracket(lnum) " {{{
209 call cursor(a:lnum, 1) " set the cursor to the start of the lnum line 197 call cursor(a:lnum, 1)
210 return searchpair('{', '', '}', 'bW', 'Skippmatch()') 198 return searchpair('{', '', '}', 'bW', 'Skippmatch()')
211 endfun 199 endfun " }}}
212 " }}}
213 200
214 function! FindTheIfOfAnElse (lnum, StopAfterFirstPrevElse) " {{{ 201 function! FindTheIfOfAnElse (lnum, StopAfterFirstPrevElse) " {{{
215 " A very clever recoursive function created by me (John Wellesz) that find the "if" corresponding to an 202
216 " "else". This function can easily be adapted for other languages :) 203 if getline(a:lnum) =~# '^\s*}\s*else\%(if\)\=\>'
217 204 let beforeelse = a:lnum
218 if getline(a:lnum) =~# '^\s*}\s*else\%(if\)\=\>' 205 else
219 let beforeelse = a:lnum " we do this so we can find the opened bracket to speed up the process 206 let beforeelse = GetLastRealCodeLNum(a:lnum - 1)
220 else 207 endif
221 let beforeelse = GetLastRealCodeLNum(a:lnum - 1) 208
222 endif 209 if !s:level
223 210 let s:iftoskip = 0
224 if !s:level 211 endif
225 let s:iftoskip = 0 212
226 endif 213 if getline(beforeelse) =~# '^\s*\%(}\s*\)\=else\%(\s*if\)\@!\>'
227 214 let s:iftoskip = s:iftoskip + 1
228 if getline(beforeelse) =~# '^\s*\%(}\s*\)\=else\%(\s*if\)\@!\>' 215 endif
229 let s:iftoskip = s:iftoskip + 1 216
230 endif 217 if getline(beforeelse) =~ '^\s*}'
231 218 let beforeelse = FindOpenBracket(beforeelse)
232 if getline(beforeelse) =~ '^\s*}' 219
233 let beforeelse = FindOpenBracket(beforeelse) 220 if getline(beforeelse) =~ '^\s*{'
234 221 let beforeelse = GetLastRealCodeLNum(beforeelse - 1)
235 if getline(beforeelse) =~ '^\s*{' 222 endif
236 let beforeelse = GetLastRealCodeLNum(beforeelse - 1) 223 endif
237 endif 224
238 endif 225
239 226 if !s:iftoskip && a:StopAfterFirstPrevElse && getline(beforeelse) =~# '^\s*\%([}]\s*\)\=else\%(if\)\=\>'
240
241 if !s:iftoskip && a:StopAfterFirstPrevElse && getline(beforeelse) =~# '^\s*\%([}]\s*\)\=else\%(if\)\=\>'
242 return beforeelse
243 endif
244
245 if getline(beforeelse) !~# '^\s*if\>' && beforeelse>1 || s:iftoskip && beforeelse>1
246
247 if s:iftoskip && getline(beforeelse) =~# '^\s*if\>'
248 let s:iftoskip = s:iftoskip - 1
249 endif
250
251 let s:level = s:level + 1
252 let beforeelse = FindTheIfOfAnElse(beforeelse, a:StopAfterFirstPrevElse)
253 endif
254
255 return beforeelse 227 return beforeelse
256 228 endif
257 endfunction 229
258 " }}} 230 if getline(beforeelse) !~# '^\s*if\>' && beforeelse>1 || s:iftoskip && beforeelse>1
231
232 if s:iftoskip && getline(beforeelse) =~# '^\s*if\>'
233 let s:iftoskip = s:iftoskip - 1
234 endif
235
236 let s:level = s:level + 1
237 let beforeelse = FindTheIfOfAnElse(beforeelse, a:StopAfterFirstPrevElse)
238 endif
239
240 return beforeelse
241
242 endfunction " }}}
259 243
260 function! IslinePHP (lnum, tofind) " {{{ 244 function! IslinePHP (lnum, tofind) " {{{
261 let cline = getline(a:lnum) 245 let cline = getline(a:lnum)
262 246
263 if a:tofind=="" 247 if a:tofind==""
264 let tofind = "^\\s*[\"']*\s*\\zs\\S" " This correct the issue where lines beginning by a 248 let tofind = "^\\s*[\"']*\s*\\zs\\S"
265 " single or double quote were not indented in some cases. 249 else
266 else 250 let tofind = a:tofind
267 let tofind = a:tofind 251 endif
268 endif 252
269 253 let tofind = tofind . '\c'
270 let tofind = tofind . '\c' " ignorecase 254
271 255 let coltotest = match (cline, tofind) + 1
272 let coltotest = match (cline, tofind) + 1 "find the first non blank char in the current line 256
273 257 let synname = synIDattr(synID(a:lnum, coltotest, 0), "name")
274 let synname = synIDattr(synID(a:lnum, coltotest, 0), "name") " ask to syntax what is its name 258
275 259 if synname =~ '^php' || synname=="Delimiter" || synname =~? '^javaScript'
276 if synname =~ '^php' || synname=="Delimiter" || synname =~? '^javaScript' 260 return synname
277 return synname 261 else
278 else 262 return ""
279 return "" 263 endif
280 endif 264 endfunction " }}}
281 endfunction
282 " }}}
283 265
284 let s:notPhpHereDoc = '\%(break\|return\|continue\|exit\);' 266 let s:notPhpHereDoc = '\%(break\|return\|continue\|exit\);'
285 let s:blockstart = '\%(\%(\%(}\s*\)\=else\%(\s\+\)\=\)\=if\>\|while\>\|switch\>\|for\%(each\)\=\>\|declare\>\|[|&]\)' 267 let s:blockstart = '\%(\%(\%(}\s*\)\=else\%(\s\+\)\=\)\=if\>\|else\>\|while\>\|switch\>\|for\%(each\)\=\>\|declare\>\|class\>\|[|&]\)'
286 268
287 let s:autorestoptions = 0 269 let s:autorestoptions = 0
288 if ! s:autorestoptions 270 if ! s:autorestoptions
289 au BufWinEnter,Syntax *.php,*.php3,*.php4,*.php5 call ResetOptions() 271 au BufWinEnter,Syntax *.php,*.php3,*.php4,*.php5 call ResetOptions()
290 let s:autorestoptions = 1 272 let s:autorestoptions = 1
291 endif 273 endif
292 274
293 function! ResetOptions() 275 function! ResetOptions()
294 if ! b:optionsset 276 if ! b:optionsset
295 setlocal formatoptions=qroc 277 setlocal formatoptions=qroc
296 let b:optionsset = 1 278 let b:optionsset = 1
297 endif 279 endif
298 endfunc 280 endfunc
299 281
300 function! GetPhpIndent() 282 function! GetPhpIndent()
301 "############################################## 283
302 "########### MAIN INDENT FUNCTION ############# 284 let UserIsEditing=0
303 "############################################## 285 if b:PHP_oldchangetick != b:changedtick
304 286 let b:PHP_oldchangetick = b:changedtick
305 let UserIsEditing=0 287 let UserIsEditing=1
306 if b:PHP_oldchangetick != b:changedtick 288 endif
307 let b:PHP_oldchangetick = b:changedtick 289
308 let UserIsEditing=1 290 if b:PHP_default_indenting
309 endif 291 let b:PHP_default_indenting = g:PHP_default_indenting * &sw
310 292 endif
311 if b:PHP_default_indenting 293
312 let b:PHP_default_indenting = g:PHP_default_indenting * &sw 294 let cline = getline(v:lnum)
313 endif 295
314 296 if !b:PHP_indentinghuge && b:PHP_lastindented > b:PHP_indentbeforelast
315 let cline = getline(v:lnum) " current line 297 if b:PHP_indentbeforelast
316 298 let b:PHP_indentinghuge = 1
317 if !b:PHP_indentinghuge && b:PHP_lastindented > b:PHP_indentbeforelast 299 echom 'Large indenting detected, speed optimizations engaged'
318 if b:PHP_indentbeforelast 300 endif
319 let b:PHP_indentinghuge = 1 301 let b:PHP_indentbeforelast = b:PHP_lastindented
320 echom 'Large indenting detected, speed optimizations engaged' 302 endif
321 endif 303
322 let b:PHP_indentbeforelast = b:PHP_lastindented 304 if b:InPHPcode_checked && prevnonblank(v:lnum - 1) != b:PHP_lastindented
323 endif 305 if b:PHP_indentinghuge
324 306 echom 'Large indenting deactivated'
325 if b:InPHPcode_checked && prevnonblank(v:lnum - 1) != b:PHP_lastindented 307 let b:PHP_indentinghuge = 0
326 if b:PHP_indentinghuge 308 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
327 echom 'Large indenting deactivated' 309 endif
328 let b:PHP_indentinghuge = 0 310 let b:PHP_lastindented = v:lnum
329 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting 311 let b:PHP_LastIndentedWasComment=0
330 endif 312 let b:PHP_InsideMultilineComment=0
331 let b:PHP_lastindented = v:lnum 313 let b:PHP_indentbeforelast = 0
332 let b:PHP_LastIndentedWasComment=0 314
333 let b:PHP_InsideMultilineComment=0 315 let b:InPHPcode = 0
334 let b:PHP_indentbeforelast = 0 316 let b:InPHPcode_checked = 0
335 317 let b:InPHPcode_and_script = 0
318 let b:InPHPcode_tofind = ""
319
320 elseif v:lnum > b:PHP_lastindented
321 let real_PHP_lastindented = b:PHP_lastindented
322 let b:PHP_lastindented = v:lnum
323 endif
324
325
326 if !b:InPHPcode_checked " {{{ One time check
327 let b:InPHPcode_checked = 1
328
329 let synname = IslinePHP (prevnonblank(v:lnum), "")
330
331 if synname!=""
332 if synname != "phpHereDoc"
333 let b:InPHPcode = 1
334 let b:InPHPcode_tofind = ""
335
336 if synname == "phpComment"
337 let b:UserIsTypingComment = 1
338 else
339 let b:UserIsTypingComment = 0
340 endif
341
342 if synname =~? '^javaScript'
343 let b:InPHPcode_and_script = 1
344 endif
345
346 else
336 let b:InPHPcode = 0 347 let b:InPHPcode = 0
337 let b:InPHPcode_checked = 0 348 let b:UserIsTypingComment = 0
338 let b:InPHPcode_and_script = 0 349
339 let b:InPHPcode_tofind = "" 350 let lnum = v:lnum - 1
340 351 while getline(lnum) !~? '<<<\a\w*$' && lnum > 1
341 elseif v:lnum > b:PHP_lastindented " we are indenting line in > order (we can rely on the line before) 352 let lnum = lnum - 1
342 let real_PHP_lastindented = b:PHP_lastindented 353 endwhile
343 let b:PHP_lastindented = v:lnum 354
344 endif 355 let b:InPHPcode_tofind = substitute( getline(lnum), '^.*<<<\(\a\w*\)\c', '^\\s*\1;$', '')
345 356 endif
346
347 if !b:InPHPcode_checked " {{{ One time check
348 let b:InPHPcode_checked = 1
349
350 let synname = IslinePHP (prevnonblank(v:lnum), "") " the line could be blank (if the user presses 'return')
351
352 if synname!=""
353 if synname != "phpHereDoc"
354 let b:InPHPcode = 1
355 let b:InPHPcode_tofind = ""
356
357 if synname == "phpComment"
358 let b:UserIsTypingComment = 1
359 else
360 let b:UserIsTypingComment = 0
361 endif
362
363 if synname =~? '^javaScript'
364 let b:InPHPcode_and_script = 1
365 endif
366
367 else
368 let b:InPHPcode = 0
369 let b:UserIsTypingComment = 0
370
371 let lnum = v:lnum - 1
372 while getline(lnum) !~? '<<<\a\w*$' && lnum > 1
373 let lnum = lnum - 1
374 endwhile
375
376 let b:InPHPcode_tofind = substitute( getline(lnum), '^.*<<<\(\a\w*\)\c', '^\\s*\1;$', '')
377 endif
378 else " IslinePHP returned "" => we are not in PHP or Javascript
379 let b:InPHPcode = 0
380 let b:UserIsTypingComment = 0
381 " Then we have to find a php start tag...
382 let b:InPHPcode_tofind = '<?\%(.*?>\)\@!\|<script.*>'
383 endif
384 endif "!b:InPHPcode_checked }}}
385
386
387 let lnum = prevnonblank(v:lnum - 1)
388 let last_line = getline(lnum)
389
390 if b:InPHPcode_tofind!=""
391 if cline =~? b:InPHPcode_tofind
392 let b:InPHPcode = 1
393 let b:InPHPcode_tofind = ""
394 let b:UserIsTypingComment = 0
395 if cline =~ '\*/' " End comment tags must be indented like start comment tags
396 call cursor(v:lnum, 1)
397 call search('\*/\zs', 'W')
398 let lnum = searchpair('/\*', '', '\*/\zs', s:searchpairflags) " find the most outside /*
399
400 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
401 let b:PHP_LastIndentedWasComment = 0 " prevent a problem if multiline /**/ comment are surounded by
402 " other types of comments
403
404 if cline =~ '^\s*\*/'
405 return indent(lnum) + 1
406 else
407 return indent(lnum)
408 endif
409
410 elseif cline =~? '<script\>' " a more accurate test is useless since there isn't any other possibility
411 let b:InPHPcode_and_script = 1
412 endif
413 endif
414 endif
415
416
417 if b:InPHPcode
418
419 if !b:InPHPcode_and_script && last_line =~ '\%(<?.*\)\@<!?>\%(.*<?\)\@!' && IslinePHP(lnum, '?>')=="Delimiter"
420 if cline !~? s:PHP_startindenttag
421 let b:InPHPcode = 0
422 let b:InPHPcode_tofind = s:PHP_startindenttag
423 elseif cline =~? '<script\>'
424 let b:InPHPcode_and_script = 1
425 endif
426
427 elseif last_line =~? '<<<\a\w*$'
428 let b:InPHPcode = 0
429 let b:InPHPcode_tofind = substitute( last_line, '^.*<<<\(\a\w*\)\c', '^\\s*\1;$', '')
430
431 elseif !UserIsEditing && cline =~ '^\s*/\*\%(.*\*/\)\@!' && getline(v:lnum + 1) !~ '^\s*\*' " XXX indent comments
432 let b:InPHPcode = 0
433 let b:InPHPcode_tofind = '\*/'
434
435 elseif cline =~? '^\s*</script>'
436 let b:InPHPcode = 0
437 let b:InPHPcode_tofind = s:PHP_startindenttag
438 endif
439 endif " }}}
440
441 if !b:InPHPcode && !b:InPHPcode_and_script
442 return -1
443 endif
444
445
446 " Indent successive // or # comment the same way the first is {{{
447 if cline =~ '^\s*\%(//\|#\|/\*.*\*/\s*$\)'
448 if b:PHP_LastIndentedWasComment == 1
449 return indent(real_PHP_lastindented) " line replaced in 1.02
450 endif
451 let b:PHP_LastIndentedWasComment = 1
452 else 357 else
358 let b:InPHPcode = 0
359 let b:UserIsTypingComment = 0
360 let b:InPHPcode_tofind = '<?\%(.*?>\)\@!\|<script.*>'
361 endif
362 endif "!b:InPHPcode_checked }}}
363
364
365 " Test if we are indenting PHP code {{{
366 let lnum = prevnonblank(v:lnum - 1)
367 let last_line = getline(lnum)
368
369 if b:InPHPcode_tofind!=""
370 if cline =~? b:InPHPcode_tofind
371 let b:InPHPcode = 1
372 let b:InPHPcode_tofind = ""
373 let b:UserIsTypingComment = 0
374 if cline =~ '\*/'
375 call cursor(v:lnum, 1)
376 if cline !~ '^\*/'
377 call search('\*/', 'W')
378 endif
379 let lnum = searchpair('/\*', '', '\*/', s:searchpairflags)
380
381 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
382
453 let b:PHP_LastIndentedWasComment = 0 383 let b:PHP_LastIndentedWasComment = 0
454 endif 384
455 " }}} 385 if cline =~ '^\s*\*/'
456 386 return indent(lnum) + 1
457 " Indent multiline /* comments correctly {{{
458
459
460 if b:PHP_InsideMultilineComment || b:UserIsTypingComment
461 if cline =~ '^\s*\*\%(\/\)\@!' " if cline == '*'
462 if last_line =~ '^\s*/\*' " if last_line == '/*'
463 return indent(lnum) + 1
464 else
465 return indent(lnum)
466 endif
467 else 387 else
468 let b:PHP_InsideMultilineComment = 0 388 return indent(lnum)
469 endif 389 endif
470 endif 390
471 391 elseif cline =~? '<script\>'
472 if !b:PHP_InsideMultilineComment && cline =~ '^\s*/\*' " if cline == '/*' 392 let b:InPHPcode_and_script = 1
473 let b:PHP_InsideMultilineComment = 1 393 endif
474 return -1 394 endif
475 endif 395 endif
476 " }}} 396
477 397 if b:InPHPcode
478 if cline =~# '^\s*<?' && cline !~ '?>' " Added the ^\s* part in version 1.03 398
479 return 0 399 if !b:InPHPcode_and_script && last_line =~ '\%(<?.*\)\@<!?>\%(.*<?\)\@!' && IslinePHP(lnum, '?>')=="Delimiter"
480 endif 400 if cline !~? s:PHP_startindenttag
481 401 let b:InPHPcode = 0
482 if cline =~ '^\s*?>' && cline !~# '<?' 402 let b:InPHPcode_tofind = s:PHP_startindenttag
483 return 0 403 elseif cline =~? '<script\>'
484 endif 404 let b:InPHPcode_and_script = 1
485 405 endif
486 if cline =~? '^\s*\a\w*;$' && cline !~? s:notPhpHereDoc 406
487 return 0 407 elseif last_line =~? '<<<\a\w*$'
488 endif 408 let b:InPHPcode = 0
489 " }}} 409 let b:InPHPcode_tofind = substitute( last_line, '^.*<<<\(\a\w*\)\c', '^\\s*\1;$', '')
490 410
491 let s:level = 0 411 elseif !UserIsEditing && cline =~ '^\s*/\*\%(.*\*/\)\@!' && getline(v:lnum + 1) !~ '^\s*\*'
492 412 let b:InPHPcode = 0
493 let lnum = GetLastRealCodeLNum(v:lnum - 1) 413 let b:InPHPcode_tofind = '\*/'
494 let last_line = getline(lnum) " last line 414
495 let ind = indent(lnum) " by default 415 elseif cline =~? '^\s*</script>'
496 let endline= s:endline 416 let b:InPHPcode = 0
497 417 let b:InPHPcode_tofind = s:PHP_startindenttag
498 if ind==0 && b:PHP_default_indenting 418 endif
499 let ind = b:PHP_default_indenting 419 endif " }}}
500 endif 420
501 421 if !b:InPHPcode && !b:InPHPcode_and_script
502 if lnum == 0 422 return -1
503 return b:PHP_default_indenting 423 endif
504 endif 424
505 425
506 426 " Indent successive // or # comment the same way the first is {{{
507 if cline =~ '^\s*}\%(}}\)\@!' 427 if cline =~ '^\s*\%(//\|#\|/\*.*\*/\s*$\)'
508 let ind = indent(FindOpenBracket(v:lnum)) 428 if b:PHP_LastIndentedWasComment == 1
509 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting 429 return indent(real_PHP_lastindented)
430 endif
431 let b:PHP_LastIndentedWasComment = 1
432 else
433 let b:PHP_LastIndentedWasComment = 0
434 endif " }}}
435
436 " Indent multiline /* comments correctly {{{
437
438 if b:PHP_InsideMultilineComment || b:UserIsTypingComment
439 if cline =~ '^\s*\*\%(\/\)\@!'
440 if last_line =~ '^\s*/\*'
441 return indent(lnum) + 1
442 else
443 return indent(lnum)
444 endif
445 else
446 let b:PHP_InsideMultilineComment = 0
447 endif
448 endif
449
450 if !b:PHP_InsideMultilineComment && cline =~ '^\s*/\*'
451 let b:PHP_InsideMultilineComment = 1
452 return -1
453 endif " }}}
454
455
456 " Things always indented at col 1 (PHP delimiter: <?, ?>, Heredoc end) {{{
457 if cline =~# '^\s*<?' && cline !~ '?>'
458 return 0
459 endif
460
461 if cline =~ '^\s*?>' && cline !~# '<?'
462 return 0
463 endif
464
465 if cline =~? '^\s*\a\w*;$' && cline !~? s:notPhpHereDoc
466 return 0
467 endif " }}}
468
469 let s:level = 0
470
471 let lnum = GetLastRealCodeLNum(v:lnum - 1)
472 let last_line = getline(lnum)
473 let ind = indent(lnum)
474 let endline= s:endline
475
476 if ind==0 && b:PHP_default_indenting
477 let ind = b:PHP_default_indenting
478 endif
479
480 if lnum == 0
481 return b:PHP_default_indenting
482 endif
483
484
485 if cline =~ '^\s*}\%(}}\)\@!'
486 let ind = indent(FindOpenBracket(v:lnum))
487 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
488 return ind
489 endif
490
491 if cline =~ '^\s*\*/'
492 call cursor(v:lnum, 1)
493 if cline !~ '^\*/'
494 call search('\*/', 'W')
495 endif
496 let lnum = searchpair('/\*', '', '\*/', s:searchpairflags)
497
498 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
499
500 if cline =~ '^\s*\*/'
501 return indent(lnum) + 1
502 else
503 return indent(lnum)
504 endif
505 endif
506
507 let defaultORcase = '^\s*\%(default\|case\).*:'
508
509 if last_line =~ '[;}]'.endline && last_line !~# defaultORcase
510 if ind==b:PHP_default_indenting
511 return b:PHP_default_indenting
512 elseif b:PHP_indentinghuge && ind==b:PHP_CurrentIndentLevel && cline !~# '^\s*\%(else\|\%(case\|default\).*:\|[})];\=\)' && last_line !~# '^\s*\%(\%(}\s*\)\=else\)' && getline(GetLastRealCodeLNum(lnum - 1))=~';'.endline
513 return b:PHP_CurrentIndentLevel
514 endif
515 endif
516
517 let LastLineClosed = 0
518
519 let terminated = '\%(;\%(\s*?>\)\=\|<<<\a\w*\|}\)'.endline
520
521 let unstated = '\%(^\s*'.s:blockstart.'.*)\|\%(//.*\)\@<!\<e'.'lse\>\)'.endline
522
523 if ind != b:PHP_default_indenting && cline =~# '^\s*else\%(if\)\=\>'
524 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
525 return indent(FindTheIfOfAnElse(v:lnum, 1))
526 elseif cline =~ '^\s*{'
527 let previous_line = last_line
528 let last_line_num = lnum
529
530 while last_line_num > 1
531
532 if previous_line =~ '^\s*\%(' . s:blockstart . '\|\%([a-zA-Z]\s*\)*function\)' && previous_line !~ '^\s*[|&]'
533
534 let ind = indent(last_line_num)
535
536 if b:PHP_BracesAtCodeLevel
537 let ind = ind + &sw
538 endif
539
540 return ind
541 endif
542
543 let last_line_num = last_line_num - 1
544 let previous_line = getline(last_line_num)
545 endwhile
546
547 elseif last_line =~# unstated && cline !~ '^\s*{\|^\s*);\='.endline
548 let ind = ind + &sw
549 return ind
550
551 elseif ind != b:PHP_default_indenting && last_line =~ terminated
552 let previous_line = last_line
553 let last_line_num = lnum
554 let LastLineClosed = 1
555
556 while 1
557 if previous_line =~ '^\s*}'
558 let last_line_num = FindOpenBracket(last_line_num)
559
560 if getline(last_line_num) =~ '^\s*{'
561 let last_line_num = GetLastRealCodeLNum(last_line_num - 1)
562 endif
563
564 let previous_line = getline(last_line_num)
565
566 continue
567 else
568
569 if getline(last_line_num) =~# '^\s*else\%(if\)\=\>'
570 let last_line_num = FindTheIfOfAnElse(last_line_num, 0)
571 continue
572 endif
573
574
575 let last_match = last_line_num
576
577 let one_ahead_indent = indent(last_line_num)
578 let last_line_num = GetLastRealCodeLNum(last_line_num - 1)
579 let two_ahead_indent = indent(last_line_num)
580 let after_previous_line = previous_line
581 let previous_line = getline(last_line_num)
582
583
584 if previous_line =~# defaultORcase.'\|{'.endline
585 break
586 endif
587
588 if after_previous_line=~# '^\s*'.s:blockstart.'.*)'.endline && previous_line =~# '[;}]'.endline
589 break
590 endif
591
592 if one_ahead_indent == two_ahead_indent || last_line_num < 1
593 if previous_line =~# '[;}]'.endline || last_line_num < 1
594 break
595 endif
596 endif
597 endif
598 endwhile
599
600 if indent(last_match) != ind
601 let ind = indent(last_match)
602 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
603
604 if cline =~# defaultORcase
605 let ind = ind - &sw
606 endif
607 return ind
608 endif
609 endif
610
611 let plinnum = GetLastRealCodeLNum(lnum - 1)
612 let pline = getline(plinnum)
613
614 let last_line = substitute(last_line,"\\(//\\|#\\)\\(\\(\\([^\"']*\\([\"']\\)[^\"']*\\5\\)\\+[^\"']*$\\)\\|\\([^\"']*$\\)\\)",'','')
615
616
617 if ind == b:PHP_default_indenting
618 if last_line =~ terminated
619 let LastLineClosed = 1
620 endif
621 endif
622
623 if !LastLineClosed
624
625 if last_line =~# '[{(]'.endline || last_line =~? '\h\w*\s*(.*,$' && pline !~ '[,(]'.endline
626
627 if !b:PHP_BracesAtCodeLevel || last_line !~# '^\s*{'
628 let ind = ind + &sw
629 endif
630
631 if b:PHP_BracesAtCodeLevel || cline !~# defaultORcase
632 let b:PHP_CurrentIndentLevel = ind
510 return ind 633 return ind
511 endif 634 endif
512 635
513 if cline =~ '^\s*\*/' " End comment tags must be indented like start comment tags 636 elseif last_line =~ '\S\+\s*),'.endline
514 call cursor(v:lnum, 1) 637 call cursor(lnum, 1)
515 call search('\*/\zs', 'W') 638 call search('),'.endline, 'W')
516 let lnum = searchpair('/\*', '', '\*/\zs', s:searchpairflags) " find the most outside /* 639 let openedparent = searchpair('(', '', ')', 'bW', 'Skippmatch()')
517 640 if openedparent != lnum
518 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting 641 let ind = indent(openedparent)
519 642 endif
520 if cline =~ '^\s*\*/' 643
521 return indent(lnum) + 1 644
522 else 645 elseif cline !~ '^\s*{' && pline =~ '\%(;\%(\s*?>\)\=\|<<<\a\w*\|{\|^\s*'.s:blockstart.'\s*(.*)\)'.endline.'\|^\s*}\|'.defaultORcase
523 return indent(lnum) 646
524 endif 647 let ind = ind + &sw
525 endif 648
526 649 endif
527 let defaultORcase = '^\s*\%(default\|case\).*:' 650
528 651 elseif last_line =~# defaultORcase
529 if last_line =~ '[;}]'.endline && last_line !~# defaultORcase 652 let ind = ind + &sw
530 if ind==b:PHP_default_indenting " if no indentation for the previous line 653 endif
531 return b:PHP_default_indenting 654
532 elseif b:PHP_indentinghuge && ind==b:PHP_CurrentIndentLevel && cline !~# '^\s*\%(else\|\%(case\|default\).*:\|[})];\=\)' && last_line !~# '^\s*\%(\%(}\s*\)\=else\)' && getline(GetLastRealCodeLNum(lnum - 1))=~';'.endline 655 if cline =~ '^\s*);\='
533 return b:PHP_CurrentIndentLevel 656 let ind = ind - &sw
534 endif 657 elseif cline =~# defaultORcase
535 endif 658 let ind = ind - &sw
536 659
537 let LastLineClosed = 0 " used to prevent redundant tests in the last part of the script 660 endif
538 661
539 let terminated = '\%(;\%(\s*?>\)\=\|<<<\a\w*\|}\)'.endline 662 let b:PHP_CurrentIndentLevel = ind
540 663 return ind
541 let unstated = '\%(^\s*'.s:blockstart.'.*)\|\%(//.*\)\@<!\<e'.'lse\>\)'.endline
542
543 if ind != b:PHP_default_indenting && cline =~# '^\s*else\%(if\)\=\>'
544 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting " prevent optimized to work at next call
545 return indent(FindTheIfOfAnElse(v:lnum, 1))
546 elseif last_line =~# unstated && cline !~ '^\s*{\|^\s*);\='.endline
547 let ind = ind + &sw
548 return ind
549
550
551 elseif ind != b:PHP_default_indenting && last_line =~ terminated
552 let previous_line = last_line
553 let last_line_num = lnum
554 let LastLineClosed = 1
555
556
557 while 1
558 if previous_line =~ '^\s*}'
559 let last_line_num = FindOpenBracket(last_line_num)
560
561 if getline(last_line_num) =~ '^\s*{'
562 let last_line_num = GetLastRealCodeLNum(last_line_num - 1)
563 endif
564
565 let previous_line = getline(last_line_num)
566
567 continue
568 else
569 if getline(last_line_num) =~# '^\s*else\%(if\)\=\>'
570 let last_line_num = FindTheIfOfAnElse(last_line_num, 0)
571 continue " re-run the loop (we could find a '}' again)
572 endif
573
574
575 let last_match = last_line_num " remember the 'topest' line we found so far
576
577 let one_ahead_indent = indent(last_line_num)
578 let last_line_num = GetLastRealCodeLNum(last_line_num - 1)
579 let two_ahead_indent = indent(last_line_num)
580 let after_previous_line = previous_line
581 let previous_line = getline(last_line_num)
582
583
584 if previous_line =~# defaultORcase.'\|{'.endline
585 break
586 endif
587
588 if after_previous_line=~# '^\s*'.s:blockstart.'.*)'.endline && previous_line =~# '[;}]'.endline
589 break
590 endif
591
592 if one_ahead_indent == two_ahead_indent || last_line_num < 1
593 if previous_line =~# '[;}]'.endline || last_line_num < 1
594 break
595 endif
596 endif
597 endif
598 endwhile
599
600 if indent(last_match) != ind " if nothing was done lets the old script continue
601 let ind = indent(last_match) " let's use the indent of the last line matched by the alhorithm above
602 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting " line added in version 1.02 to prevent optimized mode
603 " from acting in some special cases
604
605 if cline =~# defaultORcase
606 let ind = ind - &sw
607 endif
608 return ind
609 endif
610 endif
611
612 let plinnum = GetLastRealCodeLNum(lnum - 1)
613 let pline = getline(plinnum) " previous to last line
614
615 let last_line = substitute(last_line,"\\(//\\|#\\)\\(\\(\\([^\"']*\\([\"']\\)[^\"']*\\5\\)\\+[^\"']*$\\)\\|\\([^\"']*$\\)\\)",'','')
616
617
618 if ind == b:PHP_default_indenting
619 if last_line =~ terminated
620 let LastLineClosed = 1
621 endif
622 endif
623
624 if !LastLineClosed " the last line isn't a .*; or a }$ line
625 if last_line =~# '[{(]'.endline || last_line =~? '\h\w*\s*(.*,$' && pline !~ '[,(]'.endline
626
627 if !b:PHP_BracesAtCodeLevel || last_line !~# '^\s*{' " XXX mod {
628 let ind = ind + &sw
629 endif
630
631 if b:PHP_BracesAtCodeLevel || cline !~# defaultORcase " XXX mod (2) {
632 " case and default are not indented inside blocks
633 let b:PHP_CurrentIndentLevel = ind
634 return ind
635 endif
636
637 elseif last_line =~ '\S\+\s*),'.endline
638 call cursor(lnum, 1)
639 call search('),'.endline, 'W')
640 let openedparent = searchpair('(', '', ')', 'bW', 'Skippmatch()')
641 if openedparent != lnum
642 let ind = indent(openedparent)
643 endif
644
645 elseif cline !~ '^\s*{' && pline =~ '\%(;\%(\s*?>\)\=\|<<<\a\w*\|{\|^\s*'.s:blockstart.'\s*(.*)\)'.endline.'\|^\s*}\|'.defaultORcase
646
647 let ind = ind + &sw
648
649 endif
650 if b:PHP_BracesAtCodeLevel && cline =~# '^\s*{' " XXX mod {
651 let ind = ind + &sw
652 endif
653
654 elseif last_line =~# defaultORcase
655 let ind = ind + &sw
656 endif
657
658 if cline =~ '^\s*);\='
659 let ind = ind - &sw
660 elseif cline =~# defaultORcase
661 let ind = ind - &sw
662
663 endif
664
665 let b:PHP_CurrentIndentLevel = ind
666 return ind
667 endfunction 664 endfunction
668 665
669 " vim: set ts=4 sw=4: 666 " vim: set ts=8 sw=4 sts=4:
670 " vim: set ff=unix: