Mercurial > vim
view src/testdir/test49.vim @ 11416:32aed0993813 v8.0.0592
patch 8.0.0592: if a job writes to a buffer screen is not updated
commit https://github.com/vim/vim/commit/29ae377ea7039874337bc79ace9ab2b37b9056e5
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun Apr 30 19:39:39 2017 +0200
patch 8.0.0592: if a job writes to a buffer screen is not updated
Problem: If a job writes to a buffer and the user is typing a command, the
screen isn't updated. When a message is displayed the changed
buffer may cause it to be cleared. (Ramel Eshed)
Solution: Update the screen and then the command line if the screen didn't
scroll. Avoid inserting screen lines, as it clears any message.
Update the status line when the buffer changed.
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Sun, 30 Apr 2017 19:45:03 +0200 |
parents | e05695e59f6d |
children | 63b02fcf1361 |
line wrap: on
line source
" Vim script language tests " Author: Servatius Brandt <Servatius.Brandt@fujitsu-siemens.com> " Last Change: 2016 Feb 07 "------------------------------------------------------------------------------- " Test environment {{{1 "------------------------------------------------------------------------------- " Adding new tests easily. {{{2 " " Writing new tests is eased considerably with the following functions and " abbreviations (see "Commands for recording the execution path", "Automatic " argument generation"). " " To get the abbreviations, execute the command " " :let test49_set_env = 1 | source test49.vim " " To get them always (from src/testdir), put a line " " au! BufRead test49.vim let test49_set_env = 1 | source test49.vim " " into the local .vimrc file in the src/testdir directory. " if exists("test49_set_env") && test49_set_env " Automatic argument generation for the test environment commands. function! Xsum() let addend = substitute(getline("."), '^.*"\s*X:\s*\|^.*', '', "") " Evaluate arithmetic expression. if addend != "" exec "let g:Xsum = g:Xsum + " . addend endif endfunction function! Xcheck() let g:Xsum=0 ?XpathINIT?,.call Xsum() exec "norm A " return g:Xsum endfunction iab Xcheck Xcheck<Space><C-R>=Xcheck()<CR><C-O>x function! Xcomment(num) let str = "" let tabwidth = &sts ? &sts : &ts let tabs = (48+tabwidth - a:num - virtcol(".")) / tabwidth while tabs > 0 let str = str . "\t" let tabs = tabs - 1 endwhile let str = str . '" X:' return str endfunction function! Xloop() let back = line(".") . "|norm" . virtcol(".") . "|" norm 0 let last = search('X\(loop\|path\)INIT\|Xloop\>', "bW") exec back let theline = getline(last) if theline =~ 'X\(loop\|path\)INIT' let num = 1 else let num = 2 * substitute(theline, '.*Xloop\s*\(\d\+\).*', '\1', "") endif ?X\(loop\|path\)INIT? \s/\(XloopINIT!\=\s*\d\+\s\+\)\@<=\(\d\+\)/\=2*submatch(2)/ exec back exec "norm a " return num . Xcomment(strlen(num)) endfunction iab Xloop Xloop<Space><C-R>=Xloop()<CR><C-O>x function! Xpath(loopinit) let back = line(".") . "|norm" . virtcol(".") . "|" norm 0 let last = search('XpathINIT\|Xpath\>\|XloopINIT', "bW") exec back let theline = getline(last) if theline =~ 'XpathINIT' let num = 1 elseif theline =~ 'Xpath\>' let num = 2 * substitute(theline, '.*Xpath\s*\(\d\+\).*', '\1', "") else let pattern = '.*XloopINIT!\=\s*\(\d\+\)\s*\(\d\+\).*' let num = substitute(theline, pattern, '\1', "") let factor = substitute(theline, pattern, '\2', "") " The "<C-O>x" from the "Xpath" iab and the character triggering its " expansion are in the input buffer. Save and clear typeahead so " that it is not read away by the call to "input()" below. Restore " afterwards. call inputsave() let loops = input("Number of iterations in previous loop? ") call inputrestore() while (loops > 0) let num = num * factor let loops = loops - 1 endwhile endif exec "norm a " if a:loopinit return num . " 1" endif return num . Xcomment(strlen(num)) endfunction iab Xpath Xpath<Space><C-R>=Xpath(0)<CR><C-O>x iab XloopINIT XloopINIT<Space><C-R>=Xpath(1)<CR><C-O>x " Also useful (see ExtraVim below): aug ExtraVim au! au BufEnter <sfile> syn region ExtraVim \ start=+^if\s\+ExtraVim(.*)+ end=+^endif+ \ transparent keepend au BufEnter <sfile> syn match ExtraComment /^"/ \ contained containedin=ExtraVim au BufEnter <sfile> hi link ExtraComment vimComment aug END aug Xpath au BufEnter <sfile> syn keyword Xpath \ XpathINIT Xpath XloopINIT Xloop XloopNEXT Xcheck Xout au BufEnter <sfile> hi link Xpath Special aug END do BufEnter <sfile> " Do not execute the tests when sourcing this file for getting the functions " and abbreviations above, which are intended for easily adding new test " cases; they are not needed for test execution. Unlet the variable " controlling this so that an explicit ":source" command for this file will " execute the tests. unlet test49_set_env finish endif " Commands for recording the execution path. {{{2 " " The Xpath/Xloop commands can be used for computing the eXecution path by " adding (different) powers of 2 from those script lines, for which the " execution should be checked. Xloop provides different addends for each " execution of a loop. Permitted values are 2^0 to 2^30, so that 31 execution " points (multiply counted inside loops) can be tested. " " Note that the arguments of the following commands can be generated " automatically, see below. " " Usage: {{{3 " " - Use XpathINIT at the beginning of the test. " " - Use Xpath to check if a line is executed. " Argument: power of 2 (decimal). " " - To check multiple execution of loops use Xloop for automatically " computing Xpath values: " " - Use XloopINIT before the loop. " Two arguments: " - the first Xpath value (power of 2) to be used (Xnext), " - factor for computing a new Xnext value when reexecuting a loop " (by a ":continue" or ":endwhile"); this should be 2^n where " n is the number of Xloop commands inside the loop. " If XloopINIT! is used, the first execution of XloopNEXT is " a no-operation. " " - Use Xloop inside the loop: " One argument: " The argument and the Xnext value are multiplied to build the " next Xpath value. No new Xnext value is prepared. The argument " should be 2^(n-1) for the nth Xloop command inside the loop. " If the loop has only one Xloop command, the argument can be " ommitted (default: 1). " " - Use XloopNEXT before ":continue" and ":endwhile". This computes a new " Xnext value for the next execution of the loop by multiplying the old " one with the factor specified in the XloopINIT command. No Argument. " Alternatively, when XloopINIT! is used, a single XloopNEXT at the " beginning of the loop can be used. " " Nested loops are not supported. " " - Use Xcheck at end of each test. It prints the test number, the expected " execution path value, the test result ("OK" or "FAIL"), and, if the tests " fails, the actual execution path. " One argument: " Expected Xpath/Xloop sum for the correct execution path. " In order that this value can be computed automatically, do the " following: For each line in the test with an Xpath and Xloop " command, add a comment starting with "X:" and specifying an " expression that evaluates to the value contributed by this line to " the correct execution path. (For copying an Xpath argument of at " least two digits into the comment, press <C-P>.) At the end of the " test, just type "Xcheck" and press <Esc>. " " - In order to add additional information to the test output file, use the " Xout command. Argument(s) like ":echo". " " Automatic argument generation: {{{3 " " The arguments of the Xpath, XloopINIT, Xloop, and Xcheck commands can be " generated automatically, so that new tests can easily be written without " mental arithmetic. The Xcheck argument is computed from the "X:" comments " of the preceding Xpath and Xloop commands. See the commands and " abbreviations at the beginning of this file. " " Implementation: {{{3 " XpathINIT, Xpath, XloopINIT, Xloop, XloopNEXT, Xcheck, Xout. " " The variants for existing g:ExtraVimResult are needed when executing a script " in an extra Vim process, see ExtraVim below. " EXTRA_VIM_START - do not change or remove this line. com! XpathINIT let g:Xpath = 0 if exists("g:ExtraVimResult") com! -count -bar Xpath exec "!echo <count> >>" . g:ExtraVimResult else com! -count -bar Xpath let g:Xpath = g:Xpath + <count> endif com! -count -nargs=1 -bang \ XloopINIT let g:Xnext = <count> | \ let g:Xfactor = <args> | \ let g:Xskip = strlen("<bang>") if exists("g:ExtraVimResult") com! -count=1 -bar Xloop exec "!echo " . (g:Xnext * <count>) . " >>" . \ g:ExtraVimResult else com! -count=1 -bar Xloop let g:Xpath = g:Xpath + g:Xnext * <count> endif com! XloopNEXT let g:Xnext = g:Xnext * \ (g:Xskip ? 1 : g:Xfactor) | \ let g:Xskip = 0 let @r = "" let Xtest = 1 com! -count Xcheck let Xresult = "*** Test " . \ (Xtest<10?" ":Xtest<100?" ":"") . \ Xtest . ": " . ( \ (Xpath==<count>) ? "OK (".Xpath.")" : \ "FAIL (".Xpath." instead of <count>)" \ ) | \ let @R = Xresult . "\n" | \ echo Xresult | \ let Xtest = Xtest + 1 if exists("g:ExtraVimResult") com! -nargs=+ Xoutq exec "!echo @R:'" . \ substitute(substitute(<q-args>, \ "'", '&\\&&', "g"), "\n", "@NL@", "g") \ . "' >>" . g:ExtraVimResult else com! -nargs=+ Xoutq let @R = "--- Test " . \ (g:Xtest<10?" ":g:Xtest<100?" ":"") . \ g:Xtest . ": " . substitute(<q-args>, \ "\n", "&\t ", "g") . "\n" endif com! -nargs=+ Xout exec 'Xoutq' <args> " Switch off storing of lines for undoing changes. Speeds things up a little. set undolevels=-1 " EXTRA_VIM_STOP - do not change or remove this line. " ExtraVim() - Run a script file in an extra Vim process. {{{2 " " This is useful for testing immediate abortion of the script processing due to " an error in a command dynamically enclosed by a :try/:tryend region or when an " exception is thrown but not caught or when an interrupt occurs. It can also " be used for testing :finish. " " An interrupt location can be specified by an "INTERRUPT" comment. A number " telling how often this location is reached (in a loop or in several function " calls) should be specified as argument. When missing, once per script " invocation or function call is assumed. INTERRUPT locations are tested by " setting a breakpoint in that line and using the ">quit" debug command when " the breakpoint is reached. A function for which an INTERRUPT location is " specified must be defined before calling it (or executing it as a script by " using ExecAsScript below). " " This function is only called in normal modus ("g:ExtraVimResult" undefined). " " Tests to be executed as an extra script should be written as follows: " " column 1 column 1 " | | " v v " " XpathINIT XpathINIT " if ExtraVim() if ExtraVim() " ... " ... " ... " ... " endif endif " Xcheck <number> Xcheck <number> " " Double quotes in column 1 are removed before the script is executed. " They should be used if the test has unbalanced conditionals (:if/:endif, " :while:/endwhile, :try/:endtry) or for a line with a syntax error. The " extra script may use Xpath, XloopINIT, Xloop, XloopNEXT, and Xout as usual. " " A file name may be specified as argument. All messages of the extra Vim " process are then redirected to the file. An existing file is overwritten. " let ExtraVimCount = 0 let ExtraVimBase = expand("<sfile>") let ExtraVimTestEnv = "" " function! ExtraVim(...) " Count how often this function is called. let g:ExtraVimCount = g:ExtraVimCount + 1 " Disable folds to prevent that the ranges in the ":write" commands below " are extended up to the end of a closed fold. This also speeds things up " considerably. set nofoldenable " Open a buffer for this test script and copy the test environment to " a temporary file. Take account of parts relevant for the extra script " execution only. let current_buffnr = bufnr("%") execute "view +1" g:ExtraVimBase if g:ExtraVimCount == 1 let g:ExtraVimTestEnv = tempname() execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w" \ g:ExtraVimTestEnv "|']+" execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w >>" \ g:ExtraVimTestEnv "|']+" execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w >>" \ g:ExtraVimTestEnv "|']+" execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w >>" \ g:ExtraVimTestEnv "|']+" endif " Start the extra Vim script with a ":source" command for the test " environment. The source line number where the extra script will be " appended, needs to be passed as variable "ExtraVimBegin" to the script. let extra_script = tempname() exec "!echo 'source " . g:ExtraVimTestEnv . "' >" . extra_script let extra_begin = 1 " Starting behind the test environment, skip over the first g:ExtraVimCount " occurrences of "if ExtraVim()" and copy the following lines up to the " matching "endif" to the extra Vim script. execute "/E" . "ND_OF_TEST_ENVIRONMENT/" exec 'norm ' . g:ExtraVimCount . '/^\s*if\s\+ExtraVim(.*)/+' . "\n" execute ".,/^endif/-write >>" . extra_script " Open a buffer for the extra Vim script, delete all ^", and write the " script if was actually modified. execute "edit +" . (extra_begin + 1) extra_script ,$s/^"//e update " Count the INTERRUPTs and build the breakpoint and quit commands. let breakpoints = "" let debug_quits = "" let in_func = 0 exec extra_begin while search( \ '"\s*INTERRUPT\h\@!\|^\s*fu\%[nction]\>!\=\s*\%(\u\|s:\)\w*\s*(\|' \ . '^\s*\\\|^\s*endf\%[unction]\>\|' \ . '\%(^\s*fu\%[nction]!\=\s*\)\@<!\%(\u\|s:\)\w*\s*(\|' \ . 'ExecAsScript\s\+\%(\u\|s:\)\w*', \ "W") > 0 let theline = getline(".") if theline =~ '^\s*fu' " Function definition. let in_func = 1 let func_start = line(".") let func_name = substitute(theline, \ '^\s*fu\%[nction]!\=\s*\(\%(\u\|s:\)\w*\).*', '\1', "") elseif theline =~ '^\s*endf' " End of function definition. let in_func = 0 else let finding = substitute(theline, '.*\(\%' . col(".") . 'c.*\)', \ '\1', "") if finding =~ '^"\s*INTERRUPT\h\@!' " Interrupt comment. Compose as many quit commands as " specified. let cnt = substitute(finding, \ '^"\s*INTERRUPT\s*\(\d*\).*$', '\1', "") let quits = "" while cnt > 0 " Use "\r" rather than "\n" to separate the quit commands. " "\r" is not interpreted as command separator by the ":!" " command below but works to separate commands in the " external vim. let quits = quits . "q\r" let cnt = cnt - 1 endwhile if in_func " Add the function breakpoint and note the number of quits " to be used, if specified, or one for every call else. let breakpoints = breakpoints . " -c 'breakadd func " . \ (line(".") - func_start) . " " . \ func_name . "'" if quits != "" let debug_quits = debug_quits . quits elseif !exists("quits{func_name}") let quits{func_name} = "q\r" else let quits{func_name} = quits{func_name} . "q\r" endif else " Add the file breakpoint and the quits to be used for it. let breakpoints = breakpoints . " -c 'breakadd file " . \ line(".") . " " . extra_script . "'" if quits == "" let quits = "q\r" endif let debug_quits = debug_quits . quits endif else " Add the quits to be used for calling the function or executing " it as script file. if finding =~ '^ExecAsScript' " Sourcing function as script. let finding = substitute(finding, \ '^ExecAsScript\s\+\(\%(\u\|s:\)\w*\).*', '\1', "") else " Function call. let finding = substitute(finding, \ '^\(\%(\u\|s:\)\w*\).*', '\1', "") endif if exists("quits{finding}") let debug_quits = debug_quits . quits{finding} endif endif endif endwhile " Close the buffer for the script and create an (empty) resultfile. bwipeout let resultfile = tempname() exec "!>" . resultfile " Run the script in an extra vim. Switch to extra modus by passing the " resultfile in ExtraVimResult. Redirect messages to the file specified as " argument if any. Use ":debuggreedy" so that the commands provided on the " pipe are consumed at the debug prompt. Use "-N" to enable command-line " continuation ("C" in 'cpo'). Add "nviminfo" to 'viminfo' to avoid " messing up the user's viminfo file. let redirect = a:0 ? \ " -c 'au VimLeave * redir END' -c 'redir\\! >" . a:1 . "'" : "" exec "!echo '" . debug_quits . "q' | ../vim -u NONE -N -Xes" . redirect . \ " -c 'debuggreedy|set viminfo+=nviminfo'" . \ " -c 'let ExtraVimBegin = " . extra_begin . "'" . \ " -c 'let ExtraVimResult = \"" . resultfile . "\"'" . breakpoints . \ " -S " . extra_script " Build the resulting sum for resultfile and add it to g:Xpath. Add Xout " information provided by the extra Vim process to the test output. let sum = 0 exec "edit" resultfile let line = 1 while line <= line("$") let theline = getline(line) if theline =~ '^@R:' exec 'Xout "' . substitute(substitute( \ escape(escape(theline, '"'), '\"'), \ '^@R:', '', ""), '@NL@', "\n", "g") . '"' else let sum = sum + getline(line) endif let line = line + 1 endwhile bwipeout let g:Xpath = g:Xpath + sum " Delete the extra script and the resultfile. call delete(extra_script) call delete(resultfile) " Switch back to the buffer that was active when this function was entered. exec "buffer" current_buffnr " Return 0. This protects extra scripts from being run in the main Vim " process. return 0 endfunction " ExtraVimThrowpoint() - Relative throwpoint in ExtraVim script {{{2 " " Evaluates v:throwpoint and returns the throwpoint relative to the beginning of " an ExtraVim script as passed by ExtraVim() in ExtraVimBegin. " " EXTRA_VIM_START - do not change or remove this line. function! ExtraVimThrowpoint() if !exists("g:ExtraVimBegin") Xout "ExtraVimThrowpoint() used outside ExtraVim() script." return v:throwpoint endif if v:throwpoint =~ '^function\>' return v:throwpoint endif return "line " . \ (substitute(v:throwpoint, '.*, line ', '', "") - g:ExtraVimBegin) . \ " of ExtraVim() script" endfunction " EXTRA_VIM_STOP - do not change or remove this line. " MakeScript() - Make a script file from a function. {{{2 " " Create a script that consists of the body of the function a:funcname. " Replace any ":return" by a ":finish", any argument variable by a global " variable, and and every ":call" by a ":source" for the next following argument " in the variable argument list. This function is useful if similar tests are " to be made for a ":return" from a function call or a ":finish" in a script " file. " " In order to execute a function specifying an INTERRUPT location (see ExtraVim) " as a script file, use ExecAsScript below. " " EXTRA_VIM_START - do not change or remove this line. function! MakeScript(funcname, ...) let script = tempname() execute "redir! >" . script execute "function" a:funcname redir END execute "edit" script " Delete the "function" and the "endfunction" lines. Do not include the " word "function" in the pattern since it might be translated if LANG is " set. When MakeScript() is being debugged, this deletes also the debugging " output of its line 3 and 4. exec '1,/.*' . a:funcname . '(.*)/d' /^\d*\s*endfunction\>/,$d %s/^\d*//e %s/return/finish/e %s/\<a:\(\h\w*\)/g:\1/ge normal gg0 let cnt = 0 while search('\<call\s*\%(\u\|s:\)\w*\s*(.*)', 'W') > 0 let cnt = cnt + 1 s/\<call\s*\%(\u\|s:\)\w*\s*(.*)/\='source ' . a:{cnt}/ endwhile g/^\s*$/d write bwipeout return script endfunction " EXTRA_VIM_STOP - do not change or remove this line. " ExecAsScript - Source a temporary script made from a function. {{{2 " " Make a temporary script file from the function a:funcname, ":source" it, and " delete it afterwards. " " When inside ":if ExtraVim()", add a file breakpoint for each INTERRUPT " location specified in the function. " " EXTRA_VIM_START - do not change or remove this line. function! ExecAsScript(funcname) " Make a script from the function passed as argument. let script = MakeScript(a:funcname) " When running in an extra Vim process, add a file breakpoint for each " function breakpoint set when the extra Vim process was invoked by " ExtraVim(). if exists("g:ExtraVimResult") let bplist = tempname() execute "redir! >" . bplist breaklist redir END execute "edit" bplist " Get the line number from the function breakpoint. Works also when " LANG is set. execute 'v/^\s*\d\+\s\+func\s\+' . a:funcname . '\s.*/d' %s/^\s*\d\+\s\+func\s\+\%(\u\|s:\)\w*\s\D*\(\d*\).*/\1/e let cnt = 0 while cnt < line("$") let cnt = cnt + 1 if getline(cnt) != "" execute "breakadd file" getline(cnt) script endif endwhile bwipeout! call delete(bplist) endif " Source and delete the script. exec "source" script call delete(script) endfunction com! -nargs=1 -bar ExecAsScript call ExecAsScript(<f-args>) " EXTRA_VIM_STOP - do not change or remove this line. " END_OF_TEST_ENVIRONMENT - do not change or remove this line. " Tests 1 to 15 were moved to test_vimscript.vim let Xtest = 16 "------------------------------------------------------------------------------- " Test 16: Double :else or :elseif after :else {{{1 " " Multiple :elses or an :elseif after an :else are forbidden. "------------------------------------------------------------------------------- XpathINIT function! F() abort if 0 Xpath 1 " X: 0 else Xpath 2 " X: 2 else " aborts function Xpath 4 " X: 0 endif endfunction function! G() abort if 0 Xpath 8 " X: 0 else Xpath 16 " X: 16 elseif 1 " aborts function Xpath 32 " X: 0 else Xpath 64 " X: 0 endif endfunction function! H() abort if 0 Xpath 128 " X: 0 elseif 0 Xpath 256 " X: 0 else Xpath 512 " X: 512 else " aborts function Xpath 1024 " X: 0 endif endfunction function! I() abort if 0 Xpath 2048 " X: 0 elseif 0 Xpath 4096 " X: 0 else Xpath 8192 " X: 8192 elseif 1 " aborts function Xpath 16384 " X: 0 else Xpath 32768 " X: 0 endif endfunction call F() call G() call H() call I() delfunction F delfunction G delfunction H delfunction I Xcheck 8722 "------------------------------------------------------------------------------- " Test 17: Nesting of unmatched :if or :endif inside a :while {{{1 " " The :while/:endwhile takes precedence in nesting over an unclosed " :if or an unopened :endif. "------------------------------------------------------------------------------- XpathINIT function! MSG(enr, emsg) let english = v:lang == "C" || v:lang =~ '^[Ee]n' if a:enr == "" Xout "TODO: Add message number for:" a:emsg let v:errmsg = ":" . v:errmsg endif let match = 1 if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg) let match = 0 if v:errmsg == "" Xout "Message missing." else let v:errmsg = escape(v:errmsg, '"') Xout "Unexpected message:" v:errmsg endif endif return match endfunction let messages = "" " While loops inside a function are continued on error. function! F() let v:errmsg = "" XloopINIT 1 16 let loops = 3 while loops > 0 let loops = loops - 1 " 2: 1: 0: Xloop 1 " X: 1 + 1*16 + 1*16*16 if (loops == 1) Xloop 2 " X: 2*16 XloopNEXT continue elseif (loops == 0) Xloop 4 " X: 4*16*16 break elseif 1 Xloop 8 " X: 8 XloopNEXT " endif missing! endwhile " :endwhile after :if 1 Xpath 4096 " X: 16*16*16 if MSG('E171', "Missing :endif") let g:messages = g:messages . "A" endif let v:errmsg = "" XloopINIT! 8192 4 let loops = 2 while loops > 0 " 2: 1: XloopNEXT let loops = loops - 1 Xloop 1 " X: 8192 + 8192*4 if 0 Xloop 2 " X: 0 " endif missing endwhile " :endwhile after :if 0 Xpath 131072 " X: 8192*4*4 if MSG('E171', "Missing :endif") let g:messages = g:messages . "B" endif let v:errmsg = "" XloopINIT 262144 4 let loops = 2 while loops > 0 " 2: 1: let loops = loops - 1 Xloop 1 " X: 262144 + 262144 * 4 " if missing! endif " :endif without :if in while Xloop 2 " X: 524288 + 524288 * 4 XloopNEXT endwhile Xpath 4194304 " X: 262144*4*4 if MSG('E580', ":endif without :if") let g:messages = g:messages . "C" endif endfunction call F() " Error continuation outside a function is at the outermost :endwhile or :endif. let v:errmsg = "" XloopINIT! 8388608 4 let loops = 2 while loops > 0 " 2: 1: XloopNEXT let loops = loops - 1 Xloop 1 " X: 8388608 + 0 * 4 if 0 Xloop 2 " X: 0 " endif missing! Following :endwhile fails. endwhile | Xpath 134217728 " X: 0 Xpath 268435456 " X: 2*8388608*4*4 if MSG('E171', "Missing :endif") let messages = g:messages . "D" endif if messages != "ABCD" Xpath 536870912 " X: 0 Xout "messages is" messages "instead of ABCD" endif unlet loops messages delfunction F delfunction MSG Xcheck 285127993 "------------------------------------------------------------------------------- " Test 18: Interrupt (Ctrl-C pressed) {{{1 " " On an interrupt, the script processing is terminated immediately. "------------------------------------------------------------------------------- XpathINIT if ExtraVim() if 1 Xpath 1 " X: 1 while 1 Xpath 2 " X: 2 if 1 Xpath 4 " X: 4 "INTERRUPT Xpath 8 " X: 0 break finish endif | Xpath 16 " X: 0 Xpath 32 " X: 0 endwhile | Xpath 64 " X: 0 Xpath 128 " X: 0 endif | Xpath 256 " X: 0 Xpath 512 " X: 0 endif if ExtraVim() try Xpath 1024 " X: 1024 "INTERRUPT Xpath 2048 " X: 0 endtry | Xpath 4096 " X: 0 Xpath 8192 " X: 0 endif if ExtraVim() function! F() if 1 Xpath 16384 " X: 16384 while 1 Xpath 32768 " X: 32768 if 1 Xpath 65536 " X: 65536 "INTERRUPT Xpath 131072 " X: 0 break return endif | Xpath 262144 " X: 0 Xpath Xpath 524288 " X: 0 endwhile | Xpath 1048576 " X: 0 Xpath Xpath 2097152 " X: 0 endif | Xpath Xpath 4194304 " X: 0 Xpath Xpath 8388608 " X: 0 endfunction call F() | Xpath 16777216 " X: 0 Xpath 33554432 " X: 0 endif if ExtraVim() function! G() try Xpath 67108864 " X: 67108864 "INTERRUPT Xpath 134217728 " X: 0 endtry | Xpath 268435456 " X: 0 Xpath 536870912 " X: 0 endfunction call G() | Xpath 1073741824 " X: 0 " The Xpath command does not accept 2^31 (negative); display explicitly: exec "!echo 2147483648 >>" . g:ExtraVimResult " X: 0 endif Xcheck 67224583 "------------------------------------------------------------------------------- " Test 19: Aborting on errors inside :try/:endtry {{{1 " " An error in a command dynamically enclosed in a :try/:endtry region " aborts script processing immediately. It does not matter whether " the failing command is outside or inside a function and whether a " function has an "abort" attribute. "------------------------------------------------------------------------------- XpathINIT if ExtraVim() function! F() abort Xpath 1 " X: 1 asdf Xpath 2 " X: 0 endfunction try Xpath 4 " X: 4 call F() Xpath 8 " X: 0 endtry | Xpath 16 " X: 0 Xpath 32 " X: 0 endif if ExtraVim() function! G() Xpath 64 " X: 64 asdf Xpath 128 " X: 0 endfunction try Xpath 256 " X: 256 call G() Xpath 512 " X: 0 endtry | Xpath 1024 " X: 0 Xpath 2048 " X: 0 endif if ExtraVim() try Xpath 4096 " X: 4096 asdf Xpath 8192 " X: 0 endtry | Xpath 16384 " X: 0 Xpath 32768 " X: 0 endif if ExtraVim() if 1 try Xpath 65536 " X: 65536 asdf Xpath 131072 " X: 0 endtry | Xpath 262144 " X: 0 endif | Xpath 524288 " X: 0 Xpath 1048576 " X: 0 endif if ExtraVim() let p = 1 while p let p = 0 try Xpath 2097152 " X: 2097152 asdf Xpath 4194304 " X: 0 endtry | Xpath 8388608 " X: 0 endwhile | Xpath 16777216 " X: 0 Xpath 33554432 " X: 0 endif if ExtraVim() let p = 1 while p let p = 0 " try Xpath 67108864 " X: 67108864 endwhile | Xpath 134217728 " X: 0 Xpath 268435456 " X: 0 endif Xcheck 69275973 "------------------------------------------------------------------------------- " Test 20: Aborting on errors after :try/:endtry {{{1 " " When an error occurs after the last active :try/:endtry region has " been left, termination behavior is as if no :try/:endtry has been " seen. "------------------------------------------------------------------------------- XpathINIT if ExtraVim() let p = 1 while p let p = 0 try Xpath 1 " X: 1 endtry asdf endwhile | Xpath 2 " X: 0 Xpath 4 " X: 4 endif if ExtraVim() while 1 try Xpath 8 " X: 8 break Xpath 16 " X: 0 endtry endwhile Xpath 32 " X: 32 asdf Xpath 64 " X: 64 endif if ExtraVim() while 1 try Xpath 128 " X: 128 break Xpath 256 " X: 0 finally Xpath 512 " X: 512 endtry endwhile Xpath 1024 " X: 1024 asdf Xpath 2048 " X: 2048 endif if ExtraVim() while 1 try Xpath 4096 " X: 4096 finally Xpath 8192 " X: 8192 break Xpath 16384 " X: 0 endtry endwhile Xpath 32768 " X: 32768 asdf Xpath 65536 " X: 65536 endif if ExtraVim() let p = 1 while p let p = 0 try Xpath 131072 " X: 131072 continue Xpath 262144 " X: 0 endtry endwhile Xpath 524288 " X: 524288 asdf Xpath 1048576 " X: 1048576 endif if ExtraVim() let p = 1 while p let p = 0 try Xpath 2097152 " X: 2097152 continue Xpath 4194304 " X: 0 finally Xpath 8388608 " X: 8388608 endtry endwhile Xpath 16777216 " X: 16777216 asdf Xpath 33554432 " X: 33554432 endif if ExtraVim() let p = 1 while p let p = 0 try Xpath 67108864 " X: 67108864 finally Xpath 134217728 " X: 134217728 continue Xpath 268435456 " X: 0 endtry endwhile Xpath 536870912 " X: 536870912 asdf Xpath 1073741824 " X: 1073741824 endif Xcheck 1874575085 "------------------------------------------------------------------------------- " Test 21: :finally for :try after :continue/:break/:return/:finish {{{1 " " If a :try conditional stays inactive due to a preceding :continue, " :break, :return, or :finish, its :finally clause should not be " executed. "------------------------------------------------------------------------------- XpathINIT if ExtraVim() function F() let loops = 2 XloopINIT! 1 256 while loops > 0 XloopNEXT let loops = loops - 1 try if loops == 1 Xloop 1 " X: 1 continue Xloop 2 " X: 0 elseif loops == 0 Xloop 4 " X: 4*256 break Xloop 8 " X: 0 endif try " inactive Xloop 16 " X: 0 finally Xloop 32 " X: 0 endtry finally Xloop 64 " X: 64 + 64*256 endtry Xloop 128 " X: 0 endwhile try Xpath 65536 " X: 65536 return Xpath 131072 " X: 0 try " inactive Xpath 262144 " X: 0 finally Xpath 524288 " X: 0 endtry finally Xpath 1048576 " X: 1048576 endtry Xpath 2097152 " X: 0 endfunction try Xpath 4194304 " X: 4194304 call F() Xpath 8388608 " X: 8388608 finish Xpath 16777216 " X: 0 try " inactive Xpath 33554432 " X: 0 finally Xpath 67108864 " X: 0 endtry finally Xpath 134217728 " X: 134217728 endtry Xpath 268435456 " X: 0 endif Xcheck 147932225 "------------------------------------------------------------------------------- " Test 22: :finally for a :try after an error/interrupt/:throw {{{1 " " If a :try conditional stays inactive due to a preceding error or " interrupt or :throw, its :finally clause should not be executed. "------------------------------------------------------------------------------- XpathINIT if ExtraVim() function! Error() try asdf " aborting error, triggering error exception endtry endfunction Xpath 1 " X: 1 call Error() Xpath 2 " X: 0 if 1 " not active due to error try " not active since :if inactive Xpath 4 " X: 0 finally Xpath 8 " X: 0 endtry endif try " not active due to error Xpath 16 " X: 0 finally Xpath 32 " X: 0 endtry endif if ExtraVim() function! Interrupt() try "INTERRUPT " triggering interrupt exception endtry endfunction Xpath 64 " X: 64 call Interrupt() Xpath 128 " X: 0 if 1 " not active due to interrupt try " not active since :if inactive Xpath 256 " X: 0 finally Xpath 512 " X: 0 endtry endif try " not active due to interrupt Xpath 1024 " X: 0 finally Xpath 2048 " X: 0 endtry endif if ExtraVim() function! Throw() throw "xyz" endfunction Xpath 4096 " X: 4096 call Throw() Xpath 8192 " X: 0 if 1 " not active due to :throw try " not active since :if inactive Xpath 16384 " X: 0 finally Xpath 32768 " X: 0 endtry endif try " not active due to :throw Xpath 65536 " X: 0 finally Xpath 131072 " X: 0 endtry endif Xcheck 4161 "------------------------------------------------------------------------------- " Test 23: :catch clauses for a :try after a :throw {{{1 " " If a :try conditional stays inactive due to a preceding :throw, " none of its :catch clauses should be executed. "------------------------------------------------------------------------------- XpathINIT if ExtraVim() try Xpath 1 " X: 1 throw "xyz" Xpath 2 " X: 0 if 1 " not active due to :throw try " not active since :if inactive Xpath 4 " X: 0 catch /xyz/ Xpath 8 " X: 0 endtry endif catch /xyz/ Xpath 16 " X: 16 endtry Xpath 32 " X: 32 throw "abc" Xpath 64 " X: 0 try " not active due to :throw Xpath 128 " X: 0 catch /abc/ Xpath 256 " X: 0 endtry endif Xcheck 49 "------------------------------------------------------------------------------- " Test 24: :endtry for a :try after a :throw {{{1 " " If a :try conditional stays inactive due to a preceding :throw, " its :endtry should not rethrow the exception to the next surrounding " active :try conditional. "------------------------------------------------------------------------------- XpathINIT if ExtraVim() try " try 1 try " try 2 Xpath 1 " X: 1 throw "xyz" " makes try 2 inactive Xpath 2 " X: 0 try " try 3 Xpath 4 " X: 0 endtry " no rethrow to try 1 catch /xyz/ " should catch although try 2 inactive Xpath 8 " X: 8 endtry catch /xyz/ " try 1 active, but exception already caught Xpath 16 " X: 0 endtry Xpath 32 " X: 32 endif Xcheck 41 "------------------------------------------------------------------------------- " Test 25: Executing :finally clauses on normal control flow {{{1 " " Control flow in a :try conditional should always fall through to its " :finally clause. A :finally clause of a :try conditional inside an " inactive conditional should never be executed. "------------------------------------------------------------------------------- XpathINIT function! F() let loops = 3 XloopINIT 1 256 while loops > 0 " 3: 2: 1: Xloop 1 " X: 1 + 1*256 + 1*256*256 if loops >= 2 try Xloop 2 " X: 2 + 2*256 if loops == 2 try Xloop 4 " X: 4*256 finally Xloop 8 " X: 8*256 endtry endif finally Xloop 16 " X: 16 + 16*256 if loops == 2 try Xloop 32 " X: 32*256 finally Xloop 64 " X: 64*256 endtry endif endtry endif Xloop 128 " X: 128 + 128*256 + 128*256*256 let loops = loops - 1 XloopNEXT endwhile Xpath 16777216 " X: 16777216 endfunction if 1 try Xpath 33554432 " X: 33554432 call F() Xpath 67108864 " X: 67108864 finally Xpath 134217728 " X: 134217728 endtry else try Xpath 268435456 " X: 0 finally Xpath 536870912 " X: 0 endtry endif delfunction F Xcheck 260177811 "------------------------------------------------------------------------------- " Test 26: Executing :finally clauses after :continue or :break {{{1 " " For a :continue or :break dynamically enclosed in a :try/:endtry " region inside the next surrounding :while/:endwhile, if the " :continue/:break is before the :finally, the :finally clause is " executed first. If the :continue/:break is after the :finally, the " :finally clause is broken (like an :if/:endif region). "------------------------------------------------------------------------------- XpathINIT try let loops = 3 XloopINIT! 1 32 while loops > 0 XloopNEXT try try if loops == 2 " 3: 2: 1: Xloop 1 " X: 1*32 let loops = loops - 1 continue elseif loops == 1 Xloop 2 " X: 2*32*32 break finish endif Xloop 4 " X: 4 endtry finally Xloop 8 " X: 8 + 8*32 + 8*32*32 endtry Xloop 16 " X: 16 let loops = loops - 1 endwhile Xpath 32768 " X: 32768 finally Xpath 65536 " X: 65536 let loops = 3 XloopINIT 131072 16 while loops > 0 try finally try if loops == 2 Xloop 1 " X: 131072*16 let loops = loops - 1 XloopNEXT continue elseif loops == 1 Xloop 2 " X: 131072*2*16*16 break finish endif endtry Xloop 4 " X: 131072*4 endtry Xloop 8 " X: 131072*8 let loops = loops - 1 XloopNEXT endwhile Xpath 536870912 " X: 536870912 endtry Xpath 1073741824 " X: 1073741824 unlet loops Xcheck 1681500476 "------------------------------------------------------------------------------- " Test 27: Executing :finally clauses after :return {{{1 " " For a :return command dynamically enclosed in a :try/:endtry region, " :finally clauses are executed and the called function is ended. "------------------------------------------------------------------------------- XpathINIT function! F() try Xpath 1 " X: 1 try Xpath 2 " X: 2 return Xpath 4 " X: 0 finally Xpath 8 " X: 8 endtry Xpath 16 " X: 0 finally Xpath 32 " X: 32 endtry Xpath 64 " X: 0 endfunction function! G() try Xpath 128 " X: 128 return Xpath 256 " X: 0 finally Xpath 512 " X: 512 call F() Xpath 1024 " X: 1024 endtry Xpath 2048 " X: 0 endfunction function! H() try Xpath 4096 " X: 4096 call G() Xpath 8192 " X: 8192 finally Xpath 16384 " X: 16384 return Xpath 32768 " X: 0 endtry Xpath 65536 " X: 0 endfunction try Xpath 131072 " X: 131072 call H() Xpath 262144 " X: 262144 finally Xpath 524288 " X: 524288 endtry Xpath 1048576 " X: 1048576 Xcheck 1996459 " Leave F, G, and H for execution as scripts in the next test. "------------------------------------------------------------------------------- " Test 28: Executing :finally clauses after :finish {{{1 " " For a :finish command dynamically enclosed in a :try/:endtry region, " :finally clauses are executed and the sourced file is finished. " " This test executes the bodies of the functions F, G, and H from the " previous test as script files (:return replaced by :finish). "------------------------------------------------------------------------------- XpathINIT let scriptF = MakeScript("F") " X: 1 + 2 + 8 + 32 let scriptG = MakeScript("G", scriptF) " X: 128 + 512 + 1024 let scriptH = MakeScript("H", scriptG) " X: 4096 + 8192 + 16384 try Xpath 131072 " X: 131072 exec "source" scriptH Xpath 262144 " X: 262144 finally Xpath 524288 " X: 524288 endtry Xpath 1048576 " X: 1048576 call delete(scriptF) call delete(scriptG) call delete(scriptH) unlet scriptF scriptG scriptH delfunction F delfunction G delfunction H Xcheck 1996459 "------------------------------------------------------------------------------- " Test 29: Executing :finally clauses on errors {{{1 " " After an error in a command dynamically enclosed in a :try/:endtry " region, :finally clauses are executed and the script processing is " terminated. "------------------------------------------------------------------------------- XpathINIT if ExtraVim() function! F() while 1 try Xpath 1 " X: 1 while 1 try Xpath 2 " X: 2 asdf " error Xpath 4 " X: 0 finally Xpath 8 " X: 8 endtry | Xpath 16 " X: 0 Xpath 32 " X: 0 break endwhile Xpath 64 " X: 0 finally Xpath 128 " X: 128 endtry | Xpath 256 " X: 0 Xpath 512 " X: 0 break endwhile Xpath 1024 " X: 0 endfunction while 1 try Xpath 2048 " X: 2048 while 1 call F() Xpath 4096 " X: 0 break endwhile | Xpath 8192 " X: 0 Xpath 16384 " X: 0 finally Xpath 32768 " X: 32768 endtry | Xpath 65536 " X: 0 endwhile | Xpath 131072 " X: 0 Xpath 262144 " X: 0 endif if ExtraVim() function! G() abort if 1 try Xpath 524288 " X: 524288 asdf " error Xpath 1048576 " X: 0 finally Xpath 2097152 " X: 2097152 endtry | Xpath 4194304 " X: 0 endif | Xpath 8388608 " X: 0 Xpath 16777216 " X: 0 endfunction if 1 try Xpath 33554432 " X: 33554432 call G() Xpath 67108864 " X: 0 finally Xpath 134217728 " X: 134217728 endtry | Xpath 268435456 " X: 0 endif | Xpath 536870912 " X: 0 Xpath 1073741824 " X: 0 endif Xcheck 170428555 "------------------------------------------------------------------------------- " Test 30: Executing :finally clauses on interrupt {{{1 " " After an interrupt in a command dynamically enclosed in " a :try/:endtry region, :finally clauses are executed and the " script processing is terminated. "------------------------------------------------------------------------------- XpathINIT if ExtraVim() XloopINIT 1 16 function! F() try Xloop 1 " X: 1 + 1*16 "INTERRUPT Xloop 2 " X: 0 finally Xloop 4 " X: 4 + 4*16 endtry Xloop 8 " X: 0 endfunction try Xpath 256 " X: 256 try Xpath 512 " X: 512 "INTERRUPT Xpath 1024 " X: 0 finally Xpath 2048 " X: 2048 try Xpath 4096 " X: 4096 try Xpath 8192 " X: 8192 finally Xpath 16384 " X: 16384 try Xpath 32768 " X: 32768 "INTERRUPT Xpath 65536 " X: 0 endtry Xpath 131072 " X: 0 endtry Xpath 262144 " X: 0 endtry Xpath 524288 " X: 0 endtry Xpath 1048576 " X: 0 finally Xpath 2097152 " X: 2097152 try Xpath 4194304 " X: 4194304 call F() Xpath 8388608 " X: 0 finally Xpath 16777216 " X: 16777216 try Xpath 33554432 " X: 33554432 XloopNEXT ExecAsScript F Xpath 67108864 " X: 0 finally Xpath 134217728 " X: 134217728 endtry Xpath 268435456 " X: 0 endtry Xpath 536870912 " X: 0 endtry Xpath 1073741824 " X: 0 endif Xcheck 190905173 "------------------------------------------------------------------------------- " Test 31: Executing :finally clauses after :throw {{{1 " " After a :throw dynamically enclosed in a :try/:endtry region, " :finally clauses are executed and the script processing is " terminated. "------------------------------------------------------------------------------- XpathINIT if ExtraVim() XloopINIT 1 16 function! F() try Xloop 1 " X: 1 + 1*16 throw "exception" Xloop 2 " X: 0 finally Xloop 4 " X: 4 + 4*16 endtry Xloop 8 " X: 0 endfunction try Xpath 256 " X: 256 try Xpath 512 " X: 512 throw "exception" Xpath 1024 " X: 0 finally Xpath 2048 " X: 2048 try Xpath 4096 " X: 4096 try Xpath 8192 " X: 8192 finally Xpath 16384 " X: 16384 try Xpath 32768 " X: 32768 throw "exception" Xpath 65536 " X: 0 endtry Xpath 131072 " X: 0 endtry Xpath 262144 " X: 0 endtry Xpath 524288 " X: 0 endtry Xpath 1048576 " X: 0 finally Xpath 2097152 " X: 2097152 try Xpath 4194304 " X: 4194304 call F() Xpath 8388608 " X: 0 finally Xpath 16777216 " X: 16777216 try Xpath 33554432 " X: 33554432 XloopNEXT ExecAsScript F Xpath 67108864 " X: 0 finally Xpath 134217728 " X: 134217728 endtry Xpath 268435456 " X: 0 endtry Xpath 536870912 " X: 0 endtry Xpath 1073741824 " X: 0 endif Xcheck 190905173 "------------------------------------------------------------------------------- " Test 32: Remembering the :return value on :finally {{{1 " " If a :finally clause is executed due to a :return specifying " a value, this is the value visible to the caller if not overwritten " by a new :return in the :finally clause. A :return without a value " in the :finally clause overwrites with value 0. "------------------------------------------------------------------------------- XpathINIT function! F() try Xpath 1 " X: 1 try Xpath 2 " X: 2 return "ABCD" Xpath 4 " X: 0 finally Xpath 8 " X: 8 endtry Xpath 16 " X: 0 finally Xpath 32 " X: 32 endtry Xpath 64 " X: 0 endfunction function! G() try Xpath 128 " X: 128 return 8 Xpath 256 " X: 0 finally Xpath 512 " X: 512 return 16 + strlen(F()) Xpath 1024 " X: 0 endtry Xpath 2048 " X: 0 endfunction function! H() try Xpath 4096 " X: 4096 return 32 Xpath 8192 " X: 0 finally Xpath 16384 " X: 16384 return Xpath 32768 " X: 0 endtry Xpath 65536 " X: 0 endfunction function! I() try Xpath 131072 " X: 131072 finally Xpath 262144 " X: 262144 return G() + H() + 64 Xpath 524288 " X: 0 endtry Xpath 1048576 " X: 0 endfunction let retcode = I() Xpath 2097152 " X: 2097152 if retcode < 0 Xpath 4194304 " X: 0 endif if retcode % 4 Xpath 8388608 " X: 0 endif if (retcode/4) % 2 Xpath 16777216 " X: 16777216 endif if (retcode/8) % 2 Xpath 33554432 " X: 0 endif if (retcode/16) % 2 Xpath 67108864 " X: 67108864 endif if (retcode/32) % 2 Xpath 134217728 " X: 0 endif if (retcode/64) % 2 Xpath 268435456 " X: 268435456 endif if retcode/128 Xpath 536870912 " X: 0 endif unlet retcode delfunction F delfunction G delfunction H delfunction I Xcheck 354833067 "------------------------------------------------------------------------------- " Test 33: :return under :execute or user command and :finally {{{1 " " A :return command may be executed under an ":execute" or from " a user command. Executing of :finally clauses and passing through " the return code works also then. "------------------------------------------------------------------------------- XpathINIT command! -nargs=? RETURN \ try | return <args> | finally | return <args> * 2 | endtry function! F() try RETURN 8 Xpath 1 " X: 0 finally Xpath 2 " X: 2 endtry Xpath 4 " X: 0 endfunction function! G() try RETURN 32 Xpath 8 " X: 0 finally Xpath 16 " X: 16 RETURN 128 Xpath 32 " X: 0 endtry Xpath 64 " X: 0 endfunction function! H() try execute "try | return 512 | finally | return 1024 | endtry" Xpath 128 " X: 0 finally Xpath 256 " X: 256 endtry Xpath 512 " X: 0 endfunction function! I() try execute "try | return 2048 | finally | return 4096 | endtry" Xpath 1024 " X: 0 finally Xpath 2048 " X: 2048 execute "try | return 8192 | finally | return 16384 | endtry" Xpath 4096 " X: 0 endtry Xpath 8192 " X: 0 endfunction function! J() try RETURN 32768 Xpath 16384 " X: 0 finally Xpath 32768 " X: 32768 return Xpath 65536 " X: 0 endtry Xpath 131072 " X: 0 endfunction function! K() try execute "try | return 131072 | finally | return 262144 | endtry" Xpath 262144 " X: 0 finally Xpath 524288 " X: 524288 execute "try | return 524288 | finally | return | endtry" Xpath 1048576 " X: 0 endtry Xpath 2097152 " X: 0 endfunction function! L() try return Xpath 4194304 " X: 0 finally Xpath 8388608 " X: 8388608 RETURN 1048576 Xpath 16777216 " X: 0 endtry Xpath 33554432 " X: 0 endfunction function! M() try return Xpath 67108864 " X: 0 finally Xpath 134217728 " X: 134217728 execute "try | return 4194304 | finally | return 8388608 | endtry" Xpath 268435456 " X: 0 endtry Xpath 536870912 " X: 0 endfunction function! N() RETURN 16777216 endfunction function! O() execute "try | return 67108864 | finally | return 134217728 | endtry" endfunction let sum = F() + G() + H() + I() + J() + K() + L() + M() let expected = 16 + 256 + 1024 + 16384 + 0 + 0 + 2097152 + 8388608 let sum = sum + N() + O() let expected = expected + 33554432 + 134217728 if sum == expected Xout "sum = " . sum . " (ok)" else Xout "sum = " . sum . ", expected: " . expected endif Xpath 1073741824 " X: 1073741824 if sum != expected " The Xpath command does not accept 2^31 (negative); add explicitly: let Xpath = Xpath + 2147483648 " X: 0 endif unlet sum expected delfunction F delfunction G delfunction H delfunction I delfunction J delfunction K delfunction L delfunction M delfunction N delfunction O Xcheck 1216907538 "------------------------------------------------------------------------------- " Test 34: :finally reason discarded by :continue {{{1 " " When a :finally clause is executed due to a :continue, :break, " :return, :finish, error, interrupt or :throw, the jump reason is " discarded by a :continue in the finally clause. "------------------------------------------------------------------------------- XpathINIT if ExtraVim() XloopINIT! 1 8 function! C(jump) XloopNEXT let loop = 0 while loop < 2 let loop = loop + 1 if loop == 1 try if a:jump == "continue" continue elseif a:jump == "break" break elseif a:jump == "return" || a:jump == "finish" return elseif a:jump == "error" asdf elseif a:jump == "interrupt" "INTERRUPT let dummy = 0 elseif a:jump == "throw" throw "abc" endif finally continue " discards jump that caused the :finally Xloop 1 " X: 0 endtry Xloop 2 " X: 0 elseif loop == 2 Xloop 4 " X: 4*(1+8+64+512+4096+32768+262144) endif endwhile endfunction call C("continue") Xpath 2097152 " X: 2097152 call C("break") Xpath 4194304 " X: 4194304 call C("return") Xpath 8388608 " X: 8388608 let g:jump = "finish" ExecAsScript C unlet g:jump Xpath 16777216 " X: 16777216 try call C("error") Xpath 33554432 " X: 33554432 finally Xpath 67108864 " X: 67108864 try call C("interrupt") Xpath 134217728 " X: 134217728 finally Xpath 268435456 " X: 268435456 call C("throw") Xpath 536870912 " X: 536870912 endtry endtry Xpath 1073741824 " X: 1073741824 delfunction C endif Xcheck 2146584868 "------------------------------------------------------------------------------- " Test 35: :finally reason discarded by :break {{{1 " " When a :finally clause is executed due to a :continue, :break, " :return, :finish, error, interrupt or :throw, the jump reason is " discarded by a :break in the finally clause. "------------------------------------------------------------------------------- XpathINIT if ExtraVim() XloopINIT! 1 8 function! B(jump) XloopNEXT let loop = 0 while loop < 2 let loop = loop + 1 if loop == 1 try if a:jump == "continue" continue elseif a:jump == "break" break elseif a:jump == "return" || a:jump == "finish" return elseif a:jump == "error" asdf elseif a:jump == "interrupt" "INTERRUPT let dummy = 0 elseif a:jump == "throw" throw "abc" endif finally break " discards jump that caused the :finally Xloop 1 " X: 0 endtry elseif loop == 2 Xloop 2 " X: 0 endif endwhile Xloop 4 " X: 4*(1+8+64+512+4096+32768+262144) endfunction call B("continue") Xpath 2097152 " X: 2097152 call B("break") Xpath 4194304 " X: 4194304 call B("return") Xpath 8388608 " X: 8388608 let g:jump = "finish" ExecAsScript B unlet g:jump Xpath 16777216 " X: 16777216 try call B("error") Xpath 33554432 " X: 33554432 finally Xpath 67108864 " X: 67108864 try call B("interrupt") Xpath 134217728 " X: 134217728 finally Xpath 268435456 " X: 268435456 call B("throw") Xpath 536870912 " X: 536870912 endtry endtry Xpath 1073741824 " X: 1073741824 delfunction B endif Xcheck 2146584868 "------------------------------------------------------------------------------- " Test 36: :finally reason discarded by :return {{{1 " " When a :finally clause is executed due to a :continue, :break, " :return, :finish, error, interrupt or :throw, the jump reason is " discarded by a :return in the finally clause. "------------------------------------------------------------------------------- XpathINIT if ExtraVim() XloopINIT! 1 8 function! R(jump, retval) abort XloopNEXT let loop = 0 while loop < 2 let loop = loop + 1 if loop == 1 try if a:jump == "continue" continue elseif a:jump == "break" break elseif a:jump == "return" return elseif a:jump == "error" asdf elseif a:jump == "interrupt" "INTERRUPT let dummy = 0 elseif a:jump == "throw" throw "abc" endif finally return a:retval " discards jump that caused the :finally Xloop 1 " X: 0 endtry elseif loop == 2 Xloop 2 " X: 0 endif endwhile Xloop 4 " X: 0 endfunction let sum = -R("continue", -8) Xpath 2097152 " X: 2097152 let sum = sum - R("break", -16) Xpath 4194304 " X: 4194304 let sum = sum - R("return", -32) Xpath 8388608 " X: 8388608 try let sum = sum - R("error", -64) Xpath 16777216 " X: 16777216 finally Xpath 33554432 " X: 33554432 try let sum = sum - R("interrupt", -128) Xpath 67108864 " X: 67108864 finally Xpath 134217728 " X: 134217728 let sum = sum - R("throw", -256) Xpath 268435456 " X: 268435456 endtry endtry Xpath 536870912 " X: 536870912 let expected = 8 + 16 + 32 + 64 + 128 + 256 if sum != expected Xpath 1073741824 " X: 0 Xout "sum =" . sum . ", expected: " . expected endif unlet sum expected delfunction R endif Xcheck 1071644672 "------------------------------------------------------------------------------- " Test 37: :finally reason discarded by :finish {{{1 " " When a :finally clause is executed due to a :continue, :break, " :return, :finish, error, interrupt or :throw, the jump reason is " discarded by a :finish in the finally clause. "------------------------------------------------------------------------------- XpathINIT if ExtraVim() XloopINIT! 1 8 function! F(jump) " not executed as function, transformed to a script XloopNEXT let loop = 0 while loop < 2 let loop = loop + 1 if loop == 1 try if a:jump == "continue" continue elseif a:jump == "break" break elseif a:jump == "finish" finish elseif a:jump == "error" asdf elseif a:jump == "interrupt" "INTERRUPT let dummy = 0 elseif a:jump == "throw" throw "abc" endif finally finish " discards jump that caused the :finally Xloop 1 " X: 0 endtry elseif loop == 2 Xloop 2 " X: 0 endif endwhile Xloop 4 " X: 0 endfunction let scriptF = MakeScript("F") delfunction F let g:jump = "continue" exec "source" scriptF Xpath 2097152 " X: 2097152 let g:jump = "break" exec "source" scriptF Xpath 4194304 " X: 4194304 let g:jump = "finish" exec "source" scriptF Xpath 8388608 " X: 8388608 try let g:jump = "error" exec "source" scriptF Xpath 16777216 " X: 16777216 finally Xpath 33554432 " X: 33554432 try let g:jump = "interrupt" exec "source" scriptF Xpath 67108864 " X: 67108864 finally Xpath 134217728 " X: 134217728 try let g:jump = "throw" exec "source" scriptF Xpath 268435456 " X: 268435456 finally Xpath 536870912 " X: 536870912 endtry endtry endtry unlet g:jump call delete(scriptF) unlet scriptF endif Xcheck 1071644672 "------------------------------------------------------------------------------- " Test 38: :finally reason discarded by an error {{{1 " " When a :finally clause is executed due to a :continue, :break, " :return, :finish, error, interrupt or :throw, the jump reason is " discarded by an error in the finally clause. "------------------------------------------------------------------------------- XpathINIT if ExtraVim() XloopINIT! 1 4 function! E(jump) XloopNEXT let loop = 0 while loop < 2 let loop = loop + 1 if loop == 1 try if a:jump == "continue" continue elseif a:jump == "break" break elseif a:jump == "return" || a:jump == "finish" return elseif a:jump == "error" asdf elseif a:jump == "interrupt" "INTERRUPT let dummy = 0 elseif a:jump == "throw" throw "abc" endif finally asdf " error; discards jump that caused the :finally endtry elseif loop == 2 Xloop 1 " X: 0 endif endwhile Xloop 2 " X: 0 endfunction try Xpath 16384 " X: 16384 call E("continue") Xpath 32768 " X: 0 finally try Xpath 65536 " X: 65536 call E("break") Xpath 131072 " X: 0 finally try Xpath 262144 " X: 262144 call E("return") Xpath 524288 " X: 0 finally try Xpath 1048576 " X: 1048576 let g:jump = "finish" ExecAsScript E Xpath 2097152 " X: 0 finally unlet g:jump try Xpath 4194304 " X: 4194304 call E("error") Xpath 8388608 " X: 0 finally try Xpath 16777216 " X: 16777216 call E("interrupt") Xpath 33554432 " X: 0 finally try Xpath 67108864 " X: 67108864 call E("throw") Xpath 134217728 " X: 0 finally Xpath 268435456 " X: 268435456 delfunction E endtry endtry endtry endtry endtry endtry endtry Xpath 536870912 " X: 0 endif Xcheck 357908480 "------------------------------------------------------------------------------- " Test 39: :finally reason discarded by an interrupt {{{1 " " When a :finally clause is executed due to a :continue, :break, " :return, :finish, error, interrupt or :throw, the jump reason is " discarded by an interrupt in the finally clause. "------------------------------------------------------------------------------- XpathINIT if ExtraVim() XloopINIT! 1 4 function! I(jump) XloopNEXT let loop = 0 while loop < 2 let loop = loop + 1 if loop == 1 try if a:jump == "continue" continue elseif a:jump == "break" break elseif a:jump == "return" || a:jump == "finish" return elseif a:jump == "error" asdf elseif a:jump == "interrupt" "INTERRUPT let dummy = 0 elseif a:jump == "throw" throw "abc" endif finally "INTERRUPT - discards jump that caused the :finally let dummy = 0 endtry elseif loop == 2 Xloop 1 " X: 0 endif endwhile Xloop 2 " X: 0 endfunction try Xpath 16384 " X: 16384 call I("continue") Xpath 32768 " X: 0 finally try Xpath 65536 " X: 65536 call I("break") Xpath 131072 " X: 0 finally try Xpath 262144 " X: 262144 call I("return") Xpath 524288 " X: 0 finally try Xpath 1048576 " X: 1048576 let g:jump = "finish" ExecAsScript I Xpath 2097152 " X: 0 finally unlet g:jump try Xpath 4194304 " X: 4194304 call I("error") Xpath 8388608 " X: 0 finally try Xpath 16777216 " X: 16777216 call I("interrupt") Xpath 33554432 " X: 0 finally try Xpath 67108864 " X: 67108864 call I("throw") Xpath 134217728 " X: 0 finally Xpath 268435456 " X: 268435456 delfunction I endtry endtry endtry endtry endtry endtry endtry Xpath 536870912 " X: 0 endif Xcheck 357908480 "------------------------------------------------------------------------------- " Test 40: :finally reason discarded by :throw {{{1 " " When a :finally clause is executed due to a :continue, :break, " :return, :finish, error, interrupt or :throw, the jump reason is " discarded by a :throw in the finally clause. "------------------------------------------------------------------------------- XpathINIT if ExtraVim() XloopINIT! 1 4 function! T(jump) XloopNEXT let loop = 0 while loop < 2 let loop = loop + 1 if loop == 1 try if a:jump == "continue" continue elseif a:jump == "break" break elseif a:jump == "return" || a:jump == "finish" return elseif a:jump == "error" asdf elseif a:jump == "interrupt" "INTERRUPT let dummy = 0 elseif a:jump == "throw" throw "abc" endif finally throw "xyz" " discards jump that caused the :finally endtry elseif loop == 2 Xloop 1 " X: 0 endif endwhile Xloop 2 " X: 0 endfunction try Xpath 16384 " X: 16384 call T("continue") Xpath 32768 " X: 0 finally try Xpath 65536 " X: 65536 call T("break") Xpath 131072 " X: 0 finally try Xpath 262144 " X: 262144 call T("return") Xpath 524288 " X: 0 finally try Xpath 1048576 " X: 1048576 let g:jump = "finish" ExecAsScript T Xpath 2097152 " X: 0 finally unlet g:jump try Xpath 4194304 " X: 4194304 call T("error") Xpath 8388608 " X: 0 finally try Xpath 16777216 " X: 16777216 call T("interrupt") Xpath 33554432 " X: 0 finally try Xpath 67108864 " X: 67108864 call T("throw") Xpath 134217728 " X: 0 finally Xpath 268435456 " X: 268435456 delfunction T endtry endtry endtry endtry endtry endtry endtry Xpath 536870912 " X: 0 endif Xcheck 357908480 "------------------------------------------------------------------------------- " Test 41: Skipped :throw finding next command {{{1 " " A :throw in an inactive conditional must not hide a following " command. "------------------------------------------------------------------------------- XpathINIT function! F() Xpath 1 " X: 1 if 0 | throw "never" | endif | Xpath 2 " X: 2 Xpath 4 " X: 4 endfunction function! G() Xpath 8 " X: 8 while 0 | throw "never" | endwhile | Xpath 16 " X: 16 Xpath 32 " X: 32 endfunction function H() Xpath 64 " X: 64 if 0 | try | throw "never" | endtry | endif | Xpath 128 " X: 128 Xpath 256 " X: 256 endfunction Xpath 512 " X: 512 try Xpath 1024 " X: 1024 call F() Xpath 2048 " X: 2048 catch /.*/ Xpath 4096 " X: 0 Xout v:exception "in" v:throwpoint endtry Xpath 8192 " X: 8192 try Xpath 16384 " X: 16384 call G() Xpath 32768 " X: 32768 catch /.*/ Xpath 65536 " X: 0 Xout v:exception "in" v:throwpoint endtry Xpath 131072 " X: 131072 try Xpath 262144 " X: 262144 call H() Xpath 524288 " X: 524288 catch /.*/ Xpath 1048576 " X: 0 Xout v:exception "in" v:throwpoint endtry Xpath 2097152 " X: 2097152 delfunction F delfunction G delfunction H Xcheck 3076095 "------------------------------------------------------------------------------- " Test 42: Catching number and string exceptions {{{1 " " When a number is thrown, it is converted to a string exception. " Numbers and strings may be caught by specifying a regular exception " as argument to the :catch command. "------------------------------------------------------------------------------- XpathINIT try try Xpath 1 " X: 1 throw 4711 Xpath 2 " X: 0 catch /4711/ Xpath 4 " X: 4 endtry try Xpath 8 " X: 8 throw 4711 Xpath 16 " X: 0 catch /^4711$/ Xpath 32 " X: 32 endtry try Xpath 64 " X: 64 throw 4711 Xpath 128 " X: 0 catch /\d/ Xpath 256 " X: 256 endtry try Xpath 512 " X: 512 throw 4711 Xpath 1024 " X: 0 catch /^\d\+$/ Xpath 2048 " X: 2048 endtry try Xpath 4096 " X: 4096 throw "arrgh" Xpath 8192 " X: 0 catch /arrgh/ Xpath 16384 " X: 16384 endtry try Xpath 32768 " X: 32768 throw "arrgh" Xpath 65536 " X: 0 catch /^arrgh$/ Xpath 131072 " X: 131072 endtry try Xpath 262144 " X: 262144 throw "arrgh" Xpath 524288 " X: 0 catch /\l/ Xpath 1048576 " X: 1048576 endtry try Xpath 2097152 " X: 2097152 throw "arrgh" Xpath 4194304 " X: 0 catch /^\l\+$/ Xpath 8388608 " X: 8388608 endtry try try Xpath 16777216 " X: 16777216 throw "ARRGH" Xpath 33554432 " X: 0 catch /^arrgh$/ Xpath 67108864 " X: 0 endtry catch /^\carrgh$/ Xpath 134217728 " X: 134217728 endtry try Xpath 268435456 " X: 268435456 throw "" Xpath 536870912 " X: 0 catch /^$/ Xpath 1073741824 " X: 1073741824 endtry catch /.*/ " The Xpath command does not accept 2^31 (negative); add explicitly: let Xpath = Xpath + 2147483648 " X: 0 Xout v:exception "in" v:throwpoint endtry Xcheck 1505155949 "------------------------------------------------------------------------------- " Test 43: Selecting the correct :catch clause {{{1 " " When an exception is thrown and there are multiple :catch clauses, " the first matching one is taken. "------------------------------------------------------------------------------- XpathINIT XloopINIT 1 1024 let loops = 3 while loops > 0 try if loops == 3 Xloop 1 " X: 1 throw "a" Xloop 2 " X: 0 elseif loops == 2 Xloop 4 " X: 4*1024 throw "ab" Xloop 8 " X: 0 elseif loops == 1 Xloop 16 " X: 16*1024*1024 throw "abc" Xloop 32 " X: 0 endif catch /abc/ Xloop 64 " X: 64*1024*1024 catch /ab/ Xloop 128 " X: 128*1024 catch /.*/ Xloop 256 " X: 256 catch /a/ Xloop 512 " X: 0 endtry let loops = loops - 1 XloopNEXT endwhile Xpath 1073741824 " X: 1073741824 unlet loops Xcheck 1157763329 "------------------------------------------------------------------------------- " Test 44: Missing or empty :catch patterns {{{1 " " A missing or empty :catch pattern means the same as /.*/, that is, " catches everything. To catch only empty exceptions, /^$/ must be " used. A :catch with missing, empty, or /.*/ argument also works " when followed by another command separated by a bar on the same " line. :catch patterns cannot be specified between ||. But other " pattern separators can be used instead of //. "------------------------------------------------------------------------------- XpathINIT try try Xpath 1 " X: 1 throw "" catch /^$/ Xpath 2 " X: 2 endtry try Xpath 4 " X: 4 throw "" catch /.*/ Xpath 8 " X: 8 endtry try Xpath 16 " X: 16 throw "" catch // Xpath 32 " X: 32 endtry try Xpath 64 " X: 64 throw "" catch Xpath 128 " X: 128 endtry try Xpath 256 " X: 256 throw "oops" catch /^$/ Xpath 512 " X: 0 catch /.*/ Xpath 1024 " X: 1024 endtry try Xpath 2048 " X: 2048 throw "arrgh" catch /^$/ Xpath 4096 " X: 0 catch // Xpath 8192 " X: 8192 endtry try Xpath 16384 " X: 16384 throw "brrr" catch /^$/ Xpath 32768 " X: 0 catch Xpath 65536 " X: 65536 endtry try | Xpath 131072 | throw "x" | catch /.*/ | Xpath 262144 | endtry " X: 131072 + 262144 try | Xpath 524288 | throw "y" | catch // | Xpath 1048576 | endtry " X: 524288 + 1048576 while 1 try let caught = 0 let v:errmsg = "" " Extra try level: if ":catch" without arguments below raises " a syntax error because it misinterprets the "Xpath" as a pattern, " let it be caught by the ":catch /.*/" below. try try | Xpath 2097152 | throw "z" | catch | Xpath 4194304 | : endtry " X: 2097152 + 4194304 endtry catch /.*/ let caught = 1 Xout v:exception "in" v:throwpoint finally if $VIMNOERRTHROW && v:errmsg != "" Xout v:errmsg endif if caught || $VIMNOERRTHROW && v:errmsg != "" Xpath 8388608 " X: 0 endif break " discard error for $VIMNOERRTHROW endtry endwhile let cologne = 4711 try try Xpath 16777216 " X: 16777216 throw "throw cologne" " Next lines catches all and throws 4711: catch |throw cologne| Xpath 33554432 " X: 0 endtry catch /4711/ Xpath 67108864 " X: 67108864 endtry try Xpath 134217728 " X: 134217728 throw "plus" catch +plus+ Xpath 268435456 " X: 268435456 endtry Xpath 536870912 " X: 536870912 catch /.*/ Xpath 1073741824 " X: 0 Xout v:exception "in" v:throwpoint endtry unlet! caught cologne Xcheck 1031761407 "------------------------------------------------------------------------------- " Test 45: Catching exceptions from nested :try blocks {{{1 " " When :try blocks are nested, an exception is caught by the innermost " try conditional that has a matching :catch clause. "------------------------------------------------------------------------------- XpathINIT XloopINIT 1 1024 let loops = 3 while loops > 0 try try try try if loops == 3 Xloop 1 " X: 1 throw "a" Xloop 2 " X: 0 elseif loops == 2 Xloop 4 " X: 4*1024 throw "ab" Xloop 8 " X: 0 elseif loops == 1 Xloop 16 " X: 16*1024*1024 throw "abc" Xloop 32 " X: 0 endif catch /abc/ Xloop 64 " X: 64*1024*1024 endtry catch /ab/ Xloop 128 " X: 128*1024 endtry catch /.*/ Xloop 256 " X: 256 endtry catch /a/ Xloop 512 " X: 0 endtry let loops = loops - 1 XloopNEXT endwhile Xpath 1073741824 " X: 1073741824 unlet loops Xcheck 1157763329 "------------------------------------------------------------------------------- " Test 46: Executing :finally after a :throw in nested :try {{{1 " " When an exception is thrown from within nested :try blocks, the " :finally clauses of the non-catching try conditionals should be " executed before the matching :catch of the next surrounding :try " gets the control. If this also has a :finally clause, it is " executed afterwards. "------------------------------------------------------------------------------- XpathINIT let sum = 0 try Xpath 1 " X: 1 try Xpath 2 " X: 2 try Xpath 4 " X: 4 try Xpath 8 " X: 8 throw "ABC" Xpath 16 " X: 0 catch /xyz/ Xpath 32 " X: 0 finally Xpath 64 " X: 64 if sum != 0 Xpath 128 " X: 0 endif let sum = sum + 1 endtry Xpath 256 " X: 0 catch /123/ Xpath 512 " X: 0 catch /321/ Xpath 1024 " X: 0 finally Xpath 2048 " X: 2048 if sum != 1 Xpath 4096 " X: 0 endif let sum = sum + 2 endtry Xpath 8192 " X: 0 finally Xpath 16384 " X: 16384 if sum != 3 Xpath 32768 " X: 0 endif let sum = sum + 4 endtry Xpath 65536 " X: 0 catch /ABC/ Xpath 131072 " X: 131072 if sum != 7 Xpath 262144 " X: 0 endif let sum = sum + 8 finally Xpath 524288 " X: 524288 if sum != 15 Xpath 1048576 " X: 0 endif let sum = sum + 16 endtry Xpath 65536 " X: 65536 if sum != 31 Xpath 131072 " X: 0 endif unlet sum Xcheck 739407 "------------------------------------------------------------------------------- " Test 47: Throwing exceptions from a :catch clause {{{1 " " When an exception is thrown from a :catch clause, it should not be " caught by a :catch of the same :try conditional. After executing " the :finally clause (if present), surrounding try conditionals " should be checked for a matching :catch. "------------------------------------------------------------------------------- XpathINIT Xpath 1 " X: 1 try Xpath 2 " X: 2 try Xpath 4 " X: 4 try Xpath 8 " X: 8 throw "x1" Xpath 16 " X: 0 catch /x1/ Xpath 32 " X: 32 try Xpath 64 " X: 64 throw "x2" Xpath 128 " X: 0 catch /x1/ Xpath 256 " X: 0 catch /x2/ Xpath 512 " X: 512 try Xpath 1024 " X: 1024 throw "x3" Xpath 2048 " X: 0 catch /x1/ Xpath 4096 " X: 0 catch /x2/ Xpath 8192 " X: 0 finally Xpath 16384 " X: 16384 endtry Xpath 32768 " X: 0 catch /x3/ Xpath 65536 " X: 0 endtry Xpath 131072 " X: 0 catch /x1/ Xpath 262144 " X: 0 catch /x2/ Xpath 524288 " X: 0 catch /x3/ Xpath 1048576 " X: 0 finally Xpath 2097152 " X: 2097152 endtry Xpath 4194304 " X: 0 catch /x1/ Xpath 8388608 " X: 0 catch /x2/ Xpath 16777216 " X: 0 catch /x3/ Xpath 33554432 " X: 33554432 endtry Xpath 67108864 " X: 67108864 catch /.*/ Xpath 134217728 " X: 0 Xout v:exception "in" v:throwpoint endtry Xpath 268435456 " X: 268435456 Xcheck 371213935 "------------------------------------------------------------------------------- " Test 48: Throwing exceptions from a :finally clause {{{1 " " When an exception is thrown from a :finally clause, it should not be " caught by a :catch of the same :try conditional. Surrounding try " conditionals should be checked for a matching :catch. A previously " thrown exception is discarded. "------------------------------------------------------------------------------- XpathINIT try try try Xpath 1 " X: 1 catch /x1/ Xpath 2 " X: 0 finally Xpath 4 " X: 4 throw "x1" Xpath 8 " X: 0 endtry Xpath 16 " X: 0 catch /x1/ Xpath 32 " X: 32 endtry Xpath 64 " X: 64 try try Xpath 128 " X: 128 throw "x2" Xpath 256 " X: 0 catch /x2/ Xpath 512 " X: 512 catch /x3/ Xpath 1024 " X: 0 finally Xpath 2048 " X: 2048 throw "x3" Xpath 4096 " X: 0 endtry Xpath 8192 " X: 0 catch /x2/ Xpath 16384 " X: 0 catch /x3/ Xpath 32768 " X: 32768 endtry Xpath 65536 " X: 65536 try try try Xpath 131072 " X: 131072 throw "x4" Xpath 262144 " X: 0 catch /x5/ Xpath 524288 " X: 0 finally Xpath 1048576 " X: 1048576 throw "x5" " discards "x4" Xpath 2097152 " X: 0 endtry Xpath 4194304 " X: 0 catch /x4/ Xpath 8388608 " X: 0 finally Xpath 16777216 " X: 16777216 endtry Xpath 33554432 " X: 0 catch /x5/ Xpath 67108864 " X: 67108864 endtry Xpath 134217728 " X: 134217728 catch /.*/ Xpath 268435456 " X: 0 Xout v:exception "in" v:throwpoint endtry Xpath 536870912 " X: 536870912 Xcheck 756255461 "------------------------------------------------------------------------------- " Test 49: Throwing exceptions across functions {{{1 " " When an exception is thrown but not caught inside a function, the " caller is checked for a matching :catch clause. "------------------------------------------------------------------------------- XpathINIT function! C() try Xpath 1 " X: 1 throw "arrgh" Xpath 2 " X: 0 catch /arrgh/ Xpath 4 " X: 4 endtry Xpath 8 " X: 8 endfunction XloopINIT! 16 16 function! T1() XloopNEXT try Xloop 1 " X: 16 + 16*16 throw "arrgh" Xloop 2 " X: 0 finally Xloop 4 " X: 64 + 64*16 endtry Xloop 8 " X: 0 endfunction function! T2() try Xpath 4096 " X: 4096 call T1() Xpath 8192 " X: 0 finally Xpath 16384 " X: 16384 endtry Xpath 32768 " X: 0 endfunction try Xpath 65536 " X: 65536 call C() " throw and catch Xpath 131072 " X: 131072 catch /.*/ Xpath 262144 " X: 0 Xout v:exception "in" v:throwpoint endtry try Xpath 524288 " X: 524288 call T1() " throw, one level Xpath 1048576 " X: 0 catch /arrgh/ Xpath 2097152 " X: 2097152 catch /.*/ Xpath 4194304 " X: 0 Xout v:exception "in" v:throwpoint endtry try Xpath 8388608 " X: 8388608 call T2() " throw, two levels Xpath 16777216 " X: 0 catch /arrgh/ Xpath 33554432 " X: 33554432 catch /.*/ Xpath 67108864 " X: 0 Xout v:exception "in" v:throwpoint endtry Xpath 134217728 " X: 134217728 Xcheck 179000669 " Leave C, T1, and T2 for execution as scripts in the next test. "------------------------------------------------------------------------------- " Test 50: Throwing exceptions across script files {{{1 " " When an exception is thrown but not caught inside a script file, " the sourcing script or function is checked for a matching :catch " clause. " " This test executes the bodies of the functions C, T1, and T2 from " the previous test as script files (:return replaced by :finish). "------------------------------------------------------------------------------- XpathINIT let scriptC = MakeScript("C") " X: 1 + 4 + 8 delfunction C XloopINIT! 16 16 let scriptT1 = MakeScript("T1") " X: 16 + 64 + 16*16 + 64*16 delfunction T1 let scriptT2 = MakeScript("T2", scriptT1) " X: 4096 + 16384 delfunction T2 function! F() try Xpath 65536 " X: 65536 exec "source" g:scriptC Xpath 131072 " X: 131072 catch /.*/ Xpath 262144 " X: 0 Xout v:exception "in" v:throwpoint endtry try Xpath 524288 " X: 524288 exec "source" g:scriptT1 Xpath 1048576 " X: 0 catch /arrgh/ Xpath 2097152 " X: 2097152 catch /.*/ Xpath 4194304 " X: 0 Xout v:exception "in" v:throwpoint endtry endfunction try Xpath 8388608 " X: 8388608 call F() Xpath 16777216 " X: 16777216 exec "source" scriptT2 Xpath 33554432 " X: 0 catch /arrgh/ Xpath 67108864 " X: 67108864 catch /.*/ Xpath 134217728 " X: 0 Xout v:exception "in" v:throwpoint endtry Xpath 268435456 " X: 268435456 call delete(scriptC) call delete(scriptT1) call delete(scriptT2) unlet scriptC scriptT1 scriptT2 delfunction F Xcheck 363550045 "------------------------------------------------------------------------------- " Test 51: Throwing exceptions across :execute and user commands {{{1 " " A :throw command may be executed under an ":execute" or from " a user command. "------------------------------------------------------------------------------- XpathINIT command! -nargs=? THROW1 throw <args> | throw 1 command! -nargs=? THROW2 try | throw <args> | endtry | throw 2 command! -nargs=? THROW3 try | throw 3 | catch /3/ | throw <args> | endtry command! -nargs=? THROW4 try | throw 4 | finally | throw <args> | endtry try try try Xpath 1 " X: 1 THROW1 "A" catch /A/ Xpath 2 " X: 2 endtry catch /1/ Xpath 4 " X: 0 endtry try try Xpath 8 " X: 8 THROW2 "B" catch /B/ Xpath 16 " X: 16 endtry catch /2/ Xpath 32 " X: 0 endtry try try Xpath 64 " X: 64 THROW3 "C" catch /C/ Xpath 128 " X: 128 endtry catch /3/ Xpath 256 " X: 0 endtry try try Xpath 512 " X: 512 THROW4 "D" catch /D/ Xpath 1024 " X: 1024 endtry catch /4/ Xpath 2048 " X: 0 endtry try try Xpath 4096 " X: 4096 execute 'throw "E" | throw 5' catch /E/ Xpath 8192 " X: 8192 endtry catch /5/ Xpath 16384 " X: 0 endtry try try Xpath 32768 " X: 32768 execute 'try | throw "F" | endtry | throw 6' catch /F/ Xpath 65536 " X: 65536 endtry catch /6/ Xpath 131072 " X: 0 endtry try try Xpath 262144 " X: 262144 execute'try | throw 7 | catch /7/ | throw "G" | endtry' catch /G/ Xpath 524288 " X: 524288 endtry catch /7/ Xpath 1048576 " X: 0 endtry try try Xpath 2097152 " X: 2097152 execute 'try | throw 8 | finally | throw "H" | endtry' catch /H/ Xpath 4194304 " X: 4194304 endtry catch /8/ Xpath 8388608 " X: 0 endtry catch /.*/ Xpath 16777216 " X: 0 Xout v:exception "in" v:throwpoint endtry Xpath 33554432 " X: 33554432 delcommand THROW1 delcommand THROW2 delcommand THROW3 delcommand THROW4 Xcheck 40744667 "------------------------------------------------------------------------------- " Test 52: Uncaught exceptions {{{1 " " When an exception is thrown but not caught, an error message is " displayed when the script is terminated. In case of an interrupt " or error exception, the normal interrupt or error message(s) are " displayed. "------------------------------------------------------------------------------- XpathINIT let msgfile = tempname() function! MESSAGES(...) try exec "edit" g:msgfile catch /^Vim(edit):/ return 0 endtry let english = v:lang == "C" || v:lang =~ '^[Ee]n' let match = 1 norm gg let num = a:0 / 2 let cnt = 1 while cnt <= num let enr = a:{2*cnt - 1} let emsg= a:{2*cnt} let cnt = cnt + 1 if enr == "" Xout "TODO: Add message number for:" emsg elseif enr == "INT" let enr = "" endif if enr == "" && !english continue endif let pattern = (enr != "") ? enr . ':.*' : '' if english let pattern = pattern . emsg endif if !search(pattern, "W") let match = 0 Xout "No match for:" pattern endif norm $ endwhile bwipeout! return match endfunction if ExtraVim(msgfile) Xpath 1 " X: 1 throw "arrgh" endif Xpath 2 " X: 2 if !MESSAGES('E605', "Exception not caught") Xpath 4 " X: 0 endif if ExtraVim(msgfile) try Xpath 8 " X: 8 throw "oops" catch /arrgh/ Xpath 16 " X: 0 endtry Xpath 32 " X: 0 endif Xpath 64 " X: 64 if !MESSAGES('E605', "Exception not caught") Xpath 128 " X: 0 endif if ExtraVim(msgfile) function! T() throw "brrr" endfunction try Xpath 256 " X: 256 throw "arrgh" catch /.*/ Xpath 512 " X: 512 call T() endtry Xpath 1024 " X: 0 endif Xpath 2048 " X: 2048 if !MESSAGES('E605', "Exception not caught") Xpath 4096 " X: 0 endif if ExtraVim(msgfile) try Xpath 8192 " X: 8192 throw "arrgh" finally Xpath 16384 " X: 16384 throw "brrr" endtry Xpath 32768 " X: 0 endif Xpath 65536 " X: 65536 if !MESSAGES('E605', "Exception not caught") Xpath 131072 " X: 0 endif if ExtraVim(msgfile) try Xpath 262144 " X: 262144 "INTERRUPT endtry Xpath 524288 " X: 0 endif Xpath 1048576 " X: 1048576 if !MESSAGES('INT', "Interrupted") Xpath 2097152 " X: 0 endif if ExtraVim(msgfile) try Xpath 4194304 " X: 4194304 let x = novar " error E121/E15; exception: E121 catch /E15:/ " should not catch Xpath 8388608 " X: 0 endtry Xpath 16777216 " X: 0 endif Xpath 33554432 " X: 33554432 if !MESSAGES('E121', "Undefined variable", 'E15', "Invalid expression") Xpath 67108864 " X: 0 endif if ExtraVim(msgfile) try Xpath 134217728 " X: 134217728 " unlet novar # " error E108/E488; exception: E488 catch /E108:/ " should not catch Xpath 268435456 " X: 0 endtry Xpath 536870912 " X: 0 endif Xpath 1073741824 " X: 1073741824 if !MESSAGES('E108', "No such variable", 'E488', "Trailing characters") " The Xpath command does not accept 2^31 (negative); add explicitly: let Xpath = Xpath + 2147483648 " X: 0 endif call delete(msgfile) unlet msgfile Xcheck 1247112011 " Leave MESSAGES() for the next tests. "------------------------------------------------------------------------------- " Test 53: Nesting errors: :endif/:else/:elseif {{{1 " " For nesting errors of :if conditionals the correct error messages " should be given. " " This test reuses the function MESSAGES() from the previous test. " This functions checks the messages in g:msgfile. "------------------------------------------------------------------------------- XpathINIT let msgfile = tempname() if ExtraVim(msgfile) " endif endif if MESSAGES('E580', ":endif without :if") Xpath 1 " X: 1 endif if ExtraVim(msgfile) " while 1 " endif " endwhile endif if MESSAGES('E580', ":endif without :if") Xpath 2 " X: 2 endif if ExtraVim(msgfile) " try " finally " endif " endtry endif if MESSAGES('E580', ":endif without :if") Xpath 4 " X: 4 endif if ExtraVim(msgfile) " try " endif " endtry endif if MESSAGES('E580', ":endif without :if") Xpath 8 " X: 8 endif if ExtraVim(msgfile) " try " throw "a" " catch /a/ " endif " endtry endif if MESSAGES('E580', ":endif without :if") Xpath 16 " X: 16 endif if ExtraVim(msgfile) " else endif if MESSAGES('E581', ":else without :if") Xpath 32 " X: 32 endif if ExtraVim(msgfile) " while 1 " else " endwhile endif if MESSAGES('E581', ":else without :if") Xpath 64 " X: 64 endif if ExtraVim(msgfile) " try " finally " else " endtry endif if MESSAGES('E581', ":else without :if") Xpath 128 " X: 128 endif if ExtraVim(msgfile) " try " else " endtry endif if MESSAGES('E581', ":else without :if") Xpath 256 " X: 256 endif if ExtraVim(msgfile) " try " throw "a" " catch /a/ " else " endtry endif if MESSAGES('E581', ":else without :if") Xpath 512 " X: 512 endif if ExtraVim(msgfile) " elseif endif if MESSAGES('E582', ":elseif without :if") Xpath 1024 " X: 1024 endif if ExtraVim(msgfile) " while 1 " elseif " endwhile endif if MESSAGES('E582', ":elseif without :if") Xpath 2048 " X: 2048 endif if ExtraVim(msgfile) " try " finally " elseif " endtry endif if MESSAGES('E582', ":elseif without :if") Xpath 4096 " X: 4096 endif if ExtraVim(msgfile) " try " elseif " endtry endif if MESSAGES('E582', ":elseif without :if") Xpath 8192 " X: 8192 endif if ExtraVim(msgfile) " try " throw "a" " catch /a/ " elseif " endtry endif if MESSAGES('E582', ":elseif without :if") Xpath 16384 " X: 16384 endif if ExtraVim(msgfile) " if 1 " else " else " endif endif if MESSAGES('E583', "multiple :else") Xpath 32768 " X: 32768 endif if ExtraVim(msgfile) " if 1 " else " elseif 1 " endif endif if MESSAGES('E584', ":elseif after :else") Xpath 65536 " X: 65536 endif call delete(msgfile) unlet msgfile Xcheck 131071 " Leave MESSAGES() for the next test. "------------------------------------------------------------------------------- " Test 54: Nesting errors: :while/:endwhile {{{1 " " For nesting errors of :while conditionals the correct error messages " should be given. " " This test reuses the function MESSAGES() from the previous test. " This functions checks the messages in g:msgfile. "------------------------------------------------------------------------------- XpathINIT let msgfile = tempname() if ExtraVim(msgfile) " endwhile endif if MESSAGES('E588', ":endwhile without :while") Xpath 1 " X: 1 endif if ExtraVim(msgfile) " if 1 " endwhile " endif endif if MESSAGES('E588', ":endwhile without :while") Xpath 2 " X: 2 endif if ExtraVim(msgfile) " while 1 " if 1 " endwhile endif if MESSAGES('E171', "Missing :endif") Xpath 4 " X: 4 endif if ExtraVim(msgfile) " try " finally " endwhile " endtry endif if MESSAGES('E588', ":endwhile without :while") Xpath 8 " X: 8 endif if ExtraVim(msgfile) " while 1 " try " finally " endwhile endif if MESSAGES('E600', "Missing :endtry") Xpath 16 " X: 16 endif if ExtraVim(msgfile) " while 1 " if 1 " try " finally " endwhile endif if MESSAGES('E600', "Missing :endtry") Xpath 32 " X: 32 endif if ExtraVim(msgfile) " while 1 " try " finally " if 1 " endwhile endif if MESSAGES('E171', "Missing :endif") Xpath 64 " X: 64 endif if ExtraVim(msgfile) " try " endwhile " endtry endif if MESSAGES('E588', ":endwhile without :while") Xpath 128 " X: 128 endif if ExtraVim(msgfile) " while 1 " try " endwhile " endtry " endwhile endif if MESSAGES('E588', ":endwhile without :while") Xpath 256 " X: 256 endif if ExtraVim(msgfile) " try " throw "a" " catch /a/ " endwhile " endtry endif if MESSAGES('E588', ":endwhile without :while") Xpath 512 " X: 512 endif if ExtraVim(msgfile) " while 1 " try " throw "a" " catch /a/ " endwhile " endtry " endwhile endif if MESSAGES('E588', ":endwhile without :while") Xpath 1024 " X: 1024 endif call delete(msgfile) unlet msgfile Xcheck 2047 " Leave MESSAGES() for the next test. "------------------------------------------------------------------------------- " Test 55: Nesting errors: :continue/:break {{{1 " " For nesting errors of :continue and :break commands the correct " error messages should be given. " " This test reuses the function MESSAGES() from the previous test. " This functions checks the messages in g:msgfile. "------------------------------------------------------------------------------- XpathINIT let msgfile = tempname() if ExtraVim(msgfile) " continue endif if MESSAGES('E586', ":continue without :while") Xpath 1 " X: 1 endif if ExtraVim(msgfile) " if 1 " continue " endif endif if MESSAGES('E586', ":continue without :while") Xpath 2 " X: 2 endif if ExtraVim(msgfile) " try " finally " continue " endtry endif if MESSAGES('E586', ":continue without :while") Xpath 4 " X: 4 endif if ExtraVim(msgfile) " try " continue " endtry endif if MESSAGES('E586', ":continue without :while") Xpath 8 " X: 8 endif if ExtraVim(msgfile) " try " throw "a" " catch /a/ " continue " endtry endif if MESSAGES('E586', ":continue without :while") Xpath 16 " X: 16 endif if ExtraVim(msgfile) " break endif if MESSAGES('E587', ":break without :while") Xpath 32 " X: 32 endif if ExtraVim(msgfile) " if 1 " break " endif endif if MESSAGES('E587', ":break without :while") Xpath 64 " X: 64 endif if ExtraVim(msgfile) " try " finally " break " endtry endif if MESSAGES('E587', ":break without :while") Xpath 128 " X: 128 endif if ExtraVim(msgfile) " try " break " endtry endif if MESSAGES('E587', ":break without :while") Xpath 256 " X: 256 endif if ExtraVim(msgfile) " try " throw "a" " catch /a/ " break " endtry endif if MESSAGES('E587', ":break without :while") Xpath 512 " X: 512 endif call delete(msgfile) unlet msgfile Xcheck 1023 " Leave MESSAGES() for the next test. "------------------------------------------------------------------------------- " Test 56: Nesting errors: :endtry {{{1 " " For nesting errors of :try conditionals the correct error messages " should be given. " " This test reuses the function MESSAGES() from the previous test. " This functions checks the messages in g:msgfile. "------------------------------------------------------------------------------- XpathINIT let msgfile = tempname() if ExtraVim(msgfile) " endtry endif if MESSAGES('E602', ":endtry without :try") Xpath 1 " X: 1 endif if ExtraVim(msgfile) " if 1 " endtry " endif endif if MESSAGES('E602', ":endtry without :try") Xpath 2 " X: 2 endif if ExtraVim(msgfile) " while 1 " endtry " endwhile endif if MESSAGES('E602', ":endtry without :try") Xpath 4 " X: 4 endif if ExtraVim(msgfile) " try " if 1 " endtry endif if MESSAGES('E171', "Missing :endif") Xpath 8 " X: 8 endif if ExtraVim(msgfile) " try " while 1 " endtry endif if MESSAGES('E170', "Missing :endwhile") Xpath 16 " X: 16 endif if ExtraVim(msgfile) " try " finally " if 1 " endtry endif if MESSAGES('E171', "Missing :endif") Xpath 32 " X: 32 endif if ExtraVim(msgfile) " try " finally " while 1 " endtry endif if MESSAGES('E170', "Missing :endwhile") Xpath 64 " X: 64 endif if ExtraVim(msgfile) " try " throw "a" " catch /a/ " if 1 " endtry endif if MESSAGES('E171', "Missing :endif") Xpath 128 " X: 128 endif if ExtraVim(msgfile) " try " throw "a" " catch /a/ " while 1 " endtry endif if MESSAGES('E170', "Missing :endwhile") Xpath 256 " X: 256 endif call delete(msgfile) unlet msgfile delfunction MESSAGES Xcheck 511 "------------------------------------------------------------------------------- " Test 57: v:exception and v:throwpoint for user exceptions {{{1 " " v:exception evaluates to the value of the exception that was caught " most recently and is not finished. (A caught exception is finished " when the next ":catch", ":finally", or ":endtry" is reached.) " v:throwpoint evaluates to the script/function name and line number " where that exception has been thrown. "------------------------------------------------------------------------------- XpathINIT function! FuncException() let g:exception = v:exception endfunction function! FuncThrowpoint() let g:throwpoint = v:throwpoint endfunction let scriptException = MakeScript("FuncException") let scriptThrowPoint = MakeScript("FuncThrowpoint") command! CmdException let g:exception = v:exception command! CmdThrowpoint let g:throwpoint = v:throwpoint XloopINIT! 1 2 function! CHECK(n, exception, throwname, throwline) XloopNEXT let error = 0 if v:exception != a:exception Xout a:n.": v:exception is" v:exception "instead of" a:exception let error = 1 endif if v:throwpoint !~ a:throwname let name = escape(a:throwname, '\') Xout a:n.": v:throwpoint (".v:throwpoint.") does not match" name let error = 1 endif if v:throwpoint !~ a:throwline let line = escape(a:throwline, '\') Xout a:n.": v:throwpoint (".v:throwpoint.") does not match" line let error = 1 endif if error Xloop 1 " X: 0 endif endfunction function! T(arg, line) if a:line == 2 throw a:arg " in line 2 elseif a:line == 4 throw a:arg " in line 4 elseif a:line == 6 throw a:arg " in line 6 elseif a:line == 8 throw a:arg " in line 8 endif endfunction function! G(arg, line) call T(a:arg, a:line) endfunction function! F(arg, line) call G(a:arg, a:line) endfunction let scriptT = MakeScript("T") let scriptG = MakeScript("G", scriptT) let scriptF = MakeScript("F", scriptG) try Xpath 32768 " X: 32768 call F("oops", 2) catch /.*/ Xpath 65536 " X: 65536 let exception = v:exception let throwpoint = v:throwpoint call CHECK(1, "oops", '\<F\[1]\.\.G\[1]\.\.T\>', '\<2\>') exec "let exception = v:exception" exec "let throwpoint = v:throwpoint" call CHECK(2, "oops", '\<F\[1]\.\.G\[1]\.\.T\>', '\<2\>') CmdException CmdThrowpoint call CHECK(3, "oops", '\<F\[1]\.\.G\[1]\.\.T\>', '\<2\>') call FuncException() call FuncThrowpoint() call CHECK(4, "oops", '\<F\[1]\.\.G\[1]\.\.T\>', '\<2\>') exec "source" scriptException exec "source" scriptThrowPoint call CHECK(5, "oops", '\<F\[1]\.\.G\[1]\.\.T\>', '\<2\>') try Xpath 131072 " X: 131072 call G("arrgh", 4) catch /.*/ Xpath 262144 " X: 262144 let exception = v:exception let throwpoint = v:throwpoint call CHECK(6, "arrgh", '\<G\[1]\.\.T\>', '\<4\>') try Xpath 524288 " X: 524288 let g:arg = "autsch" let g:line = 6 exec "source" scriptF catch /.*/ Xpath 1048576 " X: 1048576 let exception = v:exception let throwpoint = v:throwpoint " Symbolic links in tempname()s are not resolved, whereas resolving " is done for v:throwpoint. Resolve the temporary file name for " scriptT, so that it can be matched against v:throwpoint. call CHECK(7, "autsch", resolve(scriptT), '\<6\>') finally Xpath 2097152 " X: 2097152 let exception = v:exception let throwpoint = v:throwpoint call CHECK(8, "arrgh", '\<G\[1]\.\.T\>', '\<4\>') try Xpath 4194304 " X: 4194304 let g:arg = "brrrr" let g:line = 8 exec "source" scriptG catch /.*/ Xpath 8388608 " X: 8388608 let exception = v:exception let throwpoint = v:throwpoint " Resolve scriptT for matching it against v:throwpoint. call CHECK(9, "brrrr", resolve(scriptT), '\<8\>') finally Xpath 16777216 " X: 16777216 let exception = v:exception let throwpoint = v:throwpoint call CHECK(10, "arrgh", '\<G\[1]\.\.T\>', '\<4\>') endtry Xpath 33554432 " X: 33554432 let exception = v:exception let throwpoint = v:throwpoint call CHECK(11, "arrgh", '\<G\[1]\.\.T\>', '\<4\>') endtry Xpath 67108864 " X: 67108864 let exception = v:exception let throwpoint = v:throwpoint call CHECK(12, "arrgh", '\<G\[1]\.\.T\>', '\<4\>') finally Xpath 134217728 " X: 134217728 let exception = v:exception let throwpoint = v:throwpoint call CHECK(13, "oops", '\<F\[1]\.\.G\[1]\.\.T\>', '\<2\>') endtry Xpath 268435456 " X: 268435456 let exception = v:exception let throwpoint = v:throwpoint call CHECK(14, "oops", '\<F\[1]\.\.G\[1]\.\.T\>', '\<2\>') finally Xpath 536870912 " X: 536870912 let exception = v:exception let throwpoint = v:throwpoint call CHECK(15, "", '^$', '^$') endtry Xpath 1073741824 " X: 1073741824 unlet exception throwpoint delfunction FuncException delfunction FuncThrowpoint call delete(scriptException) call delete(scriptThrowPoint) unlet scriptException scriptThrowPoint delcommand CmdException delcommand CmdThrowpoint delfunction T delfunction G delfunction F call delete(scriptT) call delete(scriptG) call delete(scriptF) unlet scriptT scriptG scriptF Xcheck 2147450880 "------------------------------------------------------------------------------- " " Test 58: v:exception and v:throwpoint for error/interrupt exceptions {{{1 " " v:exception and v:throwpoint work also for error and interrupt " exceptions. "------------------------------------------------------------------------------- XpathINIT if ExtraVim() function! T(line) if a:line == 2 delfunction T " error (function in use) in line 2 elseif a:line == 4 let dummy = 0 " INTERRUPT1 - interrupt in line 4 endif endfunction while 1 try Xpath 1 " X: 1 let caught = 0 call T(2) catch /.*/ let caught = 1 if v:exception !~ 'Vim(delfunction):' Xpath 2 " X: 0 endif if v:throwpoint !~ '\<T\>' Xpath 4 " X: 0 endif if v:throwpoint !~ '\<2\>' Xpath 8 " X: 0 endif finally Xpath 16 " X: 16 if caught || $VIMNOERRTHROW Xpath 32 " X: 32 endif if v:exception != "" Xpath 64 " X: 0 endif if v:throwpoint != "" Xpath 128 " X: 0 endif break " discard error for $VIMNOERRTHROW endtry endwhile Xpath 256 " X: 256 if v:exception != "" Xpath 512 " X: 0 endif if v:throwpoint != "" Xpath 1024 " X: 0 endif while 1 try Xpath 2048 " X: 2048 let caught = 0 call T(4) catch /.*/ let caught = 1 if v:exception != 'Vim:Interrupt' Xpath 4096 " X: 0 endif if v:throwpoint !~ '\<T\>' Xpath 8192 " X: 0 endif if v:throwpoint !~ '\<4\>' Xpath 16384 " X: 0 endif finally Xpath 32768 " X: 32768 if caught || $VIMNOINTTHROW Xpath 65536 " X: 65536 endif if v:exception != "" Xpath 131072 " X: 0 endif if v:throwpoint != "" Xpath 262144 " X: 0 endif break " discard error for $VIMNOERRTHROW endtry endwhile Xpath 524288 " X: 524288 if v:exception != "" Xpath 1048576 " X: 0 endif if v:throwpoint != "" Xpath 2097152 " X: 0 endif endif Xcheck 624945 "------------------------------------------------------------------------------- " " Test 59: v:exception and v:throwpoint when discarding exceptions {{{1 " " When a :catch clause is left by a ":break" etc or an error or " interrupt exception, v:exception and v:throwpoint are reset. They " are not affected by an exception that is discarded before being " caught. "------------------------------------------------------------------------------- XpathINIT if ExtraVim() XloopINIT! 1 2 let sfile = expand("<sfile>") function! LineNumber() return substitute(substitute(v:throwpoint, g:sfile, '', ""), \ '\D*\(\d*\).*', '\1', "") endfunction command! -nargs=1 SetLineNumber \ try | throw "line" | catch /.*/ | let <args> = LineNumber() | endtry " Check v:exception/v:throwpoint against second/fourth parameter if " specified, check for being empty else. function! CHECK(n, ...) XloopNEXT let exception = a:0 != 0 ? a:1 : "" " second parameter (optional) let emsg = a:0 != 0 ? a:2 : "" " third parameter (optional) let line = a:0 != 0 ? a:3 : 0 " fourth parameter (optional) let error = 0 if emsg != "" " exception is the error number, emsg the English error message text if exception !~ '^E\d\+$' Xout "TODO: Add message number for:" emsg elseif v:lang == "C" || v:lang =~ '^[Ee]n' if exception == "E492" && emsg == "Not an editor command" let exception = '^Vim:' . exception . ': ' . emsg else let exception = '^Vim(\a\+):' . exception . ': ' . emsg endif else if exception == "E492" let exception = '^Vim:' . exception else let exception = '^Vim(\a\+):' . exception endif endif endif if exception == "" && v:exception != "" Xout a:n.": v:exception is set:" v:exception let error = 1 elseif exception != "" && v:exception !~ exception Xout a:n.": v:exception (".v:exception.") does not match" exception let error = 1 endif if line == 0 && v:throwpoint != "" Xout a:n.": v:throwpoint is set:" v:throwpoint let error = 1 elseif line != 0 && v:throwpoint !~ '\<' . line . '\>' Xout a:n.": v:throwpoint (".v:throwpoint.") does not match" line let error = 1 endif if !error Xloop 1 " X: 2097151 endif endfunction while 1 try throw "x1" catch /.*/ break endtry endwhile call CHECK(1) while 1 try throw "x2" catch /.*/ break finally call CHECK(2) endtry break endwhile call CHECK(3) while 1 try let errcaught = 0 try try throw "x3" catch /.*/ SetLineNumber line_before_error asdf endtry catch /.*/ let errcaught = 1 call CHECK(4, 'E492', "Not an editor command", \ line_before_error + 1) endtry finally if !errcaught && $VIMNOERRTHROW call CHECK(4) endif break " discard error for $VIMNOERRTHROW endtry endwhile call CHECK(5) Xpath 2097152 " X: 2097152 while 1 try let intcaught = 0 try try throw "x4" catch /.*/ SetLineNumber two_lines_before_interrupt "INTERRUPT let dummy = 0 endtry catch /.*/ let intcaught = 1 call CHECK(6, "Vim:Interrupt", '', \ two_lines_before_interrupt + 2) endtry finally if !intcaught && $VIMNOINTTHROW call CHECK(6) endif break " discard interrupt for $VIMNOINTTHROW endtry endwhile call CHECK(7) Xpath 4194304 " X: 4194304 while 1 try let errcaught = 0 try try " if 1 SetLineNumber line_before_throw throw "x5" " missing endif catch /.*/ Xpath 8388608 " X: 0 endtry catch /.*/ let errcaught = 1 call CHECK(8, 'E171', "Missing :endif", line_before_throw + 3) endtry finally if !errcaught && $VIMNOERRTHROW call CHECK(8) endif break " discard error for $VIMNOERRTHROW endtry endwhile call CHECK(9) Xpath 16777216 " X: 16777216 try while 1 try throw "x6" finally break endtry break endwhile catch /.*/ Xpath 33554432 " X: 0 endtry call CHECK(10) try while 1 try throw "x7" finally break endtry break endwhile catch /.*/ Xpath 67108864 " X: 0 finally call CHECK(11) endtry call CHECK(12) while 1 try let errcaught = 0 try try throw "x8" finally SetLineNumber line_before_error asdf endtry catch /.*/ let errcaught = 1 call CHECK(13, 'E492', "Not an editor command", \ line_before_error + 1) endtry finally if !errcaught && $VIMNOERRTHROW call CHECK(13) endif break " discard error for $VIMNOERRTHROW endtry endwhile call CHECK(14) Xpath 134217728 " X: 134217728 while 1 try let intcaught = 0 try try throw "x9" finally SetLineNumber two_lines_before_interrupt "INTERRUPT endtry catch /.*/ let intcaught = 1 call CHECK(15, "Vim:Interrupt", '', \ two_lines_before_interrupt + 2) endtry finally if !intcaught && $VIMNOINTTHROW call CHECK(15) endif break " discard interrupt for $VIMNOINTTHROW endtry endwhile call CHECK(16) Xpath 268435456 " X: 268435456 while 1 try let errcaught = 0 try try " if 1 SetLineNumber line_before_throw throw "x10" " missing endif finally call CHECK(17) endtry catch /.*/ let errcaught = 1 call CHECK(18, 'E171', "Missing :endif", line_before_throw + 3) endtry finally if !errcaught && $VIMNOERRTHROW call CHECK(18) endif break " discard error for $VIMNOERRTHROW endtry endwhile call CHECK(19) Xpath 536870912 " X: 536870912 while 1 try let errcaught = 0 try try " if 1 SetLineNumber line_before_throw throw "x11" " missing endif endtry catch /.*/ let errcaught = 1 call CHECK(20, 'E171', "Missing :endif", line_before_throw + 3) endtry finally if !errcaught && $VIMNOERRTHROW call CHECK(20) endif break " discard error for $VIMNOERRTHROW endtry endwhile call CHECK(21) Xpath 1073741824 " X: 1073741824 endif Xcheck 2038431743 "------------------------------------------------------------------------------- " " Test 60: (Re)throwing v:exception; :echoerr. {{{1 " " A user exception can be rethrown after catching by throwing " v:exception. An error or interrupt exception cannot be rethrown " because Vim exceptions cannot be faked. A Vim exception using the " value of v:exception can, however, be triggered by the :echoerr " command. "------------------------------------------------------------------------------- XpathINIT try try Xpath 1 " X: 1 throw "oops" catch /oops/ Xpath 2 " X: 2 throw v:exception " rethrow user exception catch /.*/ Xpath 4 " X: 0 endtry catch /^oops$/ " catches rethrown user exception Xpath 8 " X: 8 catch /.*/ Xpath 16 " X: 0 endtry function! F() try let caught = 0 try Xpath 32 " X: 32 write /n/o/n/w/r/i/t/a/b/l/e/_/f/i/l/e Xpath 64 " X: 0 Xout "did_emsg was reset before executing " . \ "BufWritePost autocommands." catch /^Vim(write):/ let caught = 1 throw v:exception " throw error: cannot fake Vim exception catch /.*/ Xpath 128 " X: 0 finally Xpath 256 " X: 256 if !caught && !$VIMNOERRTHROW Xpath 512 " X: 0 endif endtry catch /^Vim(throw):/ " catches throw error let caught = caught + 1 catch /.*/ Xpath 1024 " X: 0 finally Xpath 2048 " X: 2048 if caught != 2 if !caught && !$VIMNOERRTHROW Xpath 4096 " X: 0 elseif caught Xpath 8192 " X: 0 endif return | " discard error for $VIMNOERRTHROW endif endtry endfunction call F() delfunction F function! G() try let caught = 0 try Xpath 16384 " X: 16384 asdf catch /^Vim/ " catch error exception let caught = 1 " Trigger Vim error exception with value specified after :echoerr let value = substitute(v:exception, '^Vim\((.*)\)\=:', '', "") echoerr value catch /.*/ Xpath 32768 " X: 0 finally Xpath 65536 " X: 65536 if !caught if !$VIMNOERRTHROW Xpath 131072 " X: 0 else let value = "Error" echoerr value endif endif endtry catch /^Vim(echoerr):/ let caught = caught + 1 if v:exception !~ value Xpath 262144 " X: 0 endif catch /.*/ Xpath 524288 " X: 0 finally Xpath 1048576 " X: 1048576 if caught != 2 if !caught && !$VIMNOERRTHROW Xpath 2097152 " X: 0 elseif caught Xpath 4194304 " X: 0 endif return | " discard error for $VIMNOERRTHROW endif endtry endfunction call G() delfunction G unlet! value caught if ExtraVim() try let errcaught = 0 try Xpath 8388608 " X: 8388608 let intcaught = 0 "INTERRUPT catch /^Vim:/ " catch interrupt exception let intcaught = 1 " Trigger Vim error exception with value specified after :echoerr echoerr substitute(v:exception, '^Vim\((.*)\)\=:', '', "") catch /.*/ Xpath 16777216 " X: 0 finally Xpath 33554432 " X: 33554432 if !intcaught if !$VIMNOINTTHROW Xpath 67108864 " X: 0 else echoerr "Interrupt" endif endif endtry catch /^Vim(echoerr):/ let errcaught = 1 if v:exception !~ "Interrupt" Xpath 134217728 " X: 0 endif finally Xpath 268435456 " X: 268435456 if !errcaught && !$VIMNOERRTHROW Xpath 536870912 " X: 0 endif endtry endif Xcheck 311511339 "------------------------------------------------------------------------------- " Test 61: Catching interrupt exceptions {{{1 " " When an interrupt occurs inside a :try/:endtry region, an " interrupt exception is thrown and can be caught. Its value is " "Vim:Interrupt". If the interrupt occurs after an error or a :throw " but before a matching :catch is reached, all following :catches of " that try block are ignored, but the interrupt exception can be " caught by the next surrounding try conditional. An interrupt is " ignored when there is a previous interrupt that has not been caught " or causes a :finally clause to be executed. "------------------------------------------------------------------------------- XpathINIT if ExtraVim() while 1 try try Xpath 1 " X: 1 let caught = 0 "INTERRUPT Xpath 2 " X: 0 catch /^Vim:Interrupt$/ let caught = 1 finally Xpath 4 " X: 4 if caught || $VIMNOINTTHROW Xpath 8 " X: 8 endif endtry catch /.*/ Xpath 16 " X: 0 Xout v:exception "in" v:throwpoint finally break " discard interrupt for $VIMNOINTTHROW endtry endwhile while 1 try try let caught = 0 try Xpath 32 " X: 32 asdf Xpath 64 " X: 0 catch /do_not_catch/ Xpath 128 " X: 0 catch /.*/ "INTERRUPT - throw interrupt if !$VIMNOERRTHROW Xpath 256 " X: 0 catch /.*/ Xpath 512 " X: 0 finally "INTERRUPT - throw interrupt if $VIMNOERRTHROW Xpath 1024 " X: 1024 endtry catch /^Vim:Interrupt$/ let caught = 1 finally Xpath 2048 " X: 2048 if caught || $VIMNOINTTHROW Xpath 4096 " X: 4096 endif endtry catch /.*/ Xpath 8192 " X: 0 Xout v:exception "in" v:throwpoint finally break " discard interrupt for $VIMNOINTTHROW endtry endwhile while 1 try try let caught = 0 try Xpath 16384 " X: 16384 throw "x" Xpath 32768 " X: 0 catch /do_not_catch/ Xpath 65536 " X: 0 catch /x/ "INTERRUPT Xpath 131072 " X: 0 catch /.*/ Xpath 262144 " X: 0 endtry catch /^Vim:Interrupt$/ let caught = 1 finally Xpath 524288 " X: 524288 if caught || $VIMNOINTTHROW Xpath 1048576 " X: 1048576 endif endtry catch /.*/ Xpath 2097152 " X: 0 Xout v:exception "in" v:throwpoint finally break " discard interrupt for $VIMNOINTTHROW endtry endwhile while 1 try let caught = 0 try Xpath 4194304 " X: 4194304 "INTERRUPT Xpath 8388608 " X: 0 catch /do_not_catch/ "INTERRUPT Xpath 16777216 " X: 0 catch /^Vim:Interrupt$/ let caught = 1 finally Xpath 33554432 " X: 33554432 if caught || $VIMNOINTTHROW Xpath 67108864 " X: 67108864 endif endtry catch /.*/ Xpath 134217728 " X: 0 Xout v:exception "in" v:throwpoint finally break " discard interrupt for $VIMNOINTTHROW endtry endwhile Xpath 268435456 " X: 268435456 endif Xcheck 374889517 "------------------------------------------------------------------------------- " Test 62: Catching error exceptions {{{1 " " An error inside a :try/:endtry region is converted to an exception " and can be caught. The error exception has a "Vim(cmdname):" prefix " where cmdname is the name of the failing command, or a "Vim:" prefix " if no command name is known. The "Vim" prefixes cannot be faked. "------------------------------------------------------------------------------- XpathINIT function! MSG(enr, emsg) let english = v:lang == "C" || v:lang =~ '^[Ee]n' if a:enr == "" Xout "TODO: Add message number for:" a:emsg let v:errmsg = ":" . v:errmsg endif let match = 1 if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg) let match = 0 if v:errmsg == "" Xout "Message missing." else let v:errmsg = escape(v:errmsg, '"') Xout "Unexpected message:" v:errmsg endif endif return match endfunction while 1 try try let caught = 0 unlet novar catch /^Vim(unlet):/ let caught = 1 let v:errmsg = substitute(v:exception, '^Vim(unlet):', '', "") finally Xpath 1 " X: 1 if !caught && !$VIMNOERRTHROW Xpath 2 " X: 0 endif if !MSG('E108', "No such variable") Xpath 4 " X: 0 endif endtry catch /.*/ Xpath 8 " X: 0 Xout v:exception "in" v:throwpoint finally break " discard error for $VIMNOERRTHROW endtry endwhile while 1 try try let caught = 0 throw novar " error in :throw catch /^Vim(throw):/ let caught = 1 let v:errmsg = substitute(v:exception, '^Vim(throw):', '', "") finally Xpath 16 " X: 16 if !caught && !$VIMNOERRTHROW Xpath 32 " X: 0 endif if caught ? !MSG('E121', "Undefined variable") \ : !MSG('E15', "Invalid expression") Xpath 64 " X: 0 endif endtry catch /.*/ Xpath 128 " X: 0 Xout v:exception "in" v:throwpoint finally break " discard error for $VIMNOERRTHROW endtry endwhile while 1 try try let caught = 0 throw "Vim:faked" " error: cannot fake Vim exception catch /^Vim(throw):/ let caught = 1 let v:errmsg = substitute(v:exception, '^Vim(throw):', '', "") finally Xpath 256 " X: 256 if !caught && !$VIMNOERRTHROW Xpath 512 " X: 0 endif if !MSG('E608', "Cannot :throw exceptions with 'Vim' prefix") Xpath 1024 " X: 0 endif endtry catch /.*/ Xpath 2048 " X: 0 Xout v:exception "in" v:throwpoint finally break " discard error for $VIMNOERRTHROW endtry endwhile function! F() while 1 " Missing :endwhile endfunction while 1 try try let caught = 0 call F() catch /^Vim(endfunction):/ let caught = 1 let v:errmsg = substitute(v:exception, '^Vim(endfunction):', '', "") finally Xpath 4096 " X: 4096 if !caught && !$VIMNOERRTHROW Xpath 8192 " X: 0 endif if !MSG('E170', "Missing :endwhile") Xpath 16384 " X: 0 endif endtry catch /.*/ Xpath 32768 " X: 0 Xout v:exception "in" v:throwpoint finally break " discard error for $VIMNOERRTHROW endtry endwhile while 1 try try let caught = 0 ExecAsScript F catch /^Vim:/ let caught = 1 let v:errmsg = substitute(v:exception, '^Vim:', '', "") finally Xpath 65536 " X: 65536 if !caught && !$VIMNOERRTHROW Xpath 131072 " X: 0 endif if !MSG('E170', "Missing :endwhile") Xpath 262144 " X: 0 endif endtry catch /.*/ Xpath 524288 " X: 0 Xout v:exception "in" v:throwpoint finally break " discard error for $VIMNOERRTHROW endtry endwhile function! G() call G() endfunction while 1 try let mfd_save = &mfd set mfd=3 try let caught = 0 call G() catch /^Vim(call):/ let caught = 1 let v:errmsg = substitute(v:exception, '^Vim(call):', '', "") finally Xpath 1048576 " X: 1048576 if !caught && !$VIMNOERRTHROW Xpath 2097152 " X: 0 endif if !MSG('E132', "Function call depth is higher than 'maxfuncdepth'") Xpath 4194304 " X: 0 endif endtry catch /.*/ Xpath 8388608 " X: 0 Xout v:exception "in" v:throwpoint finally let &mfd = mfd_save break " discard error for $VIMNOERRTHROW endtry endwhile function! H() return H() endfunction while 1 try let mfd_save = &mfd set mfd=3 try let caught = 0 call H() catch /^Vim(return):/ let caught = 1 let v:errmsg = substitute(v:exception, '^Vim(return):', '', "") finally Xpath 16777216 " X: 16777216 if !caught && !$VIMNOERRTHROW Xpath 33554432 " X: 0 endif if !MSG('E132', "Function call depth is higher than 'maxfuncdepth'") Xpath 67108864 " X: 0 endif endtry catch /.*/ Xpath 134217728 " X: 0 Xout v:exception "in" v:throwpoint finally let &mfd = mfd_save break " discard error for $VIMNOERRTHROW endtry endwhile unlet! caught mfd_save delfunction F delfunction G delfunction H Xpath 268435456 " X: 268435456 Xcheck 286331153 " Leave MSG() for the next test. "------------------------------------------------------------------------------- " Test 63: Suppressing error exceptions by :silent!. {{{1 " " A :silent! command inside a :try/:endtry region suppresses the " conversion of errors to an exception and the immediate abortion on " error. When the commands executed by the :silent! themselves open " a new :try/:endtry region, conversion of errors to exception and " immediate abortion is switched on again - until the next :silent! " etc. The :silent! has the effect of setting v:errmsg to the error " message text (without displaying it) and continuing with the next " script line. " " When a command triggering autocommands is executed by :silent! " inside a :try/:endtry, the autocommand execution is not suppressed " on error. " " This test reuses the function MSG() from the previous test. "------------------------------------------------------------------------------- XpathINIT XloopINIT! 1 4 let taken = "" function! S(n) abort XloopNEXT let g:taken = g:taken . "E" . a:n let v:errmsg = "" exec "asdf" . a:n " Check that ":silent!" continues: Xloop 1 " Check that ":silent!" sets "v:errmsg": if MSG('E492', "Not an editor command") Xloop 2 endif endfunction function! Foo() while 1 try try let caught = 0 " This is not silent: call S(3) " X: 0 * 16 catch /^Vim:/ let caught = 1 let errmsg3 = substitute(v:exception, '^Vim:', '', "") silent! call S(4) " X: 3 * 64 finally if !caught let errmsg3 = v:errmsg " Do call S(4) here if not executed in :catch. silent! call S(4) endif Xpath 1048576 " X: 1048576 if !caught && !$VIMNOERRTHROW Xpath 2097152 " X: 0 endif let v:errmsg = errmsg3 if !MSG('E492', "Not an editor command") Xpath 4194304 " X: 0 endif silent! call S(5) " X: 3 * 256 " Break out of try conditionals that cover ":silent!". This also " discards the aborting error when $VIMNOERRTHROW is non-zero. break endtry catch /.*/ Xpath 8388608 " X: 0 Xout v:exception "in" v:throwpoint endtry endwhile " This is a double ":silent!" (see caller). silent! call S(6) " X: 3 * 1024 endfunction function! Bar() try silent! call S(2) " X: 3 * 4 " X: 3 * 4096 silent! execute "call Foo() | call S(7)" silent! call S(8) " X: 3 * 16384 endtry " normal end of try cond that covers ":silent!" " This has a ":silent!" from the caller: call S(9) " X: 3 * 65536 endfunction silent! call S(1) " X: 3 * 1 silent! call Bar() silent! call S(10) " X: 3 * 262144 let expected = "E1E2E3E4E5E6E7E8E9E10" if taken != expected Xpath 16777216 " X: 0 Xout "'taken' is" taken "instead of" expected endif augroup TMP autocmd BufWritePost * Xpath 33554432 " X: 33554432 augroup END Xpath 67108864 " X: 67108864 write /i/m/p/o/s/s/i/b/l/e Xpath 134217728 " X: 134217728 autocmd! TMP unlet! caught errmsg3 taken expected delfunction S delfunction Foo delfunction Bar delfunction MSG Xcheck 236978127 "------------------------------------------------------------------------------- " Test 64: Error exceptions after error, interrupt or :throw {{{1 " " When an error occurs after an interrupt or a :throw but before " a matching :catch is reached, all following :catches of that try " block are ignored, but the error exception can be caught by the next " surrounding try conditional. Any previous error exception is " discarded. An error is ignored when there is a previous error that " has not been caught. "------------------------------------------------------------------------------- XpathINIT if ExtraVim() while 1 try try Xpath 1 " X: 1 let caught = 0 while 1 " if 1 " Missing :endif endwhile " throw error exception catch /^Vim(/ let caught = 1 finally Xpath 2 " X: 2 if caught || $VIMNOERRTHROW Xpath 4 " X: 4 endif endtry catch /.*/ Xpath 8 " X: 0 Xout v:exception "in" v:throwpoint finally break " discard error for $VIMNOERRTHROW endtry endwhile while 1 try try Xpath 16 " X: 16 let caught = 0 try " if 1 " Missing :endif catch /.*/ " throw error exception Xpath 32 " X: 0 catch /.*/ Xpath 64 " X: 0 endtry catch /^Vim(/ let caught = 1 finally Xpath 128 " X: 128 if caught || $VIMNOERRTHROW Xpath 256 " X: 256 endif endtry catch /.*/ Xpath 512 " X: 0 Xout v:exception "in" v:throwpoint finally break " discard error for $VIMNOERRTHROW endtry endwhile while 1 try try let caught = 0 try Xpath 1024 " X: 1024 "INTERRUPT catch /do_not_catch/ Xpath 2048 " X: 0 " if 1 " Missing :endif catch /.*/ " throw error exception Xpath 4096 " X: 0 catch /.*/ Xpath 8192 " X: 0 endtry catch /^Vim(/ let caught = 1 finally Xpath 16384 " X: 16384 if caught || $VIMNOERRTHROW Xpath 32768 " X: 32768 endif endtry catch /.*/ Xpath 65536 " X: 0 Xout v:exception "in" v:throwpoint finally break " discard error for $VIMNOERRTHROW endtry endwhile while 1 try try let caught = 0 try Xpath 131072 " X: 131072 throw "x" catch /do_not_catch/ Xpath 262144 " X: 0 " if 1 " Missing :endif catch /x/ " throw error exception Xpath 524288 " X: 0 catch /.*/ Xpath 1048576 " X: 0 endtry catch /^Vim(/ let caught = 1 finally Xpath 2097152 " X: 2097152 if caught || $VIMNOERRTHROW Xpath 4194304 " X: 4194304 endif endtry catch /.*/ Xpath 8388608 " X: 0 Xout v:exception "in" v:throwpoint finally break " discard error for $VIMNOERRTHROW endtry endwhile while 1 try try let caught = 0 Xpath 16777216 " X: 16777216 " endif " :endif without :if; throw error exception " if 1 " Missing :endif catch /do_not_catch/ " ignore new error Xpath 33554432 " X: 0 catch /^Vim(endif):/ let caught = 1 catch /^Vim(/ Xpath 67108864 " X: 0 finally Xpath 134217728 " X: 134217728 if caught || $VIMNOERRTHROW Xpath 268435456 " X: 268435456 endif endtry catch /.*/ Xpath 536870912 " X: 0 Xout v:exception "in" v:throwpoint finally break " discard error for $VIMNOERRTHROW endtry endwhile Xpath 1073741824 " X: 1073741824 endif Xcheck 1499645335 "------------------------------------------------------------------------------- " Test 65: Errors in the /pattern/ argument of a :catch {{{1 " " On an error in the /pattern/ argument of a :catch, the :catch does " not match. Any following :catches of the same :try/:endtry don't " match either. Finally clauses are executed. "------------------------------------------------------------------------------- XpathINIT function! MSG(enr, emsg) let english = v:lang == "C" || v:lang =~ '^[Ee]n' if a:enr == "" Xout "TODO: Add message number for:" a:emsg let v:errmsg = ":" . v:errmsg endif let match = 1 if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg) let match = 0 if v:errmsg == "" Xout "Message missing." else let v:errmsg = escape(v:errmsg, '"') Xout "Unexpected message:" v:errmsg endif endif return match endfunction try try Xpath 1 " X: 1 throw "oops" catch /^oops$/ Xpath 2 " X: 2 catch /\)/ " not checked; exception has already been caught Xpath 4 " X: 0 endtry Xpath 8 " X: 8 catch /.*/ Xpath 16 " X: 0 Xout v:exception "in" v:throwpoint endtry function! F() try let caught = 0 try try Xpath 32 " X: 32 throw "ab" catch /abc/ " does not catch Xpath 64 " X: 0 catch /\)/ " error; discards exception Xpath 128 " X: 0 catch /.*/ " not checked Xpath 256 " X: 0 finally Xpath 512 " X: 512 endtry Xpath 1024 " X: 0 catch /^ab$/ " checked, but original exception is discarded Xpath 2048 " X: 0 catch /^Vim(catch):/ let caught = 1 let v:errmsg = substitute(v:exception, '^Vim(catch):', '', "") finally Xpath 4096 " X: 4096 if !caught && !$VIMNOERRTHROW Xpath 8192 " X: 0 endif if !MSG('E475', "Invalid argument") Xpath 16384 " X: 0 endif if !caught return | " discard error endif endtry catch /.*/ Xpath 32768 " X: 0 Xout v:exception "in" v:throwpoint endtry endfunction call F() Xpath 65536 " X: 65536 delfunction MSG delfunction F unlet! caught Xcheck 70187 "------------------------------------------------------------------------------- " Test 66: Stop range :call on error, interrupt, or :throw {{{1 " " When a function which is multiply called for a range since it " doesn't handle the range itself has an error in a command " dynamically enclosed by :try/:endtry or gets an interrupt or " executes a :throw, no more calls for the remaining lines in the " range are made. On an error in a command not dynamically enclosed " by :try/:endtry, the function is executed again for the remaining " lines in the range. "------------------------------------------------------------------------------- XpathINIT if ExtraVim() let file = tempname() exec "edit" file insert line 1 line 2 line 3 . XloopINIT! 1 2 let taken = "" let expected = "G1EF1E(1)F1E(2)F1E(3)G2EF2E(1)G3IF3I(1)G4TF4T(1)G5AF5A(1)" function! F(reason, n) abort let g:taken = g:taken . "F" . a:n . \ substitute(a:reason, '\(\l\).*', '\u\1', "") . \ "(" . line(".") . ")" if a:reason == "error" asdf elseif a:reason == "interrupt" "INTERRUPT let dummy = 0 elseif a:reason == "throw" throw "xyz" elseif a:reason == "aborting error" XloopNEXT if g:taken != g:expected Xloop 1 " X: 0 Xout "'taken' is" g:taken "instead of" g:expected endif try bwipeout! call delete(file) asdf endtry endif endfunction function! G(reason, n) let g:taken = g:taken . "G" . a:n . \ substitute(a:reason, '\(\l\).*', '\u\1', "") 1,3call F(a:reason, a:n) endfunction Xpath 8 " X: 8 call G("error", 1) try Xpath 16 " X: 16 try call G("error", 2) Xpath 32 " X: 0 finally Xpath 64 " X: 64 try call G("interrupt", 3) Xpath 128 " X: 0 finally Xpath 256 " X: 256 try call G("throw", 4) Xpath 512 " X: 0 endtry endtry endtry catch /xyz/ Xpath 1024 " X: 1024 catch /.*/ Xpath 2048 " X: 0 Xout v:exception "in" ExtraVimThrowpoint() endtry Xpath 4096 " X: 4096 call G("aborting error", 5) Xpath 8192 " X: 0 Xout "'taken' is" taken "instead of" expected endif Xcheck 5464 "------------------------------------------------------------------------------- " Test 67: :throw across :call command {{{1 " " On a call command, an exception might be thrown when evaluating the " function name, during evaluation of the arguments, or when the " function is being executed. The exception can be caught by the " caller. "------------------------------------------------------------------------------- XpathINIT function! THROW(x, n) if a:n == 1 Xpath 1 " X: 1 elseif a:n == 2 Xpath 2 " X: 2 elseif a:n == 3 Xpath 4 " X: 4 endif throw a:x endfunction function! NAME(x, n) if a:n == 1 Xpath 8 " X: 0 elseif a:n == 2 Xpath 16 " X: 16 elseif a:n == 3 Xpath 32 " X: 32 elseif a:n == 4 Xpath 64 " X: 64 endif return a:x endfunction function! ARG(x, n) if a:n == 1 Xpath 128 " X: 0 elseif a:n == 2 Xpath 256 " X: 0 elseif a:n == 3 Xpath 512 " X: 512 elseif a:n == 4 Xpath 1024 " X: 1024 endif return a:x endfunction function! F(x, n) if a:n == 2 Xpath 2048 " X: 0 elseif a:n == 4 Xpath 4096 " X: 4096 endif endfunction while 1 try let error = 0 let v:errmsg = "" while 1 try Xpath 8192 " X: 8192 call {NAME(THROW("name", 1), 1)}(ARG(4711, 1), 1) Xpath 16384 " X: 0 catch /^name$/ Xpath 32768 " X: 32768 catch /.*/ let error = 1 Xout "1:" v:exception "in" v:throwpoint finally if !error && $VIMNOERRTHROW && v:errmsg != "" let error = 1 Xout "1:" v:errmsg endif if error Xpath 65536 " X: 0 endif let error = 0 let v:errmsg = "" break " discard error for $VIMNOERRTHROW endtry endwhile while 1 try Xpath 131072 " X: 131072 call {NAME("F", 2)}(ARG(THROW("arg", 2), 2), 2) Xpath 262144 " X: 0 catch /^arg$/ Xpath 524288 " X: 524288 catch /.*/ let error = 1 Xout "2:" v:exception "in" v:throwpoint finally if !error && $VIMNOERRTHROW && v:errmsg != "" let error = 1 Xout "2:" v:errmsg endif if error Xpath 1048576 " X: 0 endif let error = 0 let v:errmsg = "" break " discard error for $VIMNOERRTHROW endtry endwhile while 1 try Xpath 2097152 " X: 2097152 call {NAME("THROW", 3)}(ARG("call", 3), 3) Xpath 4194304 " X: 0 catch /^call$/ Xpath 8388608 " X: 8388608 catch /^0$/ " default return value Xpath 16777216 " X: 0 Xout "3:" v:throwpoint catch /.*/ let error = 1 Xout "3:" v:exception "in" v:throwpoint finally if !error && $VIMNOERRTHROW && v:errmsg != "" let error = 1 Xout "3:" v:errmsg endif if error Xpath 33554432 " X: 0 endif let error = 0 let v:errmsg = "" break " discard error for $VIMNOERRTHROW endtry endwhile while 1 try Xpath 67108864 " X: 67108864 call {NAME("F", 4)}(ARG(4711, 4), 4) Xpath 134217728 " X: 134217728 catch /.*/ let error = 1 Xout "4:" v:exception "in" v:throwpoint finally if !error && $VIMNOERRTHROW && v:errmsg != "" let error = 1 Xout "4:" v:errmsg endif if error Xpath 268435456 " X: 0 endif let error = 0 let v:errmsg = "" break " discard error for $VIMNOERRTHROW endtry endwhile catch /^0$/ " default return value Xpath 536870912 " X: 0 Xout v:throwpoint catch /.*/ let error = 1 Xout v:exception "in" v:throwpoint finally if !error && $VIMNOERRTHROW && v:errmsg != "" let error = 1 Xout v:errmsg endif if error Xpath 1073741824 " X: 0 endif break " discard error for $VIMNOERRTHROW endtry endwhile unlet error delfunction F Xcheck 212514423 " Leave THROW(), NAME(), and ARG() for the next test. "------------------------------------------------------------------------------- " Test 68: :throw across function calls in expressions {{{1 " " On a function call within an expression, an exception might be " thrown when evaluating the function name, during evaluation of the " arguments, or when the function is being executed. The exception " can be caught by the caller. " " This test reuses the functions THROW(), NAME(), and ARG() from the " previous test. "------------------------------------------------------------------------------- XpathINIT function! F(x, n) if a:n == 2 Xpath 2048 " X: 0 elseif a:n == 4 Xpath 4096 " X: 4096 endif return a:x endfunction unlet! var1 var2 var3 var4 while 1 try let error = 0 let v:errmsg = "" while 1 try Xpath 8192 " X: 8192 let var1 = {NAME(THROW("name", 1), 1)}(ARG(4711, 1), 1) Xpath 16384 " X: 0 catch /^name$/ Xpath 32768 " X: 32768 catch /.*/ let error = 1 Xout "1:" v:exception "in" v:throwpoint finally if !error && $VIMNOERRTHROW && v:errmsg != "" let error = 1 Xout "1:" v:errmsg endif if error Xpath 65536 " X: 0 endif let error = 0 let v:errmsg = "" break " discard error for $VIMNOERRTHROW endtry endwhile while 1 try Xpath 131072 " X: 131072 let var2 = {NAME("F", 2)}(ARG(THROW("arg", 2), 2), 2) Xpath 262144 " X: 0 catch /^arg$/ Xpath 524288 " X: 524288 catch /.*/ let error = 1 Xout "2:" v:exception "in" v:throwpoint finally if !error && $VIMNOERRTHROW && v:errmsg != "" let error = 1 Xout "2:" v:errmsg endif if error Xpath 1048576 " X: 0 endif let error = 0 let v:errmsg = "" break " discard error for $VIMNOERRTHROW endtry endwhile while 1 try Xpath 2097152 " X: 2097152 let var3 = {NAME("THROW", 3)}(ARG("call", 3), 3) Xpath 4194304 " X: 0 catch /^call$/ Xpath 8388608 " X: 8388608 catch /^0$/ " default return value Xpath 16777216 " X: 0 Xout "3:" v:throwpoint catch /.*/ let error = 1 Xout "3:" v:exception "in" v:throwpoint finally if !error && $VIMNOERRTHROW && v:errmsg != "" let error = 1 Xout "3:" v:errmsg endif if error Xpath 33554432 " X: 0 endif let error = 0 let v:errmsg = "" break " discard error for $VIMNOERRTHROW endtry endwhile while 1 try Xpath 67108864 " X: 67108864 let var4 = {NAME("F", 4)}(ARG(4711, 4), 4) Xpath 134217728 " X: 134217728 catch /.*/ let error = 1 Xout "4:" v:exception "in" v:throwpoint finally if !error && $VIMNOERRTHROW && v:errmsg != "" let error = 1 Xout "4:" v:errmsg endif if error Xpath 268435456 " X: 0 endif let error = 0 let v:errmsg = "" break " discard error for $VIMNOERRTHROW endtry endwhile catch /^0$/ " default return value Xpath 536870912 " X: 0 Xout v:throwpoint catch /.*/ let error = 1 Xout v:exception "in" v:throwpoint finally if !error && $VIMNOERRTHROW && v:errmsg != "" let error = 1 Xout v:errmsg endif if error Xpath 1073741824 " X: 0 endif break " discard error for $VIMNOERRTHROW endtry endwhile if exists("var1") || exists("var2") || exists("var3") || \ !exists("var4") || var4 != 4711 " The Xpath command does not accept 2^31 (negative); add explicitly: let Xpath = Xpath + 2147483648 " X: 0 if exists("var1") Xout "var1 =" var1 endif if exists("var2") Xout "var2 =" var2 endif if exists("var3") Xout "var3 =" var3 endif if !exists("var4") Xout "var4 unset" elseif var4 != 4711 Xout "var4 =" var4 endif endif unlet! error var1 var2 var3 var4 delfunction THROW delfunction NAME delfunction ARG delfunction F Xcheck 212514423 "------------------------------------------------------------------------------- " Test 69: :throw across :if, :elseif, :while {{{1 " " On an :if, :elseif, or :while command, an exception might be thrown " during evaluation of the expression to test. The exception can be " caught by the script. "------------------------------------------------------------------------------- XpathINIT XloopINIT! 1 2 function! THROW(x) XloopNEXT Xloop 1 " X: 1 + 2 + 4 throw a:x endfunction try try Xpath 8 " X: 8 if 4711 == THROW("if") + 111 Xpath 16 " X: 0 else Xpath 32 " X: 0 endif Xpath 64 " X: 0 catch /^if$/ Xpath 128 " X: 128 catch /.*/ Xpath 256 " X: 0 Xout "if:" v:exception "in" v:throwpoint endtry try Xpath 512 " X: 512 if 4711 == 4 + 7 + 1 + 1 Xpath 1024 " X: 0 elseif 4711 == THROW("elseif") + 222 Xpath 2048 " X: 0 else Xpath 4096 " X: 0 endif Xpath 8192 " X: 0 catch /^elseif$/ Xpath 16384 " X: 16384 catch /.*/ Xpath 32768 " X: 0 Xout "elseif:" v:exception "in" v:throwpoint endtry try Xpath 65536 " X: 65536 while 4711 == THROW("while") + 4711 Xpath 131072 " X: 0 break endwhile Xpath 262144 " X: 0 catch /^while$/ Xpath 524288 " X: 524288 catch /.*/ Xpath 1048576 " X: 0 Xout "while:" v:exception "in" v:throwpoint endtry catch /^0$/ " default return value Xpath 2097152 " X: 0 Xout v:throwpoint catch /.*/ Xout v:exception "in" v:throwpoint Xpath 4194304 " X: 0 endtry Xpath 8388608 " X: 8388608 delfunction THROW Xcheck 8995471 "------------------------------------------------------------------------------- " Test 70: :throw across :return or :throw {{{1 " " On a :return or :throw command, an exception might be thrown during " evaluation of the expression to return or throw, respectively. The " exception can be caught by the script. "------------------------------------------------------------------------------- XpathINIT let taken = "" function! THROW(x, n) let g:taken = g:taken . "T" . a:n throw a:x endfunction function! F(x, y, n) let g:taken = g:taken . "F" . a:n return a:x + THROW(a:y, a:n) endfunction function! G(x, y, n) let g:taken = g:taken . "G" . a:n throw a:x . THROW(a:y, a:n) return a:x endfunction try try Xpath 1 " X: 1 call F(4711, "return", 1) Xpath 2 " X: 0 catch /^return$/ Xpath 4 " X: 4 catch /.*/ Xpath 8 " X: 0 Xout "return:" v:exception "in" v:throwpoint endtry try Xpath 16 " X: 16 let var = F(4712, "return-var", 2) Xpath 32 " X: 0 catch /^return-var$/ Xpath 64 " X: 64 catch /.*/ Xpath 128 " X: 0 Xout "return-var:" v:exception "in" v:throwpoint finally unlet! var endtry try Xpath 256 " X: 256 throw "except1" . THROW("throw1", 3) Xpath 512 " X: 0 catch /^except1/ Xpath 1024 " X: 0 catch /^throw1$/ Xpath 2048 " X: 2048 catch /.*/ Xpath 4096 " X: 0 Xout "throw1:" v:exception "in" v:throwpoint endtry try Xpath 8192 " X: 8192 call G("except2", "throw2", 4) Xpath 16384 " X: 0 catch /^except2/ Xpath 32768 " X: 0 catch /^throw2$/ Xpath 65536 " X: 65536 catch /.*/ Xpath 131072 " X: 0 Xout "throw2:" v:exception "in" v:throwpoint endtry try Xpath 262144 " X: 262144 let var = G("except3", "throw3", 5) Xpath 524288 " X: 0 catch /^except3/ Xpath 1048576 " X: 0 catch /^throw3$/ Xpath 2097152 " X: 2097152 catch /.*/ Xpath 4194304 " X: 0 Xout "throw3:" v:exception "in" v:throwpoint finally unlet! var endtry let expected = "F1T1F2T2T3G4T4G5T5" if taken != expected Xpath 8388608 " X: 0 Xout "'taken' is" taken "instead of" expected endif catch /^0$/ " default return value Xpath 16777216 " X: 0 Xout v:throwpoint catch /.*/ Xpath 33554432 " X: 0 Xout v:exception "in" v:throwpoint endtry Xpath 67108864 " X: 67108864 unlet taken expected delfunction THROW delfunction F delfunction G Xcheck 69544277 "------------------------------------------------------------------------------- " Test 71: :throw across :echo variants and :execute {{{1 " " On an :echo, :echon, :echomsg, :echoerr, or :execute command, an " exception might be thrown during evaluation of the arguments to " be displayed or executed as a command, respectively. Any following " arguments are not evaluated, then. The exception can be caught by " the script. "------------------------------------------------------------------------------- XpathINIT let taken = "" function! THROW(x, n) let g:taken = g:taken . "T" . a:n throw a:x endfunction function! F(n) let g:taken = g:taken . "F" . a:n return "F" . a:n endfunction try try Xpath 1 " X: 1 echo "echo" . THROW("echo-except", 1) F(1) Xpath 2 " X: 0 catch /^echo-except$/ Xpath 4 " X: 4 catch /.*/ Xpath 8 " X: 0 Xout "echo:" v:exception "in" v:throwpoint endtry try Xpath 16 " X: 16 echon "echon" . THROW("echon-except", 2) F(2) Xpath 32 " X: 0 catch /^echon-except$/ Xpath 64 " X: 64 catch /.*/ Xpath 128 " X: 0 Xout "echon:" v:exception "in" v:throwpoint endtry try Xpath 256 " X: 256 echomsg "echomsg" . THROW("echomsg-except", 3) F(3) Xpath 512 " X: 0 catch /^echomsg-except$/ Xpath 1024 " X: 1024 catch /.*/ Xpath 2048 " X: 0 Xout "echomsg:" v:exception "in" v:throwpoint endtry try Xpath 4096 " X: 4096 echoerr "echoerr" . THROW("echoerr-except", 4) F(4) Xpath 8192 " X: 0 catch /^echoerr-except$/ Xpath 16384 " X: 16384 catch /Vim/ Xpath 32768 " X: 0 catch /echoerr/ Xpath 65536 " X: 0 catch /.*/ Xpath 131072 " X: 0 Xout "echoerr:" v:exception "in" v:throwpoint endtry try Xpath 262144 " X: 262144 execute "echo 'execute" . THROW("execute-except", 5) F(5) "'" Xpath 524288 " X: 0 catch /^execute-except$/ Xpath 1048576 " X: 1048576 catch /.*/ Xpath 2097152 " X: 0 Xout "execute:" v:exception "in" v:throwpoint endtry let expected = "T1T2T3T4T5" if taken != expected Xpath 4194304 " X: 0 Xout "'taken' is" taken "instead of" expected endif catch /^0$/ " default return value Xpath 8388608 " X: 0 Xout v:throwpoint catch /.*/ Xpath 16777216 " X: 0 Xout v:exception "in" v:throwpoint endtry Xpath 33554432 " X: 33554432 unlet taken expected delfunction THROW delfunction F Xcheck 34886997 "------------------------------------------------------------------------------- " Test 72: :throw across :let or :unlet {{{1 " " On a :let command, an exception might be thrown during evaluation " of the expression to assign. On an :let or :unlet command, the " evaluation of the name of the variable to be assigned or list or " deleted, respectively, may throw an exception. Any following " arguments are not evaluated, then. The exception can be caught by " the script. "------------------------------------------------------------------------------- XpathINIT let throwcount = 0 function! THROW(x) let g:throwcount = g:throwcount + 1 throw a:x endfunction try try let $VAR = "old_value" Xpath 1 " X: 1 let $VAR = "let(" . THROW("var") . ")" Xpath 2 " X: 0 catch /^var$/ Xpath 4 " X: 4 finally if $VAR != "old_value" Xpath 8 " X: 0 endif endtry try let @a = "old_value" Xpath 16 " X: 16 let @a = "let(" . THROW("reg") . ")" Xpath 32 " X: 0 catch /^reg$/ try Xpath 64 " X: 64 let @A = "let(" . THROW("REG") . ")" Xpath 128 " X: 0 catch /^REG$/ Xpath 256 " X: 256 endtry finally if @a != "old_value" Xpath 512 " X: 0 endif if @A != "old_value" Xpath 1024 " X: 0 endif endtry try let saved_gpath = &g:path let saved_lpath = &l:path Xpath 2048 " X: 2048 let &path = "let(" . THROW("opt") . ")" Xpath 4096 " X: 0 catch /^opt$/ try Xpath 8192 " X: 8192 let &g:path = "let(" . THROW("gopt") . ")" Xpath 16384 " X: 0 catch /^gopt$/ try Xpath 32768 " X: 32768 let &l:path = "let(" . THROW("lopt") . ")" Xpath 65536 " X: 0 catch /^lopt$/ Xpath 131072 " X: 131072 endtry endtry finally if &g:path != saved_gpath || &l:path != saved_lpath Xpath 262144 " X: 0 endif let &g:path = saved_gpath let &l:path = saved_lpath endtry unlet! var1 var2 var3 try Xpath 524288 " X: 524288 let var1 = "let(" . THROW("var1") . ")" Xpath 1048576 " X: 0 catch /^var1$/ Xpath 2097152 " X: 2097152 finally if exists("var1") Xpath 4194304 " X: 0 endif endtry try let var2 = "old_value" Xpath 8388608 " X: 8388608 let var2 = "let(" . THROW("var2"). ")" Xpath 16777216 " X: 0 catch /^var2$/ Xpath 33554432 " X: 33554432 finally if var2 != "old_value" Xpath 67108864 " X: 0 endif endtry try Xpath 134217728 " X: 134217728 let var{THROW("var3")} = 4711 Xpath 268435456 " X: 0 catch /^var3$/ Xpath 536870912 " X: 536870912 endtry let addpath = "" function ADDPATH(p) let g:addpath = g:addpath . a:p endfunction try call ADDPATH("T1") let var{THROW("var4")} var{ADDPATH("T2")} | call ADDPATH("T3") call ADDPATH("T4") catch /^var4$/ call ADDPATH("T5") endtry try call ADDPATH("T6") unlet var{THROW("var5")} var{ADDPATH("T7")} | call ADDPATH("T8") call ADDPATH("T9") catch /^var5$/ call ADDPATH("T10") endtry if addpath != "T1T5T6T10" || throwcount != 11 throw "addpath: " . addpath . ", throwcount: " . throwcount endif Xpath 1073741824 " X: 1073741824 catch /.*/ " The Xpath command does not accept 2^31 (negative); add explicitly: let Xpath = Xpath + 2147483648 " X: 0 Xout v:exception "in" v:throwpoint endtry unlet! var1 var2 var3 addpath throwcount delfunction THROW Xcheck 1789569365 "------------------------------------------------------------------------------- " Test 73: :throw across :function, :delfunction {{{1 " " The :function and :delfunction commands may cause an expression " specified in braces to be evaluated. During evaluation, an " exception might be thrown. The exception can be caught by the " script. "------------------------------------------------------------------------------- XpathINIT let taken = "" function! THROW(x, n) let g:taken = g:taken . "T" . a:n throw a:x endfunction function! EXPR(x, n) let g:taken = g:taken . "E" . a:n if a:n % 2 == 0 call THROW(a:x, a:n) endif return 2 - a:n % 2 endfunction try try " Define function. Xpath 1 " X: 1 function! F0() endfunction Xpath 2 " X: 2 function! F{EXPR("function-def-ok", 1)}() endfunction Xpath 4 " X: 4 function! F{EXPR("function-def", 2)}() endfunction Xpath 8 " X: 0 catch /^function-def-ok$/ Xpath 16 " X: 0 catch /^function-def$/ Xpath 32 " X: 32 catch /.*/ Xpath 64 " X: 0 Xout "def:" v:exception "in" v:throwpoint endtry try " List function. Xpath 128 " X: 128 function F0 Xpath 256 " X: 256 function F{EXPR("function-lst-ok", 3)} Xpath 512 " X: 512 function F{EXPR("function-lst", 4)} Xpath 1024 " X: 0 catch /^function-lst-ok$/ Xpath 2048 " X: 0 catch /^function-lst$/ Xpath 4096 " X: 4096 catch /.*/ Xpath 8192 " X: 0 Xout "lst:" v:exception "in" v:throwpoint endtry try " Delete function Xpath 16384 " X: 16384 delfunction F0 Xpath 32768 " X: 32768 delfunction F{EXPR("function-del-ok", 5)} Xpath 65536 " X: 65536 delfunction F{EXPR("function-del", 6)} Xpath 131072 " X: 0 catch /^function-del-ok$/ Xpath 262144 " X: 0 catch /^function-del$/ Xpath 524288 " X: 524288 catch /.*/ Xpath 1048576 " X: 0 Xout "del:" v:exception "in" v:throwpoint endtry let expected = "E1E2T2E3E4T4E5E6T6" if taken != expected Xpath 2097152 " X: 0 Xout "'taken' is" taken "instead of" expected endif catch /.*/ Xpath 4194304 " X: 0 Xout v:exception "in" v:throwpoint endtry Xpath 8388608 " X: 8388608 unlet taken expected delfunction THROW delfunction EXPR Xcheck 9032615 "------------------------------------------------------------------------------- " Test 74: :throw across builtin functions and commands {{{1 " " Some functions like exists(), searchpair() take expression " arguments, other functions or commands like substitute() or " :substitute cause an expression (specified in the regular " expression) to be evaluated. During evaluation an exception " might be thrown. The exception can be caught by the script. "------------------------------------------------------------------------------- XpathINIT let taken = "" function! THROW(x, n) let g:taken = g:taken . "T" . a:n throw a:x endfunction function! EXPR(x, n) let g:taken = g:taken . "E" . a:n call THROW(a:x . a:n, a:n) return "EXPR" endfunction function! SKIP(x, n) let g:taken = g:taken . "S" . a:n . "(" . line(".") let theline = getline(".") if theline =~ "skip" let g:taken = g:taken . "s)" return 1 elseif theline =~ "throw" let g:taken = g:taken . "t)" call THROW(a:x . a:n, a:n) else let g:taken = g:taken . ")" return 0 endif endfunction function! SUBST(x, n) let g:taken = g:taken . "U" . a:n . "(" . line(".") let theline = getline(".") if theline =~ "not" " SUBST() should not be called for this line let g:taken = g:taken . "n)" call THROW(a:x . a:n, a:n) elseif theline =~ "throw" let g:taken = g:taken . "t)" call THROW(a:x . a:n, a:n) else let g:taken = g:taken . ")" return "replaced" endif endfunction try try Xpath 1 " X: 1 let result = exists('*{EXPR("exists", 1)}') Xpath 2 " X: 0 catch /^exists1$/ Xpath 4 " X: 4 try let result = exists('{EXPR("exists", 2)}') Xpath 8 " X: 0 catch /^exists2$/ Xpath 16 " X: 16 catch /.*/ Xpath 32 " X: 0 Xout "exists2:" v:exception "in" v:throwpoint endtry catch /.*/ Xpath 64 " X: 0 Xout "exists1:" v:exception "in" v:throwpoint endtry try let file = tempname() exec "edit" file insert begin xx middle 3 xx middle 5 skip xx middle 7 throw xx end . normal! gg Xpath 128 " X: 128 let result = \ searchpair("begin", "middle", "end", '', 'SKIP("searchpair", 3)') Xpath 256 " X: 256 let result = \ searchpair("begin", "middle", "end", '', 'SKIP("searchpair", 4)') Xpath 512 " X: 0 let result = \ searchpair("begin", "middle", "end", '', 'SKIP("searchpair", 5)') Xpath 1024 " X: 0 catch /^searchpair[35]$/ Xpath 2048 " X: 0 catch /^searchpair4$/ Xpath 4096 " X: 4096 catch /.*/ Xpath 8192 " X: 0 Xout "searchpair:" v:exception "in" v:throwpoint finally bwipeout! call delete(file) endtry try let file = tempname() exec "edit" file insert subst 1 subst 2 not subst 4 subst throw subst 6 . normal! gg Xpath 16384 " X: 16384 1,2substitute/subst/\=SUBST("substitute", 6)/ try Xpath 32768 " X: 32768 try let v:errmsg = "" 3substitute/subst/\=SUBST("substitute", 7)/ finally if v:errmsg != "" " If exceptions are not thrown on errors, fake the error " exception in order to get the same execution path. throw "faked Vim(substitute)" endif endtry catch /Vim(substitute)/ " Pattern not found ('e' flag missing) Xpath 65536 " X: 65536 3substitute/subst/\=SUBST("substitute", 8)/e Xpath 131072 " X: 131072 endtry Xpath 262144 " X: 262144 4,6substitute/subst/\=SUBST("substitute", 9)/ Xpath 524288 " X: 0 catch /^substitute[678]/ Xpath 1048576 " X: 0 catch /^substitute9/ Xpath 2097152 " X: 2097152 finally bwipeout! call delete(file) endtry try Xpath 4194304 " X: 4194304 let var = substitute("sub", "sub", '\=THROW("substitute()y", 10)', '') Xpath 8388608 " X: 0 catch /substitute()y/ Xpath 16777216 " X: 16777216 catch /.*/ Xpath 33554432 " X: 0 Xout "substitute()y:" v:exception "in" v:throwpoint endtry try Xpath 67108864 " X: 67108864 let var = substitute("not", "sub", '\=THROW("substitute()n", 11)', '') Xpath 134217728 " X: 134217728 catch /substitute()n/ Xpath 268435456 " X: 0 catch /.*/ Xpath 536870912 " X: 0 Xout "substitute()n:" v:exception "in" v:throwpoint endtry let expected = "E1T1E2T2S3(3)S4(5s)S4(7t)T4U6(1)U6(2)U9(4)U9(5t)T9T10" if taken != expected Xpath 1073741824 " X: 0 Xout "'taken' is" taken "instead of" expected endif catch /.*/ " The Xpath command does not accept 2^31 (negative); add explicitly: let Xpath = Xpath + 2147483648 " X: 0 Xout v:exception "in" v:throwpoint endtry unlet result var taken expected delfunction THROW delfunction EXPR delfunction SKIP delfunction SUBST Xcheck 224907669 "------------------------------------------------------------------------------- " Test 75: Errors in builtin functions. {{{1 " " On an error in a builtin function called inside a :try/:endtry " region, the evaluation of the expression calling that function and " the command containing that expression are abandoned. The error can " be caught as an exception. " " A simple :call of the builtin function is a trivial case. If the " builtin function is called in the argument list of another function, " no further arguments are evaluated, and the other function is not " executed. If the builtin function is called from the argument of " a :return command, the :return command is not executed. If the " builtin function is called from the argument of a :throw command, " the :throw command is not executed. The evaluation of the " expression calling the builtin function is abandoned. "------------------------------------------------------------------------------- XpathINIT function! F1(arg1) Xpath 1 " X: 0 endfunction function! F2(arg1, arg2) Xpath 2 " X: 0 endfunction function! G() Xpath 4 " X: 0 endfunction function! H() Xpath 8 " X: 0 endfunction function! R() while 1 try let caught = 0 let v:errmsg = "" Xpath 16 " X: 16 return append(1, "s") catch /E21/ let caught = 1 catch /.*/ Xpath 32 " X: 0 finally Xpath 64 " X: 64 if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21' Xpath 128 " X: 128 endif break " discard error for $VIMNOERRTHROW endtry endwhile Xpath 256 " X: 256 endfunction try set noma " let append() fail with "E21" while 1 try let caught = 0 let v:errmsg = "" Xpath 512 " X: 512 call append(1, "s") catch /E21/ let caught = 1 catch /.*/ Xpath 1024 " X: 0 finally Xpath 2048 " X: 2048 if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21' Xpath 4096 " X: 4096 endif break " discard error for $VIMNOERRTHROW endtry endwhile while 1 try let caught = 0 let v:errmsg = "" Xpath 8192 " X: 8192 call F1('x' . append(1, "s")) catch /E21/ let caught = 1 catch /.*/ Xpath 16384 " X: 0 finally Xpath 32768 " X: 32768 if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21' Xpath 65536 " X: 65536 endif break " discard error for $VIMNOERRTHROW endtry endwhile while 1 try let caught = 0 let v:errmsg = "" Xpath 131072 " X: 131072 call F2('x' . append(1, "s"), G()) catch /E21/ let caught = 1 catch /.*/ Xpath 262144 " X: 0 finally Xpath 524288 " X: 524288 if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21' Xpath 1048576 " X: 1048576 endif break " discard error for $VIMNOERRTHROW endtry endwhile call R() while 1 try let caught = 0 let v:errmsg = "" Xpath 2097152 " X: 2097152 throw "T" . append(1, "s") catch /E21/ let caught = 1 catch /^T.*/ Xpath 4194304 " X: 0 catch /.*/ Xpath 8388608 " X: 0 finally Xpath 16777216 " X: 16777216 if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21' Xpath 33554432 " X: 33554432 endif break " discard error for $VIMNOERRTHROW endtry endwhile while 1 try let caught = 0 let v:errmsg = "" Xpath 67108864 " X: 67108864 let x = "a" let x = x . "b" . append(1, "s") . H() catch /E21/ let caught = 1 catch /.*/ Xpath 134217728 " X: 0 finally Xpath 268435456 " X: 268435456 if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21' Xpath 536870912 " X: 536870912 endif if x == "a" Xpath 1073741824 " X: 1073741824 endif break " discard error for $VIMNOERRTHROW endtry endwhile catch /.*/ " The Xpath command does not accept 2^31 (negative); add explicitly: let Xpath = Xpath + 2147483648 " X: 0 Xout v:exception "in" v:throwpoint finally set ma& endtry unlet! caught x delfunction F1 delfunction F2 delfunction G delfunction H delfunction R Xcheck 2000403408 "------------------------------------------------------------------------------- " Test 76: Errors, interrupts, :throw during expression evaluation {{{1 " " When a function call made during expression evaluation is aborted " due to an error inside a :try/:endtry region or due to an interrupt " or a :throw, the expression evaluation is aborted as well. No " message is displayed for the cancelled expression evaluation. On an " error not inside :try/:endtry, the expression evaluation continues. "------------------------------------------------------------------------------- XpathINIT if ExtraVim() let taken = "" function! ERR(n) let g:taken = g:taken . "E" . a:n asdf endfunction function! ERRabort(n) abort let g:taken = g:taken . "A" . a:n asdf endfunction " returns -1; may cause follow-up msg for illegal var/func name function! WRAP(n, arg) let g:taken = g:taken . "W" . a:n let g:saved_errmsg = v:errmsg return arg endfunction function! INT(n) let g:taken = g:taken . "I" . a:n "INTERRUPT9 let dummy = 0 endfunction function! THR(n) let g:taken = g:taken . "T" . a:n throw "should not be caught" endfunction function! CONT(n) let g:taken = g:taken . "C" . a:n endfunction function! MSG(n) let g:taken = g:taken . "M" . a:n let errmsg = (a:n >= 37 && a:n <= 44) ? g:saved_errmsg : v:errmsg let msgptn = (a:n >= 10 && a:n <= 27) ? "^$" : "asdf" if errmsg !~ msgptn let g:taken = g:taken . "x" Xout "Expr" a:n.": Unexpected message:" v:errmsg endif let v:errmsg = "" let g:saved_errmsg = "" endfunction let v:errmsg = "" try let t = 1 XloopINIT 1 2 while t <= 9 Xloop 1 " X: 511 try if t == 1 let v{ERR(t) + CONT(t)} = 0 elseif t == 2 let v{ERR(t) + CONT(t)} elseif t == 3 let var = exists('v{ERR(t) + CONT(t)}') elseif t == 4 unlet v{ERR(t) + CONT(t)} elseif t == 5 function F{ERR(t) + CONT(t)}() endfunction elseif t == 6 function F{ERR(t) + CONT(t)} elseif t == 7 let var = exists('*F{ERR(t) + CONT(t)}') elseif t == 8 delfunction F{ERR(t) + CONT(t)} elseif t == 9 let var = ERR(t) + CONT(t) endif catch /asdf/ " v:errmsg is not set when the error message is converted to an " exception. Set it to the original error message. let v:errmsg = substitute(v:exception, '^Vim:', '', "") catch /^Vim\((\a\+)\)\=:/ " An error exception has been thrown after the original error. let v:errmsg = "" finally call MSG(t) let t = t + 1 XloopNEXT continue " discard an aborting error endtry endwhile catch /.*/ Xpath 512 " X: 0 Xout v:exception "in" ExtraVimThrowpoint() endtry try let t = 10 XloopINIT 1024 2 while t <= 18 Xloop 1 " X: 1024 * 511 try if t == 10 let v{INT(t) + CONT(t)} = 0 elseif t == 11 let v{INT(t) + CONT(t)} elseif t == 12 let var = exists('v{INT(t) + CONT(t)}') elseif t == 13 unlet v{INT(t) + CONT(t)} elseif t == 14 function F{INT(t) + CONT(t)}() endfunction elseif t == 15 function F{INT(t) + CONT(t)} elseif t == 16 let var = exists('*F{INT(t) + CONT(t)}') elseif t == 17 delfunction F{INT(t) + CONT(t)} elseif t == 18 let var = INT(t) + CONT(t) endif catch /^Vim\((\a\+)\)\=:\(Interrupt\)\@!/ " An error exception has been triggered after the interrupt. let v:errmsg = substitute(v:exception, \ '^Vim\((\a\+)\)\=:', '', "") finally call MSG(t) let t = t + 1 XloopNEXT continue " discard interrupt endtry endwhile catch /.*/ Xpath 524288 " X: 0 Xout v:exception "in" ExtraVimThrowpoint() endtry try let t = 19 XloopINIT 1048576 2 while t <= 27 Xloop 1 " X: 1048576 * 511 try if t == 19 let v{THR(t) + CONT(t)} = 0 elseif t == 20 let v{THR(t) + CONT(t)} elseif t == 21 let var = exists('v{THR(t) + CONT(t)}') elseif t == 22 unlet v{THR(t) + CONT(t)} elseif t == 23 function F{THR(t) + CONT(t)}() endfunction elseif t == 24 function F{THR(t) + CONT(t)} elseif t == 25 let var = exists('*F{THR(t) + CONT(t)}') elseif t == 26 delfunction F{THR(t) + CONT(t)} elseif t == 27 let var = THR(t) + CONT(t) endif catch /^Vim\((\a\+)\)\=:/ " An error exception has been triggered after the :throw. let v:errmsg = substitute(v:exception, \ '^Vim\((\a\+)\)\=:', '', "") finally call MSG(t) let t = t + 1 XloopNEXT continue " discard exception endtry endwhile catch /.*/ Xpath 536870912 " X: 0 Xout v:exception "in" ExtraVimThrowpoint() endtry let v{ERR(28) + CONT(28)} = 0 call MSG(28) let v{ERR(29) + CONT(29)} call MSG(29) let var = exists('v{ERR(30) + CONT(30)}') call MSG(30) unlet v{ERR(31) + CONT(31)} call MSG(31) function F{ERR(32) + CONT(32)}() endfunction call MSG(32) function F{ERR(33) + CONT(33)} call MSG(33) let var = exists('*F{ERR(34) + CONT(34)}') call MSG(34) delfunction F{ERR(35) + CONT(35)} call MSG(35) let var = ERR(36) + CONT(36) call MSG(36) let saved_errmsg = "" let v{WRAP(37, ERRabort(37)) + CONT(37)} = 0 call MSG(37) let v{WRAP(38, ERRabort(38)) + CONT(38)} call MSG(38) let var = exists('v{WRAP(39, ERRabort(39)) + CONT(39)}') call MSG(39) unlet v{WRAP(40, ERRabort(40)) + CONT(40)} call MSG(40) function F{WRAP(41, ERRabort(41)) + CONT(41)}() endfunction call MSG(41) function F{WRAP(42, ERRabort(42)) + CONT(42)} call MSG(42) let var = exists('*F{WRAP(43, ERRabort(43)) + CONT(43)}') call MSG(43) delfunction F{WRAP(44, ERRabort(44)) + CONT(44)} call MSG(44) let var = ERRabort(45) + CONT(45) call MSG(45) Xpath 1073741824 " X: 1073741824 let expected = "" \ . "E1M1E2M2E3M3E4M4E5M5E6M6E7M7E8M8E9M9" \ . "I10M10I11M11I12M12I13M13I14M14I15M15I16M16I17M17I18M18" \ . "T19M19T20M20T21M21T22M22T23M23T24M24T25M25T26M26T27M27" \ . "E28C28M28E29C29M29E30C30M30E31C31M31E32C32M32E33C33M33" \ . "E34C34M34E35C35M35E36C36M36" \ . "A37W37C37M37A38W38C38M38A39W39C39M39A40W40C40M40A41W41C41M41" \ . "A42W42C42M42A43W43C43M43A44W44C44M44A45C45M45" if taken != expected " The Xpath command does not accept 2^31 (negative); display explicitly: exec "!echo 2147483648 >>" . g:ExtraVimResult " X: 0 Xout "'taken' is" taken "instead of" expected if substitute(taken, \ '\(.*\)E3C3M3x\(.*\)E30C30M30x\(.*\)A39C39M39x\(.*\)', \ '\1E3M3\2E30C30M30\3A39C39M39\4', \ "") == expected Xout "Is ++emsg_skip for var with expr_start non-NULL" \ "in f_exists ok?" endif endif unlet! v var saved_errmsg taken expected call delete(WA_t5) call delete(WA_t14) call delete(WA_t23) unlet! WA_t5 WA_t14 WA_t23 delfunction WA_t5 delfunction WA_t14 delfunction WA_t23 endif Xcheck 1610087935 "------------------------------------------------------------------------------- " Test 77: Errors, interrupts, :throw in name{brace-expression} {{{1 " " When a function call made during evaluation of an expression in " braces as part of a function name after ":function" is aborted due " to an error inside a :try/:endtry region or due to an interrupt or " a :throw, the expression evaluation is aborted as well, and the " function definition is ignored, skipping all commands to the " ":endfunction". On an error not inside :try/:endtry, the expression " evaluation continues and the function gets defined, and can be " called and deleted. "------------------------------------------------------------------------------- XpathINIT XloopINIT 1 4 function! ERR() abort Xloop 1 " X: 1 + 4 + 16 + 64 asdf endfunction " returns -1 function! OK() Xloop 2 " X: 2 * (1 + 4 + 16) let v:errmsg = "" return 0 endfunction let v:errmsg = "" Xpath 4096 " X: 4096 function! F{1 + ERR() + OK()}(arg) " F0 should be defined. if exists("a:arg") && a:arg == "calling" Xpath 8192 " X: 8192 else Xpath 16384 " X: 0 endif endfunction if v:errmsg != "" Xpath 32768 " X: 0 endif XloopNEXT Xpath 65536 " X: 65536 call F{1 + ERR() + OK()}("calling") if v:errmsg != "" Xpath 131072 " X: 0 endif XloopNEXT Xpath 262144 " X: 262144 delfunction F{1 + ERR() + OK()} if v:errmsg != "" Xpath 524288 " X: 0 endif XloopNEXT try while 1 let caught = 0 try Xpath 1048576 " X: 1048576 function! G{1 + ERR() + OK()}(arg) " G0 should not be defined, and the function body should be " skipped. if exists("a:arg") && a:arg == "calling" Xpath 2097152 " X: 0 else Xpath 4194304 " X: 0 endif " Use an unmatched ":finally" to check whether the body is " skipped when an error occurs in ERR(). This works whether or " not the exception is converted to an exception. finally Xpath 8388608 " X: 0 Xout "Body of G{1 + ERR() + OK()}() not skipped" " Discard the aborting error or exception, and break the " while loop. break " End the try conditional and start a new one to avoid " ":catch after :finally" errors. endtry try Xpath 16777216 " X: 0 endfunction " When the function was not defined, this won't be reached - whether " the body was skipped or not. When the function was defined, it " can be called and deleted here. Xpath 33554432 " X: 0 Xout "G0() has been defined" XloopNEXT try call G{1 + ERR() + OK()}("calling") catch /.*/ Xpath 67108864 " X: 0 endtry Xpath 134217728 " X: 0 XloopNEXT try delfunction G{1 + ERR() + OK()} catch /.*/ Xpath 268435456 " X: 0 endtry catch /asdf/ " Jumped to when the function is not defined and the body is " skipped. let caught = 1 catch /.*/ Xpath 536870912 " X: 0 finally if !caught && !$VIMNOERRTHROW Xpath 1073741824 " X: 0 endif break " discard error for $VIMNOERRTHROW endtry " jumped to when the body is not skipped endwhile catch /.*/ " The Xpath command does not accept 2^31 (negative); add explicitly: let Xpath = Xpath + 2147483648 " X: 0 Xout "Body of G{1 + ERR() + OK()}() not skipped, exception caught" Xout v:exception "in" v:throwpoint endtry Xcheck 1388671 "------------------------------------------------------------------------------- " Test 78: Messages on parsing errors in expression evaluation {{{1 " " When an expression evaluation detects a parsing error, an error " message is given and converted to an exception, and the expression " evaluation is aborted. "------------------------------------------------------------------------------- XpathINIT if ExtraVim() let taken = "" function! F(n) let g:taken = g:taken . "F" . a:n endfunction function! MSG(n, enr, emsg) let g:taken = g:taken . "M" . a:n let english = v:lang == "C" || v:lang =~ '^[Ee]n' if a:enr == "" Xout "TODO: Add message number for:" a:emsg let v:errmsg = ":" . v:errmsg endif if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg) if v:errmsg == "" Xout "Expr" a:n.": Message missing." let g:taken = g:taken . "x" else let v:errmsg = escape(v:errmsg, '"') Xout "Expr" a:n.": Unexpected message:" v:errmsg Xout "Expected: " . a:enr . ': ' . a:emsg let g:taken = g:taken . "X" endif endif endfunction function! CONT(n) let g:taken = g:taken . "C" . a:n endfunction let v:errmsg = "" XloopINIT 1 2 try let t = 1 while t <= 14 let g:taken = g:taken . "T" . t let v:errmsg = "" try let caught = 0 if t == 1 let v{novar + CONT(t)} = 0 elseif t == 2 let v{novar + CONT(t)} elseif t == 3 let var = exists('v{novar + CONT(t)}') elseif t == 4 unlet v{novar + CONT(t)} elseif t == 5 function F{novar + CONT(t)}() endfunction elseif t == 6 function F{novar + CONT(t)} elseif t == 7 let var = exists('*F{novar + CONT(t)}') elseif t == 8 delfunction F{novar + CONT(t)} elseif t == 9 echo novar + CONT(t) elseif t == 10 echo v{novar + CONT(t)} elseif t == 11 echo F{novar + CONT(t)} elseif t == 12 let var = novar + CONT(t) elseif t == 13 let var = v{novar + CONT(t)} elseif t == 14 let var = F{novar + CONT(t)}() endif catch /^Vim\((\a\+)\)\=:/ " v:errmsg is not set when the error message is converted to an " exception. Set it to the original error message. let v:errmsg = substitute(v:exception, \ '^Vim\((\a\+)\)\=:', '', "") let caught = 1 finally if t <= 8 && t != 3 && t != 7 call MSG(t, 'E475', 'Invalid argument\>') else if !caught " no error exceptions ($VIMNOERRTHROW set) call MSG(t, 'E15', "Invalid expression") else call MSG(t, 'E121', "Undefined variable") endif endif let t = t + 1 XloopNEXT continue " discard an aborting error endtry endwhile catch /.*/ Xloop 1 " X: 0 Xout t.":" v:exception "in" ExtraVimThrowpoint() endtry function! T(n, expr, enr, emsg) try let g:taken = g:taken . "T" . a:n let v:errmsg = "" try let caught = 0 execute "let var = " . a:expr catch /^Vim\((\a\+)\)\=:/ " v:errmsg is not set when the error message is converted to an " exception. Set it to the original error message. let v:errmsg = substitute(v:exception, \ '^Vim\((\a\+)\)\=:', '', "") let caught = 1 finally if !caught " no error exceptions ($VIMNOERRTHROW set) call MSG(a:n, 'E15', "Invalid expression") else call MSG(a:n, a:enr, a:emsg) endif XloopNEXT " Discard an aborting error: return endtry catch /.*/ Xloop 1 " X: 0 Xout a:n.":" v:exception "in" ExtraVimThrowpoint() endtry endfunction call T(15, 'Nofunc() + CONT(15)', 'E117', "Unknown function") call T(16, 'F(1 2 + CONT(16))', 'E116', "Invalid arguments") call T(17, 'F(1, 2) + CONT(17)', 'E118', "Too many arguments") call T(18, 'F() + CONT(18)', 'E119', "Not enough arguments") call T(19, '{(1} + CONT(19)', 'E110', "Missing ')'") call T(20, '("abc"[1) + CONT(20)', 'E111', "Missing ']'") call T(21, '(1 +) + CONT(21)', 'E15', "Invalid expression") call T(22, '1 2 + CONT(22)', 'E15', "Invalid expression") call T(23, '(1 ? 2) + CONT(23)', 'E109', "Missing ':' after '?'") call T(24, '("abc) + CONT(24)', 'E114', "Missing quote") call T(25, "('abc) + CONT(25)", 'E115', "Missing quote") call T(26, '& + CONT(26)', 'E112', "Option name missing") call T(27, '&asdf + CONT(27)', 'E113', "Unknown option") Xpath 134217728 " X: 134217728 let expected = "" \ . "T1M1T2M2T3M3T4M4T5M5T6M6T7M7T8M8T9M9T10M10T11M11T12M12T13M13T14M14" \ . "T15M15T16M16T17M17T18M18T19M19T20M20T21M21T22M22T23M23T24M24T25M25" \ . "T26M26T27M27" if taken != expected Xpath 268435456 " X: 0 Xout "'taken' is" taken "instead of" expected if substitute(taken, '\(.*\)T3M3x\(.*\)', '\1T3M3\2', "") == expected Xout "Is ++emsg_skip for var with expr_start non-NULL" \ "in f_exists ok?" endif endif unlet! var caught taken expected call delete(WA_t5) unlet! WA_t5 delfunction WA_t5 endif Xcheck 134217728 "------------------------------------------------------------------------------- " Test 79: Throwing one of several errors for the same command {{{1 " " When several errors appear in a row (for instance during expression " evaluation), the first as the most specific one is used when " throwing an error exception. If, however, a syntax error is " detected afterwards, this one is used for the error exception. " On a syntax error, the next command is not executed, on a normal " error, however, it is (relevant only in a function without the " "abort" flag). v:errmsg is not set. " " If throwing error exceptions is configured off, v:errmsg is always " set to the latest error message, that is, to the more general " message or the syntax error, respectively. "------------------------------------------------------------------------------- XpathINIT XloopINIT 1 2 function! NEXT(cmd) exec a:cmd . " | Xloop 1" endfunction call NEXT('echo novar') " X: 1 * 1 (checks nextcmd) XloopNEXT call NEXT('let novar #') " X: 0 * 2 (skips nextcmd) XloopNEXT call NEXT('unlet novar #') " X: 0 * 4 (skips nextcmd) XloopNEXT call NEXT('let {novar}') " X: 0 * 8 (skips nextcmd) XloopNEXT call NEXT('unlet{ novar}') " X: 0 * 16 (skips nextcmd) function! EXEC(cmd) exec a:cmd endfunction function! MATCH(expected, msg, enr, emsg) let msg = a:msg if a:enr == "" Xout "TODO: Add message number for:" a:emsg let msg = ":" . msg endif let english = v:lang == "C" || v:lang =~ '^[Ee]n' if msg !~ '^'.a:enr.':' || (english && msg !~ a:emsg) let match = 0 if a:expected " no match although expected if a:msg == "" Xout "Message missing." else let msg = escape(msg, '"') Xout "Unexpected message:" msg Xout "Expected:" a:enr . ": " . a:emsg endif endif else let match = 1 if !a:expected " match although not expected let msg = escape(msg, '"') Xout "Unexpected message:" msg Xout "Expected none." endif endif return match endfunction try while 1 " dummy loop try let v:errmsg = "" let caught = 0 let thrmsg = "" call EXEC('echo novar') " normal error catch /^Vim\((\a\+)\)\=:/ let caught = 1 let thrmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "") finally Xpath 32 " X: 32 if !caught if !$VIMNOERRTHROW Xpath 64 " X: 0 endif elseif !MATCH(1, thrmsg, 'E121', "Undefined variable") \ || v:errmsg != "" Xpath 128 " X: 0 endif if !caught && !MATCH(1, v:errmsg, 'E15', "Invalid expression") Xpath 256 " X: 0 endif break " discard error if $VIMNOERRTHROW == 1 endtry endwhile Xpath 512 " X: 512 let cmd = "let" XloopINIT 1024 32 while cmd != "" try let v:errmsg = "" let caught = 0 let thrmsg = "" call EXEC(cmd . ' novar #') " normal plus syntax error catch /^Vim\((\a\+)\)\=:/ let caught = 1 let thrmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "") finally Xloop 1 " X: 1024 * (1 + 32) if !caught if !$VIMNOERRTHROW Xloop 2 " X: 0 endif else if cmd == "let" let match = MATCH(0, thrmsg, 'E121', "Undefined variable") elseif cmd == "unlet" let match = MATCH(0, thrmsg, 'E108', "No such variable") endif if match " normal error Xloop 4 " X: 0 endif if !MATCH(1, thrmsg, 'E488', "Trailing characters") \|| v:errmsg != "" " syntax error Xloop 8 " X: 0 endif endif if !caught && !MATCH(1, v:errmsg, 'E488', "Trailing characters") " last error Xloop 16 " X: 0 endif if cmd == "let" let cmd = "unlet" else let cmd = "" endif XloopNEXT continue " discard error if $VIMNOERRTHROW == 1 endtry endwhile Xpath 1048576 " X: 1048576 let cmd = "let" XloopINIT 2097152 32 while cmd != "" try let v:errmsg = "" let caught = 0 let thrmsg = "" call EXEC(cmd . ' {novar}') " normal plus syntax error catch /^Vim\((\a\+)\)\=:/ let caught = 1 let thrmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "") finally Xloop 1 " X: 2097152 * (1 + 32) if !caught if !$VIMNOERRTHROW Xloop 2 " X: 0 endif else if MATCH(0, thrmsg, 'E121', "Undefined variable") " normal error Xloop 4 " X: 0 endif if !MATCH(1, thrmsg, 'E475', 'Invalid argument\>') \ || v:errmsg != "" " syntax error Xloop 8 " X: 0 endif endif if !caught && !MATCH(1, v:errmsg, 'E475', 'Invalid argument\>') " last error Xloop 16 " X: 0 endif if cmd == "let" let cmd = "unlet" else let cmd = "" endif XloopNEXT continue " discard error if $VIMNOERRTHROW == 1 endtry endwhile catch /.*/ " The Xpath command does not accept 2^31 (negative); add explicitly: let Xpath = Xpath + 2147483648 " X: 0 Xout v:exception "in" v:throwpoint endtry unlet! next_command thrmsg match delfunction NEXT delfunction EXEC delfunction MATCH Xcheck 70288929 "------------------------------------------------------------------------------- " Test 80: Syntax error in expression for illegal :elseif {{{1 " " If there is a syntax error in the expression after an illegal " :elseif, an error message is given (or an error exception thrown) " for the illegal :elseif rather than the expression error. "------------------------------------------------------------------------------- XpathINIT function! MSG(enr, emsg) let english = v:lang == "C" || v:lang =~ '^[Ee]n' if a:enr == "" Xout "TODO: Add message number for:" a:emsg let v:errmsg = ":" . v:errmsg endif let match = 1 if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg) let match = 0 if v:errmsg == "" Xout "Message missing." else let v:errmsg = escape(v:errmsg, '"') Xout "Unexpected message:" v:errmsg endif endif return match endfunction let v:errmsg = "" if 0 else elseif 1 ||| 2 endif Xpath 1 " X: 1 if !MSG('E584', ":elseif after :else") Xpath 2 " X: 0 endif let v:errmsg = "" if 1 else elseif 1 ||| 2 endif Xpath 4 " X: 4 if !MSG('E584', ":elseif after :else") Xpath 8 " X: 0 endif let v:errmsg = "" elseif 1 ||| 2 Xpath 16 " X: 16 if !MSG('E582', ":elseif without :if") Xpath 32 " X: 0 endif let v:errmsg = "" while 1 elseif 1 ||| 2 endwhile Xpath 64 " X: 64 if !MSG('E582', ":elseif without :if") Xpath 128 " X: 0 endif while 1 try try let v:errmsg = "" let caught = 0 if 0 else elseif 1 ||| 2 endif catch /^Vim\((\a\+)\)\=:/ let caught = 1 let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "") finally Xpath 256 " X: 256 if !caught && !$VIMNOERRTHROW Xpath 512 " X: 0 endif if !MSG('E584', ":elseif after :else") Xpath 1024 " X: 0 endif endtry catch /.*/ Xpath 2048 " X: 0 Xout v:exception "in" v:throwpoint finally break " discard error for $VIMNOERRTHROW endtry endwhile while 1 try try let v:errmsg = "" let caught = 0 if 1 else elseif 1 ||| 2 endif catch /^Vim\((\a\+)\)\=:/ let caught = 1 let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "") finally Xpath 4096 " X: 4096 if !caught && !$VIMNOERRTHROW Xpath 8192 " X: 0 endif if !MSG('E584', ":elseif after :else") Xpath 16384 " X: 0 endif endtry catch /.*/ Xpath 32768 " X: 0 Xout v:exception "in" v:throwpoint finally break " discard error for $VIMNOERRTHROW endtry endwhile while 1 try try let v:errmsg = "" let caught = 0 elseif 1 ||| 2 catch /^Vim\((\a\+)\)\=:/ let caught = 1 let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "") finally Xpath 65536 " X: 65536 if !caught && !$VIMNOERRTHROW Xpath 131072 " X: 0 endif if !MSG('E582', ":elseif without :if") Xpath 262144 " X: 0 endif endtry catch /.*/ Xpath 524288 " X: 0 Xout v:exception "in" v:throwpoint finally break " discard error for $VIMNOERRTHROW endtry endwhile while 1 try try let v:errmsg = "" let caught = 0 while 1 elseif 1 ||| 2 endwhile catch /^Vim\((\a\+)\)\=:/ let caught = 1 let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "") finally Xpath 1048576 " X: 1048576 if !caught && !$VIMNOERRTHROW Xpath 2097152 " X: 0 endif if !MSG('E582', ":elseif without :if") Xpath 4194304 " X: 0 endif endtry catch /.*/ Xpath 8388608 " X: 0 Xout v:exception "in" v:throwpoint finally break " discard error for $VIMNOERRTHROW endtry endwhile Xpath 16777216 " X: 16777216 unlet! caught delfunction MSG Xcheck 17895765 "------------------------------------------------------------------------------- " Test 81: Discarding exceptions after an error or interrupt {{{1 " " When an exception is thrown from inside a :try conditional without " :catch and :finally clauses and an error or interrupt occurs before " the :endtry is reached, the exception is discarded. "------------------------------------------------------------------------------- XpathINIT if ExtraVim() try Xpath 1 " X: 1 try Xpath 2 " X: 2 throw "arrgh" Xpath 4 " X: 0 " if 1 Xpath 8 " X: 0 " error after :throw: missing :endif endtry Xpath 16 " X: 0 catch /arrgh/ Xpath 32 " X: 0 endtry Xpath 64 " X: 0 endif if ExtraVim() try Xpath 128 " X: 128 try Xpath 256 " X: 256 throw "arrgh" Xpath 512 " X: 0 endtry " INTERRUPT Xpath 1024 " X: 0 catch /arrgh/ Xpath 2048 " X: 0 endtry Xpath 4096 " X: 0 endif Xcheck 387 "------------------------------------------------------------------------------- " Test 82: Ignoring :catch clauses after an error or interrupt {{{1 " " When an exception is thrown and an error or interrupt occurs before " the matching :catch clause is reached, the exception is discarded " and the :catch clause is ignored (also for the error or interrupt " exception being thrown then). "------------------------------------------------------------------------------- XpathINIT if ExtraVim() try try Xpath 1 " X: 1 throw "arrgh" Xpath 2 " X: 0 " if 1 Xpath 4 " X: 0 " error after :throw: missing :endif catch /.*/ Xpath 8 " X: 0 Xout v:exception "in" ExtraVimThrowpoint() catch /.*/ Xpath 16 " X: 0 Xout v:exception "in" ExtraVimThrowpoint() endtry Xpath 32 " X: 0 catch /arrgh/ Xpath 64 " X: 0 endtry Xpath 128 " X: 0 endif if ExtraVim() function! E() try try Xpath 256 " X: 256 throw "arrgh" Xpath 512 " X: 0 " if 1 Xpath 1024 " X: 0 " error after :throw: missing :endif catch /.*/ Xpath 2048 " X: 0 Xout v:exception "in" ExtraVimThrowpoint() catch /.*/ Xpath 4096 " X: 0 Xout v:exception "in" ExtraVimThrowpoint() endtry Xpath 8192 " X: 0 catch /arrgh/ Xpath 16384 " X: 0 endtry endfunction call E() Xpath 32768 " X: 0 endif if ExtraVim() try try Xpath 65536 " X: 65536 throw "arrgh" Xpath 131072 " X: 0 catch /.*/ "INTERRUPT Xpath 262144 " X: 0 Xout v:exception "in" ExtraVimThrowpoint() catch /.*/ Xpath 524288 " X: 0 Xout v:exception "in" ExtraVimThrowpoint() endtry Xpath 1048576 " X: 0 catch /arrgh/ Xpath 2097152 " X: 0 endtry Xpath 4194304 " X: 0 endif if ExtraVim() function I() try try Xpath 8388608 " X: 8388608 throw "arrgh" Xpath 16777216 " X: 0 catch /.*/ "INTERRUPT Xpath 33554432 " X: 0 Xout v:exception "in" ExtraVimThrowpoint() catch /.*/ Xpath 67108864 " X: 0 Xout v:exception "in" ExtraVimThrowpoint() endtry Xpath 134217728 " X: 0 catch /arrgh/ Xpath 268435456 " X: 0 endtry endfunction call I() Xpath 536870912 " X: 0 endif Xcheck 8454401 "------------------------------------------------------------------------------- " Test 83: Executing :finally clauses after an error or interrupt {{{1 " " When an exception is thrown and an error or interrupt occurs before " the :finally of the innermost :try is reached, the exception is " discarded and the :finally clause is executed. "------------------------------------------------------------------------------- XpathINIT if ExtraVim() try Xpath 1 " X: 1 try Xpath 2 " X: 2 throw "arrgh" Xpath 4 " X: 0 " if 1 Xpath 8 " X: 0 " error after :throw: missing :endif finally Xpath 16 " X: 16 endtry Xpath 32 " X: 0 catch /arrgh/ Xpath 64 " X: 0 endtry Xpath 128 " X: 0 endif if ExtraVim() try Xpath 256 " X: 256 try Xpath 512 " X: 512 throw "arrgh" Xpath 1024 " X: 0 finally "INTERRUPT Xpath 2048 " X: 2048 endtry Xpath 4096 " X: 0 catch /arrgh/ Xpath 8192 " X: 0 endtry Xpath 16384 " X: 0 endif Xcheck 2835 "------------------------------------------------------------------------------- " Test 84: Exceptions in autocommand sequences. {{{1 " " When an exception occurs in a sequence of autocommands for " a specific event, the rest of the sequence is not executed. The " command that triggered the autocommand execution aborts, and the " exception is propagated to the caller. " " For the FuncUndefined event under a function call expression or " :call command, the function is not executed, even when it has " been defined by the autocommands before the exception occurred. "------------------------------------------------------------------------------- XpathINIT if ExtraVim() function! INT() "INTERRUPT let dummy = 0 endfunction aug TMP autocmd! autocmd User x1 Xpath 1 " X: 1 autocmd User x1 throw "x1" autocmd User x1 Xpath 2 " X: 0 autocmd User x2 Xpath 4 " X: 4 autocmd User x2 asdf autocmd User x2 Xpath 8 " X: 0 autocmd User x3 Xpath 16 " X: 16 autocmd User x3 call INT() autocmd User x3 Xpath 32 " X: 0 autocmd FuncUndefined U1 function! U1() autocmd FuncUndefined U1 Xpath 64 " X: 0 autocmd FuncUndefined U1 endfunction autocmd FuncUndefined U1 Xpath 128 " X: 128 autocmd FuncUndefined U1 throw "U1" autocmd FuncUndefined U1 Xpath 256 " X: 0 autocmd FuncUndefined U2 function! U2() autocmd FuncUndefined U2 Xpath 512 " X: 0 autocmd FuncUndefined U2 endfunction autocmd FuncUndefined U2 Xpath 1024 " X: 1024 autocmd FuncUndefined U2 ASDF autocmd FuncUndefined U2 Xpath 2048 " X: 0 autocmd FuncUndefined U3 function! U3() autocmd FuncUndefined U3 Xpath 4096 " X: 0 autocmd FuncUndefined U3 endfunction autocmd FuncUndefined U3 Xpath 8192 " X: 8192 autocmd FuncUndefined U3 call INT() autocmd FuncUndefined U3 Xpath 16384 " X: 0 aug END try try Xpath 32768 " X: 32768 doautocmd User x1 catch /x1/ Xpath 65536 " X: 65536 endtry while 1 try Xpath 131072 " X: 131072 let caught = 0 doautocmd User x2 catch /asdf/ let caught = 1 finally Xpath 262144 " X: 262144 if !caught && !$VIMNOERRTHROW Xpath 524288 " X: 0 " Propagate uncaught error exception, else " ... but break loop for caught error exception, " or discard error and break loop if $VIMNOERRTHROW break endif endtry endwhile while 1 try Xpath 1048576 " X: 1048576 let caught = 0 doautocmd User x3 catch /Vim:Interrupt/ let caught = 1 finally Xpath 2097152 " X: 2097152 if !caught && !$VIMNOINTTHROW Xpath 4194304 " X: 0 " Propagate uncaught interrupt exception, else " ... but break loop for caught interrupt exception, " or discard interrupt and break loop if $VIMNOINTTHROW break endif endtry endwhile if exists("*U1") | delfunction U1 | endif if exists("*U2") | delfunction U2 | endif if exists("*U3") | delfunction U3 | endif try Xpath 8388608 " X: 8388608 call U1() catch /U1/ Xpath 16777216 " X: 16777216 endtry while 1 try Xpath 33554432 " X: 33554432 let caught = 0 call U2() catch /ASDF/ let caught = 1 finally Xpath 67108864 " X: 67108864 if !caught && !$VIMNOERRTHROW Xpath 134217728 " X: 0 " Propagate uncaught error exception, else " ... but break loop for caught error exception, " or discard error and break loop if $VIMNOERRTHROW break endif endtry endwhile while 1 try Xpath 268435456 " X: 268435456 let caught = 0 call U3() catch /Vim:Interrupt/ let caught = 1 finally Xpath 536870912 " X: 536870912 if !caught && !$VIMNOINTTHROW Xpath 1073741824 " X: 0 " Propagate uncaught interrupt exception, else " ... but break loop for caught interrupt exception, " or discard interrupt and break loop if $VIMNOINTTHROW break endif endtry endwhile catch /.*/ " The Xpath command does not accept 2^31 (negative); display explicitly: exec "!echo 2147483648 >>" . g:ExtraVimResult Xout "Caught" v:exception "in" v:throwpoint endtry unlet caught delfunction INT delfunction U1 delfunction U2 delfunction U3 au! TMP aug! TMP endif Xcheck 934782101 "------------------------------------------------------------------------------- " Test 85: Error exceptions in autocommands for I/O command events {{{1 " " When an I/O command is inside :try/:endtry, autocommands to be " executed after it should be skipped on an error (exception) in the " command itself or in autocommands to be executed before the command. " In the latter case, the I/O command should not be executed either. " Example 1: BufWritePre, :write, BufWritePost " Example 2: FileReadPre, :read, FileReadPost. "------------------------------------------------------------------------------- XpathINIT function! MSG(enr, emsg) let english = v:lang == "C" || v:lang =~ '^[Ee]n' if a:enr == "" Xout "TODO: Add message number for:" a:emsg let v:errmsg = ":" . v:errmsg endif let match = 1 if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg) let match = 0 if v:errmsg == "" Xout "Message missing." else let v:errmsg = escape(v:errmsg, '"') Xout "Unexpected message:" v:errmsg endif endif return match endfunction " Remove the autocommands for the events specified as arguments in all used " autogroups. function! Delete_autocommands(...) let augfile = tempname() while 1 try exec "redir >" . augfile aug redir END exec "edit" augfile g/^$/d norm G$ let wrap = "w" while search('\%( \|^\)\@<=.\{-}\%( \)\@=', wrap) > 0 let wrap = "W" exec "norm y/ \n" let argno = 1 while argno <= a:0 exec "au!" escape(@", " ") a:{argno} let argno = argno + 1 endwhile endwhile catch /.*/ finally bwipeout! call delete(augfile) break " discard errors for $VIMNOERRTHROW endtry endwhile endfunction call Delete_autocommands("BufWritePre", "BufWritePost") while 1 try try let post = 0 aug TMP au! BufWritePost * let post = 1 aug END let caught = 0 write /n/o/n/e/x/i/s/t/e/n/t catch /^Vim(write):/ let caught = 1 let v:errmsg = substitute(v:exception, '^Vim(write):', '', "") finally Xpath 1 " X: 1 if !caught && !$VIMNOERRTHROW Xpath 2 " X: 0 endif let v:errmsg = substitute(v:errmsg, '^"/n/o/n/e/x/i/s/t/e/n/t" ', \ '', "") if !MSG('E212', "Can't open file for writing") Xpath 4 " X: 0 endif if post Xpath 8 " X: 0 Xout "BufWritePost commands executed after write error" endif au! TMP aug! TMP endtry catch /.*/ Xpath 16 " X: 0 Xout v:exception "in" v:throwpoint finally break " discard error for $VIMNOERRTHROW endtry endwhile while 1 try try let post = 0 aug TMP au! BufWritePre * asdf au! BufWritePost * let post = 1 aug END let tmpfile = tempname() let caught = 0 exec "write" tmpfile catch /^Vim\((write)\)\=:/ let caught = 1 let v:errmsg = substitute(v:exception, '^Vim\((write)\)\=:', '', "") finally Xpath 32 " X: 32 if !caught && !$VIMNOERRTHROW Xpath 64 " X: 0 endif let v:errmsg = substitute(v:errmsg, '^"'.tmpfile.'" ', '', "") if !MSG('E492', "Not an editor command") Xpath 128 " X: 0 endif if filereadable(tmpfile) Xpath 256 " X: 0 Xout ":write command not suppressed after BufWritePre error" endif if post Xpath 512 " X: 0 Xout "BufWritePost commands executed after BufWritePre error" endif au! TMP aug! TMP endtry catch /.*/ Xpath 1024 " X: 0 Xout v:exception "in" v:throwpoint finally break " discard error for $VIMNOERRTHROW endtry endwhile call delete(tmpfile) call Delete_autocommands("BufWritePre", "BufWritePost", \ "BufReadPre", "BufReadPost", "FileReadPre", "FileReadPost") while 1 try try let post = 0 aug TMP au! FileReadPost * let post = 1 aug END let caught = 0 read /n/o/n/e/x/i/s/t/e/n/t catch /^Vim(read):/ let caught = 1 let v:errmsg = substitute(v:exception, '^Vim(read):', '', "") finally Xpath 2048 " X: 2048 if !caught && !$VIMNOERRTHROW Xpath 4096 " X: 0 endif let v:errmsg = substitute(v:errmsg, ' /n/o/n/e/x/i/s/t/e/n/t$', \ '', "") if !MSG('E484', "Can't open file") Xpath 8192 " X: 0 endif if post Xpath 16384 " X: 0 Xout "FileReadPost commands executed after write error" endif au! TMP aug! TMP endtry catch /.*/ Xpath 32768 " X: 0 Xout v:exception "in" v:throwpoint finally break " discard error for $VIMNOERRTHROW endtry endwhile while 1 try let infile = tempname() let tmpfile = tempname() exec "!echo XYZ >" . infile exec "edit" tmpfile try Xpath 65536 " X: 65536 try let post = 0 aug TMP au! FileReadPre * asdf au! FileReadPost * let post = 1 aug END let caught = 0 exec "0read" infile catch /^Vim\((read)\)\=:/ let caught = 1 let v:errmsg = substitute(v:exception, '^Vim\((read)\)\=:', '', \ "") finally Xpath 131072 " X: 131072 if !caught && !$VIMNOERRTHROW Xpath 262144 " X: 0 endif let v:errmsg = substitute(v:errmsg, ' '.infile.'$', '', "") if !MSG('E492', "Not an editor command") Xpath 524288 " X: 0 endif if getline("1") == "XYZ" Xpath 1048576 " X: 0 Xout ":read command not suppressed after FileReadPre error" endif if post Xpath 2097152 " X: 0 Xout "FileReadPost commands executed after " . \ "FileReadPre error" endif au! TMP aug! TMP endtry finally bwipeout! endtry catch /.*/ Xpath 4194304 " X: 0 Xout v:exception "in" v:throwpoint finally break " discard error for $VIMNOERRTHROW endtry endwhile call delete(infile) call delete(tmpfile) unlet! caught post infile tmpfile delfunction MSG delfunction Delete_autocommands Xcheck 198689 "------------------------------------------------------------------------------- " Test 86: setloclist crash {{{1 " " Executing a setloclist() on BufUnload shouldn't crash Vim "------------------------------------------------------------------------------- func F au BufUnload * :call setloclist(0, [{'bufnr':1, 'lnum':1, 'col':1, 'text': 'tango down'}]) :lvimgrep /.*/ *.mak endfunc XpathINIT ExecAsScript F delfunction F Xout "No Crash for vimgrep on BufUnload" Xcheck 0 "------------------------------------------------------------------------------- " Test 87 using (expr) ? funcref : funcref {{{1 " " Vim needs to correctly parse the funcref and even when it does " not execute the funcref, it needs to consume the trailing () "------------------------------------------------------------------------------- XpathINIT func Add2(x1, x2) return a:x1 + a:x2 endfu func GetStr() return "abcdefghijklmnopqrstuvwxyp" endfu echo function('Add2')(2,3) Xout 1 ? function('Add2')(1,2) : function('Add2')(2,3) Xout 0 ? function('Add2')(1,2) : function('Add2')(2,3) " Make sure, GetStr() still works. Xout GetStr()[0:10] delfunction GetStr delfunction Add2 Xout "Successfully executed funcref Add2" Xcheck 0 "------------------------------------------------------------------------------- " Test 88: $VIMNOERRTHROW and $VIMNOINTTHROW support {{{1 " " It is possible to configure Vim for throwing exceptions on error " or interrupt, controlled by variables $VIMNOERRTHROW and " $VIMNOINTTHROW. This is just for increasing the number of tests. " All tests here should run for all four combinations of setting " these variables to 0 or 1. The variables are intended for the " development phase only. In the final release, Vim should be " configured to always use error and interrupt exceptions. " " The test result is "OK", " " - if the $VIMNOERRTHROW and the $VIMNOINTTHROW control are not " configured and exceptions are thrown on error and on " interrupt. " " - if the $VIMNOERRTHROW or the $VIMNOINTTHROW control is " configured and works as intended. " " What actually happens, is shown in the test output. " " Otherwise, the test result is "FAIL", and the test output describes " the problem. " " IMPORTANT: This must be the last test because it sets $VIMNOERRTHROW and " $VIMNOINTTHROW. "------------------------------------------------------------------------------- XpathINIT if ExtraVim() function! ThrowOnError() XloopNEXT let caught = 0 try Xloop 1 " X: 1 + 8 + 64 asdf catch /.*/ let caught = 1 " error exception caught finally Xloop 2 " X: 2 + 16 + 128 return caught " discard aborting error endtry Xloop 4 " X: 0 endfunction let quits_skipped = 0 function! ThrowOnInterrupt() XloopNEXT let caught = 0 try Xloop 1 " X: (1 + 8 + 64) * 512 "INTERRUPT3 let dummy = 0 let g:quits_skipped = g:quits_skipped + 1 catch /.*/ let caught = 1 " interrupt exception caught finally Xloop 2 " X: (2 + 16 + 128) * 512 return caught " discard interrupt endtry Xloop 4 " X: 0 endfunction function! CheckThrow(Type) execute 'return ThrowOn' . a:Type . '()' endfunction function! CheckConfiguration(type) " type is "error" or "interrupt" let type = a:type let Type = substitute(type, '.*', '\u&', "") let VAR = '$VIMNO' . substitute(type, '\(...\).*', '\U\1', "") . 'THROW' if type == "error" XloopINIT! 1 8 elseif type == "interrupt" XloopINIT! 512 8 endif exec 'let requested_for_tests = exists(VAR) && ' . VAR . ' == 0' exec 'let suppressed_for_tests = ' . VAR . ' != 0' let used_in_tests = CheckThrow(Type) exec 'let ' . VAR . ' = 0' let request_works = CheckThrow(Type) exec 'let ' . VAR . ' = 1' let suppress_works = !CheckThrow(Type) if type == "error" XloopINIT! 262144 8 elseif type == "interrupt" XloopINIT! 2097152 8 if g:quits_skipped != 0 Xloop 1 " X: 0*2097152 Xout "Test environment error. Interrupt breakpoints skipped: " \ . g:quits_skipped . ".\n" \ . "Cannot check whether interrupt exceptions are thrown." return endif endif let failure = \ !suppressed_for_tests && !used_in_tests \ || !request_works let contradiction = \ used_in_tests \ ? suppressed_for_tests && !request_works \ : !suppressed_for_tests if failure " Failure in configuration. Xloop 2 " X: 0 * 2* (262144 + 2097152) elseif contradiction " Failure in test logic. Should not happen. Xloop 4 " X: 0 * 4 * (262144 + 2097152) endif let var_control_configured = \ request_works != used_in_tests \ || suppress_works == used_in_tests let var_control_not_configured = \ requested_for_tests || suppressed_for_tests \ ? request_works && !suppress_works \ : request_works == used_in_tests \ && suppress_works != used_in_tests let with = used_in_tests ? "with" : "without" let set = suppressed_for_tests ? "non-zero" : \ requested_for_tests ? "0" : "unset" let although = contradiction && !var_control_not_configured \ ? ",\nalthough " \ : ".\n" let output = "All tests were run " . with . " throwing exceptions on " \ . type . although if !var_control_not_configured let output = output . VAR . " was " . set . "." if !request_works && !requested_for_tests let output = output . \ "\n" . Type . " exceptions are not thrown when " . VAR . \ " is\nset to 0." endif if !suppress_works && (!used_in_tests || \ !request_works && \ !requested_for_tests && !suppressed_for_tests) let output = output . \ "\n" . Type . " exceptions are thrown when " . VAR . \ " is set to 1." endif if !failure && var_control_configured let output = output . \ "\nRun tests also with " . substitute(VAR, '^\$', '', "") \ . "=" . used_in_tests . "." \ . "\nThis is for testing in the development phase only." \ . " Remove the \n" \ . VAR . " control in the final release." endif else let output = output . \ "The " . VAR . " control is not configured." endif Xout output endfunction call CheckConfiguration("error") Xpath 16777216 " X: 16777216 call CheckConfiguration("interrupt") Xpath 33554432 " X: 33554432 endif Xcheck 50443995 " IMPORTANT: No test should be added after this test because it changes " $VIMNOERRTHROW and $VIMNOINTTHROW. "------------------------------------------------------------------------------- " Modelines {{{1 " vim: ts=8 sw=4 tw=80 fdm=marker " vim: fdt=substitute(substitute(foldtext(),\ '\\%(^+--\\)\\@<=\\(\\s*\\)\\(.\\{-}\\)\:\ \\%(\"\ \\)\\=\\(Test\ \\d*\\)\:\\s*',\ '\\3\ (\\2)\:\ \\1',\ \"\"),\ '\\(Test\\s*\\)\\(\\d\\)\\D\\@=',\ '\\1\ \\2',\ "") "-------------------------------------------------------------------------------