blob: 377ffd5afb3f0230a65b7e51e9c331ebd75eaf0c [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001" Vim indent file
2" Language: PHP
Bram Moolenaar54775062019-07-31 21:07:14 +02003" Author: John Wellesz <John.wellesz (AT) gmail (DOT) com>
4" URL: https://www.2072productions.com/vim/indent/php.vim
Bram Moolenaare6ae6222013-05-21 21:01:10 +02005" Home: https://github.com/2072/PHP-Indenting-for-VIm
John Wellesz31703422023-09-04 22:22:19 +02006" Last Change: 2023 August 18th
7" Version: 1.75
Bram Moolenaar071d4272004-06-13 20:20:40 +00008"
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00009"
Bram Moolenaare6ae6222013-05-21 21:01:10 +020010" Type :help php-indent for available options
11"
12" A fully commented version of this file is available on github
Bram Moolenaara5792f52005-11-23 21:25:05 +000013"
14"
Bram Moolenaar259f26a2018-05-15 22:25:40 +020015" If you find a bug, please open a ticket on github.com
Bram Moolenaare6ae6222013-05-21 21:01:10 +020016" ( https://github.com/2072/PHP-Indenting-for-VIm/issues ) with an example of
17" code that breaks the algorithm.
Bram Moolenaar9ff70112005-07-11 22:29:03 +000018"
Bram Moolenaare6ae6222013-05-21 21:01:10 +020019
Bram Moolenaar9ff70112005-07-11 22:29:03 +000020" NOTE: This script must be used with PHP syntax ON and with the php syntax
Bram Moolenaare6ae6222013-05-21 21:01:10 +020021" script by Lutz Eymers (http://www.isp.de/data/php.vim ) or with the
Bram Moolenaar54775062019-07-31 21:07:14 +020022" script by Peter Hodge (https://www.vim.org/scripts/script.php?script_id=1571 )
Bram Moolenaar5c736222010-01-06 20:54:52 +010023" the later is bunbdled by default with Vim 7.
Bram Moolenaar9ff70112005-07-11 22:29:03 +000024"
25"
Bram Moolenaarc236c162008-07-13 17:41:49 +000026" In the case you have syntax errors in your script such as HereDoc end
27" identifiers not at col 1 you'll have to indent your file 2 times (This
28" script will automatically put HereDoc end identifiers at col 1 if
29" they are followed by a ';').
Bram Moolenaarc9b4b052006-04-30 18:54:39 +000030"
Bram Moolenaare6ae6222013-05-21 21:01:10 +020031
Bram Moolenaar5c736222010-01-06 20:54:52 +010032" NOTE: If you are editing files in Unix file format and that (by accident)
33" there are '\r' before new lines, this script won't be able to proceed
34" correctly and will make many mistakes because it won't be able to match
35" '\s*$' correctly.
36" So you have to remove those useless characters first with a command like:
Bram Moolenaar9ff70112005-07-11 22:29:03 +000037"
Bram Moolenaar5c736222010-01-06 20:54:52 +010038" :%s /\r$//g
Bram Moolenaar9ff70112005-07-11 22:29:03 +000039"
Bram Moolenaar5c736222010-01-06 20:54:52 +010040" or simply 'let' the option PHP_removeCRwhenUnix to 1 and the script will
41" silently remove them when VIM load this script (at each bufread).
Bram Moolenaarbcb98982014-05-01 14:08:19 +020042
43
Bram Moolenaar071d4272004-06-13 20:20:40 +000044if exists("b:did_indent")
Bram Moolenaar1e015462005-09-25 22:16:38 +000045 finish
Bram Moolenaar071d4272004-06-13 20:20:40 +000046endif
47let b:did_indent = 1
48
Bram Moolenaar9ff70112005-07-11 22:29:03 +000049
Bram Moolenaared32d942014-12-06 23:33:00 +010050let g:php_sync_method = 0
Bram Moolenaar9ff70112005-07-11 22:29:03 +000051
Bram Moolenaare6ae6222013-05-21 21:01:10 +020052
Bram Moolenaar9ff70112005-07-11 22:29:03 +000053if exists("PHP_default_indenting")
Bram Moolenaar3ec574f2017-06-13 18:12:01 +020054 let b:PHP_default_indenting = PHP_default_indenting * shiftwidth()
Bram Moolenaar9ff70112005-07-11 22:29:03 +000055else
Bram Moolenaar1e015462005-09-25 22:16:38 +000056 let b:PHP_default_indenting = 0
Bram Moolenaar9ff70112005-07-11 22:29:03 +000057endif
58
Bram Moolenaare6ae6222013-05-21 21:01:10 +020059if exists("PHP_outdentSLComments")
Bram Moolenaar3ec574f2017-06-13 18:12:01 +020060 let b:PHP_outdentSLComments = PHP_outdentSLComments * shiftwidth()
Bram Moolenaare6ae6222013-05-21 21:01:10 +020061else
62 let b:PHP_outdentSLComments = 0
63endif
64
Bram Moolenaar9ff70112005-07-11 22:29:03 +000065if exists("PHP_BracesAtCodeLevel")
Bram Moolenaar1e015462005-09-25 22:16:38 +000066 let b:PHP_BracesAtCodeLevel = PHP_BracesAtCodeLevel
Bram Moolenaar9ff70112005-07-11 22:29:03 +000067else
Bram Moolenaar1e015462005-09-25 22:16:38 +000068 let b:PHP_BracesAtCodeLevel = 0
Bram Moolenaar9ff70112005-07-11 22:29:03 +000069endif
70
Bram Moolenaarc236c162008-07-13 17:41:49 +000071
Bram Moolenaara5792f52005-11-23 21:25:05 +000072if exists("PHP_autoformatcomment")
73 let b:PHP_autoformatcomment = PHP_autoformatcomment
74else
75 let b:PHP_autoformatcomment = 1
76endif
Bram Moolenaar9ff70112005-07-11 22:29:03 +000077
Bram Moolenaar8408a9a2010-07-30 22:41:22 +020078if exists("PHP_outdentphpescape")
79 let b:PHP_outdentphpescape = PHP_outdentphpescape
80else
81 let b:PHP_outdentphpescape = 1
82endif
83
Bram Moolenaar0b0f0992018-05-22 21:41:30 +020084if exists("PHP_noArrowMatching")
85 let b:PHP_noArrowMatching = PHP_noArrowMatching
86else
87 let b:PHP_noArrowMatching = 0
88endif
89
Bram Moolenaar8408a9a2010-07-30 22:41:22 +020090
91if exists("PHP_vintage_case_default_indent") && PHP_vintage_case_default_indent
92 let b:PHP_vintage_case_default_indent = 1
Bram Moolenaarc236c162008-07-13 17:41:49 +000093else
94 let b:PHP_vintage_case_default_indent = 0
95endif
96
Bram Moolenaar54775062019-07-31 21:07:14 +020097if exists("PHP_IndentFunctionCallParameters")
98 let b:PHP_IndentFunctionCallParameters = PHP_IndentFunctionCallParameters
99else
100 let b:PHP_IndentFunctionCallParameters = 0
101endif
Bram Moolenaarc236c162008-07-13 17:41:49 +0000102
Bram Moolenaar54775062019-07-31 21:07:14 +0200103if exists("PHP_IndentFunctionDeclarationParameters")
104 let b:PHP_IndentFunctionDeclarationParameters = PHP_IndentFunctionDeclarationParameters
105else
106 let b:PHP_IndentFunctionDeclarationParameters = 0
107endif
Bram Moolenaarc236c162008-07-13 17:41:49 +0000108
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000109let b:PHP_lastindented = 0
110let b:PHP_indentbeforelast = 0
111let b:PHP_indentinghuge = 0
112let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
113let b:PHP_LastIndentedWasComment = 0
114let b:PHP_InsideMultilineComment = 0
115let b:InPHPcode = 0
116let b:InPHPcode_checked = 0
117let b:InPHPcode_and_script = 0
118let b:InPHPcode_tofind = ""
119let b:PHP_oldchangetick = b:changedtick
120let b:UserIsTypingComment = 0
121let b:optionsset = 0
122
123setlocal nosmartindent
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000124setlocal noautoindent
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000125setlocal nocindent
Bram Moolenaar1e015462005-09-25 22:16:38 +0000126setlocal nolisp
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000127
Bram Moolenaar071d4272004-06-13 20:20:40 +0000128setlocal indentexpr=GetPhpIndent()
Bram Moolenaared32d942014-12-06 23:33:00 +0100129setlocal indentkeys=0{,0},0),0],:,!^F,o,O,e,*<Return>,=?>,=<?,=*/
Bram Moolenaar071d4272004-06-13 20:20:40 +0000130
dkearns0382f052023-08-29 05:32:59 +1000131let b:undo_indent = "setl ai< cin< inde< indk< lisp< si<"
Bram Moolenaar1e015462005-09-25 22:16:38 +0000132
133let s:searchpairflags = 'bWr'
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000134
135if &fileformat == "unix" && exists("PHP_removeCRwhenUnix") && PHP_removeCRwhenUnix
Bram Moolenaar1e015462005-09-25 22:16:38 +0000136 silent! %s/\r$//g
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000137endif
138
Bram Moolenaar071d4272004-06-13 20:20:40 +0000139if exists("*GetPhpIndent")
Bram Moolenaar5c736222010-01-06 20:54:52 +0100140 call ResetPhpOptions()
Bram Moolenaar54775062019-07-31 21:07:14 +0200141 finish " XXX -- comment this line for easy dev
Bram Moolenaar071d4272004-06-13 20:20:40 +0000142endif
143
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200144
John Wellesz31703422023-09-04 22:22:19 +0200145let s:endline = '\s*\%(//.*\|#\[\@!.*\|/\*.*\*/\s*\)\=$'
Bram Moolenaar54775062019-07-31 21:07:14 +0200146let s:PHP_validVariable = '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*'
John Wellesz31703422023-09-04 22:22:19 +0200147let s:notPhpHereDoc = '\<\%(break\|return\|continue\|exit\|die\|true\|false\|elseif\|else\|end\%(if\|while\|for\|foreach\|match\|switch\)\)\>'
148let s:blockstart = '\%(\%(\%(}\s*\)\=else\%(\s\+\)\=\)\=if\>\|\%(}\s*\)\?else\>\|do\>\|while\>\|match\>\|switch\>\|case\>\|default\>\|for\%(each\)\=\>\|declare\>\|class\>\|trait\>\|\%()\s*\)\=use\>\|interface\>\|abstract\>\|final\>\|try\>\|\%(}\s*\)\=catch\>\|\%(}\s*\)\=finally\>\)'
Bram Moolenaar54775062019-07-31 21:07:14 +0200149let s:functionDeclPrefix = '\<function\>\%(\s\+&\='.s:PHP_validVariable.'\)\=\s*('
150let s:functionDecl = s:functionDeclPrefix.'.*'
151let s:multilineFunctionDecl = s:functionDeclPrefix.s:endline
152let s:arrayDecl = '\<array\>\s*(.*'
153let s:multilineFunctionCall = s:PHP_validVariable.'\s*('.s:endline
Bram Moolenaare0720cb2017-03-29 13:48:40 +0200154let s:unstated = '\%(^\s*'.s:blockstart.'.*)\|\%(//.*\)\@<!\<e'.'lse\>\)'.s:endline
Bram Moolenaared32d942014-12-06 23:33:00 +0100155
156
Bram Moolenaare0720cb2017-03-29 13:48:40 +0200157let s:terminated = '\%(\%(;\%(\s*\%(?>\|}\)\)\=\|<<<\s*[''"]\=\a\w*[''"]\=$\|^\s*}\|^\s*'.s:PHP_validVariable.':\)'.s:endline.'\)'
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000158let s:PHP_startindenttag = '<?\%(.*?>\)\@!\|<script[^>]*>\%(.*<\/script>\)\@!'
John Wellesz31703422023-09-04 22:22:19 +0200159let s:matchStart = 'match\s*(\s*\$\?'.s:PHP_validVariable.'\s*)\s*{'. s:endline
160let s:structureHead = '^\s*\%(' . s:blockstart . '\)\|'. s:functionDecl . s:endline . '\|\<new\s\+class\>\|' . s:matchStart
Bram Moolenaar071d4272004-06-13 20:20:40 +0000161
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000162
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200163let s:escapeDebugStops = 0
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200164function! DebugPrintReturn(scriptLine)
165
Bram Moolenaared32d942014-12-06 23:33:00 +0100166 if ! s:escapeDebugStops
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200167 echo "debug:" . a:scriptLine
168 let c = getchar()
169 if c == "\<Del>"
170 let s:escapeDebugStops = 1
171 end
172 endif
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200173
174endfunction
175
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000176function! GetLastRealCodeLNum(startline) " {{{
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000177
Bram Moolenaar1e015462005-09-25 22:16:38 +0000178 let lnum = a:startline
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000179
Bram Moolenaar05a7bb32006-01-19 22:09:32 +0000180 if b:GetLastRealCodeLNum_ADD && b:GetLastRealCodeLNum_ADD == lnum + 1
181 let lnum = b:GetLastRealCodeLNum_ADD
182 endif
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000183
Bram Moolenaar1e015462005-09-25 22:16:38 +0000184 while lnum > 1
185 let lnum = prevnonblank(lnum)
186 let lastline = getline(lnum)
187
188 if b:InPHPcode_and_script && lastline =~ '?>\s*$'
189 let lnum = lnum - 1
190 elseif lastline =~ '^\s*?>.*<?\%(php\)\=\s*$'
191 let lnum = lnum - 1
192 elseif lastline =~ '^\s*\%(//\|#\|/\*.*\*/\s*$\)'
193 let lnum = lnum - 1
194 elseif lastline =~ '\*/\s*$'
195 call cursor(lnum, 1)
196 if lastline !~ '^\*/'
197 call search('\*/', 'W')
198 endif
Bram Moolenaara5792f52005-11-23 21:25:05 +0000199 let lnum = searchpair('/\*', '', '\*/', s:searchpairflags, 'Skippmatch2()')
Bram Moolenaar1e015462005-09-25 22:16:38 +0000200
201 let lastline = getline(lnum)
202 if lastline =~ '^\s*/\*'
203 let lnum = lnum - 1
204 else
205 break
206 endif
207
208
209 elseif lastline =~? '\%(//\s*\|?>.*\)\@<!<?\%(php\)\=\s*$\|^\s*<script\>'
210
211 while lastline !~ '\(<?.*\)\@<!?>' && lnum > 1
212 let lnum = lnum - 1
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000213 let lastline = getline(lnum)
Bram Moolenaar1e015462005-09-25 22:16:38 +0000214 endwhile
215 if lastline =~ '^\s*?>'
216 let lnum = lnum - 1
217 else
218 break
219 endif
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000220
221
Bram Moolenaar8408a9a2010-07-30 22:41:22 +0200222 elseif lastline =~? '^\a\w*;\=$' && lastline !~? s:notPhpHereDoc
Bram Moolenaarcbebd482016-02-07 23:02:56 +0100223 let tofind=substitute( lastline, '\(\a\w*\);\=', '<<<\\s*[''"]\\=\1[''"]\\=$', '')
Bram Moolenaar1e015462005-09-25 22:16:38 +0000224 while getline(lnum) !~? tofind && lnum > 1
225 let lnum = lnum - 1
226 endwhile
John Wellesz31703422023-09-04 22:22:19 +0200227 elseif lastline =~ '^\s*[''"`][;,]'.s:endline || (lastline =~ '^[^''"`]*[''"`][;,]'.s:endline && IslinePHP(lnum, "") == "SpecStringEntrails")
Bram Moolenaare0720cb2017-03-29 13:48:40 +0200228
229 let tofind=substitute( lastline, '^.*\([''"`]\)[;,].*$', '^[^\1]\\+[\1]$\\|^[^\1]\\+[=([]\\s*[\1]', '')
230 let trylnum = lnum
231 while getline(trylnum) !~? tofind && trylnum > 1
232 let trylnum = trylnum - 1
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200233 endwhile
Bram Moolenaare0720cb2017-03-29 13:48:40 +0200234
235 if trylnum == 1
236 break
237 else
238 if lastline =~ ';'.s:endline
239 while getline(trylnum) !~? s:terminated && getline(trylnum) !~? '{'.s:endline && trylnum > 1
240 let trylnum = prevnonblank(trylnum - 1)
241 endwhile
242
243
244 if trylnum == 1
245 break
246 end
247 end
248 let lnum = trylnum
249 end
Bram Moolenaar1e015462005-09-25 22:16:38 +0000250 else
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000251 break
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000252 endif
Bram Moolenaar1e015462005-09-25 22:16:38 +0000253 endwhile
254
Bram Moolenaar8408a9a2010-07-30 22:41:22 +0200255 if lnum==1 && getline(lnum) !~ '<?'
Bram Moolenaar1e015462005-09-25 22:16:38 +0000256 let lnum=0
257 endif
258
Bram Moolenaared32d942014-12-06 23:33:00 +0100259 if b:InPHPcode_and_script && 1 > b:InPHPcode
Bram Moolenaar1e015462005-09-25 22:16:38 +0000260 let b:InPHPcode_and_script = 0
261 endif
Bram Moolenaard5ab34b2007-05-05 17:15:44 +0000262
Bram Moolenaar1e015462005-09-25 22:16:38 +0000263 return lnum
264endfunction " }}}
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000265
Bram Moolenaara5792f52005-11-23 21:25:05 +0000266function! Skippmatch2()
267
268 let line = getline(".")
269
John Wellesz31703422023-09-04 22:22:19 +0200270 if line =~ "\\([\"']\\).*/\\*.*\\1" || line =~ '\%(//\|#\[\@!\).*/\*'
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200271 return 1
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200272 else
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200273 return 0
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200274 endif
Bram Moolenaara5792f52005-11-23 21:25:05 +0000275endfun
276
Bram Moolenaar8408a9a2010-07-30 22:41:22 +0200277function! Skippmatch() " {{{
Bram Moolenaar1e015462005-09-25 22:16:38 +0000278 let synname = synIDattr(synID(line("."), col("."), 0), "name")
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200279 if synname ==? "Delimiter" || synname ==? "phpRegionDelimiter" || synname =~? "^phpParent" || synname ==? "phpArrayParens" || synname =~? '^php\%(Block\|Brace\)' || synname ==? "javaScriptBraces" || synname =~? '^php\%(Doc\)\?Comment' && b:UserIsTypingComment
Bram Moolenaar1e015462005-09-25 22:16:38 +0000280 return 0
281 else
282 return 1
283 endif
284endfun " }}}
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000285
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200286function! FindOpenBracket(lnum, blockStarter) " {{{
Bram Moolenaar1e015462005-09-25 22:16:38 +0000287 call cursor(a:lnum, 1)
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200288 let line = searchpair('{', '', '}', 'bW', 'Skippmatch()')
289
290 if a:blockStarter == 1
Bram Moolenaared32d942014-12-06 23:33:00 +0100291 while line > 1
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200292 let linec = getline(line)
293
Bram Moolenaare0720cb2017-03-29 13:48:40 +0200294 if linec =~ s:terminated || linec =~ s:structureHead
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200295 break
296 endif
297
298 let line = GetLastRealCodeLNum(line - 1)
299 endwhile
300 endif
301
302 return line
Bram Moolenaar1e015462005-09-25 22:16:38 +0000303endfun " }}}
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000304
Bram Moolenaare0720cb2017-03-29 13:48:40 +0200305let s:blockChars = {'{':1, '[': 1, '(': 1, ')':-1, ']':-1, '}':-1}
Bram Moolenaar54775062019-07-31 21:07:14 +0200306let s:blockCharsLUT = {'{':'{', '}':'{', '[':'[', ']':'[', '(':'(', ')':'('}
Bram Moolenaare0720cb2017-03-29 13:48:40 +0200307function! BalanceDirection (str)
308
Bram Moolenaar54775062019-07-31 21:07:14 +0200309 let balance = {'{':0, '[': 0, '(': 0, 'none':0}
310 let director = 'none'
Bram Moolenaare0720cb2017-03-29 13:48:40 +0200311
312 for c in split(a:str, '\zs')
313 if has_key(s:blockChars, c)
Bram Moolenaar54775062019-07-31 21:07:14 +0200314 let balance[s:blockCharsLUT[c]] += s:blockChars[c]
315
316 if balance[s:blockCharsLUT[c]]
317 let director = s:blockCharsLUT[c]
318 endif
Bram Moolenaare0720cb2017-03-29 13:48:40 +0200319 endif
320 endfor
321
Bram Moolenaar54775062019-07-31 21:07:14 +0200322 return balance[director]
Bram Moolenaare0720cb2017-03-29 13:48:40 +0200323endfun
324
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200325function! StripEndlineComments (line)
John Wellesz31703422023-09-04 22:22:19 +0200326
327 let cleaned = substitute(a:line,'\v(//|#\[\@!)((([^"'']*(["''])[^"'']*\5)+[^"'']*$)|([^"'']*$))','','')
328 if cleaned != a:line
329 endif
330 return cleaned
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200331endfun
332
333function! FindArrowIndent (lnum) " {{{
334
Viktor Szépe3fc7a7e2023-08-23 21:20:00 +0200335 let parentArrowPos = -1
Bram Moolenaar54775062019-07-31 21:07:14 +0200336 let cursorPos = -1
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200337 let lnum = a:lnum
338 while lnum > 1
339 let last_line = getline(lnum)
340 if last_line =~ '^\s*->'
Viktor Szépe3fc7a7e2023-08-23 21:20:00 +0200341 let parentArrowPos = indent(a:lnum)
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200342 break
343 else
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200344
Bram Moolenaar54775062019-07-31 21:07:14 +0200345 if b:PHP_noArrowMatching
346 break
347 endif
348
349 let cleanedLnum = StripEndlineComments(last_line)
350
351 if cleanedLnum =~ ')'.s:endline
352 if BalanceDirection(cleanedLnum) <= 0
353 call cursor(lnum, 1)
354 call searchpos(')'.s:endline, 'cW', lnum)
355 let openedparent = searchpair('(', '', ')', 'bW', 'Skippmatch()')
356 let cursorPos = col(".")
357 if openedparent != lnum
358 let lnum = openedparent
359 continue
360 else
361 endif
362 else
Viktor Szépe3fc7a7e2023-08-23 21:20:00 +0200363 let parentArrowPos = -1
Bram Moolenaar54775062019-07-31 21:07:14 +0200364 break
365 end
366 endif
367
368 if cleanedLnum =~ '->'
369 call cursor(lnum, cursorPos == -1 ? strwidth(cleanedLnum) : cursorPos)
Viktor Szépe3fc7a7e2023-08-23 21:20:00 +0200370 let parentArrowPos = searchpos('->', 'cWb', lnum)[1] - 1
Bram Moolenaar54775062019-07-31 21:07:14 +0200371
372 break
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200373 else
Viktor Szépe3fc7a7e2023-08-23 21:20:00 +0200374 let parentArrowPos = -1
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200375 break
376 endif
377 endif
378 endwhile
379
Viktor Szépe3fc7a7e2023-08-23 21:20:00 +0200380 if parentArrowPos == -1
381 let parentArrowPos = indent(lnum) + shiftwidth()
Bram Moolenaar54775062019-07-31 21:07:14 +0200382 end
383
Viktor Szépe3fc7a7e2023-08-23 21:20:00 +0200384 return parentArrowPos
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200385endfun "}}}
386
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000387function! FindTheIfOfAnElse (lnum, StopAfterFirstPrevElse) " {{{
Bram Moolenaar1e015462005-09-25 22:16:38 +0000388
389 if getline(a:lnum) =~# '^\s*}\s*else\%(if\)\=\>'
390 let beforeelse = a:lnum
391 else
392 let beforeelse = GetLastRealCodeLNum(a:lnum - 1)
393 endif
394
395 if !s:level
396 let s:iftoskip = 0
397 endif
398
399 if getline(beforeelse) =~# '^\s*\%(}\s*\)\=else\%(\s*if\)\@!\>'
400 let s:iftoskip = s:iftoskip + 1
401 endif
402
403 if getline(beforeelse) =~ '^\s*}'
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200404 let beforeelse = FindOpenBracket(beforeelse, 0)
Bram Moolenaar1e015462005-09-25 22:16:38 +0000405
406 if getline(beforeelse) =~ '^\s*{'
407 let beforeelse = GetLastRealCodeLNum(beforeelse - 1)
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000408 endif
Bram Moolenaar1e015462005-09-25 22:16:38 +0000409 endif
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000410
411
Bram Moolenaar1e015462005-09-25 22:16:38 +0000412 if !s:iftoskip && a:StopAfterFirstPrevElse && getline(beforeelse) =~# '^\s*\%([}]\s*\)\=else\%(if\)\=\>'
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000413 return beforeelse
Bram Moolenaar1e015462005-09-25 22:16:38 +0000414 endif
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000415
Bram Moolenaar1e015462005-09-25 22:16:38 +0000416 if getline(beforeelse) !~# '^\s*if\>' && beforeelse>1 || s:iftoskip && beforeelse>1
417
Bram Moolenaar8408a9a2010-07-30 22:41:22 +0200418 if s:iftoskip && getline(beforeelse) =~# '^\s*if\>'
Bram Moolenaar1e015462005-09-25 22:16:38 +0000419 let s:iftoskip = s:iftoskip - 1
420 endif
421
422 let s:level = s:level + 1
423 let beforeelse = FindTheIfOfAnElse(beforeelse, a:StopAfterFirstPrevElse)
424 endif
425
426 return beforeelse
427
428endfunction " }}}
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000429
Bram Moolenaar8408a9a2010-07-30 22:41:22 +0200430let s:defaultORcase = '^\s*\%(default\|case\).*:'
431
432function! FindTheSwitchIndent (lnum) " {{{
433
Bram Moolenaar8408a9a2010-07-30 22:41:22 +0200434 let test = GetLastRealCodeLNum(a:lnum - 1)
435
436 if test <= 1
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200437 return indent(1) - shiftwidth() * b:PHP_vintage_case_default_indent
Bram Moolenaar8408a9a2010-07-30 22:41:22 +0200438 end
439
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200440 while getline(test) =~ '^\s*}' && test > 1
441 let test = GetLastRealCodeLNum(FindOpenBracket(test, 0) - 1)
Bram Moolenaar8408a9a2010-07-30 22:41:22 +0200442
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200443 if getline(test) =~ '^\s*switch\>'
444 let test = GetLastRealCodeLNum(test - 1)
Bram Moolenaar8408a9a2010-07-30 22:41:22 +0200445 endif
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200446 endwhile
Bram Moolenaar8408a9a2010-07-30 22:41:22 +0200447
448 if getline(test) =~# '^\s*switch\>'
449 return indent(test)
450 elseif getline(test) =~# s:defaultORcase
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200451 return indent(test) - shiftwidth() * b:PHP_vintage_case_default_indent
Bram Moolenaar8408a9a2010-07-30 22:41:22 +0200452 else
453 return FindTheSwitchIndent(test)
454 endif
455
456endfunction "}}}
457
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200458let s:SynPHPMatchGroups = {'phpparent':1, 'delimiter':1, 'define':1, 'storageclass':1, 'structure':1, 'exception':1}
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000459function! IslinePHP (lnum, tofind) " {{{
Bram Moolenaar1e015462005-09-25 22:16:38 +0000460 let cline = getline(a:lnum)
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000461
Bram Moolenaar1e015462005-09-25 22:16:38 +0000462 if a:tofind==""
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200463 let tofind = "^\\s*[\"'`]*\\s*\\zs\\S"
Bram Moolenaar1e015462005-09-25 22:16:38 +0000464 else
465 let tofind = a:tofind
466 endif
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000467
Bram Moolenaar1e015462005-09-25 22:16:38 +0000468 let tofind = tofind . '\c'
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000469
Bram Moolenaar1e015462005-09-25 22:16:38 +0000470 let coltotest = match (cline, tofind) + 1
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000471
Bram Moolenaar1e015462005-09-25 22:16:38 +0000472 let synname = synIDattr(synID(a:lnum, coltotest, 0), "name")
473
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200474 if synname ==? 'phpStringSingle' || synname ==? 'phpStringDouble' || synname ==? 'phpBacktick'
Bram Moolenaar54775062019-07-31 21:07:14 +0200475 if cline !~ '^\s*[''"`]' " ??? XXX
Bram Moolenaared32d942014-12-06 23:33:00 +0100476 return "SpecStringEntrails"
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200477 else
478 return synname
479 end
480 end
481
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200482 if get(s:SynPHPMatchGroups, tolower(synname)) || synname =~ '^php' || synname =~? '^javaScript'
Bram Moolenaar1e015462005-09-25 22:16:38 +0000483 return synname
484 else
485 return ""
486 endif
487endfunction " }}}
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000488
Bram Moolenaar5c736222010-01-06 20:54:52 +0100489let s:autoresetoptions = 0
490if ! s:autoresetoptions
491 let s:autoresetoptions = 1
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000492endif
493
Bram Moolenaar5c736222010-01-06 20:54:52 +0100494function! ResetPhpOptions()
Bram Moolenaared32d942014-12-06 23:33:00 +0100495 if ! b:optionsset && &filetype =~ "php"
Bram Moolenaara5792f52005-11-23 21:25:05 +0000496 if b:PHP_autoformatcomment
497
John Wellesz31703422023-09-04 22:22:19 +0200498 setlocal comments=s1:/*,mb:*,ex:*/,://,f:#[,:#
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000499
Bram Moolenaarc236c162008-07-13 17:41:49 +0000500 setlocal formatoptions-=t
Bram Moolenaara5792f52005-11-23 21:25:05 +0000501 setlocal formatoptions+=q
502 setlocal formatoptions+=r
503 setlocal formatoptions+=o
Bram Moolenaara5792f52005-11-23 21:25:05 +0000504 setlocal formatoptions+=c
505 setlocal formatoptions+=b
506 endif
Bram Moolenaar1e015462005-09-25 22:16:38 +0000507 let b:optionsset = 1
508 endif
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000509endfunc
510
Bram Moolenaar5c736222010-01-06 20:54:52 +0100511call ResetPhpOptions()
512
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200513function! GetPhpIndentVersion()
John Wellesz31703422023-09-04 22:22:19 +0200514 return "1.75"
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200515endfun
516
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000517function! GetPhpIndent()
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000518
Bram Moolenaar05a7bb32006-01-19 22:09:32 +0000519 let b:GetLastRealCodeLNum_ADD = 0
520
Bram Moolenaar1e015462005-09-25 22:16:38 +0000521 let UserIsEditing=0
522 if b:PHP_oldchangetick != b:changedtick
523 let b:PHP_oldchangetick = b:changedtick
524 let UserIsEditing=1
525 endif
526
527 if b:PHP_default_indenting
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200528 let b:PHP_default_indenting = g:PHP_default_indenting * shiftwidth()
Bram Moolenaar1e015462005-09-25 22:16:38 +0000529 endif
530
531 let cline = getline(v:lnum)
532
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000533 if !b:PHP_indentinghuge && b:PHP_lastindented > b:PHP_indentbeforelast
Bram Moolenaar1e015462005-09-25 22:16:38 +0000534 if b:PHP_indentbeforelast
535 let b:PHP_indentinghuge = 1
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000536 endif
Bram Moolenaar1e015462005-09-25 22:16:38 +0000537 let b:PHP_indentbeforelast = b:PHP_lastindented
538 endif
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000539
Bram Moolenaar1e015462005-09-25 22:16:38 +0000540 if b:InPHPcode_checked && prevnonblank(v:lnum - 1) != b:PHP_lastindented
541 if b:PHP_indentinghuge
Bram Moolenaar1e015462005-09-25 22:16:38 +0000542 let b:PHP_indentinghuge = 0
543 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000544 endif
Bram Moolenaared32d942014-12-06 23:33:00 +0100545 let real_PHP_lastindented = v:lnum
Bram Moolenaar1e015462005-09-25 22:16:38 +0000546 let b:PHP_LastIndentedWasComment=0
547 let b:PHP_InsideMultilineComment=0
548 let b:PHP_indentbeforelast = 0
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000549
Bram Moolenaar1e015462005-09-25 22:16:38 +0000550 let b:InPHPcode = 0
551 let b:InPHPcode_checked = 0
552 let b:InPHPcode_and_script = 0
553 let b:InPHPcode_tofind = ""
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000554
Bram Moolenaar1e015462005-09-25 22:16:38 +0000555 elseif v:lnum > b:PHP_lastindented
556 let real_PHP_lastindented = b:PHP_lastindented
Bram Moolenaared32d942014-12-06 23:33:00 +0100557 else
558 let real_PHP_lastindented = v:lnum
Bram Moolenaar1e015462005-09-25 22:16:38 +0000559 endif
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000560
Bram Moolenaared32d942014-12-06 23:33:00 +0100561 let b:PHP_lastindented = v:lnum
562
Bram Moolenaar1e015462005-09-25 22:16:38 +0000563
564 if !b:InPHPcode_checked " {{{ One time check
565 let b:InPHPcode_checked = 1
Bram Moolenaarcbebd482016-02-07 23:02:56 +0100566 let b:UserIsTypingComment = 0
Bram Moolenaar1e015462005-09-25 22:16:38 +0000567
Bram Moolenaar05a7bb32006-01-19 22:09:32 +0000568 let synname = ""
569 if cline !~ '<?.*?>'
570 let synname = IslinePHP (prevnonblank(v:lnum), "")
571 endif
Bram Moolenaar1e015462005-09-25 22:16:38 +0000572
573 if synname!=""
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200574 if synname ==? "SpecStringEntrails"
Bram Moolenaare0720cb2017-03-29 13:48:40 +0200575 let b:InPHPcode = -1 " thumb down
Bram Moolenaared32d942014-12-06 23:33:00 +0100576 let b:InPHPcode_tofind = ""
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200577 elseif synname !=? "phpHereDoc" && synname !=? "phpHereDocDelimiter"
Bram Moolenaar1e015462005-09-25 22:16:38 +0000578 let b:InPHPcode = 1
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000579 let b:InPHPcode_tofind = ""
580
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200581 if synname =~? '^php\%(Doc\)\?Comment'
Bram Moolenaar1e015462005-09-25 22:16:38 +0000582 let b:UserIsTypingComment = 1
Bram Moolenaarcbebd482016-02-07 23:02:56 +0100583 let b:InPHPcode_checked = 0
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000584 endif
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000585
Bram Moolenaar1e015462005-09-25 22:16:38 +0000586 if synname =~? '^javaScript'
587 let b:InPHPcode_and_script = 1
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000588 endif
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000589
Bram Moolenaar1e015462005-09-25 22:16:38 +0000590 else
591 let b:InPHPcode = 0
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000592
Bram Moolenaar1e015462005-09-25 22:16:38 +0000593 let lnum = v:lnum - 1
Bram Moolenaarcbebd482016-02-07 23:02:56 +0100594 while getline(lnum) !~? '<<<\s*[''"]\=\a\w*[''"]\=$' && lnum > 1
Bram Moolenaar1e015462005-09-25 22:16:38 +0000595 let lnum = lnum - 1
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000596 endwhile
597
Bram Moolenaarcbebd482016-02-07 23:02:56 +0100598 let b:InPHPcode_tofind = substitute( getline(lnum), '^.*<<<\s*[''"]\=\(\a\w*\)[''"]\=$', '^\\s*\1;\\=$', '')
Bram Moolenaar1e015462005-09-25 22:16:38 +0000599 endif
600 else
601 let b:InPHPcode = 0
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200602 let b:InPHPcode_tofind = s:PHP_startindenttag
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000603 endif
Bram Moolenaar1e015462005-09-25 22:16:38 +0000604 endif "!b:InPHPcode_checked }}}
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000605
606
Bram Moolenaar1e015462005-09-25 22:16:38 +0000607 " Test if we are indenting PHP code {{{
608 let lnum = prevnonblank(v:lnum - 1)
609 let last_line = getline(lnum)
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200610 let endline= s:endline
Bram Moolenaar1e015462005-09-25 22:16:38 +0000611
612 if b:InPHPcode_tofind!=""
613 if cline =~? b:InPHPcode_tofind
Bram Moolenaar1e015462005-09-25 22:16:38 +0000614 let b:InPHPcode_tofind = ""
615 let b:UserIsTypingComment = 0
Bram Moolenaared32d942014-12-06 23:33:00 +0100616
617 if b:InPHPcode == -1
618 let b:InPHPcode = 1
619 return -1
620 end
621
622 let b:InPHPcode = 1
623
Bram Moolenaar1e015462005-09-25 22:16:38 +0000624 if cline =~ '\*/'
625 call cursor(v:lnum, 1)
626 if cline !~ '^\*/'
627 call search('\*/', 'W')
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000628 endif
Bram Moolenaara5792f52005-11-23 21:25:05 +0000629 let lnum = searchpair('/\*', '', '\*/', s:searchpairflags, 'Skippmatch2()')
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000630
Bram Moolenaar1e015462005-09-25 22:16:38 +0000631 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000632
Bram Moolenaar1e015462005-09-25 22:16:38 +0000633 let b:PHP_LastIndentedWasComment = 0
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000634
Bram Moolenaar1e015462005-09-25 22:16:38 +0000635 if cline =~ '^\s*\*/'
636 return indent(lnum) + 1
637 else
638 return indent(lnum)
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000639 endif
640
Bram Moolenaar1e015462005-09-25 22:16:38 +0000641 elseif cline =~? '<script\>'
642 let b:InPHPcode_and_script = 1
Bram Moolenaar05a7bb32006-01-19 22:09:32 +0000643 let b:GetLastRealCodeLNum_ADD = v:lnum
Bram Moolenaar1e015462005-09-25 22:16:38 +0000644 endif
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000645 endif
Bram Moolenaar1e015462005-09-25 22:16:38 +0000646 endif
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000647
Bram Moolenaared32d942014-12-06 23:33:00 +0100648 if 1 == b:InPHPcode
Bram Moolenaar1e015462005-09-25 22:16:38 +0000649
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200650 if !b:InPHPcode_and_script && last_line =~ '\%(<?.*\)\@<!?>\%(.*<?\)\@!' && IslinePHP(lnum, '?>')=~?"Delimiter"
Bram Moolenaar1e015462005-09-25 22:16:38 +0000651 if cline !~? s:PHP_startindenttag
652 let b:InPHPcode = 0
653 let b:InPHPcode_tofind = s:PHP_startindenttag
654 elseif cline =~? '<script\>'
655 let b:InPHPcode_and_script = 1
656 endif
657
John Wellesz31703422023-09-04 22:22:19 +0200658 elseif last_line =~ '^[^''"`]\+[''"`]$' && last_line !~ '^\s*\%(//\|#\[\@!\|/\*.*\*/\s*$\)' " a string identifier with nothing after it and no other string identifier before
Bram Moolenaared32d942014-12-06 23:33:00 +0100659 let b:InPHPcode = -1
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200660 let b:InPHPcode_tofind = substitute( last_line, '^.*\([''"`]\).*$', '^[^\1]*\1[;,]$', '')
Bram Moolenaarcbebd482016-02-07 23:02:56 +0100661 elseif last_line =~? '<<<\s*[''"]\=\a\w*[''"]\=$'
Bram Moolenaar1e015462005-09-25 22:16:38 +0000662 let b:InPHPcode = 0
Bram Moolenaarcbebd482016-02-07 23:02:56 +0100663 let b:InPHPcode_tofind = substitute( last_line, '^.*<<<\s*[''"]\=\(\a\w*\)[''"]\=$', '^\\s*\1;\\=$', '')
Bram Moolenaar1e015462005-09-25 22:16:38 +0000664
665 elseif !UserIsEditing && cline =~ '^\s*/\*\%(.*\*/\)\@!' && getline(v:lnum + 1) !~ '^\s*\*'
666 let b:InPHPcode = 0
667 let b:InPHPcode_tofind = '\*/'
668
669 elseif cline =~? '^\s*</script>'
670 let b:InPHPcode = 0
671 let b:InPHPcode_tofind = s:PHP_startindenttag
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000672 endif
Bram Moolenaar1e015462005-09-25 22:16:38 +0000673 endif " }}}
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000674
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000675
Bram Moolenaared32d942014-12-06 23:33:00 +0100676 if 1 > b:InPHPcode && !b:InPHPcode_and_script
Bram Moolenaar1e015462005-09-25 22:16:38 +0000677 return -1
678 endif
679
Bram Moolenaar1e015462005-09-25 22:16:38 +0000680 " Indent successive // or # comment the same way the first is {{{
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200681 let addSpecial = 0
John Wellesz31703422023-09-04 22:22:19 +0200682 if cline =~ '^\s*\%(//\|#\[\@!\|/\*.*\*/\s*$\)'
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200683 let addSpecial = b:PHP_outdentSLComments
Bram Moolenaar1e015462005-09-25 22:16:38 +0000684 if b:PHP_LastIndentedWasComment == 1
685 return indent(real_PHP_lastindented)
686 endif
687 let b:PHP_LastIndentedWasComment = 1
688 else
689 let b:PHP_LastIndentedWasComment = 0
690 endif " }}}
691
692 " Indent multiline /* comments correctly {{{
693
694 if b:PHP_InsideMultilineComment || b:UserIsTypingComment
695 if cline =~ '^\s*\*\%(\/\)\@!'
696 if last_line =~ '^\s*/\*'
697 return indent(lnum) + 1
698 else
699 return indent(lnum)
700 endif
701 else
702 let b:PHP_InsideMultilineComment = 0
703 endif
704 endif
705
Bram Moolenaared32d942014-12-06 23:33:00 +0100706 if !b:PHP_InsideMultilineComment && cline =~ '^\s*/\*\%(.*\*/\)\@!'
Bram Moolenaar05a7bb32006-01-19 22:09:32 +0000707 if getline(v:lnum + 1) !~ '^\s*\*'
708 return -1
709 endif
Bram Moolenaar1e015462005-09-25 22:16:38 +0000710 let b:PHP_InsideMultilineComment = 1
Bram Moolenaar1e015462005-09-25 22:16:38 +0000711 endif " }}}
712
713
714 " Things always indented at col 1 (PHP delimiter: <?, ?>, Heredoc end) {{{
Bram Moolenaar8408a9a2010-07-30 22:41:22 +0200715 if cline =~# '^\s*<?' && cline !~ '?>' && b:PHP_outdentphpescape
Bram Moolenaar1e015462005-09-25 22:16:38 +0000716 return 0
717 endif
718
Bram Moolenaar8408a9a2010-07-30 22:41:22 +0200719 if cline =~ '^\s*?>' && cline !~# '<?' && b:PHP_outdentphpescape
Bram Moolenaar1e015462005-09-25 22:16:38 +0000720 return 0
721 endif
722
John Wellesz31703422023-09-04 22:22:19 +0200723 if (cline =~? '^\s*\a\w*;$\|^\a\w*$' || (cline =~? '^\s*[''"`][;,]' && IslinePHP(v:lnum, '[;,]') !~? '^\(phpString[SD]\|phpBacktick\)') ) && cline !~? s:notPhpHereDoc
Bram Moolenaar1e015462005-09-25 22:16:38 +0000724 return 0
725 endif " }}}
726
727 let s:level = 0
728
729 let lnum = GetLastRealCodeLNum(v:lnum - 1)
Bram Moolenaar05a7bb32006-01-19 22:09:32 +0000730
Bram Moolenaar1e015462005-09-25 22:16:38 +0000731 let last_line = getline(lnum)
732 let ind = indent(lnum)
Bram Moolenaar1e015462005-09-25 22:16:38 +0000733
734 if ind==0 && b:PHP_default_indenting
735 let ind = b:PHP_default_indenting
736 endif
737
738 if lnum == 0
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200739 return b:PHP_default_indenting + addSpecial
Bram Moolenaar1e015462005-09-25 22:16:38 +0000740 endif
741
742
743 if cline =~ '^\s*}\%(}}\)\@!'
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200744 let ind = indent(FindOpenBracket(v:lnum, 1))
Bram Moolenaar1e015462005-09-25 22:16:38 +0000745 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
John Wellesz31703422023-09-04 22:22:19 +0200746 if b:PHP_BracesAtCodeLevel
747 let ind = ind + shiftwidth()
748 endif
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000749 return ind
Bram Moolenaar1e015462005-09-25 22:16:38 +0000750 endif
751
752 if cline =~ '^\s*\*/'
753 call cursor(v:lnum, 1)
754 if cline !~ '^\*/'
755 call search('\*/', 'W')
756 endif
Bram Moolenaara5792f52005-11-23 21:25:05 +0000757 let lnum = searchpair('/\*', '', '\*/', s:searchpairflags, 'Skippmatch2()')
Bram Moolenaar1e015462005-09-25 22:16:38 +0000758
759 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
760
761 if cline =~ '^\s*\*/'
762 return indent(lnum) + 1
763 else
764 return indent(lnum)
765 endif
766 endif
767
Bram Moolenaar1e015462005-09-25 22:16:38 +0000768
Bram Moolenaar54775062019-07-31 21:07:14 +0200769 if last_line =~ '[;}]'.endline && last_line !~ '^[)\]]' && last_line !~# s:defaultORcase && last_line !~ '^\s*[''"`][;,]'
Bram Moolenaar1e015462005-09-25 22:16:38 +0000770 if ind==b:PHP_default_indenting
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200771 return b:PHP_default_indenting + addSpecial
John Wellesz31703422023-09-04 22:22:19 +0200772 elseif b:PHP_indentinghuge && ind==b:PHP_CurrentIndentLevel && cline !~# '^\s*\%(else\|\%(case\|default\).*:\|[})];\=\)' && last_line !~# '^\s*\%(\%(}\s*\)\=else\)\|^\(\s*\S\+\s*\)\+}'.endline && getline(GetLastRealCodeLNum(lnum - 1))=~';'.endline
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200773 return b:PHP_CurrentIndentLevel + addSpecial
Bram Moolenaar1e015462005-09-25 22:16:38 +0000774 endif
775 endif
776
777 let LastLineClosed = 0
778
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200779 let terminated = s:terminated
Bram Moolenaar1e015462005-09-25 22:16:38 +0000780
Bram Moolenaare0720cb2017-03-29 13:48:40 +0200781 let unstated = s:unstated
782
Bram Moolenaar1e015462005-09-25 22:16:38 +0000783
784 if ind != b:PHP_default_indenting && cline =~# '^\s*else\%(if\)\=\>'
785 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
786 return indent(FindTheIfOfAnElse(v:lnum, 1))
Bram Moolenaar8408a9a2010-07-30 22:41:22 +0200787 elseif cline =~# s:defaultORcase
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200788 return FindTheSwitchIndent(v:lnum) + shiftwidth() * b:PHP_vintage_case_default_indent
Bram Moolenaarc236c162008-07-13 17:41:49 +0000789 elseif cline =~ '^\s*)\=\s*{'
Bram Moolenaar1e015462005-09-25 22:16:38 +0000790 let previous_line = last_line
791 let last_line_num = lnum
792
793 while last_line_num > 1
794
Bram Moolenaare0720cb2017-03-29 13:48:40 +0200795 if previous_line =~ terminated || previous_line =~ s:structureHead
Bram Moolenaar1e015462005-09-25 22:16:38 +0000796
797 let ind = indent(last_line_num)
798
799 if b:PHP_BracesAtCodeLevel
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200800 let ind = ind + shiftwidth()
Bram Moolenaar1e015462005-09-25 22:16:38 +0000801 endif
802
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000803 return ind
Bram Moolenaar1e015462005-09-25 22:16:38 +0000804 endif
805
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200806 let last_line_num = GetLastRealCodeLNum(last_line_num - 1)
Bram Moolenaar1e015462005-09-25 22:16:38 +0000807 let previous_line = getline(last_line_num)
808 endwhile
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200809 elseif cline =~ '^\s*->'
810 return FindArrowIndent(lnum)
Bram Moolenaarc236c162008-07-13 17:41:49 +0000811 elseif last_line =~# unstated && cline !~ '^\s*);\='.endline
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200812 let ind = ind + shiftwidth() " we indent one level further when the preceding line is not stated
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200813 return ind + addSpecial
Bram Moolenaar1e015462005-09-25 22:16:38 +0000814
Bram Moolenaared32d942014-12-06 23:33:00 +0100815 elseif (ind != b:PHP_default_indenting || last_line =~ '^[)\]]' ) && last_line =~ terminated
Bram Moolenaar1e015462005-09-25 22:16:38 +0000816 let previous_line = last_line
817 let last_line_num = lnum
818 let LastLineClosed = 1
819
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200820 let isSingleLineBlock = 0
Bram Moolenaar1e015462005-09-25 22:16:38 +0000821 while 1
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200822 if ! isSingleLineBlock && previous_line =~ '^\s*}\|;\s*}'.endline
Bram Moolenaar1e015462005-09-25 22:16:38 +0000823
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200824 call cursor(last_line_num, 1)
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200825 if previous_line !~ '^}'
826 call search('}\|;\s*}'.endline, 'W')
827 end
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200828 let oldLastLine = last_line_num
829 let last_line_num = searchpair('{', '', '}', 'bW', 'Skippmatch()')
830
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200831 if getline(last_line_num) =~ '^\s*{'
Bram Moolenaar1e015462005-09-25 22:16:38 +0000832 let last_line_num = GetLastRealCodeLNum(last_line_num - 1)
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200833 elseif oldLastLine == last_line_num
834 let isSingleLineBlock = 1
835 continue
Bram Moolenaar1e015462005-09-25 22:16:38 +0000836 endif
837
838 let previous_line = getline(last_line_num)
839
840 continue
841 else
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200842 let isSingleLineBlock = 0
Bram Moolenaar1e015462005-09-25 22:16:38 +0000843
844 if getline(last_line_num) =~# '^\s*else\%(if\)\=\>'
845 let last_line_num = FindTheIfOfAnElse(last_line_num, 0)
846 continue
847 endif
848
849
850 let last_match = last_line_num
851
852 let one_ahead_indent = indent(last_line_num)
853 let last_line_num = GetLastRealCodeLNum(last_line_num - 1)
854 let two_ahead_indent = indent(last_line_num)
855 let after_previous_line = previous_line
856 let previous_line = getline(last_line_num)
857
858
Bram Moolenaar8408a9a2010-07-30 22:41:22 +0200859 if previous_line =~# s:defaultORcase.'\|{'.endline
Bram Moolenaar1e015462005-09-25 22:16:38 +0000860 break
861 endif
862
863 if after_previous_line=~# '^\s*'.s:blockstart.'.*)'.endline && previous_line =~# '[;}]'.endline
864 break
865 endif
866
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000867 if one_ahead_indent == two_ahead_indent || last_line_num < 1
Bram Moolenaarc236c162008-07-13 17:41:49 +0000868 if previous_line =~# '\%(;\|^\s*}\)'.endline || last_line_num < 1
Bram Moolenaar1e015462005-09-25 22:16:38 +0000869 break
870 endif
871 endif
872 endif
873 endwhile
874
875 if indent(last_match) != ind
876 let ind = indent(last_match)
877 let b:PHP_CurrentIndentLevel = b:PHP_default_indenting
878
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200879 return ind + addSpecial
Bram Moolenaar1e015462005-09-25 22:16:38 +0000880 endif
881 endif
882
Bram Moolenaared32d942014-12-06 23:33:00 +0100883 if (last_line !~ '^\s*}\%(}}\)\@!')
884 let plinnum = GetLastRealCodeLNum(lnum - 1)
885 else
886 let plinnum = GetLastRealCodeLNum(FindOpenBracket(lnum, 1) - 1)
887 endif
888
Bram Moolenaar8408a9a2010-07-30 22:41:22 +0200889 let AntepenultimateLine = getline(plinnum)
Bram Moolenaar1e015462005-09-25 22:16:38 +0000890
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200891 let last_line = StripEndlineComments(last_line)
Bram Moolenaar1e015462005-09-25 22:16:38 +0000892
893 if ind == b:PHP_default_indenting
Bram Moolenaared32d942014-12-06 23:33:00 +0100894 if last_line =~ terminated && last_line !~# s:defaultORcase
Bram Moolenaar1e015462005-09-25 22:16:38 +0000895 let LastLineClosed = 1
896 endif
897 endif
898
899 if !LastLineClosed
900
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200901 let openedparent = -1
902
Bram Moolenaar5c736222010-01-06 20:54:52 +0100903
Bram Moolenaare0720cb2017-03-29 13:48:40 +0200904 if last_line =~# '[{(\[]'.endline || last_line =~? '\h\w*\s*(.*,$' && AntepenultimateLine !~ '[,(\[]'.endline && BalanceDirection(last_line) > 0
Bram Moolenaar1e015462005-09-25 22:16:38 +0000905
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200906 let dontIndent = 0
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200907 if last_line =~ '\S\+\s*{'.endline && last_line !~ '^\s*[)\]]\+\(\s*:\s*'.s:PHP_validVariable.'\)\=\s*{'.endline && last_line !~ s:structureHead
Bram Moolenaarbcb98982014-05-01 14:08:19 +0200908 let dontIndent = 1
909 endif
910
911 if !dontIndent && (!b:PHP_BracesAtCodeLevel || last_line !~# '^\s*{')
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200912 let ind = ind + shiftwidth()
Bram Moolenaar1e015462005-09-25 22:16:38 +0000913 endif
914
Bram Moolenaar54775062019-07-31 21:07:14 +0200915 if b:PHP_IndentFunctionCallParameters && last_line =~ s:multilineFunctionCall && last_line !~ s:structureHead && last_line !~ s:arrayDecl
916 let ind = ind + b:PHP_IndentFunctionCallParameters * shiftwidth()
917 endif
918
919 if b:PHP_IndentFunctionDeclarationParameters && last_line =~ s:multilineFunctionDecl
920 let ind = ind + b:PHP_IndentFunctionDeclarationParameters * shiftwidth()
921 endif
922
Bram Moolenaar8408a9a2010-07-30 22:41:22 +0200923 if b:PHP_BracesAtCodeLevel || b:PHP_vintage_case_default_indent == 1
Bram Moolenaar1e015462005-09-25 22:16:38 +0000924 let b:PHP_CurrentIndentLevel = ind
Bram Moolenaarc236c162008-07-13 17:41:49 +0000925
Bram Moolenaar1e015462005-09-25 22:16:38 +0000926 endif
927
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200928 elseif last_line =~ '),'.endline && BalanceDirection(last_line) < 0
Bram Moolenaar1e015462005-09-25 22:16:38 +0000929 call cursor(lnum, 1)
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200930 call searchpos('),'.endline, 'cW')
Bram Moolenaar1e015462005-09-25 22:16:38 +0000931 let openedparent = searchpair('(', '', ')', 'bW', 'Skippmatch()')
932 if openedparent != lnum
933 let ind = indent(openedparent)
934 endif
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200935
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200936 elseif last_line =~ s:structureHead
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200937 let ind = ind + shiftwidth()
Bram Moolenaar1e015462005-09-25 22:16:38 +0000938
Bram Moolenaarc236c162008-07-13 17:41:49 +0000939
John Wellesz31703422023-09-04 22:22:19 +0200940 elseif AntepenultimateLine =~ '{'.endline && AntepenultimateLine !~? '^\s*use\>' && AntepenultimateLine !~? s:matchStart || AntepenultimateLine =~ terminated || AntepenultimateLine =~# s:defaultORcase
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200941 let ind = ind + shiftwidth()
Bram Moolenaar1e015462005-09-25 22:16:38 +0000942 endif
943
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200944
945 if openedparent >= 0
946 let last_line = StripEndlineComments(getline(openedparent))
947 endif
Bram Moolenaar1e015462005-09-25 22:16:38 +0000948 endif
949
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200950 if cline =~ '^\s*[)\]];\='
Bram Moolenaar54775062019-07-31 21:07:14 +0200951 call cursor(v:lnum, 1)
952 call searchpos('[)\]]', 'cW')
953 let matchedBlockChar = cline[col('.')-1]
954 let openedparent = searchpair('\M'.s:blockCharsLUT[matchedBlockChar], '', '\M'.matchedBlockChar, 'bW', 'Skippmatch()')
955 if openedparent != v:lnum
956 let ind = indent(openedparent)
957 endif
Bram Moolenaar0b0f0992018-05-22 21:41:30 +0200958
Bram Moolenaar54775062019-07-31 21:07:14 +0200959 elseif last_line =~ '^\s*->' && last_line !~? s:structureHead && BalanceDirection(last_line) <= 0
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200960 let ind = ind - shiftwidth()
Bram Moolenaar1e015462005-09-25 22:16:38 +0000961 endif
962
963 let b:PHP_CurrentIndentLevel = ind
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200964 return ind + addSpecial
Bram Moolenaar9ff70112005-07-11 22:29:03 +0000965endfunction