# HG changeset patch # User Christian Brabandt # Date 1487873705 -3600 # Node ID e05695e59f6df50605a73cf5d787fdb4f8823ddb # Parent 56b3c9414c82d0ea069074922c545f35627fd008 patch 8.0.0360: sometimes VimL is used instead of "Vim script" commit https://github.com/vim/vim/commit/b544f3c81f1e6a50322855681ac266ffaa8e313c Author: Bram Moolenaar Date: Thu Feb 23 19:03:28 2017 +0100 patch 8.0.0360: sometimes VimL is used instead of "Vim script" Problem: Sometimes VimL is used, which is confusing. Solution: Consistently use "Vim script". (Hirohito Higashi) diff --git a/runtime/doc/if_mzsch.txt b/runtime/doc/if_mzsch.txt --- a/runtime/doc/if_mzsch.txt +++ b/runtime/doc/if_mzsch.txt @@ -249,7 +249,7 @@ Windows *mzscheme-window* 5. mzeval() Vim function *mzscheme-mzeval* To facilitate bi-directional interface, you can use |mzeval()| function to -evaluate MzScheme expressions and pass their values to VimL. +evaluate MzScheme expressions and pass their values to Vim script. ============================================================================== 6. Using Function references *mzscheme-funcref* diff --git a/runtime/doc/if_pyth.txt b/runtime/doc/if_pyth.txt --- a/runtime/doc/if_pyth.txt +++ b/runtime/doc/if_pyth.txt @@ -676,11 +676,11 @@ vim.Function object *python-Function* dictionary. Note that explicit `self` keyword used when calling resulting object overrides this attribute. auto_rebind Boolean. True if partial created from this Python object - and stored in the VimL dictionary should be automatically - rebound to the dictionary it is stored in when this - dictionary is indexed. Exposes Vim internal difference - between `dict.func` (auto_rebind=True) and - `function(dict.func,dict)` (auto_rebind=False). This + and stored in the Vim script dictionary should be + automatically rebound to the dictionary it is stored in + when this dictionary is indexed. Exposes Vim internal + difference between `dict.func` (auto_rebind=True) and + `function(dict.func,dict)` (auto_rebind=False). This attribute makes no sense if `self` attribute is `None`. Constructor additionally accepts `args`, `self` and `auto_rebind` @@ -711,7 +711,7 @@ vim.Function object *python-Function* 8. pyeval() and py3eval() Vim functions *python-pyeval* To facilitate bi-directional interface, you can use |pyeval()| and |py3eval()| -functions to evaluate Python expressions and pass their values to VimL. +functions to evaluate Python expressions and pass their values to Vim script. |pyxeval()| is also available. ============================================================================== diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -3327,8 +3327,8 @@ Some folding is now supported with synta g:vimsyn_folding =~ 't' : fold tcl script < *g:vimsyn_noerror* -Not all error highlighting that syntax/vim.vim does may be correct; VimL is a -difficult language to highlight correctly. A way to suppress error +Not all error highlighting that syntax/vim.vim does may be correct; Vim script +is a difficult language to highlight correctly. A way to suppress error highlighting is to put the following line in your |vimrc|: > let g:vimsyn_noerror = 1 diff --git a/runtime/doc/usr_02.txt b/runtime/doc/usr_02.txt --- a/runtime/doc/usr_02.txt +++ b/runtime/doc/usr_02.txt @@ -589,7 +589,7 @@ 12) Registers always start with "quote". register: > :help quote: -13) Vim Script (VimL) is available at > +13) Vim script is available at > :help eval.txt < Certain aspects of the language are available at :h expr-X where "X" is a single letter. E.g. > @@ -599,10 +599,10 @@ 13) Vim Script (VimL) is available at > Also important is > :help function-list < to find a short description of all functions available. Help topics for - VimL functions always include the "()", so: > + Vim script functions always include the "()", so: > :help append() -< talks about the append VimL function rather than how to append text in the - current buffer. +< talks about the append Vim script function rather than how to append text + in the current buffer. 14) Mappings are talked about in the help page :h |map.txt|. Use > :help mapmode-i diff --git a/runtime/doc/version7.txt b/runtime/doc/version7.txt --- a/runtime/doc/version7.txt +++ b/runtime/doc/version7.txt @@ -10202,7 +10202,7 @@ objects in place of `str()` ones avoidin interfaces to some extent. Extent will be improved in the future. Added special |python-vars| objects also available for |python-buffer| and -|python-window|. They ease access to VimL variables from Python. +|python-window|. They ease access to Vim script variables from Python. Now you no longer need to alter `sys.path` to import your module: special hooks are responsible for importing from {rtp}/python2, {rtp}/python3 and diff --git a/src/Makefile b/src/Makefile --- a/src/Makefile +++ b/src/Makefile @@ -2213,7 +2213,7 @@ test_arglist \ test_usercommands \ test_utf8 \ test_viminfo \ - test_viml \ + test_vimscript \ test_visual \ test_window_cmd \ test_window_id \ diff --git a/src/eval.c b/src/eval.c --- a/src/eval.c +++ b/src/eval.c @@ -950,7 +950,7 @@ eval_expr(char_u *arg, char_u **nextcmd) /* - * Call some vimL function and return the result in "*rettv". + * Call some Vim script function and return the result in "*rettv". * Uses argv[argc] for the function arguments. Only Number and String * arguments are currently supported. * Returns OK or FAIL. @@ -1027,7 +1027,7 @@ call_vim_function( } /* - * Call vimL function "func" and return the result as a number. + * Call Vim script function "func" and return the result as a number. * Returns -1 when calling the function fails. * Uses argv[argc] for the function arguments. */ @@ -1055,7 +1055,7 @@ call_func_retnr( # if (defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)) || defined(PROTO) /* - * Call vimL function "func" and return the result as a string. + * Call Vim script function "func" and return the result as a string. * Returns NULL when calling the function fails. * Uses argv[argc] for the function arguments. */ @@ -1080,7 +1080,7 @@ call_func_retstr( # endif /* - * Call vimL function "func" and return the result as a List. + * Call Vim script function "func" and return the result as a List. * Uses argv[argc] for the function arguments. * Returns NULL when there is something wrong. */ diff --git a/src/ex_getln.c b/src/ex_getln.c --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -5140,8 +5140,8 @@ expand_shellcmd( static void * call_user_expand_func(void *(*user_expand_func)(char_u *, int, char_u **, int), expand_T *xp, int *num_file, char_u ***file); /* - * Call "user_expand_func()" to invoke a user defined VimL function and return - * the result (either a string or a List). + * Call "user_expand_func()" to invoke a user defined Vim script function and + * return the result (either a string or a List). */ static void * call_user_expand_func( diff --git a/src/if_py_both.h b/src/if_py_both.h --- a/src/if_py_both.h +++ b/src/if_py_both.h @@ -582,9 +582,9 @@ VimTryStart(void) VimTryEnd(void) { --trylevel; - /* Without this it stops processing all subsequent VimL commands and - * generates strange error messages if I e.g. try calling Test() in a - * cycle */ + /* Without this it stops processing all subsequent Vim script commands and + * generates strange error messages if I e.g. try calling Test() in a cycle + */ did_emsg = FALSE; /* Keyboard interrupt should be preferred over anything else */ if (got_int) @@ -625,7 +625,7 @@ VimTryEnd(void) discard_current_exception(); return -1; } - /* Finally transform VimL exception to python one */ + /* Finally transform Vim script exception to python one */ else { PyErr_SetVim((char *)current_exception->value); diff --git a/src/if_xcmdsrv.c b/src/if_xcmdsrv.c --- a/src/if_xcmdsrv.c +++ b/src/if_xcmdsrv.c @@ -1449,8 +1449,8 @@ server_parse_message( char_u *enc; /* - * This is a (n)otification. Sent with serverreply_send in VimL. - * Execute any autocommand and save it for later retrieval + * This is a (n)otification. Sent with serverreply_send in Vim + * script. Execute any autocommand and save it for later retrieval */ p += 2; gotWindow = 0; diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak --- a/src/testdir/Make_all.mak +++ b/src/testdir/Make_all.mak @@ -199,7 +199,7 @@ NEW_TESTS = test_arglist.res \ test_undo.res \ test_usercommands.res \ test_viminfo.res \ - test_viml.res \ + test_vimscript.res \ test_visual.res \ test_window_id.res \ test_writefile.res \ diff --git a/src/testdir/runtest.vim b/src/testdir/runtest.vim --- a/src/testdir/runtest.vim +++ b/src/testdir/runtest.vim @@ -147,7 +147,7 @@ let s:fail = 0 let s:errors = [] let s:messages = [] let s:skipped = [] -if expand('%') =~ 'test_viml.vim' +if expand('%') =~ 'test_vimscript.vim' " this test has intentional s:errors, don't use try/catch. source % else diff --git a/src/testdir/test49.vim b/src/testdir/test49.vim --- a/src/testdir/test49.vim +++ b/src/testdir/test49.vim @@ -608,7 +608,7 @@ com! -nargs=1 -bar ExecAsScript call Exe " END_OF_TEST_ENVIRONMENT - do not change or remove this line. -" Tests 1 to 15 were moved to test_viml.vim +" Tests 1 to 15 were moved to test_vimscript.vim let Xtest = 16 "------------------------------------------------------------------------------- diff --git a/src/testdir/test_viml.vim b/src/testdir/test_viml.vim deleted file mode 100644 --- a/src/testdir/test_viml.vim +++ /dev/null @@ -1,1316 +0,0 @@ -" Test various aspects of the Vim language. -" Most of this was formerly in test49. - -"------------------------------------------------------------------------------- -" Test environment {{{1 -"------------------------------------------------------------------------------- - -com! XpathINIT let g:Xpath = '' -com! -nargs=1 -bar Xpath let g:Xpath = g:Xpath . - -" Append a message to the "messages" file -func! Xout(text) - split messages - $put =a:text - wq -endfunc - -com! -nargs=1 Xout call Xout() - -" 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. -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/\ 0 - let cnt = cnt + 1 - s/\) - - -"------------------------------------------------------------------------------- -" Test 1: :endwhile in function {{{1 -" -" Detect if a broken loop is (incorrectly) reactivated by the -" :endwhile. Use a :return to prevent an endless loop, and make -" this test first to get a meaningful result on an error before other -" tests will hang. -"------------------------------------------------------------------------------- - -function! T1_F() - Xpath 'a' - let first = 1 - while 1 - Xpath 'b' - if first - Xpath 'c' - let first = 0 - break - else - Xpath 'd' - return - endif - endwhile -endfunction - -function! T1_G() - Xpath 'h' - let first = 1 - while 1 - Xpath 'i' - if first - Xpath 'j' - let first = 0 - break - else - Xpath 'k' - return - endif - if 1 " unmatched :if - endwhile -endfunction - -func Test_endwhile_function() - XpathINIT - call T1_F() - Xpath 'F' - - try - call T1_G() - catch - " Catch missing :endif - call assert_true(v:exception =~ 'E171') - Xpath 'x' - endtry - Xpath 'G' - - call assert_equal('abcFhijxG', g:Xpath) -endfunc - -"------------------------------------------------------------------------------- -" Test 2: :endwhile in script {{{1 -" -" Detect if a broken loop is (incorrectly) reactivated by the -" :endwhile. Use a :finish to prevent an endless loop, and place -" this test before others that might hang to get a meaningful result -" on an error. -" -" This test executes the bodies of the functions T1_F and T1_G from -" the previous test as script files (:return replaced by :finish). -"------------------------------------------------------------------------------- - -func Test_endwhile_script() - XpathINIT - ExecAsScript T1_F - Xpath 'F' - call DeleteTheScript() - - try - ExecAsScript T1_G - catch - " Catch missing :endif - call assert_true(v:exception =~ 'E171') - Xpath 'x' - endtry - Xpath 'G' - call DeleteTheScript() - - call assert_equal('abcFhijxG', g:Xpath) -endfunc - -"------------------------------------------------------------------------------- -" Test 3: :if, :elseif, :while, :continue, :break {{{1 -"------------------------------------------------------------------------------- - -function Test_if_while() - XpathINIT - if 1 - Xpath 'a' - let loops = 3 - while loops > -1 " main loop: loops == 3, 2, 1 (which breaks) - if loops <= 0 - let break_err = 1 - let loops = -1 - else - Xpath 'b' . loops - endif - if (loops == 2) - while loops == 2 " dummy loop - Xpath 'c' . loops - let loops = loops - 1 - continue " stop dummy loop - Xpath 'd' . loops - endwhile - continue " continue main loop - Xpath 'e' . loops - elseif (loops == 1) - let p = 1 - while p " dummy loop - Xpath 'f' . loops - let p = 0 - break " break dummy loop - Xpath 'g' . loops - endwhile - Xpath 'h' . loops - unlet p - break " break main loop - Xpath 'i' . loops - endif - if (loops > 0) - Xpath 'j' . loops - endif - while loops == 3 " dummy loop - let loops = loops - 1 - endwhile " end dummy loop - endwhile " end main loop - Xpath 'k' - else - Xpath 'l' - endif - Xpath 'm' - if exists("break_err") - Xpath 'm' - unlet break_err - endif - - unlet loops - - call assert_equal('ab3j3b2c2b1f1h1km', g:Xpath) -endfunc - -"------------------------------------------------------------------------------- -" Test 4: :return {{{1 -"------------------------------------------------------------------------------- - -function! T4_F() - if 1 - Xpath 'a' - let loops = 3 - while loops > 0 " 3: 2: 1: - Xpath 'b' . loops - if (loops == 2) - Xpath 'c' . loops - return - Xpath 'd' . loops - endif - Xpath 'e' . loops - let loops = loops - 1 - endwhile - Xpath 'f' - else - Xpath 'g' - endif -endfunction - -function Test_return() - XpathINIT - call T4_F() - Xpath '4' - - call assert_equal('ab3e3b2c24', g:Xpath) -endfunction - - -"------------------------------------------------------------------------------- -" Test 5: :finish {{{1 -" -" This test executes the body of the function T4_F from the previous -" test as a script file (:return replaced by :finish). -"------------------------------------------------------------------------------- - -function Test_finish() - XpathINIT - ExecAsScript T4_F - Xpath '5' - call DeleteTheScript() - - call assert_equal('ab3e3b2c25', g:Xpath) -endfunction - - - -"------------------------------------------------------------------------------- -" Test 6: Defining functions in :while loops {{{1 -" -" Functions can be defined inside other functions. An inner function -" gets defined when the outer function is executed. Functions may -" also be defined inside while loops. Expressions in braces for -" defining the function name are allowed. -" -" The functions are defined when sourcing the script, only the -" resulting path is checked in the test function. -"------------------------------------------------------------------------------- - -XpathINIT - -" The command CALL collects the argument of all its invocations in "calls" -" when used from a function (that is, when the global variable "calls" needs -" the "g:" prefix). This is to check that the function code is skipped when -" the function is defined. For inner functions, do so only if the outer -" function is not being executed. -" -let calls = "" -com! -nargs=1 CALL - \ if !exists("calls") && !exists("outer") | - \ let g:calls = g:calls . | - \ endif - -let i = 0 -while i < 3 - let i = i + 1 - if i == 1 - Xpath 'a' - function! F1(arg) - CALL a:arg - let outer = 1 - - let j = 0 - while j < 1 - Xpath 'b' - let j = j + 1 - function! G1(arg) - CALL a:arg - endfunction - Xpath 'c' - endwhile - endfunction - Xpath 'd' - - continue - endif - - Xpath 'e' . i - function! F{i}(i, arg) - CALL a:arg - let outer = 1 - - if a:i == 3 - Xpath 'f' - endif - let k = 0 - while k < 3 - Xpath 'g' . k - let k = k + 1 - function! G{a:i}{k}(arg) - CALL a:arg - endfunction - Xpath 'h' . k - endwhile - endfunction - Xpath 'i' - -endwhile - -if exists("*G1") - Xpath 'j' -endif -if exists("*F1") - call F1("F1") - if exists("*G1") - call G1("G1") - endif -endif - -if exists("G21") || exists("G22") || exists("G23") - Xpath 'k' -endif -if exists("*F2") - call F2(2, "F2") - if exists("*G21") - call G21("G21") - endif - if exists("*G22") - call G22("G22") - endif - if exists("*G23") - call G23("G23") - endif -endif - -if exists("G31") || exists("G32") || exists("G33") - Xpath 'l' -endif -if exists("*F3") - call F3(3, "F3") - if exists("*G31") - call G31("G31") - endif - if exists("*G32") - call G32("G32") - endif - if exists("*G33") - call G33("G33") - endif -endif - -Xpath 'm' - -let g:test6_result = g:Xpath -let g:test6_calls = calls - -unlet calls -delfunction F1 -delfunction G1 -delfunction F2 -delfunction G21 -delfunction G22 -delfunction G23 -delfunction G31 -delfunction G32 -delfunction G33 - -function Test_defining_functions() - call assert_equal('ade2ie3ibcg0h1g1h2g2h3fg0h1g1h2g2h3m', g:test6_result) - call assert_equal('F1G1F2G21G22G23F3G31G32G33', g:test6_calls) -endfunc - -"------------------------------------------------------------------------------- -" Test 7: Continuing on errors outside functions {{{1 -" -" On an error outside a function, the script processing continues -" at the line following the outermost :endif or :endwhile. When not -" inside an :if or :while, the script processing continues at the next -" line. -"------------------------------------------------------------------------------- - -XpathINIT - -if 1 - Xpath 'a' - while 1 - Xpath 'b' - asdf - Xpath 'c' - break - endwhile | Xpath 'd' - Xpath 'e' -endif | Xpath 'f' -Xpath 'g' - -while 1 - Xpath 'h' - if 1 - Xpath 'i' - asdf - Xpath 'j' - endif | Xpath 'k' - Xpath 'l' - break -endwhile | Xpath 'm' -Xpath 'n' - -asdf -Xpath 'o' - -asdf | Xpath 'p' -Xpath 'q' - -let g:test7_result = g:Xpath - -func Test_error_in_script() - call assert_equal('abghinoq', g:test7_result) -endfunc - -"------------------------------------------------------------------------------- -" Test 8: Aborting and continuing on errors inside functions {{{1 -" -" On an error inside a function without the "abort" attribute, the -" script processing continues at the next line (unless the error was -" in a :return command). On an error inside a function with the -" "abort" attribute, the function is aborted and the script processing -" continues after the function call; the value -1 is returned then. -"------------------------------------------------------------------------------- - -XpathINIT - -function! T8_F() - if 1 - Xpath 'a' - while 1 - Xpath 'b' - asdf - Xpath 'c' - asdf | Xpath 'd' - Xpath 'e' - break - endwhile - Xpath 'f' - endif | Xpath 'g' - Xpath 'h' - - while 1 - Xpath 'i' - if 1 - Xpath 'j' - asdf - Xpath 'k' - asdf | Xpath 'l' - Xpath 'm' - endif - Xpath 'n' - break - endwhile | Xpath 'o' - Xpath 'p' - - return novar " returns (default return value 0) - Xpath 'q' - return 1 " not reached -endfunction - -function! T8_G() abort - if 1 - Xpath 'r' - while 1 - Xpath 's' - asdf " returns -1 - Xpath 't' - break - endwhile - Xpath 'v' - endif | Xpath 'w' - Xpath 'x' - - return -4 " not reached -endfunction - -function! T8_H() abort - while 1 - Xpath 'A' - if 1 - Xpath 'B' - asdf " returns -1 - Xpath 'C' - endif - Xpath 'D' - break - endwhile | Xpath 'E' - Xpath 'F' - - return -4 " not reached -endfunction - -" Aborted functions (T8_G and T8_H) return -1. -let g:test8_sum = (T8_F() + 1) - 4 * T8_G() - 8 * T8_H() -Xpath 'X' -let g:test8_result = g:Xpath - -func Test_error_in_function() - call assert_equal(13, g:test8_sum) - call assert_equal('abcefghijkmnoprsABX', g:test8_result) - - delfunction T8_F - delfunction T8_G - delfunction T8_H -endfunc - - -"------------------------------------------------------------------------------- -" Test 9: Continuing after aborted functions {{{1 -" -" When a function with the "abort" attribute is aborted due to an -" error, the next function back in the call hierarchy without an -" "abort" attribute continues; the value -1 is returned then. -"------------------------------------------------------------------------------- - -XpathINIT - -function! F() abort - Xpath 'a' - let result = G() " not aborted - Xpath 'b' - if result != 2 - Xpath 'c' - endif - return 1 -endfunction - -function! G() " no abort attribute - Xpath 'd' - if H() != -1 " aborted - Xpath 'e' - endif - Xpath 'f' - return 2 -endfunction - -function! H() abort - Xpath 'g' - call I() " aborted - Xpath 'h' - return 4 -endfunction - -function! I() abort - Xpath 'i' - asdf " error - Xpath 'j' - return 8 -endfunction - -if F() != 1 - Xpath 'k' -endif - -let g:test9_result = g:Xpath - -delfunction F -delfunction G -delfunction H -delfunction I - -func Test_func_abort() - call assert_equal('adgifb', g:test9_result) -endfunc - - -"------------------------------------------------------------------------------- -" Test 10: :if, :elseif, :while argument parsing {{{1 -" -" A '"' or '|' in an argument expression must not be mixed up with -" a comment or a next command after a bar. Parsing errors should -" be recognized. -"------------------------------------------------------------------------------- - -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 - -if 1 || strlen("\"") | Xpath 'a' - Xpath 'b' -endif -Xpath 'c' - -if 0 -elseif 1 || strlen("\"") | Xpath 'd' - Xpath 'e' -endif -Xpath 'f' - -while 1 || strlen("\"") | Xpath 'g' - Xpath 'h' - break -endwhile -Xpath 'i' - -let v:errmsg = "" -if 1 ||| strlen("\"") | Xpath 'j' - Xpath 'k' -endif -Xpath 'l' -if !MSG('E15', "Invalid expression") - Xpath 'm' -endif - -let v:errmsg = "" -if 0 -elseif 1 ||| strlen("\"") | Xpath 'n' - Xpath 'o' -endif -Xpath 'p' -if !MSG('E15', "Invalid expression") - Xpath 'q' -endif - -let v:errmsg = "" -while 1 ||| strlen("\"") | Xpath 'r' - Xpath 's' - break -endwhile -Xpath 't' -if !MSG('E15', "Invalid expression") - Xpath 'u' -endif - -let g:test10_result = g:Xpath -delfunction MSG - -func Test_expr_parsing() - call assert_equal('abcdefghilpt', g:test10_result) -endfunc - - -"------------------------------------------------------------------------------- -" Test 11: :if, :elseif, :while argument evaluation after abort {{{1 -" -" When code is skipped over due to an error, the boolean argument to -" an :if, :elseif, or :while must not be evaluated. -"------------------------------------------------------------------------------- - -XpathINIT - -let calls = 0 - -function! P(num) - let g:calls = g:calls + a:num " side effect on call - return 0 -endfunction - -if 1 - Xpath 'a' - asdf " error - Xpath 'b' - if P(1) " should not be called - Xpath 'c' - elseif !P(2) " should not be called - Xpath 'd' - else - Xpath 'e' - endif - Xpath 'f' - while P(4) " should not be called - Xpath 'g' - endwhile - Xpath 'h' -endif -Xpath 'x' - -let g:test11_calls = calls -let g:test11_result = g:Xpath - -unlet calls -delfunction P - -func Test_arg_abort() - call assert_equal(0, g:test11_calls) - call assert_equal('ax', g:test11_result) -endfunc - - -"------------------------------------------------------------------------------- -" Test 12: Expressions in braces in skipped code {{{1 -" -" In code skipped over due to an error or inactive conditional, -" an expression in braces as part of a variable or function name -" should not be evaluated. -"------------------------------------------------------------------------------- - -XpathINIT - -function! NULL() - Xpath 'a' - return 0 -endfunction - -function! ZERO() - Xpath 'b' - return 0 -endfunction - -function! F0() - Xpath 'c' -endfunction - -function! F1(arg) - Xpath 'e' -endfunction - -let V0 = 1 - -Xpath 'f' -echo 0 ? F{NULL() + V{ZERO()}}() : 1 - -Xpath 'g' -if 0 - Xpath 'h' - call F{NULL() + V{ZERO()}}() -endif - -Xpath 'i' -if 1 - asdf " error - Xpath 'j' - call F1(F{NULL() + V{ZERO()}}()) -endif - -Xpath 'k' -if 1 - asdf " error - Xpath 'l' - call F{NULL() + V{ZERO()}}() -endif - -let g:test12_result = g:Xpath - -func Test_braces_skipped() - call assert_equal('fgik', g:test12_result) -endfunc - - -"------------------------------------------------------------------------------- -" Test 13: Failure in argument evaluation for :while {{{1 -" -" A failure in the expression evaluation for the condition of a :while -" causes the whole :while loop until the matching :endwhile being -" ignored. Continuation is at the next following line. -"------------------------------------------------------------------------------- - -XpathINIT - -Xpath 'a' -while asdf - Xpath 'b' - while 1 - Xpath 'c' - break - endwhile - Xpath 'd' - break -endwhile -Xpath 'e' - -while asdf | Xpath 'f' | endwhile | Xpath 'g' -Xpath 'h' -let g:test13_result = g:Xpath - -func Test_while_fail() - call assert_equal('aeh', g:test13_result) -endfunc - - -"------------------------------------------------------------------------------- -" Test 14: Failure in argument evaluation for :if {{{1 -" -" A failure in the expression evaluation for the condition of an :if -" does not cause the corresponding :else or :endif being matched to -" a previous :if/:elseif. Neither of both branches of the failed :if -" are executed. -"------------------------------------------------------------------------------- - -XpathINIT - -function! F() - Xpath 'a' - let x = 0 - if x " false - Xpath 'b' - elseif !x " always true - Xpath 'c' - let x = 1 - if g:boolvar " possibly undefined - Xpath 'd' - else - Xpath 'e' - endif - Xpath 'f' - elseif x " never executed - Xpath 'g' - endif - Xpath 'h' -endfunction - -let boolvar = 1 -call F() -Xpath '-' - -unlet boolvar -call F() -let g:test14_result = g:Xpath - -delfunction F - -func Test_if_fail() - call assert_equal('acdfh-acfh', g:test14_result) -endfunc - - -"------------------------------------------------------------------------------- -" Test 15: Failure in argument evaluation for :if (bar) {{{1 -" -" Like previous test, except that the failing :if ... | ... | :endif -" is in a single line. -"------------------------------------------------------------------------------- - -XpathINIT - -function! F() - Xpath 'a' - let x = 0 - if x " false - Xpath 'b' - elseif !x " always true - Xpath 'c' - let x = 1 - if g:boolvar | Xpath 'd' | else | Xpath 'e' | endif - Xpath 'f' - elseif x " never executed - Xpath 'g' - endif - Xpath 'h' -endfunction - -let boolvar = 1 -call F() -Xpath '-' - -unlet boolvar -call F() -let g:test15_result = g:Xpath - -delfunction F - -func Test_if_bar_fail() - call assert_equal('acdfh-acfh', g:test15_result) -endfunc - -"------------------------------------------------------------------------------- -" Test 90: Recognizing {} in variable name. {{{1 -"------------------------------------------------------------------------------- - -func Test_curlies() - let s:var = 66 - let ns = 's' - call assert_equal(66, {ns}:var) - - let g:a = {} - let g:b = 't' - let g:a[g:b] = 77 - call assert_equal(77, g:a['t']) -endfunc - -"------------------------------------------------------------------------------- -" Test 91: using type(). {{{1 -"------------------------------------------------------------------------------- - -func Test_type() - call assert_equal(0, type(0)) - call assert_equal(1, type("")) - call assert_equal(2, type(function("tr"))) - call assert_equal(2, type(function("tr", [8]))) - call assert_equal(3, type([])) - call assert_equal(4, type({})) - call assert_equal(5, type(0.0)) - call assert_equal(6, type(v:false)) - call assert_equal(6, type(v:true)) - call assert_equal(7, type(v:none)) - call assert_equal(7, type(v:null)) - call assert_equal(8, v:t_job) - call assert_equal(9, v:t_channel) - call assert_equal(v:t_number, type(0)) - call assert_equal(v:t_string, type("")) - call assert_equal(v:t_func, type(function("tr"))) - call assert_equal(v:t_func, type(function("tr", [8]))) - call assert_equal(v:t_list, type([])) - call assert_equal(v:t_dict, type({})) - call assert_equal(v:t_float, type(0.0)) - call assert_equal(v:t_bool, type(v:false)) - call assert_equal(v:t_bool, type(v:true)) - call assert_equal(v:t_none, type(v:none)) - call assert_equal(v:t_none, type(v:null)) - - - call assert_equal(0, 0 + v:false) - call assert_equal(1, 0 + v:true) - call assert_equal(0, 0 + v:none) - call assert_equal(0, 0 + v:null) - - call assert_equal('v:false', '' . v:false) - call assert_equal('v:true', '' . v:true) - call assert_equal('v:none', '' . v:none) - call assert_equal('v:null', '' . v:null) - - call assert_true(v:false == 0) - call assert_false(v:false != 0) - call assert_true(v:true == 1) - call assert_false(v:true != 1) - call assert_false(v:true == v:false) - call assert_true(v:true != v:false) - - call assert_true(v:null == 0) - call assert_false(v:null != 0) - call assert_true(v:none == 0) - call assert_false(v:none != 0) - - call assert_true(v:false is v:false) - call assert_true(v:true is v:true) - call assert_true(v:none is v:none) - call assert_true(v:null is v:null) - - call assert_false(v:false isnot v:false) - call assert_false(v:true isnot v:true) - call assert_false(v:none isnot v:none) - call assert_false(v:null isnot v:null) - - call assert_false(v:false is 0) - call assert_false(v:true is 1) - call assert_false(v:true is v:false) - call assert_false(v:none is 0) - call assert_false(v:null is 0) - call assert_false(v:null is v:none) - - call assert_true(v:false isnot 0) - call assert_true(v:true isnot 1) - call assert_true(v:true isnot v:false) - call assert_true(v:none isnot 0) - call assert_true(v:null isnot 0) - call assert_true(v:null isnot v:none) - - call assert_equal(v:false, eval(string(v:false))) - call assert_equal(v:true, eval(string(v:true))) - call assert_equal(v:none, eval(string(v:none))) - call assert_equal(v:null, eval(string(v:null))) - - call assert_equal(v:false, copy(v:false)) - call assert_equal(v:true, copy(v:true)) - call assert_equal(v:none, copy(v:none)) - call assert_equal(v:null, copy(v:null)) - - call assert_equal([v:false], deepcopy([v:false])) - call assert_equal([v:true], deepcopy([v:true])) - call assert_equal([v:none], deepcopy([v:none])) - call assert_equal([v:null], deepcopy([v:null])) - - call assert_true(empty(v:false)) - call assert_false(empty(v:true)) - call assert_true(empty(v:null)) - call assert_true(empty(v:none)) - - func ChangeYourMind() - try - return v:true - finally - return 'something else' - endtry - endfunc - - call ChangeYourMind() -endfunc - -"------------------------------------------------------------------------------- -" Test 92: skipping code {{{1 -"------------------------------------------------------------------------------- - -func Test_skip() - let Fn = function('Test_type') - call assert_false(0 && Fn[1]) - call assert_false(0 && string(Fn)) - call assert_false(0 && len(Fn)) - let l = [] - call assert_false(0 && l[1]) - call assert_false(0 && string(l)) - call assert_false(0 && len(l)) - let f = 1.0 - call assert_false(0 && f[1]) - call assert_false(0 && string(f)) - call assert_false(0 && len(f)) - let sp = v:null - call assert_false(0 && sp[1]) - call assert_false(0 && string(sp)) - call assert_false(0 && len(sp)) - -endfunc - -"------------------------------------------------------------------------------- -" Test 93: :echo and string() {{{1 -"------------------------------------------------------------------------------- - -func Test_echo_and_string() - " String - let a = 'foo bar' - redir => result - echo a - echo string(a) - redir END - let l = split(result, "\n") - call assert_equal(["foo bar", - \ "'foo bar'"], l) - - " Float - if has('float') - let a = -1.2e0 - redir => result - echo a - echo string(a) - redir END - let l = split(result, "\n") - call assert_equal(["-1.2", - \ "-1.2"], l) - endif - - " Funcref - redir => result - echo function('string') - echo string(function('string')) - redir END - let l = split(result, "\n") - call assert_equal(["string", - \ "function('string')"], l) - - " Recursive dictionary - let a = {} - let a["a"] = a - redir => result - echo a - echo string(a) - redir END - let l = split(result, "\n") - call assert_equal(["{'a': {...}}", - \ "{'a': {...}}"], l) - - " Recursive list - let a = [0] - let a[0] = a - redir => result - echo a - echo string(a) - redir END - let l = split(result, "\n") - call assert_equal(["[[...]]", - \ "[[...]]"], l) - - " Empty dictionaries in a list - let a = {} - redir => result - echo [a, a, a] - echo string([a, a, a]) - redir END - let l = split(result, "\n") - call assert_equal(["[{}, {}, {}]", - \ "[{}, {}, {}]"], l) - - " Empty dictionaries in a dictionary - let a = {} - let b = {"a": a, "b": a} - redir => result - echo b - echo string(b) - redir END - let l = split(result, "\n") - call assert_equal(["{'a': {}, 'b': {}}", - \ "{'a': {}, 'b': {}}"], l) - - " Empty lists in a list - let a = [] - redir => result - echo [a, a, a] - echo string([a, a, a]) - redir END - let l = split(result, "\n") - call assert_equal(["[[], [], []]", - \ "[[], [], []]"], l) - - " Empty lists in a dictionary - let a = [] - let b = {"a": a, "b": a} - redir => result - echo b - echo string(b) - redir END - let l = split(result, "\n") - call assert_equal(["{'a': [], 'b': []}", - \ "{'a': [], 'b': []}"], l) - - " Dictionaries in a list - let a = {"one": "yes", "two": "yes", "three": "yes"} - redir => result - echo [a, a, a] - echo string([a, a, a]) - redir END - let l = split(result, "\n") - call assert_equal(["[{'one': 'yes', 'two': 'yes', 'three': 'yes'}, {...}, {...}]", - \ "[{'one': 'yes', 'two': 'yes', 'three': 'yes'}, {'one': 'yes', 'two': 'yes', 'three': 'yes'}, {'one': 'yes', 'two': 'yes', 'three': 'yes'}]"], l) - - " Dictionaries in a dictionary - let a = {"one": "yes", "two": "yes", "three": "yes"} - let b = {"a": a, "b": a} - redir => result - echo b - echo string(b) - redir END - let l = split(result, "\n") - call assert_equal(["{'a': {'one': 'yes', 'two': 'yes', 'three': 'yes'}, 'b': {...}}", - \ "{'a': {'one': 'yes', 'two': 'yes', 'three': 'yes'}, 'b': {'one': 'yes', 'two': 'yes', 'three': 'yes'}}"], l) - - " Lists in a list - let a = [1, 2, 3] - redir => result - echo [a, a, a] - echo string([a, a, a]) - redir END - let l = split(result, "\n") - call assert_equal(["[[1, 2, 3], [...], [...]]", - \ "[[1, 2, 3], [1, 2, 3], [1, 2, 3]]"], l) - - " Lists in a dictionary - let a = [1, 2, 3] - let b = {"a": a, "b": a} - redir => result - echo b - echo string(b) - redir END - let l = split(result, "\n") - call assert_equal(["{'a': [1, 2, 3], 'b': [...]}", - \ "{'a': [1, 2, 3], 'b': [1, 2, 3]}"], l) - -endfunc - -"------------------------------------------------------------------------------- -" Test 94: 64-bit Numbers {{{1 -"------------------------------------------------------------------------------- - -func Test_num64() - if !has('num64') - return - endif - - call assert_notequal( 4294967296, 0) - call assert_notequal(-4294967296, 0) - call assert_equal( 4294967296, 0xFFFFffff + 1) - call assert_equal(-4294967296, -0xFFFFffff - 1) - - call assert_equal( 9223372036854775807, 1 / 0) - call assert_equal(-9223372036854775807, -1 / 0) - call assert_equal(-9223372036854775807 - 1, 0 / 0) - - call assert_equal( 0x7FFFffffFFFFffff, float2nr( 1.0e150)) - call assert_equal(-0x7FFFffffFFFFffff, float2nr(-1.0e150)) - - let rng = range(0xFFFFffff, 0x100000001) - call assert_equal([0xFFFFffff, 0x100000000, 0x100000001], rng) - call assert_equal(0x100000001, max(rng)) - call assert_equal(0xFFFFffff, min(rng)) - call assert_equal(rng, sort(range(0x100000001, 0xFFFFffff, -1), 'N')) -endfunc - -"------------------------------------------------------------------------------- -" Test 95: lines of :append, :change, :insert {{{1 -"------------------------------------------------------------------------------- - -function! DefineFunction(name, body) - let func = join(['function! ' . a:name . '()'] + a:body + ['endfunction'], "\n") - exec func -endfunction - -func Test_script_lines() - " :append - try - call DefineFunction('T_Append', [ - \ 'append', - \ 'py < + +" Append a message to the "messages" file +func! Xout(text) + split messages + $put =a:text + wq +endfunc + +com! -nargs=1 Xout call Xout() + +" 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. +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/\ 0 + let cnt = cnt + 1 + s/\) + + +"------------------------------------------------------------------------------- +" Test 1: :endwhile in function {{{1 +" +" Detect if a broken loop is (incorrectly) reactivated by the +" :endwhile. Use a :return to prevent an endless loop, and make +" this test first to get a meaningful result on an error before other +" tests will hang. +"------------------------------------------------------------------------------- + +function! T1_F() + Xpath 'a' + let first = 1 + while 1 + Xpath 'b' + if first + Xpath 'c' + let first = 0 + break + else + Xpath 'd' + return + endif + endwhile +endfunction + +function! T1_G() + Xpath 'h' + let first = 1 + while 1 + Xpath 'i' + if first + Xpath 'j' + let first = 0 + break + else + Xpath 'k' + return + endif + if 1 " unmatched :if + endwhile +endfunction + +func Test_endwhile_function() + XpathINIT + call T1_F() + Xpath 'F' + + try + call T1_G() + catch + " Catch missing :endif + call assert_true(v:exception =~ 'E171') + Xpath 'x' + endtry + Xpath 'G' + + call assert_equal('abcFhijxG', g:Xpath) +endfunc + +"------------------------------------------------------------------------------- +" Test 2: :endwhile in script {{{1 +" +" Detect if a broken loop is (incorrectly) reactivated by the +" :endwhile. Use a :finish to prevent an endless loop, and place +" this test before others that might hang to get a meaningful result +" on an error. +" +" This test executes the bodies of the functions T1_F and T1_G from +" the previous test as script files (:return replaced by :finish). +"------------------------------------------------------------------------------- + +func Test_endwhile_script() + XpathINIT + ExecAsScript T1_F + Xpath 'F' + call DeleteTheScript() + + try + ExecAsScript T1_G + catch + " Catch missing :endif + call assert_true(v:exception =~ 'E171') + Xpath 'x' + endtry + Xpath 'G' + call DeleteTheScript() + + call assert_equal('abcFhijxG', g:Xpath) +endfunc + +"------------------------------------------------------------------------------- +" Test 3: :if, :elseif, :while, :continue, :break {{{1 +"------------------------------------------------------------------------------- + +function Test_if_while() + XpathINIT + if 1 + Xpath 'a' + let loops = 3 + while loops > -1 " main loop: loops == 3, 2, 1 (which breaks) + if loops <= 0 + let break_err = 1 + let loops = -1 + else + Xpath 'b' . loops + endif + if (loops == 2) + while loops == 2 " dummy loop + Xpath 'c' . loops + let loops = loops - 1 + continue " stop dummy loop + Xpath 'd' . loops + endwhile + continue " continue main loop + Xpath 'e' . loops + elseif (loops == 1) + let p = 1 + while p " dummy loop + Xpath 'f' . loops + let p = 0 + break " break dummy loop + Xpath 'g' . loops + endwhile + Xpath 'h' . loops + unlet p + break " break main loop + Xpath 'i' . loops + endif + if (loops > 0) + Xpath 'j' . loops + endif + while loops == 3 " dummy loop + let loops = loops - 1 + endwhile " end dummy loop + endwhile " end main loop + Xpath 'k' + else + Xpath 'l' + endif + Xpath 'm' + if exists("break_err") + Xpath 'm' + unlet break_err + endif + + unlet loops + + call assert_equal('ab3j3b2c2b1f1h1km', g:Xpath) +endfunc + +"------------------------------------------------------------------------------- +" Test 4: :return {{{1 +"------------------------------------------------------------------------------- + +function! T4_F() + if 1 + Xpath 'a' + let loops = 3 + while loops > 0 " 3: 2: 1: + Xpath 'b' . loops + if (loops == 2) + Xpath 'c' . loops + return + Xpath 'd' . loops + endif + Xpath 'e' . loops + let loops = loops - 1 + endwhile + Xpath 'f' + else + Xpath 'g' + endif +endfunction + +function Test_return() + XpathINIT + call T4_F() + Xpath '4' + + call assert_equal('ab3e3b2c24', g:Xpath) +endfunction + + +"------------------------------------------------------------------------------- +" Test 5: :finish {{{1 +" +" This test executes the body of the function T4_F from the previous +" test as a script file (:return replaced by :finish). +"------------------------------------------------------------------------------- + +function Test_finish() + XpathINIT + ExecAsScript T4_F + Xpath '5' + call DeleteTheScript() + + call assert_equal('ab3e3b2c25', g:Xpath) +endfunction + + + +"------------------------------------------------------------------------------- +" Test 6: Defining functions in :while loops {{{1 +" +" Functions can be defined inside other functions. An inner function +" gets defined when the outer function is executed. Functions may +" also be defined inside while loops. Expressions in braces for +" defining the function name are allowed. +" +" The functions are defined when sourcing the script, only the +" resulting path is checked in the test function. +"------------------------------------------------------------------------------- + +XpathINIT + +" The command CALL collects the argument of all its invocations in "calls" +" when used from a function (that is, when the global variable "calls" needs +" the "g:" prefix). This is to check that the function code is skipped when +" the function is defined. For inner functions, do so only if the outer +" function is not being executed. +" +let calls = "" +com! -nargs=1 CALL + \ if !exists("calls") && !exists("outer") | + \ let g:calls = g:calls . | + \ endif + +let i = 0 +while i < 3 + let i = i + 1 + if i == 1 + Xpath 'a' + function! F1(arg) + CALL a:arg + let outer = 1 + + let j = 0 + while j < 1 + Xpath 'b' + let j = j + 1 + function! G1(arg) + CALL a:arg + endfunction + Xpath 'c' + endwhile + endfunction + Xpath 'd' + + continue + endif + + Xpath 'e' . i + function! F{i}(i, arg) + CALL a:arg + let outer = 1 + + if a:i == 3 + Xpath 'f' + endif + let k = 0 + while k < 3 + Xpath 'g' . k + let k = k + 1 + function! G{a:i}{k}(arg) + CALL a:arg + endfunction + Xpath 'h' . k + endwhile + endfunction + Xpath 'i' + +endwhile + +if exists("*G1") + Xpath 'j' +endif +if exists("*F1") + call F1("F1") + if exists("*G1") + call G1("G1") + endif +endif + +if exists("G21") || exists("G22") || exists("G23") + Xpath 'k' +endif +if exists("*F2") + call F2(2, "F2") + if exists("*G21") + call G21("G21") + endif + if exists("*G22") + call G22("G22") + endif + if exists("*G23") + call G23("G23") + endif +endif + +if exists("G31") || exists("G32") || exists("G33") + Xpath 'l' +endif +if exists("*F3") + call F3(3, "F3") + if exists("*G31") + call G31("G31") + endif + if exists("*G32") + call G32("G32") + endif + if exists("*G33") + call G33("G33") + endif +endif + +Xpath 'm' + +let g:test6_result = g:Xpath +let g:test6_calls = calls + +unlet calls +delfunction F1 +delfunction G1 +delfunction F2 +delfunction G21 +delfunction G22 +delfunction G23 +delfunction G31 +delfunction G32 +delfunction G33 + +function Test_defining_functions() + call assert_equal('ade2ie3ibcg0h1g1h2g2h3fg0h1g1h2g2h3m', g:test6_result) + call assert_equal('F1G1F2G21G22G23F3G31G32G33', g:test6_calls) +endfunc + +"------------------------------------------------------------------------------- +" Test 7: Continuing on errors outside functions {{{1 +" +" On an error outside a function, the script processing continues +" at the line following the outermost :endif or :endwhile. When not +" inside an :if or :while, the script processing continues at the next +" line. +"------------------------------------------------------------------------------- + +XpathINIT + +if 1 + Xpath 'a' + while 1 + Xpath 'b' + asdf + Xpath 'c' + break + endwhile | Xpath 'd' + Xpath 'e' +endif | Xpath 'f' +Xpath 'g' + +while 1 + Xpath 'h' + if 1 + Xpath 'i' + asdf + Xpath 'j' + endif | Xpath 'k' + Xpath 'l' + break +endwhile | Xpath 'm' +Xpath 'n' + +asdf +Xpath 'o' + +asdf | Xpath 'p' +Xpath 'q' + +let g:test7_result = g:Xpath + +func Test_error_in_script() + call assert_equal('abghinoq', g:test7_result) +endfunc + +"------------------------------------------------------------------------------- +" Test 8: Aborting and continuing on errors inside functions {{{1 +" +" On an error inside a function without the "abort" attribute, the +" script processing continues at the next line (unless the error was +" in a :return command). On an error inside a function with the +" "abort" attribute, the function is aborted and the script processing +" continues after the function call; the value -1 is returned then. +"------------------------------------------------------------------------------- + +XpathINIT + +function! T8_F() + if 1 + Xpath 'a' + while 1 + Xpath 'b' + asdf + Xpath 'c' + asdf | Xpath 'd' + Xpath 'e' + break + endwhile + Xpath 'f' + endif | Xpath 'g' + Xpath 'h' + + while 1 + Xpath 'i' + if 1 + Xpath 'j' + asdf + Xpath 'k' + asdf | Xpath 'l' + Xpath 'm' + endif + Xpath 'n' + break + endwhile | Xpath 'o' + Xpath 'p' + + return novar " returns (default return value 0) + Xpath 'q' + return 1 " not reached +endfunction + +function! T8_G() abort + if 1 + Xpath 'r' + while 1 + Xpath 's' + asdf " returns -1 + Xpath 't' + break + endwhile + Xpath 'v' + endif | Xpath 'w' + Xpath 'x' + + return -4 " not reached +endfunction + +function! T8_H() abort + while 1 + Xpath 'A' + if 1 + Xpath 'B' + asdf " returns -1 + Xpath 'C' + endif + Xpath 'D' + break + endwhile | Xpath 'E' + Xpath 'F' + + return -4 " not reached +endfunction + +" Aborted functions (T8_G and T8_H) return -1. +let g:test8_sum = (T8_F() + 1) - 4 * T8_G() - 8 * T8_H() +Xpath 'X' +let g:test8_result = g:Xpath + +func Test_error_in_function() + call assert_equal(13, g:test8_sum) + call assert_equal('abcefghijkmnoprsABX', g:test8_result) + + delfunction T8_F + delfunction T8_G + delfunction T8_H +endfunc + + +"------------------------------------------------------------------------------- +" Test 9: Continuing after aborted functions {{{1 +" +" When a function with the "abort" attribute is aborted due to an +" error, the next function back in the call hierarchy without an +" "abort" attribute continues; the value -1 is returned then. +"------------------------------------------------------------------------------- + +XpathINIT + +function! F() abort + Xpath 'a' + let result = G() " not aborted + Xpath 'b' + if result != 2 + Xpath 'c' + endif + return 1 +endfunction + +function! G() " no abort attribute + Xpath 'd' + if H() != -1 " aborted + Xpath 'e' + endif + Xpath 'f' + return 2 +endfunction + +function! H() abort + Xpath 'g' + call I() " aborted + Xpath 'h' + return 4 +endfunction + +function! I() abort + Xpath 'i' + asdf " error + Xpath 'j' + return 8 +endfunction + +if F() != 1 + Xpath 'k' +endif + +let g:test9_result = g:Xpath + +delfunction F +delfunction G +delfunction H +delfunction I + +func Test_func_abort() + call assert_equal('adgifb', g:test9_result) +endfunc + + +"------------------------------------------------------------------------------- +" Test 10: :if, :elseif, :while argument parsing {{{1 +" +" A '"' or '|' in an argument expression must not be mixed up with +" a comment or a next command after a bar. Parsing errors should +" be recognized. +"------------------------------------------------------------------------------- + +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 + +if 1 || strlen("\"") | Xpath 'a' + Xpath 'b' +endif +Xpath 'c' + +if 0 +elseif 1 || strlen("\"") | Xpath 'd' + Xpath 'e' +endif +Xpath 'f' + +while 1 || strlen("\"") | Xpath 'g' + Xpath 'h' + break +endwhile +Xpath 'i' + +let v:errmsg = "" +if 1 ||| strlen("\"") | Xpath 'j' + Xpath 'k' +endif +Xpath 'l' +if !MSG('E15', "Invalid expression") + Xpath 'm' +endif + +let v:errmsg = "" +if 0 +elseif 1 ||| strlen("\"") | Xpath 'n' + Xpath 'o' +endif +Xpath 'p' +if !MSG('E15', "Invalid expression") + Xpath 'q' +endif + +let v:errmsg = "" +while 1 ||| strlen("\"") | Xpath 'r' + Xpath 's' + break +endwhile +Xpath 't' +if !MSG('E15', "Invalid expression") + Xpath 'u' +endif + +let g:test10_result = g:Xpath +delfunction MSG + +func Test_expr_parsing() + call assert_equal('abcdefghilpt', g:test10_result) +endfunc + + +"------------------------------------------------------------------------------- +" Test 11: :if, :elseif, :while argument evaluation after abort {{{1 +" +" When code is skipped over due to an error, the boolean argument to +" an :if, :elseif, or :while must not be evaluated. +"------------------------------------------------------------------------------- + +XpathINIT + +let calls = 0 + +function! P(num) + let g:calls = g:calls + a:num " side effect on call + return 0 +endfunction + +if 1 + Xpath 'a' + asdf " error + Xpath 'b' + if P(1) " should not be called + Xpath 'c' + elseif !P(2) " should not be called + Xpath 'd' + else + Xpath 'e' + endif + Xpath 'f' + while P(4) " should not be called + Xpath 'g' + endwhile + Xpath 'h' +endif +Xpath 'x' + +let g:test11_calls = calls +let g:test11_result = g:Xpath + +unlet calls +delfunction P + +func Test_arg_abort() + call assert_equal(0, g:test11_calls) + call assert_equal('ax', g:test11_result) +endfunc + + +"------------------------------------------------------------------------------- +" Test 12: Expressions in braces in skipped code {{{1 +" +" In code skipped over due to an error or inactive conditional, +" an expression in braces as part of a variable or function name +" should not be evaluated. +"------------------------------------------------------------------------------- + +XpathINIT + +function! NULL() + Xpath 'a' + return 0 +endfunction + +function! ZERO() + Xpath 'b' + return 0 +endfunction + +function! F0() + Xpath 'c' +endfunction + +function! F1(arg) + Xpath 'e' +endfunction + +let V0 = 1 + +Xpath 'f' +echo 0 ? F{NULL() + V{ZERO()}}() : 1 + +Xpath 'g' +if 0 + Xpath 'h' + call F{NULL() + V{ZERO()}}() +endif + +Xpath 'i' +if 1 + asdf " error + Xpath 'j' + call F1(F{NULL() + V{ZERO()}}()) +endif + +Xpath 'k' +if 1 + asdf " error + Xpath 'l' + call F{NULL() + V{ZERO()}}() +endif + +let g:test12_result = g:Xpath + +func Test_braces_skipped() + call assert_equal('fgik', g:test12_result) +endfunc + + +"------------------------------------------------------------------------------- +" Test 13: Failure in argument evaluation for :while {{{1 +" +" A failure in the expression evaluation for the condition of a :while +" causes the whole :while loop until the matching :endwhile being +" ignored. Continuation is at the next following line. +"------------------------------------------------------------------------------- + +XpathINIT + +Xpath 'a' +while asdf + Xpath 'b' + while 1 + Xpath 'c' + break + endwhile + Xpath 'd' + break +endwhile +Xpath 'e' + +while asdf | Xpath 'f' | endwhile | Xpath 'g' +Xpath 'h' +let g:test13_result = g:Xpath + +func Test_while_fail() + call assert_equal('aeh', g:test13_result) +endfunc + + +"------------------------------------------------------------------------------- +" Test 14: Failure in argument evaluation for :if {{{1 +" +" A failure in the expression evaluation for the condition of an :if +" does not cause the corresponding :else or :endif being matched to +" a previous :if/:elseif. Neither of both branches of the failed :if +" are executed. +"------------------------------------------------------------------------------- + +XpathINIT + +function! F() + Xpath 'a' + let x = 0 + if x " false + Xpath 'b' + elseif !x " always true + Xpath 'c' + let x = 1 + if g:boolvar " possibly undefined + Xpath 'd' + else + Xpath 'e' + endif + Xpath 'f' + elseif x " never executed + Xpath 'g' + endif + Xpath 'h' +endfunction + +let boolvar = 1 +call F() +Xpath '-' + +unlet boolvar +call F() +let g:test14_result = g:Xpath + +delfunction F + +func Test_if_fail() + call assert_equal('acdfh-acfh', g:test14_result) +endfunc + + +"------------------------------------------------------------------------------- +" Test 15: Failure in argument evaluation for :if (bar) {{{1 +" +" Like previous test, except that the failing :if ... | ... | :endif +" is in a single line. +"------------------------------------------------------------------------------- + +XpathINIT + +function! F() + Xpath 'a' + let x = 0 + if x " false + Xpath 'b' + elseif !x " always true + Xpath 'c' + let x = 1 + if g:boolvar | Xpath 'd' | else | Xpath 'e' | endif + Xpath 'f' + elseif x " never executed + Xpath 'g' + endif + Xpath 'h' +endfunction + +let boolvar = 1 +call F() +Xpath '-' + +unlet boolvar +call F() +let g:test15_result = g:Xpath + +delfunction F + +func Test_if_bar_fail() + call assert_equal('acdfh-acfh', g:test15_result) +endfunc + +"------------------------------------------------------------------------------- +" Test 90: Recognizing {} in variable name. {{{1 +"------------------------------------------------------------------------------- + +func Test_curlies() + let s:var = 66 + let ns = 's' + call assert_equal(66, {ns}:var) + + let g:a = {} + let g:b = 't' + let g:a[g:b] = 77 + call assert_equal(77, g:a['t']) +endfunc + +"------------------------------------------------------------------------------- +" Test 91: using type(). {{{1 +"------------------------------------------------------------------------------- + +func Test_type() + call assert_equal(0, type(0)) + call assert_equal(1, type("")) + call assert_equal(2, type(function("tr"))) + call assert_equal(2, type(function("tr", [8]))) + call assert_equal(3, type([])) + call assert_equal(4, type({})) + call assert_equal(5, type(0.0)) + call assert_equal(6, type(v:false)) + call assert_equal(6, type(v:true)) + call assert_equal(7, type(v:none)) + call assert_equal(7, type(v:null)) + call assert_equal(8, v:t_job) + call assert_equal(9, v:t_channel) + call assert_equal(v:t_number, type(0)) + call assert_equal(v:t_string, type("")) + call assert_equal(v:t_func, type(function("tr"))) + call assert_equal(v:t_func, type(function("tr", [8]))) + call assert_equal(v:t_list, type([])) + call assert_equal(v:t_dict, type({})) + call assert_equal(v:t_float, type(0.0)) + call assert_equal(v:t_bool, type(v:false)) + call assert_equal(v:t_bool, type(v:true)) + call assert_equal(v:t_none, type(v:none)) + call assert_equal(v:t_none, type(v:null)) + + + call assert_equal(0, 0 + v:false) + call assert_equal(1, 0 + v:true) + call assert_equal(0, 0 + v:none) + call assert_equal(0, 0 + v:null) + + call assert_equal('v:false', '' . v:false) + call assert_equal('v:true', '' . v:true) + call assert_equal('v:none', '' . v:none) + call assert_equal('v:null', '' . v:null) + + call assert_true(v:false == 0) + call assert_false(v:false != 0) + call assert_true(v:true == 1) + call assert_false(v:true != 1) + call assert_false(v:true == v:false) + call assert_true(v:true != v:false) + + call assert_true(v:null == 0) + call assert_false(v:null != 0) + call assert_true(v:none == 0) + call assert_false(v:none != 0) + + call assert_true(v:false is v:false) + call assert_true(v:true is v:true) + call assert_true(v:none is v:none) + call assert_true(v:null is v:null) + + call assert_false(v:false isnot v:false) + call assert_false(v:true isnot v:true) + call assert_false(v:none isnot v:none) + call assert_false(v:null isnot v:null) + + call assert_false(v:false is 0) + call assert_false(v:true is 1) + call assert_false(v:true is v:false) + call assert_false(v:none is 0) + call assert_false(v:null is 0) + call assert_false(v:null is v:none) + + call assert_true(v:false isnot 0) + call assert_true(v:true isnot 1) + call assert_true(v:true isnot v:false) + call assert_true(v:none isnot 0) + call assert_true(v:null isnot 0) + call assert_true(v:null isnot v:none) + + call assert_equal(v:false, eval(string(v:false))) + call assert_equal(v:true, eval(string(v:true))) + call assert_equal(v:none, eval(string(v:none))) + call assert_equal(v:null, eval(string(v:null))) + + call assert_equal(v:false, copy(v:false)) + call assert_equal(v:true, copy(v:true)) + call assert_equal(v:none, copy(v:none)) + call assert_equal(v:null, copy(v:null)) + + call assert_equal([v:false], deepcopy([v:false])) + call assert_equal([v:true], deepcopy([v:true])) + call assert_equal([v:none], deepcopy([v:none])) + call assert_equal([v:null], deepcopy([v:null])) + + call assert_true(empty(v:false)) + call assert_false(empty(v:true)) + call assert_true(empty(v:null)) + call assert_true(empty(v:none)) + + func ChangeYourMind() + try + return v:true + finally + return 'something else' + endtry + endfunc + + call ChangeYourMind() +endfunc + +"------------------------------------------------------------------------------- +" Test 92: skipping code {{{1 +"------------------------------------------------------------------------------- + +func Test_skip() + let Fn = function('Test_type') + call assert_false(0 && Fn[1]) + call assert_false(0 && string(Fn)) + call assert_false(0 && len(Fn)) + let l = [] + call assert_false(0 && l[1]) + call assert_false(0 && string(l)) + call assert_false(0 && len(l)) + let f = 1.0 + call assert_false(0 && f[1]) + call assert_false(0 && string(f)) + call assert_false(0 && len(f)) + let sp = v:null + call assert_false(0 && sp[1]) + call assert_false(0 && string(sp)) + call assert_false(0 && len(sp)) + +endfunc + +"------------------------------------------------------------------------------- +" Test 93: :echo and string() {{{1 +"------------------------------------------------------------------------------- + +func Test_echo_and_string() + " String + let a = 'foo bar' + redir => result + echo a + echo string(a) + redir END + let l = split(result, "\n") + call assert_equal(["foo bar", + \ "'foo bar'"], l) + + " Float + if has('float') + let a = -1.2e0 + redir => result + echo a + echo string(a) + redir END + let l = split(result, "\n") + call assert_equal(["-1.2", + \ "-1.2"], l) + endif + + " Funcref + redir => result + echo function('string') + echo string(function('string')) + redir END + let l = split(result, "\n") + call assert_equal(["string", + \ "function('string')"], l) + + " Recursive dictionary + let a = {} + let a["a"] = a + redir => result + echo a + echo string(a) + redir END + let l = split(result, "\n") + call assert_equal(["{'a': {...}}", + \ "{'a': {...}}"], l) + + " Recursive list + let a = [0] + let a[0] = a + redir => result + echo a + echo string(a) + redir END + let l = split(result, "\n") + call assert_equal(["[[...]]", + \ "[[...]]"], l) + + " Empty dictionaries in a list + let a = {} + redir => result + echo [a, a, a] + echo string([a, a, a]) + redir END + let l = split(result, "\n") + call assert_equal(["[{}, {}, {}]", + \ "[{}, {}, {}]"], l) + + " Empty dictionaries in a dictionary + let a = {} + let b = {"a": a, "b": a} + redir => result + echo b + echo string(b) + redir END + let l = split(result, "\n") + call assert_equal(["{'a': {}, 'b': {}}", + \ "{'a': {}, 'b': {}}"], l) + + " Empty lists in a list + let a = [] + redir => result + echo [a, a, a] + echo string([a, a, a]) + redir END + let l = split(result, "\n") + call assert_equal(["[[], [], []]", + \ "[[], [], []]"], l) + + " Empty lists in a dictionary + let a = [] + let b = {"a": a, "b": a} + redir => result + echo b + echo string(b) + redir END + let l = split(result, "\n") + call assert_equal(["{'a': [], 'b': []}", + \ "{'a': [], 'b': []}"], l) + + " Dictionaries in a list + let a = {"one": "yes", "two": "yes", "three": "yes"} + redir => result + echo [a, a, a] + echo string([a, a, a]) + redir END + let l = split(result, "\n") + call assert_equal(["[{'one': 'yes', 'two': 'yes', 'three': 'yes'}, {...}, {...}]", + \ "[{'one': 'yes', 'two': 'yes', 'three': 'yes'}, {'one': 'yes', 'two': 'yes', 'three': 'yes'}, {'one': 'yes', 'two': 'yes', 'three': 'yes'}]"], l) + + " Dictionaries in a dictionary + let a = {"one": "yes", "two": "yes", "three": "yes"} + let b = {"a": a, "b": a} + redir => result + echo b + echo string(b) + redir END + let l = split(result, "\n") + call assert_equal(["{'a': {'one': 'yes', 'two': 'yes', 'three': 'yes'}, 'b': {...}}", + \ "{'a': {'one': 'yes', 'two': 'yes', 'three': 'yes'}, 'b': {'one': 'yes', 'two': 'yes', 'three': 'yes'}}"], l) + + " Lists in a list + let a = [1, 2, 3] + redir => result + echo [a, a, a] + echo string([a, a, a]) + redir END + let l = split(result, "\n") + call assert_equal(["[[1, 2, 3], [...], [...]]", + \ "[[1, 2, 3], [1, 2, 3], [1, 2, 3]]"], l) + + " Lists in a dictionary + let a = [1, 2, 3] + let b = {"a": a, "b": a} + redir => result + echo b + echo string(b) + redir END + let l = split(result, "\n") + call assert_equal(["{'a': [1, 2, 3], 'b': [...]}", + \ "{'a': [1, 2, 3], 'b': [1, 2, 3]}"], l) + +endfunc + +"------------------------------------------------------------------------------- +" Test 94: 64-bit Numbers {{{1 +"------------------------------------------------------------------------------- + +func Test_num64() + if !has('num64') + return + endif + + call assert_notequal( 4294967296, 0) + call assert_notequal(-4294967296, 0) + call assert_equal( 4294967296, 0xFFFFffff + 1) + call assert_equal(-4294967296, -0xFFFFffff - 1) + + call assert_equal( 9223372036854775807, 1 / 0) + call assert_equal(-9223372036854775807, -1 / 0) + call assert_equal(-9223372036854775807 - 1, 0 / 0) + + call assert_equal( 0x7FFFffffFFFFffff, float2nr( 1.0e150)) + call assert_equal(-0x7FFFffffFFFFffff, float2nr(-1.0e150)) + + let rng = range(0xFFFFffff, 0x100000001) + call assert_equal([0xFFFFffff, 0x100000000, 0x100000001], rng) + call assert_equal(0x100000001, max(rng)) + call assert_equal(0xFFFFffff, min(rng)) + call assert_equal(rng, sort(range(0x100000001, 0xFFFFffff, -1), 'N')) +endfunc + +"------------------------------------------------------------------------------- +" Test 95: lines of :append, :change, :insert {{{1 +"------------------------------------------------------------------------------- + +function! DefineFunction(name, body) + let func = join(['function! ' . a:name . '()'] + a:body + ['endfunction'], "\n") + exec func +endfunction + +func Test_script_lines() + " :append + try + call DefineFunction('T_Append', [ + \ 'append', + \ 'py <