1 " Vim script language tests
2 " Author: Servatius Brandt <Servatius.Brandt@fujitsu-siemens.com>
3 " Last Change: 2006 Apr 28
5 "-------------------------------------------------------------------------------
6 " Test environment {{{1
7 "-------------------------------------------------------------------------------
10 " Adding new tests easily. {{{2
12 " Writing new tests is eased considerably with the following functions and
13 " abbreviations (see "Commands for recording the execution path", "Automatic
14 " argument generation").
16 " To get the abbreviations, execute the command
18 " :let test49_set_env = 1 | source test49.vim
20 " To get them always (from src/testdir), put a line
22 " au! BufRead test49.vim let test49_set_env = 1 | source test49.vim
24 " into the local .vimrc file in the src/testdir directory.
26 if exists("test49_set_env") && test49_set_env
28 " Automatic argument generation for the test environment commands.
31 let addend = substitute(getline("."), '^.*"\s*X:\s*\|^.*', '', "")
32 " Evaluate arithmetic expression.
34 exec "let g:Xsum = g:Xsum + " . addend
40 ?XpathINIT?,.call Xsum()
45 iab Xcheck Xcheck<Space><C-R>=Xcheck()<CR><C-O>x
47 function! Xcomment(num)
49 let tabwidth = &sts ? &sts : &ts
50 let tabs = (48+tabwidth - a:num - virtcol(".")) / tabwidth
55 let str = str . '" X:'
60 let back = line(".") . "|norm" . virtcol(".") . "|"
62 let last = search('X\(loop\|path\)INIT\|Xloop\>', "bW")
64 let theline = getline(last)
65 if theline =~ 'X\(loop\|path\)INIT'
68 let num = 2 * substitute(theline, '.*Xloop\s*\(\d\+\).*', '\1', "")
71 \s/\(XloopINIT!\=\s*\d\+\s\+\)\@<=\(\d\+\)/\=2*submatch(2)/
74 return num . Xcomment(strlen(num))
77 iab Xloop Xloop<Space><C-R>=Xloop()<CR><C-O>x
79 function! Xpath(loopinit)
80 let back = line(".") . "|norm" . virtcol(".") . "|"
82 let last = search('XpathINIT\|Xpath\>\|XloopINIT', "bW")
84 let theline = getline(last)
85 if theline =~ 'XpathINIT'
87 elseif theline =~ 'Xpath\>'
88 let num = 2 * substitute(theline, '.*Xpath\s*\(\d\+\).*', '\1', "")
90 let pattern = '.*XloopINIT!\=\s*\(\d\+\)\s*\(\d\+\).*'
91 let num = substitute(theline, pattern, '\1', "")
92 let factor = substitute(theline, pattern, '\2', "")
93 " The "<C-O>x" from the "Xpath" iab and the character triggering its
94 " expansion are in the input buffer. Save and clear typeahead so
95 " that it is not read away by the call to "input()" below. Restore
98 let loops = input("Number of iterations in previous loop? ")
101 let num = num * factor
102 let loops = loops - 1
109 return num . Xcomment(strlen(num))
112 iab Xpath Xpath<Space><C-R>=Xpath(0)<CR><C-O>x
113 iab XloopINIT XloopINIT<Space><C-R>=Xpath(1)<CR><C-O>x
115 " Also useful (see ExtraVim below):
118 au BufEnter <sfile> syn region ExtraVim
119 \ start=+^if\s\+ExtraVim(.*)+ end=+^endif+
120 \ transparent keepend
121 au BufEnter <sfile> syn match ExtraComment /^"/
122 \ contained containedin=ExtraVim
123 au BufEnter <sfile> hi link ExtraComment vimComment
127 au BufEnter <sfile> syn keyword Xpath
128 \ XpathINIT Xpath XloopINIT Xloop XloopNEXT Xcheck Xout
129 au BufEnter <sfile> hi link Xpath Special
134 " Do not execute the tests when sourcing this file for getting the functions
135 " and abbreviations above, which are intended for easily adding new test
136 " cases; they are not needed for test execution. Unlet the variable
137 " controlling this so that an explicit ":source" command for this file will
145 " Commands for recording the execution path. {{{2
147 " The Xpath/Xloop commands can be used for computing the eXecution path by
148 " adding (different) powers of 2 from those script lines, for which the
149 " execution should be checked. Xloop provides different addends for each
150 " execution of a loop. Permitted values are 2^0 to 2^30, so that 31 execution
151 " points (multiply counted inside loops) can be tested.
153 " Note that the arguments of the following commands can be generated
154 " automatically, see below.
158 " - Use XpathINIT at the beginning of the test.
160 " - Use Xpath to check if a line is executed.
161 " Argument: power of 2 (decimal).
163 " - To check multiple execution of loops use Xloop for automatically
164 " computing Xpath values:
166 " - Use XloopINIT before the loop.
168 " - the first Xpath value (power of 2) to be used (Xnext),
169 " - factor for computing a new Xnext value when reexecuting a loop
170 " (by a ":continue" or ":endwhile"); this should be 2^n where
171 " n is the number of Xloop commands inside the loop.
172 " If XloopINIT! is used, the first execution of XloopNEXT is
175 " - Use Xloop inside the loop:
177 " The argument and the Xnext value are multiplied to build the
178 " next Xpath value. No new Xnext value is prepared. The argument
179 " should be 2^(n-1) for the nth Xloop command inside the loop.
180 " If the loop has only one Xloop command, the argument can be
181 " ommitted (default: 1).
183 " - Use XloopNEXT before ":continue" and ":endwhile". This computes a new
184 " Xnext value for the next execution of the loop by multiplying the old
185 " one with the factor specified in the XloopINIT command. No Argument.
186 " Alternatively, when XloopINIT! is used, a single XloopNEXT at the
187 " beginning of the loop can be used.
189 " Nested loops are not supported.
191 " - Use Xcheck at end of each test. It prints the test number, the expected
192 " execution path value, the test result ("OK" or "FAIL"), and, if the tests
193 " fails, the actual execution path.
195 " Expected Xpath/Xloop sum for the correct execution path.
196 " In order that this value can be computed automatically, do the
197 " following: For each line in the test with an Xpath and Xloop
198 " command, add a comment starting with "X:" and specifying an
199 " expression that evaluates to the value contributed by this line to
200 " the correct execution path. (For copying an Xpath argument of at
201 " least two digits into the comment, press <C-P>.) At the end of the
202 " test, just type "Xcheck" and press <Esc>.
204 " - In order to add additional information to the test output file, use the
205 " Xout command. Argument(s) like ":echo".
207 " Automatic argument generation: {{{3
209 " The arguments of the Xpath, XloopINIT, Xloop, and Xcheck commands can be
210 " generated automatically, so that new tests can easily be written without
211 " mental arithmetic. The Xcheck argument is computed from the "X:" comments
212 " of the preceding Xpath and Xloop commands. See the commands and
213 " abbreviations at the beginning of this file.
215 " Implementation: {{{3
216 " XpathINIT, Xpath, XloopINIT, Xloop, XloopNEXT, Xcheck, Xout.
218 " The variants for existing g:ExtraVimResult are needed when executing a script
219 " in an extra Vim process, see ExtraVim below.
221 " EXTRA_VIM_START - do not change or remove this line.
223 com! XpathINIT let g:Xpath = 0
225 if exists("g:ExtraVimResult")
226 com! -count -bar Xpath exec "!echo <count> >>" . g:ExtraVimResult
228 com! -count -bar Xpath let g:Xpath = g:Xpath + <count>
231 com! -count -nargs=1 -bang
232 \ XloopINIT let g:Xnext = <count> |
233 \ let g:Xfactor = <args> |
234 \ let g:Xskip = strlen("<bang>")
236 if exists("g:ExtraVimResult")
237 com! -count=1 -bar Xloop exec "!echo " . (g:Xnext * <count>) . " >>" .
240 com! -count=1 -bar Xloop let g:Xpath = g:Xpath + g:Xnext * <count>
243 com! XloopNEXT let g:Xnext = g:Xnext *
244 \ (g:Xskip ? 1 : g:Xfactor) |
249 com! -count Xcheck let Xresult = "*** Test " .
250 \ (Xtest<10?" ":Xtest<100?" ":"") .
252 \ (Xpath==<count>) ? "OK (".Xpath.")" :
253 \ "FAIL (".Xpath." instead of <count>)"
255 \ let @R = Xresult . "\n" |
257 \ let Xtest = Xtest + 1
259 if exists("g:ExtraVimResult")
260 com! -nargs=+ Xoutq exec "!echo @R:'" .
261 \ substitute(substitute(<q-args>,
262 \ "'", '&\\&&', "g"), "\n", "@NL@", "g")
263 \ . "' >>" . g:ExtraVimResult
265 com! -nargs=+ Xoutq let @R = "--- Test " .
266 \ (g:Xtest<10?" ":g:Xtest<100?" ":"") .
267 \ g:Xtest . ": " . substitute(<q-args>,
268 \ "\n", "&\t ", "g") . "\n"
270 com! -nargs=+ Xout exec 'Xoutq' <args>
272 " Switch off storing of lines for undoing changes. Speeds things up a little.
275 " EXTRA_VIM_STOP - do not change or remove this line.
278 " ExtraVim() - Run a script file in an extra Vim process. {{{2
280 " This is useful for testing immediate abortion of the script processing due to
281 " an error in a command dynamically enclosed by a :try/:tryend region or when an
282 " exception is thrown but not caught or when an interrupt occurs. It can also
283 " be used for testing :finish.
285 " An interrupt location can be specified by an "INTERRUPT" comment. A number
286 " telling how often this location is reached (in a loop or in several function
287 " calls) should be specified as argument. When missing, once per script
288 " invocation or function call is assumed. INTERRUPT locations are tested by
289 " setting a breakpoint in that line and using the ">quit" debug command when
290 " the breakpoint is reached. A function for which an INTERRUPT location is
291 " specified must be defined before calling it (or executing it as a script by
292 " using ExecAsScript below).
294 " This function is only called in normal modus ("g:ExtraVimResult" undefined).
296 " Tests to be executed as an extra script should be written as follows:
302 " XpathINIT XpathINIT
303 " if ExtraVim() if ExtraVim()
307 " Xcheck <number> Xcheck <number>
309 " Double quotes in column 1 are removed before the script is executed.
310 " They should be used if the test has unbalanced conditionals (:if/:endif,
311 " :while:/endwhile, :try/:endtry) or for a line with a syntax error. The
312 " extra script may use Xpath, XloopINIT, Xloop, XloopNEXT, and Xout as usual.
314 " A file name may be specified as argument. All messages of the extra Vim
315 " process are then redirected to the file. An existing file is overwritten.
317 let ExtraVimCount = 0
318 let ExtraVimBase = expand("<sfile>")
319 let ExtraVimTestEnv = ""
321 function! ExtraVim(...)
322 " Count how often this function is called.
323 let g:ExtraVimCount = g:ExtraVimCount + 1
325 " Disable folds to prevent that the ranges in the ":write" commands below
326 " are extended up to the end of a closed fold. This also speeds things up
330 " Open a buffer for this test script and copy the test environment to
331 " a temporary file. Take account of parts relevant for the extra script
333 let current_buffnr = bufnr("%")
334 execute "view +1" g:ExtraVimBase
335 if g:ExtraVimCount == 1
336 let g:ExtraVimTestEnv = tempname()
337 execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w"
338 \ g:ExtraVimTestEnv "|']+"
339 execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w >>"
340 \ g:ExtraVimTestEnv "|']+"
341 execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w >>"
342 \ g:ExtraVimTestEnv "|']+"
343 execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w >>"
344 \ g:ExtraVimTestEnv "|']+"
347 " Start the extra Vim script with a ":source" command for the test
348 " environment. The source line number where the extra script will be
349 " appended, needs to be passed as variable "ExtraVimBegin" to the script.
350 let extra_script = tempname()
351 exec "!echo 'source " . g:ExtraVimTestEnv . "' >" . extra_script
354 " Starting behind the test environment, skip over the first g:ExtraVimCount
355 " occurrences of "if ExtraVim()" and copy the following lines up to the
356 " matching "endif" to the extra Vim script.
357 execute "/E" . "ND_OF_TEST_ENVIRONMENT/"
358 exec 'norm ' . g:ExtraVimCount . '/^\s*if\s\+ExtraVim(.*)/+' . "\n"
359 execute ".,/^endif/-write >>" . extra_script
361 " Open a buffer for the extra Vim script, delete all ^", and write the
362 " script if was actually modified.
363 execute "edit +" . (extra_begin + 1) extra_script
367 " Count the INTERRUPTs and build the breakpoint and quit commands.
373 \ '"\s*INTERRUPT\h\@!\|^\s*fu\%[nction]\>!\=\s*\%(\u\|s:\)\w*\s*(\|'
374 \ . '^\s*\\\|^\s*endf\%[unction]\>\|'
375 \ . '\%(^\s*fu\%[nction]!\=\s*\)\@<!\%(\u\|s:\)\w*\s*(\|'
376 \ . 'ExecAsScript\s\+\%(\u\|s:\)\w*',
378 let theline = getline(".")
379 if theline =~ '^\s*fu'
380 " Function definition.
382 let func_start = line(".")
383 let func_name = substitute(theline,
384 \ '^\s*fu\%[nction]!\=\s*\(\%(\u\|s:\)\w*\).*', '\1', "")
385 elseif theline =~ '^\s*endf'
386 " End of function definition.
389 let finding = substitute(theline, '.*\(\%' . col(".") . 'c.*\)',
391 if finding =~ '^"\s*INTERRUPT\h\@!'
392 " Interrupt comment. Compose as many quit commands as
394 let cnt = substitute(finding,
395 \ '^"\s*INTERRUPT\s*\(\d*\).*$', '\1', "")
398 " Use "\r" rather than "\n" to separate the quit commands.
399 " "\r" is not interpreted as command separator by the ":!"
400 " command below but works to separate commands in the
402 let quits = quits . "q\r"
406 " Add the function breakpoint and note the number of quits
407 " to be used, if specified, or one for every call else.
408 let breakpoints = breakpoints . " -c 'breakadd func " .
409 \ (line(".") - func_start) . " " .
412 let debug_quits = debug_quits . quits
413 elseif !exists("quits{func_name}")
414 let quits{func_name} = "q\r"
416 let quits{func_name} = quits{func_name} . "q\r"
419 " Add the file breakpoint and the quits to be used for it.
420 let breakpoints = breakpoints . " -c 'breakadd file " .
421 \ line(".") . " " . extra_script . "'"
425 let debug_quits = debug_quits . quits
428 " Add the quits to be used for calling the function or executing
430 if finding =~ '^ExecAsScript'
431 " Sourcing function as script.
432 let finding = substitute(finding,
433 \ '^ExecAsScript\s\+\(\%(\u\|s:\)\w*\).*', '\1', "")
436 let finding = substitute(finding,
437 \ '^\(\%(\u\|s:\)\w*\).*', '\1', "")
439 if exists("quits{finding}")
440 let debug_quits = debug_quits . quits{finding}
446 " Close the buffer for the script and create an (empty) resultfile.
448 let resultfile = tempname()
449 exec "!>" . resultfile
451 " Run the script in an extra vim. Switch to extra modus by passing the
452 " resultfile in ExtraVimResult. Redirect messages to the file specified as
453 " argument if any. Use ":debuggreedy" so that the commands provided on the
454 " pipe are consumed at the debug prompt. Use "-N" to enable command-line
455 " continuation ("C" in 'cpo'). Add "nviminfo" to 'viminfo' to avoid
456 " messing up the user's viminfo file.
458 \ " -c 'au VimLeave * redir END' -c 'redir\\! >" . a:1 . "'" : ""
459 exec "!echo '" . debug_quits . "q' | ../vim -u NONE -N -Xes" . redirect .
460 \ " -c 'debuggreedy|set viminfo+=nviminfo'" .
461 \ " -c 'let ExtraVimBegin = " . extra_begin . "'" .
462 \ " -c 'let ExtraVimResult = \"" . resultfile . "\"'" . breakpoints .
463 \ " -S " . extra_script
465 " Build the resulting sum for resultfile and add it to g:Xpath. Add Xout
466 " information provided by the extra Vim process to the test output.
468 exec "edit" resultfile
470 while line <= line("$")
471 let theline = getline(line)
473 exec 'Xout "' . substitute(substitute(
474 \ escape(escape(theline, '"'), '\"'),
475 \ '^@R:', '', ""), '@NL@', "\n", "g") . '"'
477 let sum = sum + getline(line)
482 let g:Xpath = g:Xpath + sum
484 " Delete the extra script and the resultfile.
485 call delete(extra_script)
486 call delete(resultfile)
488 " Switch back to the buffer that was active when this function was entered.
489 exec "buffer" current_buffnr
491 " Return 0. This protects extra scripts from being run in the main Vim
497 " ExtraVimThrowpoint() - Relative throwpoint in ExtraVim script {{{2
499 " Evaluates v:throwpoint and returns the throwpoint relative to the beginning of
500 " an ExtraVim script as passed by ExtraVim() in ExtraVimBegin.
502 " EXTRA_VIM_START - do not change or remove this line.
503 function! ExtraVimThrowpoint()
504 if !exists("g:ExtraVimBegin")
505 Xout "ExtraVimThrowpoint() used outside ExtraVim() script."
509 if v:throwpoint =~ '^function\>'
514 \ (substitute(v:throwpoint, '.*, line ', '', "") - g:ExtraVimBegin) .
515 \ " of ExtraVim() script"
517 " EXTRA_VIM_STOP - do not change or remove this line.
520 " MakeScript() - Make a script file from a function. {{{2
522 " Create a script that consists of the body of the function a:funcname.
523 " Replace any ":return" by a ":finish", any argument variable by a global
524 " variable, and and every ":call" by a ":source" for the next following argument
525 " in the variable argument list. This function is useful if similar tests are
526 " to be made for a ":return" from a function call or a ":finish" in a script
529 " In order to execute a function specifying an INTERRUPT location (see ExtraVim)
530 " as a script file, use ExecAsScript below.
532 " EXTRA_VIM_START - do not change or remove this line.
533 function! MakeScript(funcname, ...)
534 let script = tempname()
535 execute "redir! >" . script
536 execute "function" a:funcname
538 execute "edit" script
539 " Delete the "function" and the "endfunction" lines. Do not include the
540 " word "function" in the pattern since it might be translated if LANG is
541 " set. When MakeScript() is being debugged, this deletes also the debugging
542 " output of its line 3 and 4.
543 exec '1,/.*' . a:funcname . '(.*)/d'
544 /^\d*\s*endfunction\>/,$d
547 %s/\<a:\(\h\w*\)/g:\1/ge
550 while search('\<call\s*\%(\u\|s:\)\w*\s*(.*)', 'W') > 0
552 s/\<call\s*\%(\u\|s:\)\w*\s*(.*)/\='source ' . a:{cnt}/
559 " EXTRA_VIM_STOP - do not change or remove this line.
562 " ExecAsScript - Source a temporary script made from a function. {{{2
564 " Make a temporary script file from the function a:funcname, ":source" it, and
565 " delete it afterwards.
567 " When inside ":if ExtraVim()", add a file breakpoint for each INTERRUPT
568 " location specified in the function.
570 " EXTRA_VIM_START - do not change or remove this line.
571 function! ExecAsScript(funcname)
572 " Make a script from the function passed as argument.
573 let script = MakeScript(a:funcname)
575 " When running in an extra Vim process, add a file breakpoint for each
576 " function breakpoint set when the extra Vim process was invoked by
578 if exists("g:ExtraVimResult")
579 let bplist = tempname()
580 execute "redir! >" . bplist
583 execute "edit" bplist
584 " Get the line number from the function breakpoint. Works also when
586 execute 'v/^\s*\d\+\s\+func\s\+' . a:funcname . '\s.*/d'
587 %s/^\s*\d\+\s\+func\s\+\%(\u\|s:\)\w*\s\D*\(\d*\).*/\1/e
589 while cnt < line("$")
591 if getline(cnt) != ""
592 execute "breakadd file" getline(cnt) script
599 " Source and delete the script.
604 com! -nargs=1 -bar ExecAsScript call ExecAsScript(<f-args>)
605 " EXTRA_VIM_STOP - do not change or remove this line.
608 " END_OF_TEST_ENVIRONMENT - do not change or remove this line.
611 "-------------------------------------------------------------------------------
612 " Test 1: :endwhile in function {{{1
614 " Detect if a broken loop is (incorrectly) reactivated by the
615 " :endwhile. Use a :return to prevent an endless loop, and make
616 " this test first to get a meaningful result on an error before other
618 "-------------------------------------------------------------------------------
627 Xloop 1 " X: 2 + 0 * 16
629 Xloop 2 " X: 4 + 0 * 32
634 Xloop 4 " X: 0 + 0 * 64
644 Xpath 256 " X: 256 + 0 * 2048
648 Xloop 1 " X: 512 + 0 * 4096
650 Xloop 2 " X: 1024 + 0 * 8192
655 Xloop 4 " X: 0 + 0 * 16384
663 Xpath 32768 " X: 32768
667 " Leave F and G for execution as scripts in the next test.
670 "-------------------------------------------------------------------------------
671 " Test 2: :endwhile in script {{{1
673 " Detect if a broken loop is (incorrectly) reactivated by the
674 " :endwhile. Use a :finish to prevent an endless loop, and place
675 " this test before others that might hang to get a meaningful result
678 " This test executes the bodies of the functions F and G from the
679 " previous test as script files (:return replaced by :finish).
680 "-------------------------------------------------------------------------------
684 ExecAsScript F " X: 1 + 2 + 4
687 ExecAsScript G " X: 256 + 512 + 1024
688 Xpath 32768 " X: 32768
697 "-------------------------------------------------------------------------------
698 " Test 3: :if, :elseif, :while, :continue, :break {{{1
699 "-------------------------------------------------------------------------------
706 while loops > -1 " main loop: loops == 3, 2, 1 (which breaks)
711 Xloop 1 " X: 2 + 2*512 + 2*512*512
714 while loops == 2 " dummy loop
716 let loops = loops - 1
717 continue " stop dummy loop
721 continue " continue main loop
726 Xloop 16 " X: 32*512*512
728 break " break dummy loop
731 Xloop 64 " X: 128*512*512
733 break " break main loop
739 while loops == 3 " dummy loop
740 let loops = loops - 1
741 endwhile " end dummy loop
743 endwhile " end main loop
744 Xpath 268435456 " X: 1024*512*512
746 Xpath 536870912 " X: 0
748 Xpath 1073741824 " X: 4096*512*512
749 if exists("break_err")
750 " The Xpath command does not accept 2^31 (negative); add explicitly:
751 let Xpath = Xpath + 2147483648 " X: 0
760 "-------------------------------------------------------------------------------
761 " Test 4: :return {{{1
762 "-------------------------------------------------------------------------------
771 while loops > 0 " 3: 2: 1:
772 Xloop 1 " X: 2 + 2*16 + 0*16*16
779 let loops = loops - 1
789 Xpath 32768 " X: 8*16*16*16
793 " Leave F for execution as a script in the next test.
796 "-------------------------------------------------------------------------------
797 " Test 5: :finish {{{1
799 " This test executes the body of the function F from the previous test
800 " as a script file (:return replaced by :finish).
801 "-------------------------------------------------------------------------------
805 ExecAsScript F " X: 1 + 2 + 2*16 + 4*16 + 16
806 Xpath 32768 " X: 32768
814 "-------------------------------------------------------------------------------
815 " Test 6: Defining functions in :while loops {{{1
817 " Functions can be defined inside other functions. An inner function
818 " gets defined when the outer function is executed. Functions may
819 " also be defined inside while loops. Expressions in braces for
820 " defining the function name are allowed.
821 "-------------------------------------------------------------------------------
827 " The command CALL collects the argument of all its invocations in "calls"
828 " when used from a function (that is, when the global variable "calls" needs
829 " the "g:" prefix). This is to check that the function code is skipped when
830 " the function is defined. For inner functions, do so only if the outer
831 " function is not being executed.
835 \ if !exists("calls") && !exists("outer") |
836 \ let g:calls = g:calls . <args> |
871 Xloop 4 " X: 4 * (16 + 256)
872 function! F{i}(i, arg)
885 Xloop 1 " X: 16384*(1+4+16+64+256+1024)
887 function! G{a:i}{k}(arg)
890 Xloop 2 " X: 32768*(1+4+16+64+256+1024)
893 Xloop 8 " X: 8 * (16 + 256)
898 Xpath 67108864 " X: 0
907 if exists("G21") || exists("G21") || exists("G21")
908 Xpath 134217728 " X: 0
923 if exists("G31") || exists("G31") || exists("G31")
924 Xpath 268435456 " X: 0
939 Xpath 536870912 " X: 536870912
941 if calls != "F1G1F2G21G22G23F3G31G32G33"
942 Xpath 1073741824 " X: 0
943 Xout "calls is" calls
961 "-------------------------------------------------------------------------------
962 " Test 7: Continuing on errors outside functions {{{1
964 " On an error outside a function, the script processing continues
965 " at the line following the outermost :endif or :endwhile. When not
966 " inside an :if or :while, the script processing continues at the next
968 "-------------------------------------------------------------------------------
979 endwhile | Xpath 8 " X: 0
981 endif | Xpath 32 " X: 0
990 endif | Xpath 1024 " X: 0
993 endwhile | Xpath 4096 " X: 0
997 Xpath 16384 " X: 16384
999 asdf | Xpath 32768 " X: 0
1000 Xpath 65536 " X: 65536
1005 "-------------------------------------------------------------------------------
1006 " Test 8: Aborting and continuing on errors inside functions {{{1
1008 " On an error inside a function without the "abort" attribute, the
1009 " script processing continues at the next line (unless the error was
1010 " in a :return command). On an error inside a function with the
1011 " "abort" attribute, the function is aborted and the script processing
1012 " continues after the function call; the value -1 is returned then.
1013 "-------------------------------------------------------------------------------
1024 asdf | Xpath 8 " X: 0
1029 endif | Xpath 64 " X: 64
1037 Xpath 1024 " X: 1024
1038 asdf | Xpath 2048 " X: 0
1039 Xpath 4096 " X: 4096
1041 Xpath 8192 " X: 8192
1043 endwhile | Xpath 16384 " X: 16384
1044 Xpath 32768 " X: 32768
1046 return novar " returns (default return value 0)
1048 return 1 " not reached
1053 Xpath 131072 " X: 131072
1055 Xpath 262144 " X: 262144
1060 Xpath 1048576 " X: 0
1061 endif | Xpath 2097152 " X: 0
1062 Xpath Xpath 4194304 " X: 0
1064 return -4 " not reached
1069 Xpath 8388608 " X: 8388608
1071 Xpath 16777216 " X: 16777216
1073 Xpath 33554432 " X: 0
1075 Xpath 67108864 " X: 0
1077 endwhile | Xpath 134217728 " X: 0
1078 Xpath 268435456 " X: 0
1080 return -4 " not reached
1083 " Aborted functions (G and H) return -1.
1084 let sum = (F() + 1) - 4*G() - 8*H()
1085 Xpath 536870912 " X: 536870912
1087 Xpath 1073741824 " X: 0
1099 "-------------------------------------------------------------------------------
1100 " Test 9: Continuing after aborted functions {{{1
1102 " When a function with the "abort" attribute is aborted due to an
1103 " error, the next function back in the call hierarchy without an
1104 " "abort" attribute continues; the value -1 is returned then.
1105 "-------------------------------------------------------------------------------
1111 let result = G() " not aborted
1119 function! G() " no abort attribute
1121 if H() != -1 " aborted
1154 "-------------------------------------------------------------------------------
1155 " Test 10: :if, :elseif, :while argument parsing {{{1
1157 " A '"' or '|' in an argument expression must not be mixed up with
1158 " a comment or a next command after a bar. Parsing errors should
1160 "-------------------------------------------------------------------------------
1164 function! MSG(enr, emsg)
1165 let english = v:lang == "C" || v:lang =~ '^[Ee]n'
1167 Xout "TODO: Add message number for:" a:emsg
1168 let v:errmsg = ":" . v:errmsg
1171 if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
1174 Xout "Message missing."
1176 let v:errmsg = escape(v:errmsg, '"')
1177 Xout "Unexpected message:" v:errmsg
1183 if 1 || strlen("\"") | Xpath 1 " X: 1
1189 elseif 1 || strlen("\"") | Xpath 8 " X: 8
1194 while 1 || strlen("\"") | Xpath 64 " X: 64
1201 if 1 ||| strlen("\"") | Xpath 512 " X: 0
1204 Xpath 2048 " X: 2048
1205 if !MSG('E15', "Invalid expression")
1211 elseif 1 ||| strlen("\"") | Xpath 8192 " X: 0
1214 Xpath 32768 " X: 32768
1215 if !MSG('E15', "Invalid expression")
1220 while 1 ||| strlen("\"") | Xpath 131072 " X: 0
1224 Xpath 524288 " X: 524288
1225 if !MSG('E15', "Invalid expression")
1226 Xpath 1048576 " X: 0
1234 "-------------------------------------------------------------------------------
1235 " Test 11: :if, :elseif, :while argument evaluation after abort {{{1
1237 " When code is skipped over due to an error, the boolean argument to
1238 " an :if, :elseif, or :while must not be evaluated.
1239 "-------------------------------------------------------------------------------
1246 let g:calls = g:calls + a:num " side effect on call
1254 if P(1) " should not be called
1256 elseif !P(2) " should not be called
1262 while P(4) " should not be called
1277 Xpath 2048 " X: 2048
1285 "-------------------------------------------------------------------------------
1286 " Test 12: Expressions in braces in skipped code {{{1
1288 " In code skipped over due to an error or inactive conditional,
1289 " an expression in braces as part of a variable or function name
1290 " should not be evaluated.
1291 "-------------------------------------------------------------------------------
1317 Xpath 8192 " X: 8192
1318 echo 0 ? F{NULL() + V{ZERO()}}() : 1
1321 Xpath 16384 " X: 16384
1324 call F{NULL() + V{ZERO()}}()
1328 Xpath 65536 " X: 65536
1332 call F1(F{NULL() + V{ZERO()}}())
1336 Xpath 262144 " X: 262144
1340 call F{NULL() + V{ZERO()}}()
1346 "-------------------------------------------------------------------------------
1347 " Test 13: Failure in argument evaluation for :while {{{1
1349 " A failure in the expression evaluation for the condition of a :while
1350 " causes the whole :while loop until the matching :endwhile being
1351 " ignored. Continuation is at the next following line.
1352 "-------------------------------------------------------------------------------
1368 while asdf | Xpath 32 | endwhile | Xpath 64 " X: 0
1374 "-------------------------------------------------------------------------------
1375 " Test 14: Failure in argument evaluation for :if {{{1
1377 " A failure in the expression evaluation for the condition of an :if
1378 " does not cause the corresponding :else or :endif being matched to
1379 " a previous :if/:elseif. Neither of both branches of the failed :if
1381 "-------------------------------------------------------------------------------
1387 Xloop 1 " X: 1 + 256 * 1
1390 Xloop 2 " X: 0 + 256 * 0
1391 elseif !x " always true
1392 Xloop 4 " X: 4 + 256 * 4
1394 if g:boolvar " possibly undefined
1395 Xloop 8 " X: 8 + 256 * 0
1397 Xloop 16 " X: 0 + 256 * 0
1399 Xloop 32 " X: 32 + 256 * 32
1400 elseif x " never executed
1401 Xloop 64 " X: 0 + 256 * 0
1403 Xloop 128 " X: 128 + 256 * 128
1418 "-------------------------------------------------------------------------------
1419 " Test 15: Failure in argument evaluation for :if (bar) {{{1
1421 " Like previous test, except that the failing :if ... | ... | :endif
1422 " is in a single line.
1423 "-------------------------------------------------------------------------------
1429 Xloop 1 " X: 1 + 256 * 1
1432 Xloop 2 " X: 0 + 256 * 0
1433 elseif !x " always true
1434 Xloop 4 " X: 4 + 256 * 4
1436 if g:boolvar | Xloop 8 | else | Xloop 16 | endif " X: 8
1437 Xloop 32 " X: 32 + 256 * 32
1438 elseif x " never executed
1439 Xloop 64 " X: 0 + 256 * 0
1441 Xloop 128 " X: 128 + 256 * 128
1456 "-------------------------------------------------------------------------------
1457 " Test 16: Double :else or :elseif after :else {{{1
1459 " Multiple :elses or an :elseif after an :else are forbidden.
1460 "-------------------------------------------------------------------------------
1469 else " aborts function
1479 elseif 1 " aborts function
1493 else " aborts function
1504 Xpath 8192 " X: 8192
1505 elseif 1 " aborts function
1525 "-------------------------------------------------------------------------------
1526 " Test 17: Nesting of unmatched :if or :endif inside a :while {{{1
1528 " The :while/:endwhile takes precedence in nesting over an unclosed
1529 " :if or an unopened :endif.
1530 "-------------------------------------------------------------------------------
1534 function! MSG(enr, emsg)
1535 let english = v:lang == "C" || v:lang =~ '^[Ee]n'
1537 Xout "TODO: Add message number for:" a:emsg
1538 let v:errmsg = ":" . v:errmsg
1541 if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
1544 Xout "Message missing."
1546 let v:errmsg = escape(v:errmsg, '"')
1547 Xout "Unexpected message:" v:errmsg
1555 " While loops inside a function are continued on error.
1561 let loops = loops - 1 " 2: 1: 0:
1562 Xloop 1 " X: 1 + 1*16 + 1*16*16
1568 Xloop 4 " X: 4*16*16
1574 endwhile " :endwhile after :if 1
1575 Xpath 4096 " X: 16*16*16
1576 if MSG('E171', "Missing :endif")
1577 let g:messages = g:messages . "A"
1583 while loops > 0 " 2: 1:
1585 let loops = loops - 1
1586 Xloop 1 " X: 8192 + 8192*4
1590 endwhile " :endwhile after :if 0
1591 Xpath 131072 " X: 8192*4*4
1592 if MSG('E171', "Missing :endif")
1593 let g:messages = g:messages . "B"
1599 while loops > 0 " 2: 1:
1600 let loops = loops - 1
1601 Xloop 1 " X: 262144 + 262144 * 4
1603 endif " :endif without :if in while
1604 Xloop 2 " X: 524288 + 524288 * 4
1607 Xpath 4194304 " X: 262144*4*4
1608 if MSG('E580', ":endif without :if")
1609 let g:messages = g:messages . "C"
1615 " Error continuation outside a function is at the outermost :endwhile or :endif.
1617 XloopINIT! 8388608 4
1619 while loops > 0 " 2: 1:
1621 let loops = loops - 1
1622 Xloop 1 " X: 8388608 + 0 * 4
1625 " endif missing! Following :endwhile fails.
1626 endwhile | Xpath 134217728 " X: 0
1627 Xpath 268435456 " X: 2*8388608*4*4
1628 if MSG('E171', "Missing :endif")
1629 let messages = g:messages . "D"
1632 if messages != "ABCD"
1633 Xpath 536870912 " X: 0
1634 Xout "messages is" messages "instead of ABCD"
1637 unlet loops messages
1644 "-------------------------------------------------------------------------------
1645 " Test 18: Interrupt (Ctrl-C pressed) {{{1
1647 " On an interrupt, the script processing is terminated immediately.
1648 "-------------------------------------------------------------------------------
1663 endif | Xpath 16 " X: 0
1665 endwhile | Xpath 64 " X: 0
1667 endif | Xpath 256 " X: 0
1673 Xpath 1024 " X: 1024
1676 endtry | Xpath 4096 " X: 0
1683 Xpath 16384 " X: 16384
1685 Xpath 32768 " X: 32768
1687 Xpath 65536 " X: 65536
1692 endif | Xpath 262144 " X: 0
1693 Xpath Xpath 524288 " X: 0
1694 endwhile | Xpath 1048576 " X: 0
1695 Xpath Xpath 2097152 " X: 0
1696 endif | Xpath Xpath 4194304 " X: 0
1697 Xpath Xpath 8388608 " X: 0
1700 call F() | Xpath 16777216 " X: 0
1701 Xpath 33554432 " X: 0
1707 Xpath 67108864 " X: 67108864
1709 Xpath 134217728 " X: 0
1710 endtry | Xpath 268435456 " X: 0
1711 Xpath 536870912 " X: 0
1714 call G() | Xpath 1073741824 " X: 0
1715 " The Xpath command does not accept 2^31 (negative); display explicitly:
1716 exec "!echo 2147483648 >>" . g:ExtraVimResult
1723 "-------------------------------------------------------------------------------
1724 " Test 19: Aborting on errors inside :try/:endtry {{{1
1726 " An error in a command dynamically enclosed in a :try/:endtry region
1727 " aborts script processing immediately. It does not matter whether
1728 " the failing command is outside or inside a function and whether a
1729 " function has an "abort" attribute.
1730 "-------------------------------------------------------------------------------
1745 endtry | Xpath 16 " X: 0
1760 endtry | Xpath 1024 " X: 0
1766 Xpath 4096 " X: 4096
1769 endtry | Xpath 16384 " X: 0
1776 Xpath 65536 " X: 65536
1779 endtry | Xpath 262144 " X: 0
1780 endif | Xpath 524288 " X: 0
1781 Xpath 1048576 " X: 0
1789 Xpath 2097152 " X: 2097152
1791 Xpath 4194304 " X: 0
1792 endtry | Xpath 8388608 " X: 0
1793 endwhile | Xpath 16777216 " X: 0
1794 Xpath 33554432 " X: 0
1802 Xpath 67108864 " X: 67108864
1803 endwhile | Xpath 134217728 " X: 0
1804 Xpath 268435456 " X: 0
1808 "-------------------------------------------------------------------------------
1809 " Test 20: Aborting on errors after :try/:endtry {{{1
1811 " When an error occurs after the last active :try/:endtry region has
1812 " been left, termination behavior is as if no :try/:endtry has been
1814 "-------------------------------------------------------------------------------
1826 endwhile | Xpath 2 " X: 0
1853 Xpath 1024 " X: 1024
1855 Xpath 2048 " X: 2048
1861 Xpath 4096 " X: 4096
1863 Xpath 8192 " X: 8192
1868 Xpath 32768 " X: 32768
1870 Xpath 65536 " X: 65536
1878 Xpath 131072 " X: 131072
1883 Xpath 524288 " X: 524288
1885 Xpath 1048576 " X: 1048576
1893 Xpath 2097152 " X: 2097152
1895 Xpath 4194304 " X: 0
1897 Xpath 8388608 " X: 8388608
1900 Xpath 16777216 " X: 16777216
1902 Xpath 33554432 " X: 33554432
1910 Xpath 67108864 " X: 67108864
1912 Xpath 134217728 " X: 134217728
1914 Xpath 268435456 " X: 0
1917 Xpath 536870912 " X: 536870912
1919 Xpath 1073741824 " X: 1073741824
1925 "-------------------------------------------------------------------------------
1926 " Test 21: :finally for :try after :continue/:break/:return/:finish {{{1
1928 " If a :try conditional stays inactive due to a preceding :continue,
1929 " :break, :return, or :finish, its :finally clause should not be
1931 "-------------------------------------------------------------------------------
1941 let loops = loops - 1
1959 Xloop 64 " X: 64 + 64*256
1965 Xpath 65536 " X: 65536
1974 Xpath 1048576 " X: 1048576
1976 Xpath 2097152 " X: 0
1980 Xpath 4194304 " X: 4194304
1982 Xpath 8388608 " X: 8388608
1984 Xpath 16777216 " X: 0
1986 Xpath 33554432 " X: 0
1988 Xpath 67108864 " X: 0
1991 Xpath 134217728 " X: 134217728
1993 Xpath 268435456 " X: 0
1999 "-------------------------------------------------------------------------------
2000 " Test 22: :finally for a :try after an error/interrupt/:throw {{{1
2002 " If a :try conditional stays inactive due to a preceding error or
2003 " interrupt or :throw, its :finally clause should not be executed.
2004 "-------------------------------------------------------------------------------
2011 asdf " aborting error, triggering error exception
2019 if 1 " not active due to error
2020 try " not active since :if inactive
2027 try " not active due to error
2035 function! Interrupt()
2037 "INTERRUPT " triggering interrupt exception
2045 if 1 " not active due to interrupt
2046 try " not active since :if inactive
2053 try " not active due to interrupt
2065 Xpath 4096 " X: 4096
2069 if 1 " not active due to :throw
2070 try " not active since :if inactive
2077 try " not active due to :throw
2087 "-------------------------------------------------------------------------------
2088 " Test 23: :catch clauses for a :try after a :throw {{{1
2090 " If a :try conditional stays inactive due to a preceding :throw,
2091 " none of its :catch clauses should be executed.
2092 "-------------------------------------------------------------------------------
2102 if 1 " not active due to :throw
2103 try " not active since :if inactive
2117 try " not active due to :throw
2127 "-------------------------------------------------------------------------------
2128 " Test 24: :endtry for a :try after a :throw {{{1
2130 " If a :try conditional stays inactive due to a preceding :throw,
2131 " its :endtry should not rethrow the exception to the next surrounding
2132 " active :try conditional.
2133 "-------------------------------------------------------------------------------
2141 throw "xyz" " makes try 2 inactive
2146 endtry " no rethrow to try 1
2147 catch /xyz/ " should catch although try 2 inactive
2150 catch /xyz/ " try 1 active, but exception already caught
2159 "-------------------------------------------------------------------------------
2160 " Test 25: Executing :finally clauses on normal control flow {{{1
2162 " Control flow in a :try conditional should always fall through to its
2163 " :finally clause. A :finally clause of a :try conditional inside an
2164 " inactive conditional should never be executed.
2165 "-------------------------------------------------------------------------------
2172 while loops > 0 " 3: 2: 1:
2173 Xloop 1 " X: 1 + 1*256 + 1*256*256
2176 Xloop 2 " X: 2 + 2*256
2185 Xloop 16 " X: 16 + 16*256
2188 Xloop 32 " X: 32*256
2190 Xloop 64 " X: 64*256
2195 Xloop 128 " X: 128 + 128*256 + 128*256*256
2196 let loops = loops - 1
2199 Xpath 16777216 " X: 16777216
2204 Xpath 33554432 " X: 33554432
2206 Xpath 67108864 " X: 67108864
2208 Xpath 134217728 " X: 134217728
2212 Xpath 268435456 " X: 0
2214 Xpath 536870912 " X: 0
2223 "-------------------------------------------------------------------------------
2224 " Test 26: Executing :finally clauses after :continue or :break {{{1
2226 " For a :continue or :break dynamically enclosed in a :try/:endtry
2227 " region inside the next surrounding :while/:endwhile, if the
2228 " :continue/:break is before the :finally, the :finally clause is
2229 " executed first. If the :continue/:break is after the :finally, the
2230 " :finally clause is broken (like an :if/:endif region).
2231 "-------------------------------------------------------------------------------
2242 if loops == 2 " 3: 2: 1:
2244 let loops = loops - 1
2247 Xloop 2 " X: 2*32*32
2254 Xloop 8 " X: 8 + 8*32 + 8*32*32
2257 let loops = loops - 1
2259 Xpath 32768 " X: 32768
2261 Xpath 65536 " X: 65536
2269 Xloop 1 " X: 131072*16
2270 let loops = loops - 1
2274 Xloop 2 " X: 131072*2*16*16
2279 Xloop 4 " X: 131072*4
2281 Xloop 8 " X: 131072*8
2282 let loops = loops - 1
2285 Xpath 536870912 " X: 536870912
2287 Xpath 1073741824 " X: 1073741824
2294 "-------------------------------------------------------------------------------
2295 " Test 27: Executing :finally clauses after :return {{{1
2297 " For a :return command dynamically enclosed in a :try/:endtry region,
2298 " :finally clauses are executed and the called function is ended.
2299 "-------------------------------------------------------------------------------
2328 Xpath 1024 " X: 1024
2335 Xpath 4096 " X: 4096
2337 Xpath 8192 " X: 8192
2339 Xpath 16384 " X: 16384
2347 Xpath 131072 " X: 131072
2349 Xpath 262144 " X: 262144
2351 Xpath 524288 " X: 524288
2353 Xpath 1048576 " X: 1048576
2357 " Leave F, G, and H for execution as scripts in the next test.
2360 "-------------------------------------------------------------------------------
2361 " Test 28: Executing :finally clauses after :finish {{{1
2363 " For a :finish command dynamically enclosed in a :try/:endtry region,
2364 " :finally clauses are executed and the sourced file is finished.
2366 " This test executes the bodies of the functions F, G, and H from the
2367 " previous test as script files (:return replaced by :finish).
2368 "-------------------------------------------------------------------------------
2372 let scriptF = MakeScript("F") " X: 1 + 2 + 8 + 32
2373 let scriptG = MakeScript("G", scriptF) " X: 128 + 512 + 1024
2374 let scriptH = MakeScript("H", scriptG) " X: 4096 + 8192 + 16384
2377 Xpath 131072 " X: 131072
2378 exec "source" scriptH
2379 Xpath 262144 " X: 262144
2381 Xpath 524288 " X: 524288
2383 Xpath 1048576 " X: 1048576
2385 call delete(scriptF)
2386 call delete(scriptG)
2387 call delete(scriptH)
2388 unlet scriptF scriptG scriptH
2396 "-------------------------------------------------------------------------------
2397 " Test 29: Executing :finally clauses on errors {{{1
2399 " After an error in a command dynamically enclosed in a :try/:endtry
2400 " region, :finally clauses are executed and the script processing is
2402 "-------------------------------------------------------------------------------
2418 endtry | Xpath 16 " X: 0
2425 endtry | Xpath 256 " X: 0
2434 Xpath 2048 " X: 2048
2439 endwhile | Xpath 8192 " X: 0
2442 Xpath 32768 " X: 32768
2443 endtry | Xpath 65536 " X: 0
2444 endwhile | Xpath 131072 " X: 0
2452 Xpath 524288 " X: 524288
2454 Xpath 1048576 " X: 0
2456 Xpath 2097152 " X: 2097152
2457 endtry | Xpath 4194304 " X: 0
2458 endif | Xpath 8388608 " X: 0
2459 Xpath 16777216 " X: 0
2464 Xpath 33554432 " X: 33554432
2466 Xpath 67108864 " X: 0
2468 Xpath 134217728 " X: 134217728
2469 endtry | Xpath 268435456 " X: 0
2470 endif | Xpath 536870912 " X: 0
2471 Xpath 1073741824 " X: 0
2477 "-------------------------------------------------------------------------------
2478 " Test 30: Executing :finally clauses on interrupt {{{1
2480 " After an interrupt in a command dynamically enclosed in
2481 " a :try/:endtry region, :finally clauses are executed and the
2482 " script processing is terminated.
2483 "-------------------------------------------------------------------------------
2492 Xloop 1 " X: 1 + 1*16
2496 Xloop 4 " X: 4 + 4*16
2508 Xpath 2048 " X: 2048
2510 Xpath 4096 " X: 4096
2512 Xpath 8192 " X: 8192
2514 Xpath 16384 " X: 16384
2516 Xpath 32768 " X: 32768
2526 Xpath 1048576 " X: 0
2528 Xpath 2097152 " X: 2097152
2530 Xpath 4194304 " X: 4194304
2532 Xpath 8388608 " X: 0
2534 Xpath 16777216 " X: 16777216
2536 Xpath 33554432 " X: 33554432
2539 Xpath 67108864 " X: 0
2541 Xpath 134217728 " X: 134217728
2543 Xpath 268435456 " X: 0
2545 Xpath 536870912 " X: 0
2547 Xpath 1073741824 " X: 0
2553 "-------------------------------------------------------------------------------
2554 " Test 31: Executing :finally clauses after :throw {{{1
2556 " After a :throw dynamically enclosed in a :try/:endtry region,
2557 " :finally clauses are executed and the script processing is
2559 "-------------------------------------------------------------------------------
2568 Xloop 1 " X: 1 + 1*16
2572 Xloop 4 " X: 4 + 4*16
2584 Xpath 2048 " X: 2048
2586 Xpath 4096 " X: 4096
2588 Xpath 8192 " X: 8192
2590 Xpath 16384 " X: 16384
2592 Xpath 32768 " X: 32768
2602 Xpath 1048576 " X: 0
2604 Xpath 2097152 " X: 2097152
2606 Xpath 4194304 " X: 4194304
2608 Xpath 8388608 " X: 0
2610 Xpath 16777216 " X: 16777216
2612 Xpath 33554432 " X: 33554432
2615 Xpath 67108864 " X: 0
2617 Xpath 134217728 " X: 134217728
2619 Xpath 268435456 " X: 0
2621 Xpath 536870912 " X: 0
2623 Xpath 1073741824 " X: 0
2629 "-------------------------------------------------------------------------------
2630 " Test 32: Remembering the :return value on :finally {{{1
2632 " If a :finally clause is executed due to a :return specifying
2633 " a value, this is the value visible to the caller if not overwritten
2634 " by a new :return in the :finally clause. A :return without a value
2635 " in the :finally clause overwrites with value 0.
2636 "-------------------------------------------------------------------------------
2664 return 16 + strlen(F())
2672 Xpath 4096 " X: 4096
2676 Xpath 16384 " X: 16384
2685 Xpath 131072 " X: 131072
2687 Xpath 262144 " X: 262144
2688 return G() + H() + 64
2691 Xpath 1048576 " X: 0
2695 Xpath 2097152 " X: 2097152
2698 Xpath 4194304 " X: 0
2701 Xpath 8388608 " X: 0
2704 Xpath 16777216 " X: 16777216
2707 Xpath 33554432 " X: 0
2710 Xpath 67108864 " X: 67108864
2713 Xpath 134217728 " X: 0
2716 Xpath 268435456 " X: 268435456
2719 Xpath 536870912 " X: 0
2731 "-------------------------------------------------------------------------------
2732 " Test 33: :return under :execute or user command and :finally {{{1
2734 " A :return command may be executed under an ":execute" or from
2735 " a user command. Executing of :finally clauses and passing through
2736 " the return code works also then.
2737 "-------------------------------------------------------------------------------
2740 command! -nargs=? RETURN
2741 \ try | return <args> | finally | return <args> * 2 | endtry
2767 execute "try | return 512 | finally | return 1024 | endtry"
2777 execute "try | return 2048 | finally | return 4096 | endtry"
2780 Xpath 2048 " X: 2048
2781 execute "try | return 8192 | finally | return 16384 | endtry"
2792 Xpath 32768 " X: 32768
2801 execute "try | return 131072 | finally | return 262144 | endtry"
2804 Xpath 524288 " X: 524288
2805 execute "try | return 524288 | finally | return | endtry"
2806 Xpath 1048576 " X: 0
2808 Xpath 2097152 " X: 0
2814 Xpath 4194304 " X: 0
2816 Xpath 8388608 " X: 8388608
2818 Xpath 16777216 " X: 0
2820 Xpath 33554432 " X: 0
2826 Xpath 67108864 " X: 0
2828 Xpath 134217728 " X: 134217728
2829 execute "try | return 4194304 | finally | return 8388608 | endtry"
2830 Xpath 268435456 " X: 0
2832 Xpath 536870912 " X: 0
2840 execute "try | return 67108864 | finally | return 134217728 | endtry"
2843 let sum = F() + G() + H() + I() + J() + K() + L() + M()
2844 let expected = 16 + 256 + 1024 + 16384 + 0 + 0 + 2097152 + 8388608
2845 let sum = sum + N() + O()
2846 let expected = expected + 33554432 + 134217728
2849 Xout "sum = " . sum . " (ok)"
2851 Xout "sum = " . sum . ", expected: " . expected
2854 Xpath 1073741824 " X: 1073741824
2857 " The Xpath command does not accept 2^31 (negative); add explicitly:
2858 let Xpath = Xpath + 2147483648 " X: 0
2876 "-------------------------------------------------------------------------------
2877 " Test 34: :finally reason discarded by :continue {{{1
2879 " When a :finally clause is executed due to a :continue, :break,
2880 " :return, :finish, error, interrupt or :throw, the jump reason is
2881 " discarded by a :continue in the finally clause.
2882 "-------------------------------------------------------------------------------
2897 if a:jump == "continue"
2899 elseif a:jump == "break"
2901 elseif a:jump == "return" || a:jump == "finish"
2903 elseif a:jump == "error"
2905 elseif a:jump == "interrupt"
2908 elseif a:jump == "throw"
2912 continue " discards jump that caused the :finally
2917 Xloop 4 " X: 4*(1+8+64+512+4096+32768+262144)
2923 Xpath 2097152 " X: 2097152
2925 Xpath 4194304 " X: 4194304
2927 Xpath 8388608 " X: 8388608
2928 let g:jump = "finish"
2931 Xpath 16777216 " X: 16777216
2934 Xpath 33554432 " X: 33554432
2936 Xpath 67108864 " X: 67108864
2939 Xpath 134217728 " X: 134217728
2941 Xpath 268435456 " X: 268435456
2943 Xpath 536870912 " X: 536870912
2946 Xpath 1073741824 " X: 1073741824
2955 "-------------------------------------------------------------------------------
2956 " Test 35: :finally reason discarded by :break {{{1
2958 " When a :finally clause is executed due to a :continue, :break,
2959 " :return, :finish, error, interrupt or :throw, the jump reason is
2960 " discarded by a :break in the finally clause.
2961 "-------------------------------------------------------------------------------
2976 if a:jump == "continue"
2978 elseif a:jump == "break"
2980 elseif a:jump == "return" || a:jump == "finish"
2982 elseif a:jump == "error"
2984 elseif a:jump == "interrupt"
2987 elseif a:jump == "throw"
2991 break " discards jump that caused the :finally
2998 Xloop 4 " X: 4*(1+8+64+512+4096+32768+262144)
3002 Xpath 2097152 " X: 2097152
3004 Xpath 4194304 " X: 4194304
3006 Xpath 8388608 " X: 8388608
3007 let g:jump = "finish"
3010 Xpath 16777216 " X: 16777216
3013 Xpath 33554432 " X: 33554432
3015 Xpath 67108864 " X: 67108864
3018 Xpath 134217728 " X: 134217728
3020 Xpath 268435456 " X: 268435456
3022 Xpath 536870912 " X: 536870912
3025 Xpath 1073741824 " X: 1073741824
3034 "-------------------------------------------------------------------------------
3035 " Test 36: :finally reason discarded by :return {{{1
3037 " When a :finally clause is executed due to a :continue, :break,
3038 " :return, :finish, error, interrupt or :throw, the jump reason is
3039 " discarded by a :return in the finally clause.
3040 "-------------------------------------------------------------------------------
3048 function! R(jump, retval) abort
3055 if a:jump == "continue"
3057 elseif a:jump == "break"
3059 elseif a:jump == "return"
3061 elseif a:jump == "error"
3063 elseif a:jump == "interrupt"
3066 elseif a:jump == "throw"
3070 return a:retval " discards jump that caused the :finally
3080 let sum = -R("continue", -8)
3081 Xpath 2097152 " X: 2097152
3082 let sum = sum - R("break", -16)
3083 Xpath 4194304 " X: 4194304
3084 let sum = sum - R("return", -32)
3085 Xpath 8388608 " X: 8388608
3087 let sum = sum - R("error", -64)
3088 Xpath 16777216 " X: 16777216
3090 Xpath 33554432 " X: 33554432
3092 let sum = sum - R("interrupt", -128)
3093 Xpath 67108864 " X: 67108864
3095 Xpath 134217728 " X: 134217728
3096 let sum = sum - R("throw", -256)
3097 Xpath 268435456 " X: 268435456
3100 Xpath 536870912 " X: 536870912
3102 let expected = 8 + 16 + 32 + 64 + 128 + 256
3104 Xpath 1073741824 " X: 0
3105 Xout "sum =" . sum . ", expected: " . expected
3116 "-------------------------------------------------------------------------------
3117 " Test 37: :finally reason discarded by :finish {{{1
3119 " When a :finally clause is executed due to a :continue, :break,
3120 " :return, :finish, error, interrupt or :throw, the jump reason is
3121 " discarded by a :finish in the finally clause.
3122 "-------------------------------------------------------------------------------
3130 function! F(jump) " not executed as function, transformed to a script
3137 if a:jump == "continue"
3139 elseif a:jump == "break"
3141 elseif a:jump == "finish"
3143 elseif a:jump == "error"
3145 elseif a:jump == "interrupt"
3148 elseif a:jump == "throw"
3152 finish " discards jump that caused the :finally
3162 let scriptF = MakeScript("F")
3165 let g:jump = "continue"
3166 exec "source" scriptF
3167 Xpath 2097152 " X: 2097152
3168 let g:jump = "break"
3169 exec "source" scriptF
3170 Xpath 4194304 " X: 4194304
3171 let g:jump = "finish"
3172 exec "source" scriptF
3173 Xpath 8388608 " X: 8388608
3175 let g:jump = "error"
3176 exec "source" scriptF
3177 Xpath 16777216 " X: 16777216
3179 Xpath 33554432 " X: 33554432
3181 let g:jump = "interrupt"
3182 exec "source" scriptF
3183 Xpath 67108864 " X: 67108864
3185 Xpath 134217728 " X: 134217728
3187 let g:jump = "throw"
3188 exec "source" scriptF
3189 Xpath 268435456 " X: 268435456
3191 Xpath 536870912 " X: 536870912
3197 call delete(scriptF)
3205 "-------------------------------------------------------------------------------
3206 " Test 38: :finally reason discarded by an error {{{1
3208 " When a :finally clause is executed due to a :continue, :break,
3209 " :return, :finish, error, interrupt or :throw, the jump reason is
3210 " discarded by an error in the finally clause.
3211 "-------------------------------------------------------------------------------
3226 if a:jump == "continue"
3228 elseif a:jump == "break"
3230 elseif a:jump == "return" || a:jump == "finish"
3232 elseif a:jump == "error"
3234 elseif a:jump == "interrupt"
3237 elseif a:jump == "throw"
3241 asdf " error; discards jump that caused the :finally
3251 Xpath 16384 " X: 16384
3256 Xpath 65536 " X: 65536
3261 Xpath 262144 " X: 262144
3266 Xpath 1048576 " X: 1048576
3267 let g:jump = "finish"
3269 Xpath 2097152 " X: 0
3273 Xpath 4194304 " X: 4194304
3275 Xpath 8388608 " X: 0
3278 Xpath 16777216 " X: 16777216
3280 Xpath 33554432 " X: 0
3283 Xpath 67108864 " X: 67108864
3285 Xpath 134217728 " X: 0
3287 Xpath 268435456 " X: 268435456
3296 Xpath 536870912 " X: 0
3303 "-------------------------------------------------------------------------------
3304 " Test 39: :finally reason discarded by an interrupt {{{1
3306 " When a :finally clause is executed due to a :continue, :break,
3307 " :return, :finish, error, interrupt or :throw, the jump reason is
3308 " discarded by an interrupt in the finally clause.
3309 "-------------------------------------------------------------------------------
3324 if a:jump == "continue"
3326 elseif a:jump == "break"
3328 elseif a:jump == "return" || a:jump == "finish"
3330 elseif a:jump == "error"
3332 elseif a:jump == "interrupt"
3335 elseif a:jump == "throw"
3339 "INTERRUPT - discards jump that caused the :finally
3350 Xpath 16384 " X: 16384
3355 Xpath 65536 " X: 65536
3360 Xpath 262144 " X: 262144
3365 Xpath 1048576 " X: 1048576
3366 let g:jump = "finish"
3368 Xpath 2097152 " X: 0
3372 Xpath 4194304 " X: 4194304
3374 Xpath 8388608 " X: 0
3377 Xpath 16777216 " X: 16777216
3379 Xpath 33554432 " X: 0
3382 Xpath 67108864 " X: 67108864
3384 Xpath 134217728 " X: 0
3386 Xpath 268435456 " X: 268435456
3395 Xpath 536870912 " X: 0
3402 "-------------------------------------------------------------------------------
3403 " Test 40: :finally reason discarded by :throw {{{1
3405 " When a :finally clause is executed due to a :continue, :break,
3406 " :return, :finish, error, interrupt or :throw, the jump reason is
3407 " discarded by a :throw in the finally clause.
3408 "-------------------------------------------------------------------------------
3423 if a:jump == "continue"
3425 elseif a:jump == "break"
3427 elseif a:jump == "return" || a:jump == "finish"
3429 elseif a:jump == "error"
3431 elseif a:jump == "interrupt"
3434 elseif a:jump == "throw"
3438 throw "xyz" " discards jump that caused the :finally
3448 Xpath 16384 " X: 16384
3453 Xpath 65536 " X: 65536
3458 Xpath 262144 " X: 262144
3463 Xpath 1048576 " X: 1048576
3464 let g:jump = "finish"
3466 Xpath 2097152 " X: 0
3470 Xpath 4194304 " X: 4194304
3472 Xpath 8388608 " X: 0
3475 Xpath 16777216 " X: 16777216
3477 Xpath 33554432 " X: 0
3480 Xpath 67108864 " X: 67108864
3482 Xpath 134217728 " X: 0
3484 Xpath 268435456 " X: 268435456
3493 Xpath 536870912 " X: 0
3500 "-------------------------------------------------------------------------------
3501 " Test 41: Skipped :throw finding next command {{{1
3503 " A :throw in an inactive conditional must not hide a following
3505 "-------------------------------------------------------------------------------
3511 if 0 | throw "never" | endif | Xpath 2 " X: 2
3517 while 0 | throw "never" | endwhile | Xpath 16 " X: 16
3523 if 0 | try | throw "never" | endtry | endif | Xpath 128 " X: 128
3530 Xpath 1024 " X: 1024
3532 Xpath 2048 " X: 2048
3535 Xout v:exception "in" v:throwpoint
3538 Xpath 8192 " X: 8192
3541 Xpath 16384 " X: 16384
3543 Xpath 32768 " X: 32768
3546 Xout v:exception "in" v:throwpoint
3549 Xpath 131072 " X: 131072
3552 Xpath 262144 " X: 262144
3554 Xpath 524288 " X: 524288
3556 Xpath 1048576 " X: 0
3557 Xout v:exception "in" v:throwpoint
3560 Xpath 2097152 " X: 2097152
3569 "-------------------------------------------------------------------------------
3570 " Test 42: Catching number and string exceptions {{{1
3572 " When a number is thrown, it is converted to a string exception.
3573 " Numbers and strings may be caught by specifying a regular exception
3574 " as argument to the :catch command.
3575 "-------------------------------------------------------------------------------
3610 Xpath 2048 " X: 2048
3614 Xpath 4096 " X: 4096
3618 Xpath 16384 " X: 16384
3622 Xpath 32768 " X: 32768
3626 Xpath 131072 " X: 131072
3630 Xpath 262144 " X: 262144
3634 Xpath 1048576 " X: 1048576
3638 Xpath 2097152 " X: 2097152
3640 Xpath 4194304 " X: 0
3642 Xpath 8388608 " X: 8388608
3647 Xpath 16777216 " X: 16777216
3649 Xpath 33554432 " X: 0
3651 Xpath 67108864 " X: 0
3654 Xpath 134217728 " X: 134217728
3658 Xpath 268435456 " X: 268435456
3660 Xpath 536870912 " X: 0
3662 Xpath 1073741824 " X: 1073741824
3666 " The Xpath command does not accept 2^31 (negative); add explicitly:
3667 let Xpath = Xpath + 2147483648 " X: 0
3668 Xout v:exception "in" v:throwpoint
3674 "-------------------------------------------------------------------------------
3675 " Test 43: Selecting the correct :catch clause {{{1
3677 " When an exception is thrown and there are multiple :catch clauses,
3678 " the first matching one is taken.
3679 "-------------------------------------------------------------------------------
3696 Xloop 16 " X: 16*1024*1024
3701 Xloop 64 " X: 64*1024*1024
3703 Xloop 128 " X: 128*1024
3710 let loops = loops - 1
3713 Xpath 1073741824 " X: 1073741824
3720 "-------------------------------------------------------------------------------
3721 " Test 44: Missing or empty :catch patterns {{{1
3723 " A missing or empty :catch pattern means the same as /.*/, that is,
3724 " catches everything. To catch only empty exceptions, /^$/ must be
3725 " used. A :catch with missing, empty, or /.*/ argument also works
3726 " when followed by another command separated by a bar on the same
3727 " line. :catch patterns cannot be specified between ||. But other
3728 " pattern separators can be used instead of //.
3729 "-------------------------------------------------------------------------------
3768 Xpath 1024 " X: 1024
3772 Xpath 2048 " X: 2048
3777 Xpath 8192 " X: 8192
3781 Xpath 16384 " X: 16384
3786 Xpath 65536 " X: 65536
3789 try | Xpath 131072 | throw "x" | catch /.*/ | Xpath 262144 | endtry
3790 " X: 131072 + 262144
3792 try | Xpath 524288 | throw "y" | catch // | Xpath 1048576 | endtry
3793 " X: 524288 + 1048576
3799 " Extra try level: if ":catch" without arguments below raises
3800 " a syntax error because it misinterprets the "Xpath" as a pattern,
3801 " let it be caught by the ":catch /.*/" below.
3803 try | Xpath 2097152 | throw "z" | catch | Xpath 4194304 | :
3804 endtry " X: 2097152 + 4194304
3808 Xout v:exception "in" v:throwpoint
3810 if $VIMNOERRTHROW && v:errmsg != ""
3813 if caught || $VIMNOERRTHROW && v:errmsg != ""
3814 Xpath 8388608 " X: 0
3816 break " discard error for $VIMNOERRTHROW
3823 Xpath 16777216 " X: 16777216
3824 throw "throw cologne"
3825 " Next lines catches all and throws 4711:
3826 catch |throw cologne|
3827 Xpath 33554432 " X: 0
3830 Xpath 67108864 " X: 67108864
3834 Xpath 134217728 " X: 134217728
3837 Xpath 268435456 " X: 268435456
3840 Xpath 536870912 " X: 536870912
3842 Xpath 1073741824 " X: 0
3843 Xout v:exception "in" v:throwpoint
3846 unlet! caught cologne
3851 "-------------------------------------------------------------------------------
3852 " Test 45: Catching exceptions from nested :try blocks {{{1
3854 " When :try blocks are nested, an exception is caught by the innermost
3855 " try conditional that has a matching :catch clause.
3856 "-------------------------------------------------------------------------------
3876 Xloop 16 " X: 16*1024*1024
3881 Xloop 64 " X: 64*1024*1024
3884 Xloop 128 " X: 128*1024
3893 let loops = loops - 1
3896 Xpath 1073741824 " X: 1073741824
3903 "-------------------------------------------------------------------------------
3904 " Test 46: Executing :finally after a :throw in nested :try {{{1
3906 " When an exception is thrown from within nested :try blocks, the
3907 " :finally clauses of the non-catching try conditionals should be
3908 " executed before the matching :catch of the next surrounding :try
3909 " gets the control. If this also has a :finally clause, it is
3910 " executed afterwards.
3911 "-------------------------------------------------------------------------------
3942 Xpath 2048 " X: 2048
3950 Xpath 16384 " X: 16384
3958 Xpath 131072 " X: 131072
3964 Xpath 524288 " X: 524288
3966 Xpath 1048576 " X: 0
3970 Xpath 65536 " X: 65536
3980 "-------------------------------------------------------------------------------
3981 " Test 47: Throwing exceptions from a :catch clause {{{1
3983 " When an exception is thrown from a :catch clause, it should not be
3984 " caught by a :catch of the same :try conditional. After executing
3985 " the :finally clause (if present), surrounding try conditionals
3986 " should be checked for a matching :catch.
3987 "-------------------------------------------------------------------------------
4011 Xpath 1024 " X: 1024
4019 Xpath 16384 " X: 16384
4031 Xpath 1048576 " X: 0
4033 Xpath 2097152 " X: 2097152
4035 Xpath 4194304 " X: 0
4037 Xpath 8388608 " X: 0
4039 Xpath 16777216 " X: 0
4041 Xpath 33554432 " X: 33554432
4043 Xpath 67108864 " X: 67108864
4045 Xpath 134217728 " X: 0
4046 Xout v:exception "in" v:throwpoint
4048 Xpath 268435456 " X: 268435456
4053 "-------------------------------------------------------------------------------
4054 " Test 48: Throwing exceptions from a :finally clause {{{1
4056 " When an exception is thrown from a :finally clause, it should not be
4057 " caught by a :catch of the same :try conditional. Surrounding try
4058 " conditionals should be checked for a matching :catch. A previously
4059 " thrown exception is discarded.
4060 "-------------------------------------------------------------------------------
4092 Xpath 2048 " X: 2048
4100 Xpath 32768 " X: 32768
4102 Xpath 65536 " X: 65536
4107 Xpath 131072 " X: 131072
4113 Xpath 1048576 " X: 1048576
4114 throw "x5" " discards "x4"
4115 Xpath 2097152 " X: 0
4117 Xpath 4194304 " X: 0
4119 Xpath 8388608 " X: 0
4121 Xpath 16777216 " X: 16777216
4123 Xpath 33554432 " X: 0
4125 Xpath 67108864 " X: 67108864
4127 Xpath 134217728 " X: 134217728
4130 Xpath 268435456 " X: 0
4131 Xout v:exception "in" v:throwpoint
4133 Xpath 536870912 " X: 536870912
4138 "-------------------------------------------------------------------------------
4139 " Test 49: Throwing exceptions across functions {{{1
4141 " When an exception is thrown but not caught inside a function, the
4142 " caller is checked for a matching :catch clause.
4143 "-------------------------------------------------------------------------------
4163 Xloop 1 " X: 16 + 16*16
4167 Xloop 4 " X: 64 + 64*16
4174 Xpath 4096 " X: 4096
4178 Xpath 16384 " X: 16384
4184 Xpath 65536 " X: 65536
4185 call C() " throw and catch
4186 Xpath 131072 " X: 131072
4189 Xout v:exception "in" v:throwpoint
4193 Xpath 524288 " X: 524288
4194 call T1() " throw, one level
4195 Xpath 1048576 " X: 0
4197 Xpath 2097152 " X: 2097152
4199 Xpath 4194304 " X: 0
4200 Xout v:exception "in" v:throwpoint
4204 Xpath 8388608 " X: 8388608
4205 call T2() " throw, two levels
4206 Xpath 16777216 " X: 0
4208 Xpath 33554432 " X: 33554432
4210 Xpath 67108864 " X: 0
4211 Xout v:exception "in" v:throwpoint
4213 Xpath 134217728 " X: 134217728
4217 " Leave C, T1, and T2 for execution as scripts in the next test.
4220 "-------------------------------------------------------------------------------
4221 " Test 50: Throwing exceptions across script files {{{1
4223 " When an exception is thrown but not caught inside a script file,
4224 " the sourcing script or function is checked for a matching :catch
4227 " This test executes the bodies of the functions C, T1, and T2 from
4228 " the previous test as script files (:return replaced by :finish).
4229 "-------------------------------------------------------------------------------
4233 let scriptC = MakeScript("C") " X: 1 + 4 + 8
4238 let scriptT1 = MakeScript("T1") " X: 16 + 64 + 16*16 + 64*16
4241 let scriptT2 = MakeScript("T2", scriptT1) " X: 4096 + 16384
4246 Xpath 65536 " X: 65536
4247 exec "source" g:scriptC
4248 Xpath 131072 " X: 131072
4251 Xout v:exception "in" v:throwpoint
4255 Xpath 524288 " X: 524288
4256 exec "source" g:scriptT1
4257 Xpath 1048576 " X: 0
4259 Xpath 2097152 " X: 2097152
4261 Xpath 4194304 " X: 0
4262 Xout v:exception "in" v:throwpoint
4267 Xpath 8388608 " X: 8388608
4269 Xpath 16777216 " X: 16777216
4270 exec "source" scriptT2
4271 Xpath 33554432 " X: 0
4273 Xpath 67108864 " X: 67108864
4275 Xpath 134217728 " X: 0
4276 Xout v:exception "in" v:throwpoint
4278 Xpath 268435456 " X: 268435456
4280 call delete(scriptC)
4281 call delete(scriptT1)
4282 call delete(scriptT2)
4283 unlet scriptC scriptT1 scriptT2
4289 "-------------------------------------------------------------------------------
4290 " Test 51: Throwing exceptions across :execute and user commands {{{1
4292 " A :throw command may be executed under an ":execute" or from
4294 "-------------------------------------------------------------------------------
4298 command! -nargs=? THROW1 throw <args> | throw 1
4299 command! -nargs=? THROW2 try | throw <args> | endtry | throw 2
4300 command! -nargs=? THROW3 try | throw 3 | catch /3/ | throw <args> | endtry
4301 command! -nargs=? THROW4 try | throw 4 | finally | throw <args> | endtry
4343 Xpath 1024 " X: 1024
4351 Xpath 4096 " X: 4096
4352 execute 'throw "E" | throw 5'
4354 Xpath 8192 " X: 8192
4362 Xpath 32768 " X: 32768
4363 execute 'try | throw "F" | endtry | throw 6'
4365 Xpath 65536 " X: 65536
4373 Xpath 262144 " X: 262144
4374 execute'try | throw 7 | catch /7/ | throw "G" | endtry'
4376 Xpath 524288 " X: 524288
4379 Xpath 1048576 " X: 0
4384 Xpath 2097152 " X: 2097152
4385 execute 'try | throw 8 | finally | throw "H" | endtry'
4387 Xpath 4194304 " X: 4194304
4390 Xpath 8388608 " X: 0
4394 Xpath 16777216 " X: 0
4395 Xout v:exception "in" v:throwpoint
4398 Xpath 33554432 " X: 33554432
4408 "-------------------------------------------------------------------------------
4409 " Test 52: Uncaught exceptions {{{1
4411 " When an exception is thrown but not caught, an error message is
4412 " displayed when the script is terminated. In case of an interrupt
4413 " or error exception, the normal interrupt or error message(s) are
4415 "-------------------------------------------------------------------------------
4419 let msgfile = tempname()
4421 function! MESSAGES(...)
4423 exec "edit" g:msgfile
4428 let english = v:lang == "C" || v:lang =~ '^[Ee]n'
4435 let enr = a:{2*cnt - 1}
4440 Xout "TODO: Add message number for:" emsg
4444 if enr == "" && !english
4447 let pattern = (enr != "") ? enr . ':.*' : ''
4449 let pattern = pattern . emsg
4451 if !search(pattern, "W")
4453 Xout "No match for:" pattern
4462 if ExtraVim(msgfile)
4468 if !MESSAGES('E605', "Exception not caught")
4472 if ExtraVim(msgfile)
4483 if !MESSAGES('E605', "Exception not caught")
4487 if ExtraVim(msgfile)
4502 Xpath 2048 " X: 2048
4503 if !MESSAGES('E605', "Exception not caught")
4507 if ExtraVim(msgfile)
4509 Xpath 8192 " X: 8192
4512 Xpath 16384 " X: 16384
4518 Xpath 65536 " X: 65536
4519 if !MESSAGES('E605', "Exception not caught")
4523 if ExtraVim(msgfile)
4525 Xpath 262144 " X: 262144
4531 Xpath 1048576 " X: 1048576
4532 if !MESSAGES('INT', "Interrupted")
4533 Xpath 2097152 " X: 0
4536 if ExtraVim(msgfile)
4538 Xpath 4194304 " X: 4194304
4539 let x = novar " error E121/E15; exception: E121
4540 catch /E15:/ " should not catch
4541 Xpath 8388608 " X: 0
4543 Xpath 16777216 " X: 0
4546 Xpath 33554432 " X: 33554432
4547 if !MESSAGES('E121', "Undefined variable", 'E15', "Invalid expression")
4548 Xpath 67108864 " X: 0
4551 if ExtraVim(msgfile)
4553 Xpath 134217728 " X: 134217728
4554 " unlet novar # " error E108/E488; exception: E488
4555 catch /E108:/ " should not catch
4556 Xpath 268435456 " X: 0
4558 Xpath 536870912 " X: 0
4561 Xpath 1073741824 " X: 1073741824
4562 if !MESSAGES('E108', "No such variable", 'E488', "Trailing characters")
4563 " The Xpath command does not accept 2^31 (negative); add explicitly:
4564 let Xpath = Xpath + 2147483648 " X: 0
4567 call delete(msgfile)
4572 " Leave MESSAGES() for the next tests.
4575 "-------------------------------------------------------------------------------
4576 " Test 53: Nesting errors: :endif/:else/:elseif {{{1
4578 " For nesting errors of :if conditionals the correct error messages
4581 " This test reuses the function MESSAGES() from the previous test.
4582 " This functions checks the messages in g:msgfile.
4583 "-------------------------------------------------------------------------------
4587 let msgfile = tempname()
4589 if ExtraVim(msgfile)
4592 if MESSAGES('E580', ":endif without :if")
4596 if ExtraVim(msgfile)
4601 if MESSAGES('E580', ":endif without :if")
4605 if ExtraVim(msgfile)
4611 if MESSAGES('E580', ":endif without :if")
4615 if ExtraVim(msgfile)
4620 if MESSAGES('E580', ":endif without :if")
4624 if ExtraVim(msgfile)
4631 if MESSAGES('E580', ":endif without :if")
4635 if ExtraVim(msgfile)
4638 if MESSAGES('E581', ":else without :if")
4642 if ExtraVim(msgfile)
4647 if MESSAGES('E581', ":else without :if")
4651 if ExtraVim(msgfile)
4657 if MESSAGES('E581', ":else without :if")
4661 if ExtraVim(msgfile)
4666 if MESSAGES('E581', ":else without :if")
4670 if ExtraVim(msgfile)
4677 if MESSAGES('E581', ":else without :if")
4681 if ExtraVim(msgfile)
4684 if MESSAGES('E582', ":elseif without :if")
4685 Xpath 1024 " X: 1024
4688 if ExtraVim(msgfile)
4693 if MESSAGES('E582', ":elseif without :if")
4694 Xpath 2048 " X: 2048
4697 if ExtraVim(msgfile)
4703 if MESSAGES('E582', ":elseif without :if")
4704 Xpath 4096 " X: 4096
4707 if ExtraVim(msgfile)
4712 if MESSAGES('E582', ":elseif without :if")
4713 Xpath 8192 " X: 8192
4716 if ExtraVim(msgfile)
4723 if MESSAGES('E582', ":elseif without :if")
4724 Xpath 16384 " X: 16384
4727 if ExtraVim(msgfile)
4733 if MESSAGES('E583', "multiple :else")
4734 Xpath 32768 " X: 32768
4737 if ExtraVim(msgfile)
4743 if MESSAGES('E584', ":elseif after :else")
4744 Xpath 65536 " X: 65536
4747 call delete(msgfile)
4752 " Leave MESSAGES() for the next test.
4755 "-------------------------------------------------------------------------------
4756 " Test 54: Nesting errors: :while/:endwhile {{{1
4758 " For nesting errors of :while conditionals the correct error messages
4761 " This test reuses the function MESSAGES() from the previous test.
4762 " This functions checks the messages in g:msgfile.
4763 "-------------------------------------------------------------------------------
4767 let msgfile = tempname()
4769 if ExtraVim(msgfile)
4772 if MESSAGES('E588', ":endwhile without :while")
4776 if ExtraVim(msgfile)
4781 if MESSAGES('E588', ":endwhile without :while")
4785 if ExtraVim(msgfile)
4790 if MESSAGES('E171', "Missing :endif")
4794 if ExtraVim(msgfile)
4800 if MESSAGES('E588', ":endwhile without :while")
4804 if ExtraVim(msgfile)
4810 if MESSAGES('E600', "Missing :endtry")
4814 if ExtraVim(msgfile)
4821 if MESSAGES('E600', "Missing :endtry")
4825 if ExtraVim(msgfile)
4832 if MESSAGES('E171', "Missing :endif")
4836 if ExtraVim(msgfile)
4841 if MESSAGES('E588', ":endwhile without :while")
4845 if ExtraVim(msgfile)
4852 if MESSAGES('E588', ":endwhile without :while")
4856 if ExtraVim(msgfile)
4863 if MESSAGES('E588', ":endwhile without :while")
4867 if ExtraVim(msgfile)
4876 if MESSAGES('E588', ":endwhile without :while")
4877 Xpath 1024 " X: 1024
4881 call delete(msgfile)
4886 " Leave MESSAGES() for the next test.
4889 "-------------------------------------------------------------------------------
4890 " Test 55: Nesting errors: :continue/:break {{{1
4892 " For nesting errors of :continue and :break commands the correct
4893 " error messages should be given.
4895 " This test reuses the function MESSAGES() from the previous test.
4896 " This functions checks the messages in g:msgfile.
4897 "-------------------------------------------------------------------------------
4901 let msgfile = tempname()
4903 if ExtraVim(msgfile)
4906 if MESSAGES('E586', ":continue without :while")
4910 if ExtraVim(msgfile)
4915 if MESSAGES('E586', ":continue without :while")
4919 if ExtraVim(msgfile)
4925 if MESSAGES('E586', ":continue without :while")
4929 if ExtraVim(msgfile)
4934 if MESSAGES('E586', ":continue without :while")
4938 if ExtraVim(msgfile)
4945 if MESSAGES('E586', ":continue without :while")
4949 if ExtraVim(msgfile)
4952 if MESSAGES('E587', ":break without :while")
4956 if ExtraVim(msgfile)
4961 if MESSAGES('E587', ":break without :while")
4965 if ExtraVim(msgfile)
4971 if MESSAGES('E587', ":break without :while")
4975 if ExtraVim(msgfile)
4980 if MESSAGES('E587', ":break without :while")
4984 if ExtraVim(msgfile)
4991 if MESSAGES('E587', ":break without :while")
4995 call delete(msgfile)
5000 " Leave MESSAGES() for the next test.
5003 "-------------------------------------------------------------------------------
5004 " Test 56: Nesting errors: :endtry {{{1
5006 " For nesting errors of :try conditionals the correct error messages
5009 " This test reuses the function MESSAGES() from the previous test.
5010 " This functions checks the messages in g:msgfile.
5011 "-------------------------------------------------------------------------------
5015 let msgfile = tempname()
5017 if ExtraVim(msgfile)
5020 if MESSAGES('E602', ":endtry without :try")
5024 if ExtraVim(msgfile)
5029 if MESSAGES('E602', ":endtry without :try")
5033 if ExtraVim(msgfile)
5038 if MESSAGES('E602', ":endtry without :try")
5042 if ExtraVim(msgfile)
5047 if MESSAGES('E171', "Missing :endif")
5051 if ExtraVim(msgfile)
5056 if MESSAGES('E170', "Missing :endwhile")
5060 if ExtraVim(msgfile)
5066 if MESSAGES('E171', "Missing :endif")
5070 if ExtraVim(msgfile)
5076 if MESSAGES('E170', "Missing :endwhile")
5080 if ExtraVim(msgfile)
5087 if MESSAGES('E171', "Missing :endif")
5091 if ExtraVim(msgfile)
5098 if MESSAGES('E170', "Missing :endwhile")
5102 call delete(msgfile)
5105 delfunction MESSAGES
5110 "-------------------------------------------------------------------------------
5111 " Test 57: v:exception and v:throwpoint for user exceptions {{{1
5113 " v:exception evaluates to the value of the exception that was caught
5114 " most recently and is not finished. (A caught exception is finished
5115 " when the next ":catch", ":finally", or ":endtry" is reached.)
5116 " v:throwpoint evaluates to the script/function name and line number
5117 " where that exception has been thrown.
5118 "-------------------------------------------------------------------------------
5122 function! FuncException()
5123 let g:exception = v:exception
5126 function! FuncThrowpoint()
5127 let g:throwpoint = v:throwpoint
5130 let scriptException = MakeScript("FuncException")
5131 let scriptThrowPoint = MakeScript("FuncThrowpoint")
5133 command! CmdException let g:exception = v:exception
5134 command! CmdThrowpoint let g:throwpoint = v:throwpoint
5138 function! CHECK(n, exception, throwname, throwline)
5141 if v:exception != a:exception
5142 Xout a:n.": v:exception is" v:exception "instead of" a:exception
5145 if v:throwpoint !~ a:throwname
5146 let name = escape(a:throwname, '\')
5147 Xout a:n.": v:throwpoint (".v:throwpoint.") does not match" name
5150 if v:throwpoint !~ a:throwline
5151 let line = escape(a:throwline, '\')
5152 Xout a:n.": v:throwpoint (".v:throwpoint.") does not match" line
5160 function! T(arg, line)
5162 throw a:arg " in line 2
5164 throw a:arg " in line 4
5166 throw a:arg " in line 6
5168 throw a:arg " in line 8
5172 function! G(arg, line)
5173 call T(a:arg, a:line)
5176 function! F(arg, line)
5177 call G(a:arg, a:line)
5180 let scriptT = MakeScript("T")
5181 let scriptG = MakeScript("G", scriptT)
5182 let scriptF = MakeScript("F", scriptG)
5185 Xpath 32768 " X: 32768
5188 Xpath 65536 " X: 65536
5189 let exception = v:exception
5190 let throwpoint = v:throwpoint
5191 call CHECK(1, "oops", '\<F\.\.G\.\.T\>', '\<2\>')
5192 exec "let exception = v:exception"
5193 exec "let throwpoint = v:throwpoint"
5194 call CHECK(2, "oops", '\<F\.\.G\.\.T\>', '\<2\>')
5197 call CHECK(3, "oops", '\<F\.\.G\.\.T\>', '\<2\>')
5198 call FuncException()
5199 call FuncThrowpoint()
5200 call CHECK(4, "oops", '\<F\.\.G\.\.T\>', '\<2\>')
5201 exec "source" scriptException
5202 exec "source" scriptThrowPoint
5203 call CHECK(5, "oops", '\<F\.\.G\.\.T\>', '\<2\>')
5205 Xpath 131072 " X: 131072
5208 Xpath 262144 " X: 262144
5209 let exception = v:exception
5210 let throwpoint = v:throwpoint
5211 call CHECK(6, "arrgh", '\<G\.\.T\>', '\<4\>')
5213 Xpath 524288 " X: 524288
5214 let g:arg = "autsch"
5216 exec "source" scriptF
5218 Xpath 1048576 " X: 1048576
5219 let exception = v:exception
5220 let throwpoint = v:throwpoint
5221 " Symbolic links in tempname()s are not resolved, whereas resolving
5222 " is done for v:throwpoint. Resolve the temporary file name for
5223 " scriptT, so that it can be matched against v:throwpoint.
5224 call CHECK(7, "autsch", resolve(scriptT), '\<6\>')
5226 Xpath 2097152 " X: 2097152
5227 let exception = v:exception
5228 let throwpoint = v:throwpoint
5229 call CHECK(8, "arrgh", '\<G\.\.T\>', '\<4\>')
5231 Xpath 4194304 " X: 4194304
5234 exec "source" scriptG
5236 Xpath 8388608 " X: 8388608
5237 let exception = v:exception
5238 let throwpoint = v:throwpoint
5239 " Resolve scriptT for matching it against v:throwpoint.
5240 call CHECK(9, "brrrr", resolve(scriptT), '\<8\>')
5242 Xpath 16777216 " X: 16777216
5243 let exception = v:exception
5244 let throwpoint = v:throwpoint
5245 call CHECK(10, "arrgh", '\<G\.\.T\>', '\<4\>')
5247 Xpath 33554432 " X: 33554432
5248 let exception = v:exception
5249 let throwpoint = v:throwpoint
5250 call CHECK(11, "arrgh", '\<G\.\.T\>', '\<4\>')
5252 Xpath 67108864 " X: 67108864
5253 let exception = v:exception
5254 let throwpoint = v:throwpoint
5255 call CHECK(12, "arrgh", '\<G\.\.T\>', '\<4\>')
5257 Xpath 134217728 " X: 134217728
5258 let exception = v:exception
5259 let throwpoint = v:throwpoint
5260 call CHECK(13, "oops", '\<F\.\.G\.\.T\>', '\<2\>')
5262 Xpath 268435456 " X: 268435456
5263 let exception = v:exception
5264 let throwpoint = v:throwpoint
5265 call CHECK(14, "oops", '\<F\.\.G\.\.T\>', '\<2\>')
5267 Xpath 536870912 " X: 536870912
5268 let exception = v:exception
5269 let throwpoint = v:throwpoint
5270 call CHECK(15, "", '^$', '^$')
5273 Xpath 1073741824 " X: 1073741824
5275 unlet exception throwpoint
5276 delfunction FuncException
5277 delfunction FuncThrowpoint
5278 call delete(scriptException)
5279 call delete(scriptThrowPoint)
5280 unlet scriptException scriptThrowPoint
5281 delcommand CmdException
5282 delcommand CmdThrowpoint
5286 call delete(scriptT)
5287 call delete(scriptG)
5288 call delete(scriptF)
5289 unlet scriptT scriptG scriptF
5294 "-------------------------------------------------------------------------------
5296 " Test 58: v:exception and v:throwpoint for error/interrupt exceptions {{{1
5298 " v:exception and v:throwpoint work also for error and interrupt
5300 "-------------------------------------------------------------------------------
5308 delfunction T " error (function in use) in line 2
5310 let dummy = 0 " INTERRUPT1 - interrupt in line 4
5321 if v:exception !~ 'Vim(delfunction):'
5324 if v:throwpoint !~ '\<T\>'
5327 if v:throwpoint !~ '\<2\>'
5332 if caught || $VIMNOERRTHROW
5335 if v:exception != ""
5338 if v:throwpoint != ""
5341 break " discard error for $VIMNOERRTHROW
5346 if v:exception != ""
5349 if v:throwpoint != ""
5355 Xpath 2048 " X: 2048
5360 if v:exception != 'Vim:Interrupt'
5363 if v:throwpoint !~ '\<T\>'
5366 if v:throwpoint !~ '\<4\>'
5370 Xpath 32768 " X: 32768
5371 if caught || $VIMNOINTTHROW
5372 Xpath 65536 " X: 65536
5374 if v:exception != ""
5377 if v:throwpoint != ""
5380 break " discard error for $VIMNOERRTHROW
5384 Xpath 524288 " X: 524288
5385 if v:exception != ""
5386 Xpath 1048576 " X: 0
5388 if v:throwpoint != ""
5389 Xpath 2097152 " X: 0
5397 "-------------------------------------------------------------------------------
5399 " Test 59: v:exception and v:throwpoint when discarding exceptions {{{1
5401 " When a :catch clause is left by a ":break" etc or an error or
5402 " interrupt exception, v:exception and v:throwpoint are reset. They
5403 " are not affected by an exception that is discarded before being
5405 "-------------------------------------------------------------------------------
5413 let sfile = expand("<sfile>")
5415 function! LineNumber()
5416 return substitute(substitute(v:throwpoint, g:sfile, '', ""),
5417 \ '\D*\(\d*\).*', '\1', "")
5420 command! -nargs=1 SetLineNumber
5421 \ try | throw "line" | catch /.*/ | let <args> = LineNumber() | endtry
5423 " Check v:exception/v:throwpoint against second/fourth parameter if
5424 " specified, check for being empty else.
5425 function! CHECK(n, ...)
5427 let exception = a:0 != 0 ? a:1 : "" " second parameter (optional)
5428 let emsg = a:0 != 0 ? a:2 : "" " third parameter (optional)
5429 let line = a:0 != 0 ? a:3 : 0 " fourth parameter (optional)
5432 " exception is the error number, emsg the English error message text
5433 if exception !~ '^E\d\+$'
5434 Xout "TODO: Add message number for:" emsg
5435 elseif v:lang == "C" || v:lang =~ '^[Ee]n'
5436 if exception == "E492" && emsg == "Not an editor command"
5437 let exception = '^Vim:' . exception . ': ' . emsg
5439 let exception = '^Vim(\a\+):' . exception . ': ' . emsg
5442 if exception == "E492"
5443 let exception = '^Vim:' . exception
5445 let exception = '^Vim(\a\+):' . exception
5449 if exception == "" && v:exception != ""
5450 Xout a:n.": v:exception is set:" v:exception
5452 elseif exception != "" && v:exception !~ exception
5453 Xout a:n.": v:exception (".v:exception.") does not match" exception
5456 if line == 0 && v:throwpoint != ""
5457 Xout a:n.": v:throwpoint is set:" v:throwpoint
5459 elseif line != 0 && v:throwpoint !~ '\<' . line . '\>'
5460 Xout a:n.": v:throwpoint (".v:throwpoint.") does not match" line
5464 Xloop 1 " X: 2097151
5496 SetLineNumber line_before_error
5501 call CHECK(4, 'E492', "Not an editor command",
5502 \ line_before_error + 1)
5505 if !errcaught && $VIMNOERRTHROW
5508 break " discard error for $VIMNOERRTHROW
5513 Xpath 2097152 " X: 2097152
5522 SetLineNumber two_lines_before_interrupt
5528 call CHECK(6, "Vim:Interrupt", '',
5529 \ two_lines_before_interrupt + 2)
5532 if !intcaught && $VIMNOINTTHROW
5535 break " discard interrupt for $VIMNOINTTHROW
5540 Xpath 4194304 " X: 4194304
5548 SetLineNumber line_before_throw
5552 Xpath 8388608 " X: 0
5556 call CHECK(8, 'E171', "Missing :endif", line_before_throw + 3)
5559 if !errcaught && $VIMNOERRTHROW
5562 break " discard error for $VIMNOERRTHROW
5567 Xpath 16777216 " X: 16777216
5579 Xpath 33554432 " X: 0
5593 Xpath 67108864 " X: 0
5606 SetLineNumber line_before_error
5611 call CHECK(13, 'E492', "Not an editor command",
5612 \ line_before_error + 1)
5615 if !errcaught && $VIMNOERRTHROW
5618 break " discard error for $VIMNOERRTHROW
5623 Xpath 134217728 " X: 134217728
5632 SetLineNumber two_lines_before_interrupt
5637 call CHECK(15, "Vim:Interrupt", '',
5638 \ two_lines_before_interrupt + 2)
5641 if !intcaught && $VIMNOINTTHROW
5644 break " discard interrupt for $VIMNOINTTHROW
5649 Xpath 268435456 " X: 268435456
5657 SetLineNumber line_before_throw
5665 call CHECK(18, 'E171', "Missing :endif", line_before_throw + 3)
5668 if !errcaught && $VIMNOERRTHROW
5671 break " discard error for $VIMNOERRTHROW
5676 Xpath 536870912 " X: 536870912
5684 SetLineNumber line_before_throw
5690 call CHECK(20, 'E171', "Missing :endif", line_before_throw + 3)
5693 if !errcaught && $VIMNOERRTHROW
5696 break " discard error for $VIMNOERRTHROW
5701 Xpath 1073741824 " X: 1073741824
5708 "-------------------------------------------------------------------------------
5710 " Test 60: (Re)throwing v:exception; :echoerr. {{{1
5712 " A user exception can be rethrown after catching by throwing
5713 " v:exception. An error or interrupt exception cannot be rethrown
5714 " because Vim exceptions cannot be faked. A Vim exception using the
5715 " value of v:exception can, however, be triggered by the :echoerr
5717 "-------------------------------------------------------------------------------
5727 throw v:exception " rethrow user exception
5731 catch /^oops$/ " catches rethrown user exception
5742 write /n/o/n/w/r/i/t/a/b/l/e/_/f/i/l/e
5744 Xout "did_emsg was reset before executing " .
5745 \ "BufWritePost autocommands."
5746 catch /^Vim(write):/
5748 throw v:exception " throw error: cannot fake Vim exception
5753 if !caught && !$VIMNOERRTHROW
5757 catch /^Vim(throw):/ " catches throw error
5758 let caught = caught + 1
5762 Xpath 2048 " X: 2048
5764 if !caught && !$VIMNOERRTHROW
5769 return | " discard error for $VIMNOERRTHROW
5781 Xpath 16384 " X: 16384
5783 catch /^Vim/ " catch error exception
5785 " Trigger Vim error exception with value specified after :echoerr
5786 let value = substitute(v:exception, '^Vim\((.*)\)\=:', '', "")
5791 Xpath 65536 " X: 65536
5801 catch /^Vim(echoerr):/
5802 let caught = caught + 1
5803 if v:exception !~ value
5809 Xpath 1048576 " X: 1048576
5811 if !caught && !$VIMNOERRTHROW
5812 Xpath 2097152 " X: 0
5814 Xpath 4194304 " X: 0
5816 return | " discard error for $VIMNOERRTHROW
5830 Xpath 8388608 " X: 8388608
5833 catch /^Vim:/ " catch interrupt exception
5835 " Trigger Vim error exception with value specified after :echoerr
5836 echoerr substitute(v:exception, '^Vim\((.*)\)\=:', '', "")
5838 Xpath 16777216 " X: 0
5840 Xpath 33554432 " X: 33554432
5843 Xpath 67108864 " X: 0
5849 catch /^Vim(echoerr):/
5851 if v:exception !~ "Interrupt"
5852 Xpath 134217728 " X: 0
5855 Xpath 268435456 " X: 268435456
5856 if !errcaught && !$VIMNOERRTHROW
5857 Xpath 536870912 " X: 0
5865 "-------------------------------------------------------------------------------
5866 " Test 61: Catching interrupt exceptions {{{1
5868 " When an interrupt occurs inside a :try/:endtry region, an
5869 " interrupt exception is thrown and can be caught. Its value is
5870 " "Vim:Interrupt". If the interrupt occurs after an error or a :throw
5871 " but before a matching :catch is reached, all following :catches of
5872 " that try block are ignored, but the interrupt exception can be
5873 " caught by the next surrounding try conditional. An interrupt is
5874 " ignored when there is a previous interrupt that has not been caught
5875 " or causes a :finally clause to be executed.
5876 "-------------------------------------------------------------------------------
5889 catch /^Vim:Interrupt$/
5893 if caught || $VIMNOINTTHROW
5899 Xout v:exception "in" v:throwpoint
5901 break " discard interrupt for $VIMNOINTTHROW
5913 catch /do_not_catch/
5915 catch /.*/ "INTERRUPT - throw interrupt if !$VIMNOERRTHROW
5919 finally "INTERRUPT - throw interrupt if $VIMNOERRTHROW
5920 Xpath 1024 " X: 1024
5922 catch /^Vim:Interrupt$/
5925 Xpath 2048 " X: 2048
5926 if caught || $VIMNOINTTHROW
5927 Xpath 4096 " X: 4096
5932 Xout v:exception "in" v:throwpoint
5934 break " discard interrupt for $VIMNOINTTHROW
5943 Xpath 16384 " X: 16384
5946 catch /do_not_catch/
5948 catch /x/ "INTERRUPT
5953 catch /^Vim:Interrupt$/
5956 Xpath 524288 " X: 524288
5957 if caught || $VIMNOINTTHROW
5958 Xpath 1048576 " X: 1048576
5962 Xpath 2097152 " X: 0
5963 Xout v:exception "in" v:throwpoint
5965 break " discard interrupt for $VIMNOINTTHROW
5973 Xpath 4194304 " X: 4194304
5975 Xpath 8388608 " X: 0
5976 catch /do_not_catch/ "INTERRUPT
5977 Xpath 16777216 " X: 0
5978 catch /^Vim:Interrupt$/
5981 Xpath 33554432 " X: 33554432
5982 if caught || $VIMNOINTTHROW
5983 Xpath 67108864 " X: 67108864
5987 Xpath 134217728 " X: 0
5988 Xout v:exception "in" v:throwpoint
5990 break " discard interrupt for $VIMNOINTTHROW
5994 Xpath 268435456 " X: 268435456
6001 "-------------------------------------------------------------------------------
6002 " Test 62: Catching error exceptions {{{1
6004 " An error inside a :try/:endtry region is converted to an exception
6005 " and can be caught. The error exception has a "Vim(cmdname):" prefix
6006 " where cmdname is the name of the failing command, or a "Vim:" prefix
6007 " if no command name is known. The "Vim" prefixes cannot be faked.
6008 "-------------------------------------------------------------------------------
6012 function! MSG(enr, emsg)
6013 let english = v:lang == "C" || v:lang =~ '^[Ee]n'
6015 Xout "TODO: Add message number for:" a:emsg
6016 let v:errmsg = ":" . v:errmsg
6019 if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
6022 Xout "Message missing."
6024 let v:errmsg = escape(v:errmsg, '"')
6025 Xout "Unexpected message:" v:errmsg
6036 catch /^Vim(unlet):/
6038 let v:errmsg = substitute(v:exception, '^Vim(unlet):', '', "")
6041 if !caught && !$VIMNOERRTHROW
6044 if !MSG('E108', "No such variable")
6050 Xout v:exception "in" v:throwpoint
6052 break " discard error for $VIMNOERRTHROW
6060 throw novar " error in :throw
6061 catch /^Vim(throw):/
6063 let v:errmsg = substitute(v:exception, '^Vim(throw):', '', "")
6066 if !caught && !$VIMNOERRTHROW
6069 if caught ? !MSG('E121', "Undefined variable")
6070 \ : !MSG('E15', "Invalid expression")
6076 Xout v:exception "in" v:throwpoint
6078 break " discard error for $VIMNOERRTHROW
6086 throw "Vim:faked" " error: cannot fake Vim exception
6087 catch /^Vim(throw):/
6089 let v:errmsg = substitute(v:exception, '^Vim(throw):', '', "")
6092 if !caught && !$VIMNOERRTHROW
6095 if !MSG('E608', "Cannot :throw exceptions with 'Vim' prefix")
6101 Xout v:exception "in" v:throwpoint
6103 break " discard error for $VIMNOERRTHROW
6117 catch /^Vim(endfunction):/
6119 let v:errmsg = substitute(v:exception, '^Vim(endfunction):', '', "")
6121 Xpath 4096 " X: 4096
6122 if !caught && !$VIMNOERRTHROW
6125 if !MSG('E170', "Missing :endwhile")
6131 Xout v:exception "in" v:throwpoint
6133 break " discard error for $VIMNOERRTHROW
6144 let v:errmsg = substitute(v:exception, '^Vim:', '', "")
6146 Xpath 65536 " X: 65536
6147 if !caught && !$VIMNOERRTHROW
6150 if !MSG('E170', "Missing :endwhile")
6156 Xout v:exception "in" v:throwpoint
6158 break " discard error for $VIMNOERRTHROW
6175 let v:errmsg = substitute(v:exception, '^Vim(call):', '', "")
6177 Xpath 1048576 " X: 1048576
6178 if !caught && !$VIMNOERRTHROW
6179 Xpath 2097152 " X: 0
6181 if !MSG('E132', "Function call depth is higher than 'maxfuncdepth'")
6182 Xpath 4194304 " X: 0
6186 Xpath 8388608 " X: 0
6187 Xout v:exception "in" v:throwpoint
6190 break " discard error for $VIMNOERRTHROW
6205 catch /^Vim(return):/
6207 let v:errmsg = substitute(v:exception, '^Vim(return):', '', "")
6209 Xpath 16777216 " X: 16777216
6210 if !caught && !$VIMNOERRTHROW
6211 Xpath 33554432 " X: 0
6213 if !MSG('E132', "Function call depth is higher than 'maxfuncdepth'")
6214 Xpath 67108864 " X: 0
6218 Xpath 134217728 " X: 0
6219 Xout v:exception "in" v:throwpoint
6222 break " discard error for $VIMNOERRTHROW
6226 unlet! caught mfd_save
6230 Xpath 268435456 " X: 268435456
6234 " Leave MSG() for the next test.
6237 "-------------------------------------------------------------------------------
6238 " Test 63: Suppressing error exceptions by :silent!. {{{1
6240 " A :silent! command inside a :try/:endtry region suppresses the
6241 " conversion of errors to an exception and the immediate abortion on
6242 " error. When the commands executed by the :silent! themselves open
6243 " a new :try/:endtry region, conversion of errors to exception and
6244 " immediate abortion is switched on again - until the next :silent!
6245 " etc. The :silent! has the effect of setting v:errmsg to the error
6246 " message text (without displaying it) and continuing with the next
6249 " When a command triggering autocommands is executed by :silent!
6250 " inside a :try/:endtry, the autocommand execution is not suppressed
6253 " This test reuses the function MSG() from the previous test.
6254 "-------------------------------------------------------------------------------
6262 function! S(n) abort
6264 let g:taken = g:taken . "E" . a:n
6268 " Check that ":silent!" continues:
6271 " Check that ":silent!" sets "v:errmsg":
6272 if MSG('E492', "Not an editor command")
6282 " This is not silent:
6283 call S(3) " X: 0 * 16
6286 let errmsg3 = substitute(v:exception, '^Vim:', '', "")
6287 silent! call S(4) " X: 3 * 64
6290 let errmsg3 = v:errmsg
6291 " Do call S(4) here if not executed in :catch.
6294 Xpath 1048576 " X: 1048576
6295 if !caught && !$VIMNOERRTHROW
6296 Xpath 2097152 " X: 0
6298 let v:errmsg = errmsg3
6299 if !MSG('E492', "Not an editor command")
6300 Xpath 4194304 " X: 0
6302 silent! call S(5) " X: 3 * 256
6303 " Break out of try conditionals that cover ":silent!". This also
6304 " discards the aborting error when $VIMNOERRTHROW is non-zero.
6308 Xpath 8388608 " X: 0
6309 Xout v:exception "in" v:throwpoint
6312 " This is a double ":silent!" (see caller).
6313 silent! call S(6) " X: 3 * 1024
6318 silent! call S(2) " X: 3 * 4
6320 silent! execute "call Foo() | call S(7)"
6321 silent! call S(8) " X: 3 * 16384
6322 endtry " normal end of try cond that covers ":silent!"
6323 " This has a ":silent!" from the caller:
6324 call S(9) " X: 3 * 65536
6327 silent! call S(1) " X: 3 * 1
6329 silent! call S(10) " X: 3 * 262144
6331 let expected = "E1E2E3E4E5E6E7E8E9E10"
6332 if taken != expected
6333 Xpath 16777216 " X: 0
6334 Xout "'taken' is" taken "instead of" expected
6338 autocmd BufWritePost * Xpath 33554432 " X: 33554432
6341 Xpath 67108864 " X: 67108864
6342 write /i/m/p/o/s/s/i/b/l/e
6343 Xpath 134217728 " X: 134217728
6346 unlet! caught errmsg3 taken expected
6355 "-------------------------------------------------------------------------------
6356 " Test 64: Error exceptions after error, interrupt or :throw {{{1
6358 " When an error occurs after an interrupt or a :throw but before
6359 " a matching :catch is reached, all following :catches of that try
6360 " block are ignored, but the error exception can be caught by the next
6361 " surrounding try conditional. Any previous error exception is
6362 " discarded. An error is ignored when there is a previous error that
6363 " has not been caught.
6364 "-------------------------------------------------------------------------------
6378 endwhile " throw error exception
6383 if caught || $VIMNOERRTHROW
6389 Xout v:exception "in" v:throwpoint
6391 break " discard error for $VIMNOERRTHROW
6403 catch /.*/ " throw error exception
6412 if caught || $VIMNOERRTHROW
6418 Xout v:exception "in" v:throwpoint
6420 break " discard error for $VIMNOERRTHROW
6429 Xpath 1024 " X: 1024
6431 catch /do_not_catch/
6435 catch /.*/ " throw error exception
6443 Xpath 16384 " X: 16384
6444 if caught || $VIMNOERRTHROW
6445 Xpath 32768 " X: 32768
6450 Xout v:exception "in" v:throwpoint
6452 break " discard error for $VIMNOERRTHROW
6461 Xpath 131072 " X: 131072
6463 catch /do_not_catch/
6467 catch /x/ " throw error exception
6470 Xpath 1048576 " X: 0
6475 Xpath 2097152 " X: 2097152
6476 if caught || $VIMNOERRTHROW
6477 Xpath 4194304 " X: 4194304
6481 Xpath 8388608 " X: 0
6482 Xout v:exception "in" v:throwpoint
6484 break " discard error for $VIMNOERRTHROW
6492 Xpath 16777216 " X: 16777216
6493 " endif " :endif without :if; throw error exception
6496 catch /do_not_catch/ " ignore new error
6497 Xpath 33554432 " X: 0
6498 catch /^Vim(endif):/
6501 Xpath 67108864 " X: 0
6503 Xpath 134217728 " X: 134217728
6504 if caught || $VIMNOERRTHROW
6505 Xpath 268435456 " X: 268435456
6509 Xpath 536870912 " X: 0
6510 Xout v:exception "in" v:throwpoint
6512 break " discard error for $VIMNOERRTHROW
6516 Xpath 1073741824 " X: 1073741824
6523 "-------------------------------------------------------------------------------
6524 " Test 65: Errors in the /pattern/ argument of a :catch {{{1
6526 " On an error in the /pattern/ argument of a :catch, the :catch does
6527 " not match. Any following :catches of the same :try/:endtry don't
6528 " match either. Finally clauses are executed.
6529 "-------------------------------------------------------------------------------
6533 function! MSG(enr, emsg)
6534 let english = v:lang == "C" || v:lang =~ '^[Ee]n'
6536 Xout "TODO: Add message number for:" a:emsg
6537 let v:errmsg = ":" . v:errmsg
6540 if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
6543 Xout "Message missing."
6545 let v:errmsg = escape(v:errmsg, '"')
6546 Xout "Unexpected message:" v:errmsg
6558 catch /\)/ " not checked; exception has already been caught
6564 Xout v:exception "in" v:throwpoint
6574 catch /abc/ " does not catch
6576 catch /\)/ " error; discards exception
6578 catch /.*/ " not checked
6584 catch /^ab$/ " checked, but original exception is discarded
6586 catch /^Vim(catch):/
6588 let v:errmsg = substitute(v:exception, '^Vim(catch):', '', "")
6590 Xpath 4096 " X: 4096
6591 if !caught && !$VIMNOERRTHROW
6594 if caught ? !MSG('E55', 'Unmatched \\)')
6595 \ : !MSG('E475', "Invalid argument")
6599 return | " discard error
6604 Xout v:exception "in" v:throwpoint
6609 Xpath 65536 " X: 65536
6618 "-------------------------------------------------------------------------------
6619 " Test 66: Stop range :call on error, interrupt, or :throw {{{1
6621 " When a function which is multiply called for a range since it
6622 " doesn't handle the range itself has an error in a command
6623 " dynamically enclosed by :try/:endtry or gets an interrupt or
6624 " executes a :throw, no more calls for the remaining lines in the
6625 " range are made. On an error in a command not dynamically enclosed
6626 " by :try/:endtry, the function is executed again for the remaining
6627 " lines in the range.
6628 "-------------------------------------------------------------------------------
6634 let file = tempname()
6646 let expected = "G1EF1E(1)F1E(2)F1E(3)G2EF2E(1)G3IF3I(1)G4TF4T(1)G5AF5A(1)"
6648 function! F(reason, n) abort
6649 let g:taken = g:taken . "F" . a:n .
6650 \ substitute(a:reason, '\(\l\).*', '\u\1', "") .
6651 \ "(" . line(".") . ")"
6653 if a:reason == "error"
6655 elseif a:reason == "interrupt"
6658 elseif a:reason == "throw"
6660 elseif a:reason == "aborting error"
6662 if g:taken != g:expected
6664 Xout "'taken' is" g:taken "instead of" g:expected
6674 function! G(reason, n)
6675 let g:taken = g:taken . "G" . a:n .
6676 \ substitute(a:reason, '\(\l\).*', '\u\1', "")
6677 1,3call F(a:reason, a:n)
6690 call G("interrupt", 3)
6701 Xpath 1024 " X: 1024
6704 Xout v:exception "in" ExtraVimThrowpoint()
6706 Xpath 4096 " X: 4096
6707 call G("aborting error", 5)
6709 Xout "'taken' is" taken "instead of" expected
6716 "-------------------------------------------------------------------------------
6717 " Test 67: :throw across :call command {{{1
6719 " On a call command, an exception might be thrown when evaluating the
6720 " function name, during evaluation of the arguments, or when the
6721 " function is being executed. The exception can be caught by the
6723 "-------------------------------------------------------------------------------
6727 function! THROW(x, n)
6738 function! NAME(x, n)
6759 Xpath 1024 " X: 1024
6768 Xpath 4096 " X: 4096
6779 Xpath 8192 " X: 8192
6780 call {NAME(THROW("name", 1), 1)}(ARG(4711, 1), 1)
6783 Xpath 32768 " X: 32768
6786 Xout "1:" v:exception "in" v:throwpoint
6788 if !error && $VIMNOERRTHROW && v:errmsg != ""
6797 break " discard error for $VIMNOERRTHROW
6803 Xpath 131072 " X: 131072
6804 call {NAME("F", 2)}(ARG(THROW("arg", 2), 2), 2)
6807 Xpath 524288 " X: 524288
6810 Xout "2:" v:exception "in" v:throwpoint
6812 if !error && $VIMNOERRTHROW && v:errmsg != ""
6817 Xpath 1048576 " X: 0
6821 break " discard error for $VIMNOERRTHROW
6827 Xpath 2097152 " X: 2097152
6828 call {NAME("THROW", 3)}(ARG("call", 3), 3)
6829 Xpath 4194304 " X: 0
6831 Xpath 8388608 " X: 8388608
6832 catch /^0$/ " default return value
6833 Xpath 16777216 " X: 0
6834 Xout "3:" v:throwpoint
6837 Xout "3:" v:exception "in" v:throwpoint
6839 if !error && $VIMNOERRTHROW && v:errmsg != ""
6844 Xpath 33554432 " X: 0
6848 break " discard error for $VIMNOERRTHROW
6854 Xpath 67108864 " X: 67108864
6855 call {NAME("F", 4)}(ARG(4711, 4), 4)
6856 Xpath 134217728 " X: 134217728
6859 Xout "4:" v:exception "in" v:throwpoint
6861 if !error && $VIMNOERRTHROW && v:errmsg != ""
6866 Xpath 268435456 " X: 0
6870 break " discard error for $VIMNOERRTHROW
6874 catch /^0$/ " default return value
6875 Xpath 536870912 " X: 0
6879 Xout v:exception "in" v:throwpoint
6881 if !error && $VIMNOERRTHROW && v:errmsg != ""
6886 Xpath 1073741824 " X: 0
6888 break " discard error for $VIMNOERRTHROW
6897 " Leave THROW(), NAME(), and ARG() for the next test.
6900 "-------------------------------------------------------------------------------
6901 " Test 68: :throw across function calls in expressions {{{1
6903 " On a function call within an expression, an exception might be
6904 " thrown when evaluating the function name, during evaluation of the
6905 " arguments, or when the function is being executed. The exception
6906 " can be caught by the caller.
6908 " This test reuses the functions THROW(), NAME(), and ARG() from the
6910 "-------------------------------------------------------------------------------
6918 Xpath 4096 " X: 4096
6923 unlet! var1 var2 var3 var4
6932 Xpath 8192 " X: 8192
6933 let var1 = {NAME(THROW("name", 1), 1)}(ARG(4711, 1), 1)
6936 Xpath 32768 " X: 32768
6939 Xout "1:" v:exception "in" v:throwpoint
6941 if !error && $VIMNOERRTHROW && v:errmsg != ""
6950 break " discard error for $VIMNOERRTHROW
6956 Xpath 131072 " X: 131072
6957 let var2 = {NAME("F", 2)}(ARG(THROW("arg", 2), 2), 2)
6960 Xpath 524288 " X: 524288
6963 Xout "2:" v:exception "in" v:throwpoint
6965 if !error && $VIMNOERRTHROW && v:errmsg != ""
6970 Xpath 1048576 " X: 0
6974 break " discard error for $VIMNOERRTHROW
6980 Xpath 2097152 " X: 2097152
6981 let var3 = {NAME("THROW", 3)}(ARG("call", 3), 3)
6982 Xpath 4194304 " X: 0
6984 Xpath 8388608 " X: 8388608
6985 catch /^0$/ " default return value
6986 Xpath 16777216 " X: 0
6987 Xout "3:" v:throwpoint
6990 Xout "3:" v:exception "in" v:throwpoint
6992 if !error && $VIMNOERRTHROW && v:errmsg != ""
6997 Xpath 33554432 " X: 0
7001 break " discard error for $VIMNOERRTHROW
7007 Xpath 67108864 " X: 67108864
7008 let var4 = {NAME("F", 4)}(ARG(4711, 4), 4)
7009 Xpath 134217728 " X: 134217728
7012 Xout "4:" v:exception "in" v:throwpoint
7014 if !error && $VIMNOERRTHROW && v:errmsg != ""
7019 Xpath 268435456 " X: 0
7023 break " discard error for $VIMNOERRTHROW
7027 catch /^0$/ " default return value
7028 Xpath 536870912 " X: 0
7032 Xout v:exception "in" v:throwpoint
7034 if !error && $VIMNOERRTHROW && v:errmsg != ""
7039 Xpath 1073741824 " X: 0
7041 break " discard error for $VIMNOERRTHROW
7045 if exists("var1") || exists("var2") || exists("var3") ||
7046 \ !exists("var4") || var4 != 4711
7047 " The Xpath command does not accept 2^31 (negative); add explicitly:
7048 let Xpath = Xpath + 2147483648 " X: 0
7065 unlet! error var1 var2 var3 var4
7074 "-------------------------------------------------------------------------------
7075 " Test 69: :throw across :if, :elseif, :while {{{1
7077 " On an :if, :elseif, or :while command, an exception might be thrown
7078 " during evaluation of the expression to test. The exception can be
7079 " caught by the script.
7080 "-------------------------------------------------------------------------------
7088 Xloop 1 " X: 1 + 2 + 4
7096 if 4711 == THROW("if") + 111
7106 Xout "if:" v:exception "in" v:throwpoint
7111 if 4711 == 4 + 7 + 1 + 1
7113 elseif 4711 == THROW("elseif") + 222
7120 Xpath 16384 " X: 16384
7123 Xout "elseif:" v:exception "in" v:throwpoint
7127 Xpath 65536 " X: 65536
7128 while 4711 == THROW("while") + 4711
7134 Xpath 524288 " X: 524288
7136 Xpath 1048576 " X: 0
7137 Xout "while:" v:exception "in" v:throwpoint
7140 catch /^0$/ " default return value
7141 Xpath 2097152 " X: 0
7144 Xout v:exception "in" v:throwpoint
7145 Xpath 4194304 " X: 0
7148 Xpath 8388608 " X: 8388608
7155 "-------------------------------------------------------------------------------
7156 " Test 70: :throw across :return or :throw {{{1
7158 " On a :return or :throw command, an exception might be thrown during
7159 " evaluation of the expression to return or throw, respectively. The
7160 " exception can be caught by the script.
7161 "-------------------------------------------------------------------------------
7167 function! THROW(x, n)
7168 let g:taken = g:taken . "T" . a:n
7172 function! F(x, y, n)
7173 let g:taken = g:taken . "F" . a:n
7174 return a:x + THROW(a:y, a:n)
7177 function! G(x, y, n)
7178 let g:taken = g:taken . "G" . a:n
7179 throw a:x . THROW(a:y, a:n)
7186 call F(4711, "return", 1)
7192 Xout "return:" v:exception "in" v:throwpoint
7197 let var = F(4712, "return-var", 2)
7199 catch /^return-var$/
7203 Xout "return-var:" v:exception "in" v:throwpoint
7210 throw "except1" . THROW("throw1", 3)
7215 Xpath 2048 " X: 2048
7218 Xout "throw1:" v:exception "in" v:throwpoint
7222 Xpath 8192 " X: 8192
7223 call G("except2", "throw2", 4)
7228 Xpath 65536 " X: 65536
7231 Xout "throw2:" v:exception "in" v:throwpoint
7235 Xpath 262144 " X: 262144
7236 let var = G("except3", "throw3", 5)
7239 Xpath 1048576 " X: 0
7241 Xpath 2097152 " X: 2097152
7243 Xpath 4194304 " X: 0
7244 Xout "throw3:" v:exception "in" v:throwpoint
7249 let expected = "F1T1F2T2T3G4T4G5T5"
7250 if taken != expected
7251 Xpath 8388608 " X: 0
7252 Xout "'taken' is" taken "instead of" expected
7255 catch /^0$/ " default return value
7256 Xpath 16777216 " X: 0
7259 Xpath 33554432 " X: 0
7260 Xout v:exception "in" v:throwpoint
7263 Xpath 67108864 " X: 67108864
7265 unlet taken expected
7273 "-------------------------------------------------------------------------------
7274 " Test 71: :throw across :echo variants and :execute {{{1
7276 " On an :echo, :echon, :echomsg, :echoerr, or :execute command, an
7277 " exception might be thrown during evaluation of the arguments to
7278 " be displayed or executed as a command, respectively. Any following
7279 " arguments are not evaluated, then. The exception can be caught by
7281 "-------------------------------------------------------------------------------
7287 function! THROW(x, n)
7288 let g:taken = g:taken . "T" . a:n
7293 let g:taken = g:taken . "F" . a:n
7300 echo "echo" . THROW("echo-except", 1) F(1)
7302 catch /^echo-except$/
7306 Xout "echo:" v:exception "in" v:throwpoint
7311 echon "echon" . THROW("echon-except", 2) F(2)
7313 catch /^echon-except$/
7317 Xout "echon:" v:exception "in" v:throwpoint
7322 echomsg "echomsg" . THROW("echomsg-except", 3) F(3)
7324 catch /^echomsg-except$/
7325 Xpath 1024 " X: 1024
7328 Xout "echomsg:" v:exception "in" v:throwpoint
7332 Xpath 4096 " X: 4096
7333 echoerr "echoerr" . THROW("echoerr-except", 4) F(4)
7335 catch /^echoerr-except$/
7336 Xpath 16384 " X: 16384
7343 Xout "echoerr:" v:exception "in" v:throwpoint
7347 Xpath 262144 " X: 262144
7348 execute "echo 'execute" . THROW("execute-except", 5) F(5) "'"
7350 catch /^execute-except$/
7351 Xpath 1048576 " X: 1048576
7353 Xpath 2097152 " X: 0
7354 Xout "execute:" v:exception "in" v:throwpoint
7357 let expected = "T1T2T3T4T5"
7358 if taken != expected
7359 Xpath 4194304 " X: 0
7360 Xout "'taken' is" taken "instead of" expected
7363 catch /^0$/ " default return value
7364 Xpath 8388608 " X: 0
7367 Xpath 16777216 " X: 0
7368 Xout v:exception "in" v:throwpoint
7371 Xpath 33554432 " X: 33554432
7373 unlet taken expected
7380 "-------------------------------------------------------------------------------
7381 " Test 72: :throw across :let or :unlet {{{1
7383 " On a :let command, an exception might be thrown during evaluation
7384 " of the expression to assign. On an :let or :unlet command, the
7385 " evaluation of the name of the variable to be assigned or list or
7386 " deleted, respectively, may throw an exception. Any following
7387 " arguments are not evaluated, then. The exception can be caught by
7389 "-------------------------------------------------------------------------------
7396 let g:throwcount = g:throwcount + 1
7402 let $VAR = "old_value"
7404 let $VAR = "let(" . THROW("var") . ")"
7409 if $VAR != "old_value"
7415 let @a = "old_value"
7417 let @a = "let(" . THROW("reg") . ")"
7422 let @A = "let(" . THROW("REG") . ")"
7428 if @a != "old_value"
7431 if @A != "old_value"
7437 let saved_gpath = &g:path
7438 let saved_lpath = &l:path
7439 Xpath 2048 " X: 2048
7440 let &path = "let(" . THROW("opt") . ")"
7444 Xpath 8192 " X: 8192
7445 let &g:path = "let(" . THROW("gopt") . ")"
7449 Xpath 32768 " X: 32768
7450 let &l:path = "let(" . THROW("lopt") . ")"
7453 Xpath 131072 " X: 131072
7457 if &g:path != saved_gpath || &l:path != saved_lpath
7460 let &g:path = saved_gpath
7461 let &l:path = saved_lpath
7464 unlet! var1 var2 var3
7467 Xpath 524288 " X: 524288
7468 let var1 = "let(" . THROW("var1") . ")"
7469 Xpath 1048576 " X: 0
7471 Xpath 2097152 " X: 2097152
7474 Xpath 4194304 " X: 0
7479 let var2 = "old_value"
7480 Xpath 8388608 " X: 8388608
7481 let var2 = "let(" . THROW("var2"). ")"
7482 Xpath 16777216 " X: 0
7484 Xpath 33554432 " X: 33554432
7486 if var2 != "old_value"
7487 Xpath 67108864 " X: 0
7492 Xpath 134217728 " X: 134217728
7493 let var{THROW("var3")} = 4711
7494 Xpath 268435456 " X: 0
7496 Xpath 536870912 " X: 536870912
7502 let g:addpath = g:addpath . a:p
7507 let var{THROW("var4")} var{ADDPATH("T2")} | call ADDPATH("T3")
7515 unlet var{THROW("var5")} var{ADDPATH("T7")} | call ADDPATH("T8")
7521 if addpath != "T1T5T6T10" || throwcount != 11
7522 throw "addpath: " . addpath . ", throwcount: " . throwcount
7525 Xpath 1073741824 " X: 1073741824
7528 " The Xpath command does not accept 2^31 (negative); add explicitly:
7529 let Xpath = Xpath + 2147483648 " X: 0
7530 Xout v:exception "in" v:throwpoint
7533 unlet! var1 var2 var3 addpath throwcount
7539 "-------------------------------------------------------------------------------
7540 " Test 73: :throw across :function, :delfunction {{{1
7542 " The :function and :delfunction commands may cause an expression
7543 " specified in braces to be evaluated. During evaluation, an
7544 " exception might be thrown. The exception can be caught by the
7546 "-------------------------------------------------------------------------------
7552 function! THROW(x, n)
7553 let g:taken = g:taken . "T" . a:n
7557 function! EXPR(x, n)
7558 let g:taken = g:taken . "E" . a:n
7560 call THROW(a:x, a:n)
7572 function! F{EXPR("function-def-ok", 1)}()
7575 function! F{EXPR("function-def", 2)}()
7578 catch /^function-def-ok$/
7580 catch /^function-def$/
7584 Xout "def:" v:exception "in" v:throwpoint
7592 function F{EXPR("function-lst-ok", 3)}
7594 function F{EXPR("function-lst", 4)}
7596 catch /^function-lst-ok$/
7598 catch /^function-lst$/
7599 Xpath 4096 " X: 4096
7602 Xout "lst:" v:exception "in" v:throwpoint
7607 Xpath 16384 " X: 16384
7609 Xpath 32768 " X: 32768
7610 delfunction F{EXPR("function-del-ok", 5)}
7611 Xpath 65536 " X: 65536
7612 delfunction F{EXPR("function-del", 6)}
7614 catch /^function-del-ok$/
7616 catch /^function-del$/
7617 Xpath 524288 " X: 524288
7619 Xpath 1048576 " X: 0
7620 Xout "del:" v:exception "in" v:throwpoint
7623 let expected = "E1E2T2E3E4T4E5E6T6"
7624 if taken != expected
7625 Xpath 2097152 " X: 0
7626 Xout "'taken' is" taken "instead of" expected
7630 Xpath 4194304 " X: 0
7631 Xout v:exception "in" v:throwpoint
7634 Xpath 8388608 " X: 8388608
7636 unlet taken expected
7643 "-------------------------------------------------------------------------------
7644 " Test 74: :throw across builtin functions and commands {{{1
7646 " Some functions like exists(), searchpair() take expression
7647 " arguments, other functions or commands like substitute() or
7648 " :substitute cause an expression (specified in the regular
7649 " expression) to be evaluated. During evaluation an exception
7650 " might be thrown. The exception can be caught by the script.
7651 "-------------------------------------------------------------------------------
7657 function! THROW(x, n)
7658 let g:taken = g:taken . "T" . a:n
7662 function! EXPR(x, n)
7663 let g:taken = g:taken . "E" . a:n
7664 call THROW(a:x . a:n, a:n)
7668 function! SKIP(x, n)
7669 let g:taken = g:taken . "S" . a:n . "(" . line(".")
7670 let theline = getline(".")
7671 if theline =~ "skip"
7672 let g:taken = g:taken . "s)"
7674 elseif theline =~ "throw"
7675 let g:taken = g:taken . "t)"
7676 call THROW(a:x . a:n, a:n)
7678 let g:taken = g:taken . ")"
7683 function! SUBST(x, n)
7684 let g:taken = g:taken . "U" . a:n . "(" . line(".")
7685 let theline = getline(".")
7686 if theline =~ "not" " SUBST() should not be called for this line
7687 let g:taken = g:taken . "n)"
7688 call THROW(a:x . a:n, a:n)
7689 elseif theline =~ "throw"
7690 let g:taken = g:taken . "t)"
7691 call THROW(a:x . a:n, a:n)
7693 let g:taken = g:taken . ")"
7701 let result = exists('*{EXPR("exists", 1)}')
7706 let result = exists('{EXPR("exists", 2)}')
7712 Xout "exists2:" v:exception "in" v:throwpoint
7716 Xout "exists1:" v:exception "in" v:throwpoint
7720 let file = tempname()
7736 \ searchpair("begin", "middle", "end", '', 'SKIP("searchpair", 3)')
7739 \ searchpair("begin", "middle", "end", '', 'SKIP("searchpair", 4)')
7742 \ searchpair("begin", "middle", "end", '', 'SKIP("searchpair", 5)')
7744 catch /^searchpair[35]$/
7746 catch /^searchpair4$/
7747 Xpath 4096 " X: 4096
7750 Xout "searchpair:" v:exception "in" v:throwpoint
7757 let file = tempname()
7768 Xpath 16384 " X: 16384
7769 1,2substitute/subst/\=SUBST("substitute", 6)/
7771 Xpath 32768 " X: 32768
7774 3substitute/subst/\=SUBST("substitute", 7)/
7777 " If exceptions are not thrown on errors, fake the error
7778 " exception in order to get the same execution path.
7779 throw "faked Vim(substitute)"
7782 catch /Vim(substitute)/ " Pattern not found ('e' flag missing)
7783 Xpath 65536 " X: 65536
7784 3substitute/subst/\=SUBST("substitute", 8)/e
7785 Xpath 131072 " X: 131072
7787 Xpath 262144 " X: 262144
7788 4,6substitute/subst/\=SUBST("substitute", 9)/
7790 catch /^substitute[678]/
7791 Xpath 1048576 " X: 0
7792 catch /^substitute9/
7793 Xpath 2097152 " X: 2097152
7800 Xpath 4194304 " X: 4194304
7801 let var = substitute("sub", "sub", '\=THROW("substitute()y", 10)', '')
7802 Xpath 8388608 " X: 0
7803 catch /substitute()y/
7804 Xpath 16777216 " X: 16777216
7806 Xpath 33554432 " X: 0
7807 Xout "substitute()y:" v:exception "in" v:throwpoint
7811 Xpath 67108864 " X: 67108864
7812 let var = substitute("not", "sub", '\=THROW("substitute()n", 11)', '')
7813 Xpath 134217728 " X: 134217728
7814 catch /substitute()n/
7815 Xpath 268435456 " X: 0
7817 Xpath 536870912 " X: 0
7818 Xout "substitute()n:" v:exception "in" v:throwpoint
7821 let expected = "E1T1E2T2S3(3)S4(5s)S4(7t)T4U6(1)U6(2)U9(4)U9(5t)T9T10"
7822 if taken != expected
7823 Xpath 1073741824 " X: 0
7824 Xout "'taken' is" taken "instead of" expected
7828 " The Xpath command does not accept 2^31 (negative); add explicitly:
7829 let Xpath = Xpath + 2147483648 " X: 0
7830 Xout v:exception "in" v:throwpoint
7833 unlet result var taken expected
7842 "-------------------------------------------------------------------------------
7843 " Test 75: Errors in builtin functions. {{{1
7845 " On an error in a builtin function called inside a :try/:endtry
7846 " region, the evaluation of the expression calling that function and
7847 " the command containing that expression are abandoned. The error can
7848 " be caught as an exception.
7850 " A simple :call of the builtin function is a trivial case. If the
7851 " builtin function is called in the argument list of another function,
7852 " no further arguments are evaluated, and the other function is not
7853 " executed. If the builtin function is called from the argument of
7854 " a :return command, the :return command is not executed. If the
7855 " builtin function is called from the argument of a :throw command,
7856 " the :throw command is not executed. The evaluation of the
7857 " expression calling the builtin function is abandoned.
7858 "-------------------------------------------------------------------------------
7866 function! F2(arg1, arg2)
7884 return append(1, "s")
7891 if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
7894 break " discard error for $VIMNOERRTHROW
7901 set noma " let append() fail with "E21"
7914 Xpath 2048 " X: 2048
7915 if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
7916 Xpath 4096 " X: 4096
7918 break " discard error for $VIMNOERRTHROW
7926 Xpath 8192 " X: 8192
7927 call F1('x' . append(1, "s"))
7933 Xpath 32768 " X: 32768
7934 if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
7935 Xpath 65536 " X: 65536
7937 break " discard error for $VIMNOERRTHROW
7945 Xpath 131072 " X: 131072
7946 call F2('x' . append(1, "s"), G())
7952 Xpath 524288 " X: 524288
7953 if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
7954 Xpath 1048576 " X: 1048576
7956 break " discard error for $VIMNOERRTHROW
7966 Xpath 2097152 " X: 2097152
7967 throw "T" . append(1, "s")
7971 Xpath 4194304 " X: 0
7973 Xpath 8388608 " X: 0
7975 Xpath 16777216 " X: 16777216
7976 if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
7977 Xpath 33554432 " X: 33554432
7979 break " discard error for $VIMNOERRTHROW
7987 Xpath 67108864 " X: 67108864
7989 let x = x . "b" . append(1, "s") . H()
7993 Xpath 134217728 " X: 0
7995 Xpath 268435456 " X: 268435456
7996 if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
7997 Xpath 536870912 " X: 536870912
8000 Xpath 1073741824 " X: 1073741824
8002 break " discard error for $VIMNOERRTHROW
8006 " The Xpath command does not accept 2^31 (negative); add explicitly:
8007 let Xpath = Xpath + 2147483648 " X: 0
8008 Xout v:exception "in" v:throwpoint
8023 "-------------------------------------------------------------------------------
8024 " Test 76: Errors, interrupts, :throw during expression evaluation {{{1
8026 " When a function call made during expression evaluation is aborted
8027 " due to an error inside a :try/:endtry region or due to an interrupt
8028 " or a :throw, the expression evaluation is aborted as well. No
8029 " message is displayed for the cancelled expression evaluation. On an
8030 " error not inside :try/:endtry, the expression evaluation continues.
8031 "-------------------------------------------------------------------------------
8040 let g:taken = g:taken . "E" . a:n
8044 function! ERRabort(n) abort
8045 let g:taken = g:taken . "A" . a:n
8047 endfunction " returns -1; may cause follow-up msg for illegal var/func name
8049 function! WRAP(n, arg)
8050 let g:taken = g:taken . "W" . a:n
8051 let g:saved_errmsg = v:errmsg
8056 let g:taken = g:taken . "I" . a:n
8062 let g:taken = g:taken . "T" . a:n
8063 throw "should not be caught"
8067 let g:taken = g:taken . "C" . a:n
8071 let g:taken = g:taken . "M" . a:n
8072 let errmsg = (a:n >= 37 && a:n <= 44) ? g:saved_errmsg : v:errmsg
8073 let msgptn = (a:n >= 10 && a:n <= 27) ? "^$" : "asdf"
8075 let g:taken = g:taken . "x"
8076 Xout "Expr" a:n.": Unexpected message:" v:errmsg
8079 let g:saved_errmsg = ""
8091 let v{ERR(t) + CONT(t)} = 0
8093 let v{ERR(t) + CONT(t)}
8095 let var = exists('v{ERR(t) + CONT(t)}')
8097 unlet v{ERR(t) + CONT(t)}
8099 function F{ERR(t) + CONT(t)}()
8102 function F{ERR(t) + CONT(t)}
8104 let var = exists('*F{ERR(t) + CONT(t)}')
8106 delfunction F{ERR(t) + CONT(t)}
8108 let var = ERR(t) + CONT(t)
8111 " v:errmsg is not set when the error message is converted to an
8112 " exception. Set it to the original error message.
8113 let v:errmsg = substitute(v:exception, '^Vim:', '', "")
8114 catch /^Vim\((\a\+)\)\=:/
8115 " An error exception has been thrown after the original error.
8121 continue " discard an aborting error
8126 Xout v:exception "in" ExtraVimThrowpoint()
8133 Xloop 1 " X: 1024 * 511
8136 let v{INT(t) + CONT(t)} = 0
8138 let v{INT(t) + CONT(t)}
8140 let var = exists('v{INT(t) + CONT(t)}')
8142 unlet v{INT(t) + CONT(t)}
8144 function F{INT(t) + CONT(t)}()
8147 function F{INT(t) + CONT(t)}
8149 let var = exists('*F{INT(t) + CONT(t)}')
8151 delfunction F{INT(t) + CONT(t)}
8153 let var = INT(t) + CONT(t)
8155 catch /^Vim\((\a\+)\)\=:\(Interrupt\)\@!/
8156 " An error exception has been triggered after the interrupt.
8157 let v:errmsg = substitute(v:exception,
8158 \ '^Vim\((\a\+)\)\=:', '', "")
8163 continue " discard interrupt
8168 Xout v:exception "in" ExtraVimThrowpoint()
8175 Xloop 1 " X: 1048576 * 511
8178 let v{THR(t) + CONT(t)} = 0
8180 let v{THR(t) + CONT(t)}
8182 let var = exists('v{THR(t) + CONT(t)}')
8184 unlet v{THR(t) + CONT(t)}
8186 function F{THR(t) + CONT(t)}()
8189 function F{THR(t) + CONT(t)}
8191 let var = exists('*F{THR(t) + CONT(t)}')
8193 delfunction F{THR(t) + CONT(t)}
8195 let var = THR(t) + CONT(t)
8197 catch /^Vim\((\a\+)\)\=:/
8198 " An error exception has been triggered after the :throw.
8199 let v:errmsg = substitute(v:exception,
8200 \ '^Vim\((\a\+)\)\=:', '', "")
8205 continue " discard exception
8209 Xpath 536870912 " X: 0
8210 Xout v:exception "in" ExtraVimThrowpoint()
8213 let v{ERR(28) + CONT(28)} = 0
8215 let v{ERR(29) + CONT(29)}
8217 let var = exists('v{ERR(30) + CONT(30)}')
8219 unlet v{ERR(31) + CONT(31)}
8221 function F{ERR(32) + CONT(32)}()
8224 function F{ERR(33) + CONT(33)}
8226 let var = exists('*F{ERR(34) + CONT(34)}')
8228 delfunction F{ERR(35) + CONT(35)}
8230 let var = ERR(36) + CONT(36)
8233 let saved_errmsg = ""
8235 let v{WRAP(37, ERRabort(37)) + CONT(37)} = 0
8237 let v{WRAP(38, ERRabort(38)) + CONT(38)}
8239 let var = exists('v{WRAP(39, ERRabort(39)) + CONT(39)}')
8241 unlet v{WRAP(40, ERRabort(40)) + CONT(40)}
8243 function F{WRAP(41, ERRabort(41)) + CONT(41)}()
8246 function F{WRAP(42, ERRabort(42)) + CONT(42)}
8248 let var = exists('*F{WRAP(43, ERRabort(43)) + CONT(43)}')
8250 delfunction F{WRAP(44, ERRabort(44)) + CONT(44)}
8252 let var = ERRabort(45) + CONT(45)
8255 Xpath 1073741824 " X: 1073741824
8258 \ . "E1M1E2M2E3M3E4M4E5M5E6M6E7M7E8M8E9M9"
8259 \ . "I10M10I11M11I12M12I13M13I14M14I15M15I16M16I17M17I18M18"
8260 \ . "T19M19T20M20T21M21T22M22T23M23T24M24T25M25T26M26T27M27"
8261 \ . "E28C28M28E29C29M29E30C30M30E31C31M31E32C32M32E33C33M33"
8262 \ . "E34C34M34E35C35M35E36C36M36"
8263 \ . "A37W37C37M37A38W38C38M38A39W39C39M39A40W40C40M40A41W41C41M41"
8264 \ . "A42W42C42M42A43W43C43M43A44W44C44M44A45C45M45"
8266 if taken != expected
8267 " The Xpath command does not accept 2^31 (negative); display explicitly:
8268 exec "!echo 2147483648 >>" . g:ExtraVimResult
8270 Xout "'taken' is" taken "instead of" expected
8271 if substitute(taken,
8272 \ '\(.*\)E3C3M3x\(.*\)E30C30M30x\(.*\)A39C39M39x\(.*\)',
8273 \ '\1E3M3\2E30C30M30\3A39C39M39\4',
8275 Xout "Is ++emsg_skip for var with expr_start non-NULL"
8280 unlet! v var saved_errmsg taken expected
8284 unlet! WA_t5 WA_t14 WA_t23
8294 "-------------------------------------------------------------------------------
8295 " Test 77: Errors, interrupts, :throw in name{brace-expression} {{{1
8297 " When a function call made during evaluation of an expression in
8298 " braces as part of a function name after ":function" is aborted due
8299 " to an error inside a :try/:endtry region or due to an interrupt or
8300 " a :throw, the expression evaluation is aborted as well, and the
8301 " function definition is ignored, skipping all commands to the
8302 " ":endfunction". On an error not inside :try/:endtry, the expression
8303 " evaluation continues and the function gets defined, and can be
8304 " called and deleted.
8305 "-------------------------------------------------------------------------------
8311 function! ERR() abort
8312 Xloop 1 " X: 1 + 4 + 16 + 64
8314 endfunction " returns -1
8317 Xloop 2 " X: 2 * (1 + 4 + 16)
8324 Xpath 4096 " X: 4096
8325 function! F{1 + ERR() + OK()}(arg)
8326 " F0 should be defined.
8327 if exists("a:arg") && a:arg == "calling"
8328 Xpath 8192 " X: 8192
8338 Xpath 65536 " X: 65536
8339 call F{1 + ERR() + OK()}("calling")
8345 Xpath 262144 " X: 262144
8346 delfunction F{1 + ERR() + OK()}
8356 Xpath 1048576 " X: 1048576
8357 function! G{1 + ERR() + OK()}(arg)
8358 " G0 should not be defined, and the function body should be
8360 if exists("a:arg") && a:arg == "calling"
8361 Xpath 2097152 " X: 0
8363 Xpath 4194304 " X: 0
8365 " Use an unmatched ":finally" to check whether the body is
8366 " skipped when an error occurs in ERR(). This works whether or
8367 " not the exception is converted to an exception.
8369 Xpath 8388608 " X: 0
8370 Xout "Body of G{1 + ERR() + OK()}() not skipped"
8371 " Discard the aborting error or exception, and break the
8374 " End the try conditional and start a new one to avoid
8375 " ":catch after :finally" errors.
8378 Xpath 16777216 " X: 0
8381 " When the function was not defined, this won't be reached - whether
8382 " the body was skipped or not. When the function was defined, it
8383 " can be called and deleted here.
8384 Xpath 33554432 " X: 0
8385 Xout "G0() has been defined"
8388 call G{1 + ERR() + OK()}("calling")
8390 Xpath 67108864 " X: 0
8392 Xpath 134217728 " X: 0
8395 delfunction G{1 + ERR() + OK()}
8397 Xpath 268435456 " X: 0
8400 " Jumped to when the function is not defined and the body is
8404 Xpath 536870912 " X: 0
8406 if !caught && !$VIMNOERRTHROW
8407 Xpath 1073741824 " X: 0
8409 break " discard error for $VIMNOERRTHROW
8410 endtry " jumped to when the body is not skipped
8413 " The Xpath command does not accept 2^31 (negative); add explicitly:
8414 let Xpath = Xpath + 2147483648 " X: 0
8415 Xout "Body of G{1 + ERR() + OK()}() not skipped, exception caught"
8416 Xout v:exception "in" v:throwpoint
8422 "-------------------------------------------------------------------------------
8423 " Test 78: Messages on parsing errors in expression evaluation {{{1
8425 " When an expression evaluation detects a parsing error, an error
8426 " message is given and converted to an exception, and the expression
8427 " evaluation is aborted.
8428 "-------------------------------------------------------------------------------
8437 let g:taken = g:taken . "F" . a:n
8440 function! MSG(n, enr, emsg)
8441 let g:taken = g:taken . "M" . a:n
8442 let english = v:lang == "C" || v:lang =~ '^[Ee]n'
8444 Xout "TODO: Add message number for:" a:emsg
8445 let v:errmsg = ":" . v:errmsg
8447 if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
8449 Xout "Expr" a:n.": Message missing."
8450 let g:taken = g:taken . "x"
8452 let v:errmsg = escape(v:errmsg, '"')
8453 Xout "Expr" a:n.": Unexpected message:" v:errmsg
8454 Xout "Expected: " . a:enr . ': ' . a:emsg
8455 let g:taken = g:taken . "X"
8461 let g:taken = g:taken . "C" . a:n
8470 let g:taken = g:taken . "T" . t
8475 let v{novar + CONT(t)} = 0
8477 let v{novar + CONT(t)}
8479 let var = exists('v{novar + CONT(t)}')
8481 unlet v{novar + CONT(t)}
8483 function F{novar + CONT(t)}()
8486 function F{novar + CONT(t)}
8488 let var = exists('*F{novar + CONT(t)}')
8490 delfunction F{novar + CONT(t)}
8492 echo novar + CONT(t)
8494 echo v{novar + CONT(t)}
8496 echo F{novar + CONT(t)}
8498 let var = novar + CONT(t)
8500 let var = v{novar + CONT(t)}
8502 let var = F{novar + CONT(t)}()
8504 catch /^Vim\((\a\+)\)\=:/
8505 " v:errmsg is not set when the error message is converted to an
8506 " exception. Set it to the original error message.
8507 let v:errmsg = substitute(v:exception,
8508 \ '^Vim\((\a\+)\)\=:', '', "")
8511 if t <= 8 && t != 3 && t != 7
8512 call MSG(t, 'E475', 'Invalid argument\>')
8514 if !caught " no error exceptions ($VIMNOERRTHROW set)
8515 call MSG(t, 'E15', "Invalid expression")
8517 call MSG(t, 'E121', "Undefined variable")
8522 continue " discard an aborting error
8527 Xout t.":" v:exception "in" ExtraVimThrowpoint()
8530 function! T(n, expr, enr, emsg)
8532 let g:taken = g:taken . "T" . a:n
8536 execute "let var = " . a:expr
8537 catch /^Vim\((\a\+)\)\=:/
8538 " v:errmsg is not set when the error message is converted to an
8539 " exception. Set it to the original error message.
8540 let v:errmsg = substitute(v:exception,
8541 \ '^Vim\((\a\+)\)\=:', '', "")
8544 if !caught " no error exceptions ($VIMNOERRTHROW set)
8545 call MSG(a:n, 'E15', "Invalid expression")
8547 call MSG(a:n, a:enr, a:emsg)
8550 " Discard an aborting error:
8555 Xout a:n.":" v:exception "in" ExtraVimThrowpoint()
8559 call T(15, 'Nofunc() + CONT(15)', 'E117', "Unknown function")
8560 call T(16, 'F(1 2 + CONT(16))', 'E116', "Invalid arguments")
8561 call T(17, 'F(1, 2) + CONT(17)', 'E118', "Too many arguments")
8562 call T(18, 'F() + CONT(18)', 'E119', "Not enough arguments")
8563 call T(19, '{(1} + CONT(19)', 'E110', "Missing ')'")
8564 call T(20, '("abc"[1) + CONT(20)', 'E111', "Missing ']'")
8565 call T(21, '(1 +) + CONT(21)', 'E15', "Invalid expression")
8566 call T(22, '1 2 + CONT(22)', 'E15', "Invalid expression")
8567 call T(23, '(1 ? 2) + CONT(23)', 'E109', "Missing ':' after '?'")
8568 call T(24, '("abc) + CONT(24)', 'E114', "Missing quote")
8569 call T(25, "('abc) + CONT(25)", 'E115', "Missing quote")
8570 call T(26, '& + CONT(26)', 'E112', "Option name missing")
8571 call T(27, '&asdf + CONT(27)', 'E113', "Unknown option")
8573 Xpath 134217728 " X: 134217728
8576 \ . "T1M1T2M2T3M3T4M4T5M5T6M6T7M7T8M8T9M9T10M10T11M11T12M12T13M13T14M14"
8577 \ . "T15M15T16M16T17M17T18M18T19M19T20M20T21M21T22M22T23M23T24M24T25M25"
8580 if taken != expected
8581 Xpath 268435456 " X: 0
8582 Xout "'taken' is" taken "instead of" expected
8583 if substitute(taken, '\(.*\)T3M3x\(.*\)', '\1T3M3\2', "") == expected
8584 Xout "Is ++emsg_skip for var with expr_start non-NULL"
8589 unlet! var caught taken expected
8599 "-------------------------------------------------------------------------------
8600 " Test 79: Throwing one of several errors for the same command {{{1
8602 " When several errors appear in a row (for instance during expression
8603 " evaluation), the first as the most specific one is used when
8604 " throwing an error exception. If, however, a syntax error is
8605 " detected afterwards, this one is used for the error exception.
8606 " On a syntax error, the next command is not executed, on a normal
8607 " error, however, it is (relevant only in a function without the
8608 " "abort" flag). v:errmsg is not set.
8610 " If throwing error exceptions is configured off, v:errmsg is always
8611 " set to the latest error message, that is, to the more general
8612 " message or the syntax error, respectively.
8613 "-------------------------------------------------------------------------------
8620 exec a:cmd . " | Xloop 1"
8623 call NEXT('echo novar') " X: 1 * 1 (checks nextcmd)
8625 call NEXT('let novar #') " X: 0 * 2 (skips nextcmd)
8627 call NEXT('unlet novar #') " X: 0 * 4 (skips nextcmd)
8629 call NEXT('let {novar}') " X: 0 * 8 (skips nextcmd)
8631 call NEXT('unlet{ novar}') " X: 0 * 16 (skips nextcmd)
8637 function! MATCH(expected, msg, enr, emsg)
8640 Xout "TODO: Add message number for:" a:emsg
8643 let english = v:lang == "C" || v:lang =~ '^[Ee]n'
8644 if msg !~ '^'.a:enr.':' || (english && msg !~ a:emsg)
8646 if a:expected " no match although expected
8648 Xout "Message missing."
8650 let msg = escape(msg, '"')
8651 Xout "Unexpected message:" msg
8652 Xout "Expected:" a:enr . ": " . a:emsg
8657 if !a:expected " match although not expected
8658 let msg = escape(msg, '"')
8659 Xout "Unexpected message:" msg
8660 Xout "Expected none."
8668 while 1 " dummy loop
8673 call EXEC('echo novar') " normal error
8674 catch /^Vim\((\a\+)\)\=:/
8676 let thrmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
8683 elseif !MATCH(1, thrmsg, 'E121', "Undefined variable")
8687 if !caught && !MATCH(1, v:errmsg, 'E15', "Invalid expression")
8690 break " discard error if $VIMNOERRTHROW == 1
8702 call EXEC(cmd . ' novar #') " normal plus syntax error
8703 catch /^Vim\((\a\+)\)\=:/
8705 let thrmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
8707 Xloop 1 " X: 1024 * (1 + 32)
8714 let match = MATCH(0, thrmsg, 'E106', "Unknown variable")
8715 elseif cmd == "unlet"
8716 let match = MATCH(0, thrmsg, 'E108', "No such variable")
8718 if match " normal error
8721 if !MATCH(1, thrmsg, 'E488', "Trailing characters")
8727 if !caught && !MATCH(1, v:errmsg, 'E488', "Trailing characters")
8737 continue " discard error if $VIMNOERRTHROW == 1
8741 Xpath 1048576 " X: 1048576
8743 XloopINIT 2097152 32
8749 call EXEC(cmd . ' {novar}') " normal plus syntax error
8750 catch /^Vim\((\a\+)\)\=:/
8752 let thrmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
8754 Xloop 1 " X: 2097152 * (1 + 32)
8760 if MATCH(0, thrmsg, 'E121', "Undefined variable") " normal error
8763 if !MATCH(1, thrmsg, 'E475', 'Invalid argument\>')
8764 \ || v:errmsg != "" " syntax error
8768 if !caught && !MATCH(1, v:errmsg, 'E475', 'Invalid argument\>')
8778 continue " discard error if $VIMNOERRTHROW == 1
8783 " The Xpath command does not accept 2^31 (negative); add explicitly:
8784 let Xpath = Xpath + 2147483648 " X: 0
8785 Xout v:exception "in" v:throwpoint
8788 unlet! next_command thrmsg match
8796 "-------------------------------------------------------------------------------
8797 " Test 80: Syntax error in expression for illegal :elseif {{{1
8799 " If there is a syntax error in the expression after an illegal
8800 " :elseif, an error message is given (or an error exception thrown)
8801 " for the illegal :elseif rather than the expression error.
8802 "-------------------------------------------------------------------------------
8806 function! MSG(enr, emsg)
8807 let english = v:lang == "C" || v:lang =~ '^[Ee]n'
8809 Xout "TODO: Add message number for:" a:emsg
8810 let v:errmsg = ":" . v:errmsg
8813 if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
8816 Xout "Message missing."
8818 let v:errmsg = escape(v:errmsg, '"')
8819 Xout "Unexpected message:" v:errmsg
8831 if !MSG('E584', ":elseif after :else")
8841 if !MSG('E584', ":elseif after :else")
8848 if !MSG('E582', ":elseif without :if")
8857 if !MSG('E582', ":elseif without :if")
8870 catch /^Vim\((\a\+)\)\=:/
8872 let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
8875 if !caught && !$VIMNOERRTHROW
8878 if !MSG('E584', ":elseif after :else")
8884 Xout v:exception "in" v:throwpoint
8886 break " discard error for $VIMNOERRTHROW
8899 catch /^Vim\((\a\+)\)\=:/
8901 let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
8903 Xpath 4096 " X: 4096
8904 if !caught && !$VIMNOERRTHROW
8907 if !MSG('E584', ":elseif after :else")
8913 Xout v:exception "in" v:throwpoint
8915 break " discard error for $VIMNOERRTHROW
8925 catch /^Vim\((\a\+)\)\=:/
8927 let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
8929 Xpath 65536 " X: 65536
8930 if !caught && !$VIMNOERRTHROW
8933 if !MSG('E582', ":elseif without :if")
8939 Xout v:exception "in" v:throwpoint
8941 break " discard error for $VIMNOERRTHROW
8953 catch /^Vim\((\a\+)\)\=:/
8955 let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
8957 Xpath 1048576 " X: 1048576
8958 if !caught && !$VIMNOERRTHROW
8959 Xpath 2097152 " X: 0
8961 if !MSG('E582', ":elseif without :if")
8962 Xpath 4194304 " X: 0
8966 Xpath 8388608 " X: 0
8967 Xout v:exception "in" v:throwpoint
8969 break " discard error for $VIMNOERRTHROW
8973 Xpath 16777216 " X: 16777216
8981 "-------------------------------------------------------------------------------
8982 " Test 81: Discarding exceptions after an error or interrupt {{{1
8984 " When an exception is thrown from inside a :try conditional without
8985 " :catch and :finally clauses and an error or interrupt occurs before
8986 " the :endtry is reached, the exception is discarded.
8987 "-------------------------------------------------------------------------------
9000 " error after :throw: missing :endif
9027 "-------------------------------------------------------------------------------
9028 " Test 82: Ignoring :catch clauses after an error or interrupt {{{1
9030 " When an exception is thrown and an error or interrupt occurs before
9031 " the matching :catch clause is reached, the exception is discarded
9032 " and the :catch clause is ignored (also for the error or interrupt
9033 " exception being thrown then).
9034 "-------------------------------------------------------------------------------
9046 " error after :throw: missing :endif
9049 Xout v:exception "in" ExtraVimThrowpoint()
9052 Xout v:exception "in" ExtraVimThrowpoint()
9070 " error after :throw: missing :endif
9073 Xout v:exception "in" ExtraVimThrowpoint()
9076 Xout v:exception "in" ExtraVimThrowpoint()
9091 Xpath 65536 " X: 65536
9094 catch /.*/ "INTERRUPT
9096 Xout v:exception "in" ExtraVimThrowpoint()
9099 Xout v:exception "in" ExtraVimThrowpoint()
9101 Xpath 1048576 " X: 0
9103 Xpath 2097152 " X: 0
9105 Xpath 4194304 " X: 0
9112 Xpath 8388608 " X: 8388608
9114 Xpath 16777216 " X: 0
9115 catch /.*/ "INTERRUPT
9116 Xpath 33554432 " X: 0
9117 Xout v:exception "in" ExtraVimThrowpoint()
9119 Xpath 67108864 " X: 0
9120 Xout v:exception "in" ExtraVimThrowpoint()
9122 Xpath 134217728 " X: 0
9124 Xpath 268435456 " X: 0
9129 Xpath 536870912 " X: 0
9135 "-------------------------------------------------------------------------------
9136 " Test 83: Executing :finally clauses after an error or interrupt {{{1
9138 " When an exception is thrown and an error or interrupt occurs before
9139 " the :finally of the innermost :try is reached, the exception is
9140 " discarded and the :finally clause is executed.
9141 "-------------------------------------------------------------------------------
9154 " error after :throw: missing :endif
9173 Xpath 2048 " X: 2048
9185 "-------------------------------------------------------------------------------
9186 " Test 84: Exceptions in autocommand sequences. {{{1
9188 " When an exception occurs in a sequence of autocommands for
9189 " a specific event, the rest of the sequence is not executed. The
9190 " command that triggered the autocommand execution aborts, and the
9191 " exception is propagated to the caller.
9193 " For the FuncUndefined event under a function call expression or
9194 " :call command, the function is not executed, even when it has
9195 " been defined by the autocommands before the exception occurred.
9196 "-------------------------------------------------------------------------------
9210 autocmd User x1 Xpath 1 " X: 1
9211 autocmd User x1 throw "x1"
9212 autocmd User x1 Xpath 2 " X: 0
9214 autocmd User x2 Xpath 4 " X: 4
9215 autocmd User x2 asdf
9216 autocmd User x2 Xpath 8 " X: 0
9218 autocmd User x3 Xpath 16 " X: 16
9219 autocmd User x3 call INT()
9220 autocmd User x3 Xpath 32 " X: 0
9222 autocmd FuncUndefined U1 function! U1()
9223 autocmd FuncUndefined U1 Xpath 64 " X: 0
9224 autocmd FuncUndefined U1 endfunction
9225 autocmd FuncUndefined U1 Xpath 128 " X: 128
9226 autocmd FuncUndefined U1 throw "U1"
9227 autocmd FuncUndefined U1 Xpath 256 " X: 0
9229 autocmd FuncUndefined U2 function! U2()
9230 autocmd FuncUndefined U2 Xpath 512 " X: 0
9231 autocmd FuncUndefined U2 endfunction
9232 autocmd FuncUndefined U2 Xpath 1024 " X: 1024
9233 autocmd FuncUndefined U2 ASDF
9234 autocmd FuncUndefined U2 Xpath 2048 " X: 0
9236 autocmd FuncUndefined U3 function! U3()
9237 autocmd FuncUndefined U3 Xpath 4096 " X: 0
9238 autocmd FuncUndefined U3 endfunction
9239 autocmd FuncUndefined U3 Xpath 8192 " X: 8192
9240 autocmd FuncUndefined U3 call INT()
9241 autocmd FuncUndefined U3 Xpath 16384 " X: 0
9246 Xpath 32768 " X: 32768
9249 Xpath 65536 " X: 65536
9254 Xpath 131072 " X: 131072
9260 Xpath 262144 " X: 262144
9261 if !caught && !$VIMNOERRTHROW
9263 " Propagate uncaught error exception,
9265 " ... but break loop for caught error exception,
9266 " or discard error and break loop if $VIMNOERRTHROW
9274 Xpath 1048576 " X: 1048576
9277 catch /Vim:Interrupt/
9280 Xpath 2097152 " X: 2097152
9281 if !caught && !$VIMNOINTTHROW
9282 Xpath 4194304 " X: 0
9283 " Propagate uncaught interrupt exception,
9285 " ... but break loop for caught interrupt exception,
9286 " or discard interrupt and break loop if $VIMNOINTTHROW
9292 if exists("*U1") | delfunction U1 | endif
9293 if exists("*U2") | delfunction U2 | endif
9294 if exists("*U3") | delfunction U3 | endif
9297 Xpath 8388608 " X: 8388608
9300 Xpath 16777216 " X: 16777216
9305 Xpath 33554432 " X: 33554432
9311 Xpath 67108864 " X: 67108864
9312 if !caught && !$VIMNOERRTHROW
9313 Xpath 134217728 " X: 0
9314 " Propagate uncaught error exception,
9316 " ... but break loop for caught error exception,
9317 " or discard error and break loop if $VIMNOERRTHROW
9325 Xpath 268435456 " X: 268435456
9328 catch /Vim:Interrupt/
9331 Xpath 536870912 " X: 536870912
9332 if !caught && !$VIMNOINTTHROW
9333 Xpath 1073741824 " X: 0
9334 " Propagate uncaught interrupt exception,
9336 " ... but break loop for caught interrupt exception,
9337 " or discard interrupt and break loop if $VIMNOINTTHROW
9343 " The Xpath command does not accept 2^31 (negative); display explicitly:
9344 exec "!echo 2147483648 >>" . g:ExtraVimResult
9345 Xout "Caught" v:exception "in" v:throwpoint
9360 "-------------------------------------------------------------------------------
9361 " Test 85: Error exceptions in autocommands for I/O command events {{{1
9363 " When an I/O command is inside :try/:endtry, autocommands to be
9364 " executed after it should be skipped on an error (exception) in the
9365 " command itself or in autocommands to be executed before the command.
9366 " In the latter case, the I/O command should not be executed either.
9367 " Example 1: BufWritePre, :write, BufWritePost
9368 " Example 2: FileReadPre, :read, FileReadPost.
9369 "-------------------------------------------------------------------------------
9373 function! MSG(enr, emsg)
9374 let english = v:lang == "C" || v:lang =~ '^[Ee]n'
9376 Xout "TODO: Add message number for:" a:emsg
9377 let v:errmsg = ":" . v:errmsg
9380 if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
9383 Xout "Message missing."
9385 let v:errmsg = escape(v:errmsg, '"')
9386 Xout "Unexpected message:" v:errmsg
9392 " Remove the autocommands for the events specified as arguments in all used
9394 function! Delete_autocommands(...)
9395 let augfile = tempname()
9398 exec "redir >" . augfile
9405 while search('\%( \|^\)\@<=.\{-}\%( \)\@=', wrap) > 0
9410 exec "au!" escape(@", " ") a:{argno}
9411 let argno = argno + 1
9417 call delete(augfile)
9418 break " discard errors for $VIMNOERRTHROW
9423 call Delete_autocommands("BufWritePre", "BufWritePost")
9430 au! BufWritePost * let post = 1
9433 write /n/o/n/e/x/i/s/t/e/n/t
9434 catch /^Vim(write):/
9436 let v:errmsg = substitute(v:exception, '^Vim(write):', '', "")
9439 if !caught && !$VIMNOERRTHROW
9442 let v:errmsg = substitute(v:errmsg, '^"/n/o/n/e/x/i/s/t/e/n/t" ',
9444 if !MSG('E212', "Can't open file for writing")
9449 Xout "BufWritePost commands executed after write error"
9456 Xout v:exception "in" v:throwpoint
9458 break " discard error for $VIMNOERRTHROW
9467 au! BufWritePre * asdf
9468 au! BufWritePost * let post = 1
9470 let tmpfile = tempname()
9472 exec "write" tmpfile
9473 catch /^Vim\((write)\)\=:/
9475 let v:errmsg = substitute(v:exception, '^Vim\((write)\)\=:', '', "")
9478 if !caught && !$VIMNOERRTHROW
9481 let v:errmsg = substitute(v:errmsg, '^"'.tmpfile.'" ', '', "")
9482 if !MSG('E492', "Not an editor command")
9485 if filereadable(tmpfile)
9487 Xout ":write command not suppressed after BufWritePre error"
9491 Xout "BufWritePost commands executed after BufWritePre error"
9498 Xout v:exception "in" v:throwpoint
9500 break " discard error for $VIMNOERRTHROW
9504 call delete(tmpfile)
9506 call Delete_autocommands("BufWritePre", "BufWritePost",
9507 \ "BufReadPre", "BufReadPost", "FileReadPre", "FileReadPost")
9514 au! FileReadPost * let post = 1
9517 read /n/o/n/e/x/i/s/t/e/n/t
9520 let v:errmsg = substitute(v:exception, '^Vim(read):', '', "")
9522 Xpath 2048 " X: 2048
9523 if !caught && !$VIMNOERRTHROW
9526 let v:errmsg = substitute(v:errmsg, ' /n/o/n/e/x/i/s/t/e/n/t$',
9528 if !MSG('E484', "Can't open file")
9533 Xout "FileReadPost commands executed after write error"
9540 Xout v:exception "in" v:throwpoint
9542 break " discard error for $VIMNOERRTHROW
9548 let infile = tempname()
9549 let tmpfile = tempname()
9550 exec "!echo XYZ >" . infile
9553 Xpath 65536 " X: 65536
9557 au! FileReadPre * asdf
9558 au! FileReadPost * let post = 1
9562 catch /^Vim\((read)\)\=:/
9564 let v:errmsg = substitute(v:exception, '^Vim\((read)\)\=:', '',
9567 Xpath 131072 " X: 131072
9568 if !caught && !$VIMNOERRTHROW
9571 let v:errmsg = substitute(v:errmsg, ' '.infile.'$', '', "")
9572 if !MSG('E492', "Not an editor command")
9575 if getline("1") == "XYZ"
9576 Xpath 1048576 " X: 0
9577 Xout ":read command not suppressed after FileReadPre error"
9580 Xpath 2097152 " X: 0
9581 Xout "FileReadPost commands executed after " .
9582 \ "FileReadPre error"
9591 Xpath 4194304 " X: 0
9592 Xout v:exception "in" v:throwpoint
9594 break " discard error for $VIMNOERRTHROW
9599 call delete(tmpfile)
9600 unlet! caught post infile tmpfile
9602 delfunction Delete_autocommands
9607 "-------------------------------------------------------------------------------
9608 " Test 86: $VIMNOERRTHROW and $VIMNOINTTHROW support {{{1
9610 " It is possible to configure Vim for throwing exceptions on error
9611 " or interrupt, controlled by variables $VIMNOERRTHROW and
9612 " $VIMNOINTTHROW. This is just for increasing the number of tests.
9613 " All tests here should run for all four combinations of setting
9614 " these variables to 0 or 1. The variables are intended for the
9615 " development phase only. In the final release, Vim should be
9616 " configured to always use error and interrupt exceptions.
9618 " The test result is "OK",
9620 " - if the $VIMNOERRTHROW and the $VIMNOINTTHROW control are not
9621 " configured and exceptions are thrown on error and on
9624 " - if the $VIMNOERRTHROW or the $VIMNOINTTHROW control is
9625 " configured and works as intended.
9627 " What actually happens, is shown in the test output.
9629 " Otherwise, the test result is "FAIL", and the test output describes
9632 " IMPORTANT: This must be the last test because it sets $VIMNOERRTHROW and
9634 "-------------------------------------------------------------------------------
9640 function! ThrowOnError()
9644 Xloop 1 " X: 1 + 8 + 64
9647 let caught = 1 " error exception caught
9649 Xloop 2 " X: 2 + 16 + 128
9650 return caught " discard aborting error
9655 let quits_skipped = 0
9657 function! ThrowOnInterrupt()
9661 Xloop 1 " X: (1 + 8 + 64) * 512
9664 let g:quits_skipped = g:quits_skipped + 1
9666 let caught = 1 " interrupt exception caught
9668 Xloop 2 " X: (2 + 16 + 128) * 512
9669 return caught " discard interrupt
9674 function! CheckThrow(Type)
9675 execute 'return ThrowOn' . a:Type . '()'
9678 function! CheckConfiguration(type) " type is "error" or "interrupt"
9681 let Type = substitute(type, '.*', '\u&', "")
9682 let VAR = '$VIMNO' . substitute(type, '\(...\).*', '\U\1', "") . 'THROW'
9686 elseif type == "interrupt"
9690 exec 'let requested_for_tests = exists(VAR) && ' . VAR . ' == 0'
9691 exec 'let suppressed_for_tests = ' . VAR . ' != 0'
9692 let used_in_tests = CheckThrow(Type)
9694 exec 'let ' . VAR . ' = 0'
9695 let request_works = CheckThrow(Type)
9697 exec 'let ' . VAR . ' = 1'
9698 let suppress_works = !CheckThrow(Type)
9702 elseif type == "interrupt"
9703 XloopINIT! 2097152 8
9705 if g:quits_skipped != 0
9706 Xloop 1 " X: 0*2097152
9707 Xout "Test environment error. Interrupt breakpoints skipped: "
9708 \ . g:quits_skipped . ".\n"
9709 \ . "Cannot check whether interrupt exceptions are thrown."
9715 \ !suppressed_for_tests && !used_in_tests
9720 \ ? suppressed_for_tests && !request_works
9721 \ : !suppressed_for_tests
9724 " Failure in configuration.
9725 Xloop 2 " X: 0 * 2* (262144 + 2097152)
9726 elseif contradiction
9727 " Failure in test logic. Should not happen.
9728 Xloop 4 " X: 0 * 4 * (262144 + 2097152)
9731 let var_control_configured =
9732 \ request_works != used_in_tests
9733 \ || suppress_works == used_in_tests
9735 let var_control_not_configured =
9736 \ requested_for_tests || suppressed_for_tests
9737 \ ? request_works && !suppress_works
9738 \ : request_works == used_in_tests
9739 \ && suppress_works != used_in_tests
9741 let with = used_in_tests ? "with" : "without"
9743 let set = suppressed_for_tests ? "non-zero" :
9744 \ requested_for_tests ? "0" : "unset"
9746 let although = contradiction && !var_control_not_configured
9750 let output = "All tests were run " . with . " throwing exceptions on "
9753 if !var_control_not_configured
9754 let output = output . VAR . " was " . set . "."
9756 if !request_works && !requested_for_tests
9757 let output = output .
9758 \ "\n" . Type . " exceptions are not thrown when " . VAR .
9762 if !suppress_works && (!used_in_tests ||
9764 \ !requested_for_tests && !suppressed_for_tests)
9765 let output = output .
9766 \ "\n" . Type . " exceptions are thrown when " . VAR .
9770 if !failure && var_control_configured
9771 let output = output .
9772 \ "\nRun tests also with " . substitute(VAR, '^\$', '', "")
9773 \ . "=" . used_in_tests . "."
9774 \ . "\nThis is for testing in the development phase only."
9775 \ . " Remove the \n"
9776 \ . VAR . " control in the final release."
9779 let output = output .
9780 \ "The " . VAR . " control is not configured."
9786 call CheckConfiguration("error")
9787 Xpath 16777216 " X: 16777216
9788 call CheckConfiguration("interrupt")
9789 Xpath 33554432 " X: 33554432
9794 " IMPORTANT: No test should be added after this test because it changes
9795 " $VIMNOERRTHROW and $VIMNOINTTHROW.
9798 "-------------------------------------------------------------------------------
9800 " vim: ts=8 sw=4 tw=80 fdm=marker
9801 " vim: fdt=substitute(substitute(foldtext(),\ '\\%(^+--\\)\\@<=\\(\\s*\\)\\(.\\{-}\\)\:\ \\%(\"\ \\)\\=\\(Test\ \\d*\\)\:\\s*',\ '\\3\ (\\2)\:\ \\1',\ \"\"),\ '\\(Test\\s*\\)\\(\\d\\)\\D\\@=',\ '\\1\ \\2',\ "")
9802 "-------------------------------------------------------------------------------