diff --git a/runtime/autoload/ccomplete.vim b/runtime/autoload/ccomplete.vim index 156b3af025..971e7367ce 100644 --- a/runtime/autoload/ccomplete.vim +++ b/runtime/autoload/ccomplete.vim @@ -1,7 +1,7 @@ " Vim completion script " Language: C " Maintainer: Bram Moolenaar -" Last Change: 2018 Aug 20 +" Last Change: 2020 Apr 08 let s:cpo_save = &cpo set cpo&vim @@ -635,3 +635,5 @@ endfunc let &cpo = s:cpo_save unlet s:cpo_save + +" vim: noet sw=2 sts=2 diff --git a/runtime/autoload/dist/ft.vim b/runtime/autoload/dist/ft.vim index 5c43ba280c..844a5ad73b 100644 --- a/runtime/autoload/dist/ft.vim +++ b/runtime/autoload/dist/ft.vim @@ -1,7 +1,7 @@ " Vim functions for file type detection " " Maintainer: Bram Moolenaar -" Last Change: 2020 Jan 02 +" Last Change: 2020 Mar 30 " These functions are moved here from runtime/filetype.vim to make startup " faster. @@ -325,7 +325,7 @@ endfunc func dist#ft#FTmm() let n = 1 - while n < 10 + while n < 20 let line = getline(n) if line =~ '^\s*\(#\s*\(include\|import\)\>\|@import\>\|/\*\)' setf objcpp diff --git a/runtime/doc/change.txt b/runtime/doc/change.txt index 1fc6c0a9a3..0b2c5be1db 100644 --- a/runtime/doc/change.txt +++ b/runtime/doc/change.txt @@ -1458,7 +1458,7 @@ text. Put it in your autoload directory, e.g. ~/.vim/autoload/format.vim: > func! format#Format() " only reformat on explicit gq command if mode() != 'n' - " fall back to Vims internal reformatting + " fall back to Vim's internal reformatting return 1 endif let lines = getline(v:lnum, v:lnum + v:count - 1) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index dc81d4b379..80b7df25a2 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1,4 +1,4 @@ -*eval.txt* For Vim version 8.2. Last change: 2020 Mar 26 +*eval.txt* For Vim version 8.2. Last change: 2020 Apr 08 VIM REFERENCE MANUAL by Bram Moolenaar @@ -5149,10 +5149,11 @@ getcompletion({pat}, {type} [, {filtered}]) *getcompletion()* < *getcurpos()* getcurpos() Get the position of the cursor. This is like getpos('.'), but - includes an extra item in the list: - [bufnum, lnum, col, off, curswant] ~ + includes an extra "curswant" item in the list: + [0, lnum, col, off, curswant] ~ The "curswant" number is the preferred column when moving the cursor vertically. Also see |getpos()|. + The first "bufnum" item is always zero. This can be used to save and restore the cursor position: > let save_cursor = getcurpos() @@ -8929,18 +8930,10 @@ settagstack({nr}, {dict} [, {action}]) *settagstack()* Returns zero for success, -1 for failure. - Examples: - Set current index of the tag stack to 4: > - call settagstack(1005, {'curidx' : 4}) - -< Empty the tag stack of window 3: > + Examples (for more examples see |tagstack-examples||): + Empty the tag stack of window 3: > call settagstack(3, {'items' : []}) -< Push a new item onto the tag stack: > - let pos = [bufnr('myfile.txt'), 10, 1, 0] - let newtag = [{'tagname' : 'mytag', 'from' : pos}] - call settagstack(2, {'items' : newtag}, 'a') - < Save and restore the tag stack: > let stack = gettagstack(1003) " do something else @@ -9036,6 +9029,8 @@ simplify({filename}) *simplify()* directory. In order to resolve all the involved symbolic links before simplifying the path name, use |resolve()|. + Can also be used as a |method|: > + GetName()->simplify() sin({expr}) *sin()* Return the sine of {expr}, measured in radians, as a |Float|. @@ -10888,6 +10883,7 @@ hpux HP-UX version of Vim. iconv Can use iconv() for conversion. insert_expand Compiled with support for CTRL-X expansion commands in Insert mode. (always true) +job Compiled with support for |channel| and |job| jumplist Compiled with |jumplist| support. keymap Compiled with 'keymap' support. lambda Compiled with |lambda| support. @@ -11255,8 +11251,8 @@ It is allowed to define another function inside a function body. You can provide default values for positional named arguments. This makes them optional for function calls. When a positional argument is not specified at a call, the default expression is used to initialize it. -This only works for functions declared with `:function`, not for lambda -expressions |expr-lambda|. +This only works for functions declared with `:function` or `:def`, not for +lambda expressions |expr-lambda|. Example: > function Something(key, value = 10) @@ -11294,9 +11290,10 @@ Example that does NOT work: > :function NoGood(first = a:second, second = 10) :endfunction < -When not using "...", the number of arguments in a function call must be equal -to the number of mandatory named arguments. When using "...", the number of -arguments may be larger. +When not using "...", the number of arguments in a function call must be at +least equal to the number of mandatory named arguments. When using "...", the +number of arguments may be larger than the total of mandatory and optional +arguments. *local-variables* Inside a function local variables can be used. These will disappear when the @@ -11653,7 +11650,7 @@ This does NOT work: > Like above, but append/add/subtract the value for each |List| item. -:let [{name}, ..., ; {lastname}] = {expr1} +:let [{name}, ..., ; {lastname}] = {expr1} *E452* Like |:let-unpack| above, but the |List| may have more items than there are names. A list of the remaining items is assigned to {lastname}. If there are no diff --git a/runtime/doc/gui_w32.txt b/runtime/doc/gui_w32.txt index fda3618336..30e2287826 100644 --- a/runtime/doc/gui_w32.txt +++ b/runtime/doc/gui_w32.txt @@ -199,7 +199,7 @@ With..." menu. This means you can use Vim to edit many files. Not every file One reason to add this is to be able to edit HTML files directly from Internet Explorer. To enable this use the "Tools" menu, "Internet Options..." entry. In the dialog select the "Programs" tab and select Vim in the "HTML editor" -choice. If it's not there than installing didn't work properly. +choice. If it's not there then installing didn't work properly. Doing this manually can be done with this script: diff --git a/runtime/doc/help.txt b/runtime/doc/help.txt index 58c10e0209..409e116494 100644 --- a/runtime/doc/help.txt +++ b/runtime/doc/help.txt @@ -1,4 +1,4 @@ -*help.txt* For Vim version 8.2. Last change: 2019 Jul 21 +*help.txt* For Vim version 8.2. Last change: 2020 Apr 05 VIM - main help file k @@ -31,7 +31,7 @@ Get specific help: It is possible to go directly to whatever you want help help entries for "word". Or use ":helpgrep word". |:helpgrep| - Getting started: Do the Vim tutor, a 20 minute interactive training for the + Getting started: Do the Vim tutor, a 30-minute interactive course for the basic commands, see |vimtutor|. Read the user manual from start to end: |usr_01.txt| @@ -41,7 +41,7 @@ through the help of many others. See |credits|. *doc-file-list* *Q_ct* BASIC: |quickref| Overview of the most common commands you will use -|tutor| 20 minutes training course for beginners +|tutor| 30-minute interactive course for beginners |copying| About copyrights |iccf| Helping poor children in Uganda |sponsor| Sponsor Vim development, become a registered Vim user @@ -144,7 +144,7 @@ Special issues ~ |remote.txt| using Vim as a server or client |term.txt| using different terminals and mice |terminal.txt| Terminal window support -|popup.txt| popop window support +|popup.txt| popup window support Programming language support ~ |indent.txt| automatic indenting for C and other languages diff --git a/runtime/doc/insert.txt b/runtime/doc/insert.txt index 934c1c57a9..99c2d40e7d 100644 --- a/runtime/doc/insert.txt +++ b/runtime/doc/insert.txt @@ -154,6 +154,8 @@ CTRL-R CTRL-R {register} *i_CTRL-R_CTRL-R* you also want to avoid these, use CTRL-R CTRL-O, see below. The '.' register (last inserted text) is still inserted as typed. + After this command, the '.' register contains the text from + the register as if it was inserted by typing it. CTRL-R CTRL-O {register} *i_CTRL-R_CTRL-O* Insert the contents of a register literally and don't @@ -163,6 +165,9 @@ CTRL-R CTRL-O {register} *i_CTRL-R_CTRL-O* Does not replace characters! The '.' register (last inserted text) is still inserted as typed. + After this command, the '.' register contains the command + typed and not the text. I.e., the literals "^R^O" and not the + text from the register. CTRL-R CTRL-P {register} *i_CTRL-R_CTRL-P* Insert the contents of a register literally and fix the @@ -170,6 +175,9 @@ CTRL-R CTRL-P {register} *i_CTRL-R_CTRL-P* Does not replace characters! The '.' register (last inserted text) is still inserted as typed. + After this command, the '.' register contains the command + typed and not the text. I.e., the literals "^R^P" and not the + text from the register. *i_CTRL-T* CTRL-T Insert one shiftwidth of indent at the start of the current diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 89a98b84af..ed55b8d4e1 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1,4 +1,4 @@ -*options.txt* For Vim version 8.2. Last change: 2020 Mar 02 +*options.txt* For Vim version 8.2. Last change: 2020 Apr 10 VIM REFERENCE MANUAL by Bram Moolenaar @@ -8107,7 +8107,7 @@ A jump table for the options with a short description can be found at |Q_op|. - VIM the server name |v:servername| or "VIM" Only works if the terminal supports setting window titles (currently Amiga console, Win32 console, all GUI versions and - terminals with a non- empty 't_ts' option - these are Unix xterm and + terminals with a non-empty 't_ts' option - these are Unix xterm and iris-ansi by default, where 't_ts' is taken from the builtin termcap). *X11* When Vim was compiled with HAVE_X11 defined, the original title will diff --git a/runtime/doc/os_beos.txt b/runtime/doc/os_beos.txt index ba0e07f8d4..916162fa4b 100644 --- a/runtime/doc/os_beos.txt +++ b/runtime/doc/os_beos.txt @@ -138,7 +138,7 @@ and merge it back in. 6. The $VIM directory *beos-vimdir* -$VIM is the symbolic name for the place where Vims support files are stored. +$VIM is the symbolic name for the place where Vim's support files are stored. The default value for $VIM is set at compile time and can be determined with > :version diff --git a/runtime/doc/os_haiku.txt b/runtime/doc/os_haiku.txt index aabfe1c85b..2c02994d50 100644 --- a/runtime/doc/os_haiku.txt +++ b/runtime/doc/os_haiku.txt @@ -88,7 +88,7 @@ Stuff that does not work yet: 4. The $VIM directory *haiku-vimdir* -$VIM is the symbolic name for the place where Vims support files are stored. +$VIM is the symbolic name for the place where Vim's support files are stored. The default value for $VIM is set at compile time and can be determined with > :version diff --git a/runtime/doc/tags b/runtime/doc/tags index 5981af8eff..6ff6b11b87 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -4298,6 +4298,7 @@ E447 editing.txt /*E447* E448 various.txt /*E448* E449 eval.txt /*E449* E45 message.txt /*E45* +E452 eval.txt /*E452* E455 print.txt /*E455* E456 print.txt /*E456* E457 print.txt /*E457* @@ -9477,6 +9478,7 @@ tags-file-format tagsrch.txt /*tags-file-format* tags-option tagsrch.txt /*tags-option* tagsrch.txt tagsrch.txt /*tagsrch.txt* tagstack tagsrch.txt /*tagstack* +tagstack-examples tagsrch.txt /*tagstack-examples* tan() eval.txt /*tan()* tanh() eval.txt /*tanh()* tar pi_tar.txt /*tar* diff --git a/runtime/doc/tagsrch.txt b/runtime/doc/tagsrch.txt index ed406e8dc3..0b22deba13 100644 --- a/runtime/doc/tagsrch.txt +++ b/runtime/doc/tagsrch.txt @@ -1,4 +1,4 @@ -*tagsrch.txt* For Vim version 8.2. Last change: 2020 Jan 30 +*tagsrch.txt* For Vim version 8.2. Last change: 2020 Apr 03 VIM REFERENCE MANUAL by Bram Moolenaar @@ -185,6 +185,29 @@ commands explained above the tag stack will look like this: The |gettagstack()| function returns the tag stack of a specified window. The |settagstack()| function modifies the tag stack of a window. + *tagstack-examples* +Write to the tag stack just like `:tag` but with a user-defined +jumper#jump_to_tag function: > + " Store where we're jumping from before we jump. + let tag = expand('') + let pos = [bufnr()] + getcurpos()[1:] + let item = {'bufnr': pos[0], 'from': pos, 'tagname': tag} + if jumper#jump_to_tag(tag) + " Jump was successful, write previous location to tag stack. + let winid = win_getid() + let stack = gettagstack(winid) + let stack['items'] = [item] + call settagstack(winid, stack, 't') + endif +< +Set current index of the tag stack to 4: > + call settagstack(1005, {'curidx' : 4}) +< +Push a new item onto the tag stack: > + let pos = [bufnr('myfile.txt'), 10, 1, 0] + let newtag = [{'tagname' : 'mytag', 'from' : pos}] + call settagstack(2, {'items' : newtag}, 'a') +< *E73* When you try to use the tag stack while it doesn't contain anything you will get an error message. diff --git a/runtime/doc/terminal.txt b/runtime/doc/terminal.txt index ac9d658412..8105b072f4 100644 --- a/runtime/doc/terminal.txt +++ b/runtime/doc/terminal.txt @@ -960,7 +960,7 @@ Currently supported commands: directory, thus it's best to use the full path. [options] is only used when opening a new window. If present, - it must be a Dict. Similarly to |++opt|, These entries are + it must be a Dict. Similarly to |++opt|, these entries are recognized: "ff" file format: "dos", "mac" or "unix" "fileformat" idem diff --git a/runtime/doc/testing.txt b/runtime/doc/testing.txt index 458aa7cbb0..9c87cba642 100644 --- a/runtime/doc/testing.txt +++ b/runtime/doc/testing.txt @@ -1,4 +1,4 @@ -*testing.txt* For Vim version 8.2. Last change: 2020 Feb 22 +*testing.txt* For Vim version 8.2. Last change: 2020 Apr 10 VIM REFERENCE MANUAL by Bram Moolenaar @@ -107,7 +107,7 @@ test_null_dict() *test_null_dict()* test_null_function() *test_null_function()* - Return a |FuncRef| that is null. Only useful for testing. + Return a |Funcref| that is null. Only useful for testing. test_null_job() *test_null_job()* diff --git a/runtime/doc/todo.txt b/runtime/doc/todo.txt index afa40227b7..c7269216ed 100644 --- a/runtime/doc/todo.txt +++ b/runtime/doc/todo.txt @@ -1,4 +1,4 @@ -*todo.txt* For Vim version 8.2. Last change: 2020 Mar 27 +*todo.txt* For Vim version 8.2. Last change: 2020 Apr 10 VIM REFERENCE MANUAL by Bram Moolenaar @@ -39,9 +39,19 @@ browser use: https://github.com/vim/vim/issues/1234 -------------------- Known bugs and current work ----------------------- Vim9 script: +func and partial types: +- check using func type with default arguments and varargs. + func(type, type?, ...): rettype +- Type checking arguments when calling :def function and test +- Calling unknown user function does not give proper error message: + assert_equal('123text', RefDef2Arg()) typo for "RetDef2Arg" - "func" inside "vim9script" doesn't work? (Ben Jackson, #5670) -- "let x = x + 1" should say that "x" is not defined (declare local after - evaluating expresion). +- :func inside vim9script must still use a:arg +- define function and create funcref in one step: + let ref = def(arg: type): rettype + body + enddef +Also: - "echo Func()" is an error if Func() does not return anything. - better implementation for partial and tests for that. - Make "g:imported = Export.exported" work in Vim9 script. @@ -50,7 +60,6 @@ Vim9 script: - Disallow unlet for local/script/imported vars - Support type for ":let"/":const" at script level for Vim9 script. (Ben Jackson, #5671) -- :func inside vim9script must still use a:arg - Make "++nr" work. - Check that import in legacy script works and puts item in s: - Error in any command in "vim9script" aborts sourcing. @@ -60,23 +69,19 @@ Vim9 script: - Test try/catch and throw better, also nested. Test return inside try/finally jumps to finally and then returns. - call autoload function. -- Type checking arguments when calling :def function - Implement more expressions, e.g. [a:b] - can use func as reference: def SomeFunc() ... map(list, SomeFunc) -- define function and create funcref in one step: - let ref = def(arg: type): rettype - Also extends lambda - Test: Function declared inside a :def function is local, disappears at the end of the function. Unless g: is used, just like with variables. - Can we omit \ for line continuation inside (), {}, ? Requires parsing while reading a function. Like fgetline in do_one_cmd()? - implement :type +- import type declaration? - implement class - implement interface - predefined class: Promise -- import statement for type declaration? - Make accessing varargs faster: arg[expr] EVAL expr LOADVARARG (varags idx) @@ -106,6 +111,8 @@ Popup windows: - Figure out the size and position better if wrapping inserts indent Text properties: +- Patch to fix that split / join does not update properties properly (Axel + Forsman, #5839) Alternative: #5875. - "cc" does not call inserted_bytes(). (Axel Forsman, #5763) - Get E685 with a sequence of commands. (#5674) - Combining text property with 'cursorline' does not always work (Billie @@ -176,17 +183,22 @@ Terminal emulator window: conversions. Error numbers available: -E451, E452, E453, E454, E460, E489, E491, E565, E578, E610, E611, E653, +E453, E454, E460, E489, E491, E565, E578, E610, E611, E653, E654, E856, E857, E861, E900 +Buffer autocommands are a bit inconsistent. Add a separate set of +autocommands for the buffer lifecycle: + BufIsCreated (after buffer ID exists) + BufIsLoaded (after buffer ID has content) + BufIsUnloaded (after buffer ID no longer has) + BufIsWiped (after buffer ID was wiped) + BufIsRenamed (after buffer ID gets another name) +The buffer list and windows are locked, no changes possible + Patch to fix drawing error with DirectX. (James Grant, #5688) Causes flicker on resizing. -Patch to make lambda functions faster (Ken Takata) -https://github.com/vim/vim/pull/5727 - LGTM remark: size derived from user input (getenv). Don't see how. - -Patch to use more FOR_ALL_ macros and use them. (Yegappan Lakshmanan, #5339) +In gvim always set t_Co to 16777216 (#5903) Patch to explain use of "%" in :!. (David Briscoe, #5591) diff --git a/runtime/doc/usr_22.txt b/runtime/doc/usr_22.txt index 00c0007de2..bdba90614b 100644 --- a/runtime/doc/usr_22.txt +++ b/runtime/doc/usr_22.txt @@ -1,4 +1,4 @@ -*usr_22.txt* For Vim version 8.2. Last change: 2019 Dec 07 +*usr_22.txt* For Vim version 8.2. Last change: 2020 Mar 28 VIM USER MANUAL - by Bram Moolenaar @@ -84,7 +84,7 @@ browser. This is what you get: > a................Hiding Files or Directories................|netrw-a| mb...............Bookmarking a Directory....................|netrw-mb| gb...............Changing to a Bookmarked Directory.........|netrw-gb| - c................Make Browsing Directory The Current Dir....|netrw-c| + cd...............Make Browsing Directory The Current Dir....|netrw-c| d................Make A New Directory.......................|netrw-d| D................Deleting Files or Directories..............|netrw-D| ............Edit File/Directory Hiding List............|netrw-ctrl-h| @@ -121,7 +121,7 @@ The following normal-mode commands may be used to control the browser display: As a sampling of extra normal-mode commands: - c Change Vim's notion of the current directory to be + cd Change Vim's notion of the current directory to be the same as the browser directory. (see |g:netrw_keepdir| to control this, too) R Rename the file or directory under the cursor; a diff --git a/runtime/doc/vim9.txt b/runtime/doc/vim9.txt index 1c180708ae..1337d4a6d3 100644 --- a/runtime/doc/vim9.txt +++ b/runtime/doc/vim9.txt @@ -1,4 +1,4 @@ -*vim9.txt* For Vim version 8.2. Last change: 2020 Apr 03 +*vim9.txt* For Vim version 8.2. Last change: 2020 Apr 09 VIM REFERENCE MANUAL by Bram Moolenaar @@ -120,6 +120,13 @@ and without `:let`, because there is no rule about where they are declared. Variables cannot shadow previously defined variables. Variables may shadow Ex commands, rename the variable if needed. +Global variables must be prefixed with "g:", also at the script level. +However, global user defined functions are used without "g:". > + vim9script + let script_local = 'text' + let g:global = 'value' + let Funcref = ThatFunction + Since "&opt = value" is now assigning a value to option "opt", ":&" cannot be used to repeat a `:substitute` command. @@ -156,6 +163,18 @@ since the function has to be looked up by name. And a typo in the function name will only be found when the call is executed. +Omitting function() ~ + +A user defined function can be used as a function reference in an expression +without `function()`. The argument types and return type will then be checked. +The function must already have been defined. > + + let Funcref = MyFunction + +When using `function()` the resulting type is "func", a function with any +number of arguments and any return type. The function can be defined later. + + No curly braces expansion ~ |curly-braces-names| cannot be used. @@ -213,8 +232,7 @@ few exceptions. blob non-empty list non-empty (different from JavaScript) dictionary non-empty (different from JavaScript) - func when not NULL - partial when not NULL + func when there is a function name special v:true job when not NULL channel when not NULL @@ -301,6 +319,7 @@ The following builtin types are supported: job channel func + func: {type} func({type}, ...) func({type}, ...): {type} @@ -318,12 +337,22 @@ memory. A partial and function can be declared in more or less specific ways: func any kind of function reference, no type - checking + checking for arguments or return value func: {type} any number and type of arguments with specific return type -func({type} ...) function with argument types, does not return +func({type}) function with argument type, does not return a value -func({type} ...): {type} function with argument types and return type +func({type}): {type} function with argument type and return type +func(?{type}) function with type of optional argument, does + not return a value +func(...{type}) function with type of variable number of + arguments, does not return a value +func({type}, ?{type}, ...{type}): {type} + function with: + - type of mandatory argument + - type of optional argument + - type of variable number of arguments + - return type If the return type is "void" the function does not return a value. diff --git a/runtime/ftplugin/man.vim b/runtime/ftplugin/man.vim index d7ce4d8acb..44efd4eb65 100644 --- a/runtime/ftplugin/man.vim +++ b/runtime/ftplugin/man.vim @@ -1,8 +1,7 @@ " Vim filetype plugin file " Language: man " Maintainer: SungHyun Nam -" Last Change: 2020 Mar 25 -" (fix by Jason Franklin) +" Last Change: 2020 Apr 6 " To make the ":Man" command available before editing a manual page, source " this script from your startup vimrc file. @@ -205,6 +204,7 @@ func GetPage(cmdmods, ...) let s:env_has_u = (v:shell_error == 0) endif let env_cmd = s:env_has_u ? 'env -u MANPAGER' : 'env MANPAGER=cat' + let env_cmd .= ' GROFF_NO_SGR=1' let man_cmd = env_cmd . ' man ' . s:GetCmdArg(sect, page) . ' | col -b' silent exec "r !" . man_cmd diff --git a/runtime/ftplugin/rst.vim b/runtime/ftplugin/rst.vim index f0646e9f36..ff7a402d10 100644 --- a/runtime/ftplugin/rst.vim +++ b/runtime/ftplugin/rst.vim @@ -3,7 +3,7 @@ " Maintainer: Marshall Ward " Original Maintainer: Nikolai Weibull " Website: https://github.com/marshallward/vim-restructuredtext -" Latest Revision: 2018-12-29 +" Latest Revision: 2020-03-31 if exists("b:did_ftplugin") finish @@ -34,7 +34,7 @@ if exists("g:rst_style") && g:rst_style != 0 setlocal expandtab shiftwidth=3 softtabstop=3 tabstop=8 endif -if has('patch-7.3.867') " Introduced the TextChanged event. +if g:rst_fold_enabled != 0 && has('patch-7.3.867') " Introduced the TextChanged event. setlocal foldmethod=expr setlocal foldexpr=RstFold#GetRstFold() setlocal foldtext=RstFold#GetRstFoldText() diff --git a/runtime/indent/rst.vim b/runtime/indent/rst.vim index c1ef8c9957..a31ad8e080 100644 --- a/runtime/indent/rst.vim +++ b/runtime/indent/rst.vim @@ -1,7 +1,9 @@ " Vim indent file -" Language: reStructuredText Documentation Format -" Previous Maintainer: Nikolai Weibull -" Latest Revision: 2011-08-03 +" Vim reST indent file +" Language: reStructuredText Documentation Format +" Maintainer: Marshall Ward +" Previous Maintainer: Nikolai Weibull +" Latest Revision: 2020-03-31 if exists("b:did_indent") finish @@ -18,6 +20,12 @@ endif let s:itemization_pattern = '^\s*[-*+]\s' let s:enumeration_pattern = '^\s*\%(\d\+\|#\)\.\s\+' +let s:note_pattern = '^\.\. ' + +function! s:get_paragraph_start() + let paragraph_mark_start = getpos("'{")[1] + return getline(paragraph_mark_start) =~ '\S' ? paragraph_mark_start : paragraph_mark_start + 1 +endfunction function GetRSTIndent() let lnum = prevnonblank(v:lnum - 1) @@ -28,6 +36,13 @@ function GetRSTIndent() let ind = indent(lnum) let line = getline(lnum) + let psnum = s:get_paragraph_start() + if psnum != 0 + if getline(psnum) =~ s:note_pattern + let ind = 3 + endif + endif + if line =~ s:itemization_pattern let ind += 2 elseif line =~ s:enumeration_pattern diff --git a/runtime/syntax/rst.vim b/runtime/syntax/rst.vim index c865cf6905..a90c90be21 100644 --- a/runtime/syntax/rst.vim +++ b/runtime/syntax/rst.vim @@ -1,9 +1,9 @@ -" Vim syntax file +" Vim reST syntax file " Language: reStructuredText documentation format " Maintainer: Marshall Ward " Previous Maintainer: Nikolai Weibull " Website: https://github.com/marshallward/vim-restructuredtext -" Latest Revision: 2018-12-29 +" Latest Revision: 2020-03-31 if exists("b:current_syntax") finish @@ -21,7 +21,7 @@ syn cluster rstCruft contains=rstEmphasis,rstStrongEmphasis, \ rstInlineInternalTargets,rstFootnoteReference,rstHyperlinkReference syn region rstLiteralBlock matchgroup=rstDelimiter - \ start='::\_s*\n\ze\z(\s\+\)' skip='^$' end='^\z1\@!' + \ start='\(^\z(\s*\).*\)\@<=::\n\s*\n' skip='^\s*$' end='^\(\z1\s\+\)\@!' \ contains=@NoSpell syn region rstQuotedLiteralBlock matchgroup=rstDelimiter @@ -90,16 +90,28 @@ execute 'syn match rstSubstitutionDefinition contained' . \ ' /|.*|\_s\+/ nextgroup=@rstDirectives' function! s:DefineOneInlineMarkup(name, start, middle, end, char_left, char_right) + " Only escape the first char of a multichar delimiter (e.g. \* inside **) + if a:start[0] == '\' + let first = a:start[0:1] + else + let first = a:start[0] + endif + + execute 'syn match rstEscape'.a:name.' +\\\\\|\\'.first.'+'.' contained' + execute 'syn region rst' . a:name . \ ' start=+' . a:char_left . '\zs' . a:start . \ '\ze[^[:space:]' . a:char_right . a:start[strlen(a:start) - 1] . ']+' . \ a:middle . - \ ' end=+\S' . a:end . '\ze\%($\|\s\|[''"’)\]}>/:.,;!?\\-]\)+' + \ ' end=+' . a:end . '\ze\%($\|\s\|[''"’)\]}>/:.,;!?\\-]\)+' . + \ ' contains=rstEscape' . a:name + + execute 'hi def link rstEscape'.a:name.' Special' endfunction function! s:DefineInlineMarkup(name, start, middle, end) let middle = a:middle != "" ? - \ (' skip=+\\\\\|\\' . a:middle . '+') : + \ (' skip=+\\\\\|\\' . a:middle . '\|\s' . a:middle . '+') : \ "" call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, "'", "'") @@ -161,7 +173,7 @@ syn match rstStandaloneHyperlink contains=@NoSpell \ "\<\%(\%(\%(https\=\|file\|ftp\|gopher\)://\|\%(mailto\|news\):\)[^[:space:]'\"<>]\+\|www[[:alnum:]_-]*\.[[:alnum:]_-]\+\.[^[:space:]'\"<>]\+\)[[:alnum:]/]" syn region rstCodeBlock contained matchgroup=rstDirective - \ start=+\%(sourcecode\|code\%(-block\)\=\)::\s\+.*\_s*\n\ze\z(\s\+\)+ + \ start=+\%(sourcecode\|code\%(-block\)\=\)::\s*\(\S*\)\?\s*\n\%(\s*:.*:\s*.*\s*\n\)*\n\ze\z(\s\+\)+ \ skip=+^$+ \ end=+^\z1\@!+ \ contains=@NoSpell diff --git a/runtime/syntax/vhdl.vim b/runtime/syntax/vhdl.vim index b40b096525..06fc2e795e 100644 --- a/runtime/syntax/vhdl.vim +++ b/runtime/syntax/vhdl.vim @@ -3,7 +3,7 @@ " Maintainer: Daniel Kho " Previous Maintainer: Czo " Credits: Stephan Hegel -" Last Changed: 2020 Mar 09 by Daniel Kho +" Last Changed: 2020 Apr 04 by Daniel Kho " quit when a syntax file was already loaded if exists("b:current_syntax") @@ -16,10 +16,10 @@ set cpo&vim " case is not significant syn case ignore -" VHDL keywords -syn keyword vhdlStatement access after alias all assert +" VHDL 1076-2019 keywords +syn keyword vhdlStatement access after alias all syn keyword vhdlStatement architecture array attribute -syn keyword vhdlStatement assume assume_guarantee +syn keyword vhdlStatement assert assume syn keyword vhdlStatement begin block body buffer bus syn keyword vhdlStatement case component configuration constant syn keyword vhdlStatement context cover @@ -34,20 +34,19 @@ syn keyword vhdlStatement map syn keyword vhdlStatement new next null syn keyword vhdlStatement of on open others out syn keyword vhdlStatement package port postponed procedure process pure -syn keyword vhdlStatement parameter property protected +syn keyword vhdlStatement parameter property protected private syn keyword vhdlStatement range record register reject report return -syn keyword vhdlStatement release restrict restrict_guarantee -syn keyword vhdlStatement select severity signal shared -syn keyword vhdlStatement subtype +syn keyword vhdlStatement release restrict +syn keyword vhdlStatement select severity signal shared subtype syn keyword vhdlStatement sequence strong syn keyword vhdlStatement then to transport type syn keyword vhdlStatement unaffected units until use -syn keyword vhdlStatement variable -" VHDL-2019 interface -syn keyword vhdlStatement view -syn keyword vhdlStatement vmode vprop vunit +syn keyword vhdlStatement variable view +syn keyword vhdlStatement vpkg vmode vprop vunit syn keyword vhdlStatement wait when while with -syn keyword vhdlStatement note warning error failure + +" VHDL predefined severity levels +syn keyword vhdlAttribute note warning error failure " Linting of conditionals. syn match vhdlStatement "\<\(if\|else\)\>" @@ -265,4 +264,5 @@ let b:current_syntax = "vhdl" let &cpo = s:cpo_save unlet s:cpo_save + " vim: ts=8 diff --git a/runtime/tutor/tutor b/runtime/tutor/tutor index 426fb57569..3add4f66df 100644 --- a/runtime/tutor/tutor +++ b/runtime/tutor/tutor @@ -7,7 +7,7 @@ enough of the commands that you will be able to easily use Vim as an all-purpose editor. - The approximate time required to complete the tutor is 25-30 minutes, + The approximate time required to complete the tutor is 30 minutes, depending upon how much time is spent with experimentation. ATTENTION: diff --git a/runtime/tutor/tutor.utf-8 b/runtime/tutor/tutor.utf-8 index 426fb57569..3add4f66df 100644 --- a/runtime/tutor/tutor.utf-8 +++ b/runtime/tutor/tutor.utf-8 @@ -7,7 +7,7 @@ enough of the commands that you will be able to easily use Vim as an all-purpose editor. - The approximate time required to complete the tutor is 25-30 minutes, + The approximate time required to complete the tutor is 30 minutes, depending upon how much time is spent with experimentation. ATTENTION: diff --git a/src/Makefile b/src/Makefile index cc6a20abd0..24c69342cf 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2318,7 +2318,7 @@ test1 \ # export TEST_FILTER=Test_terminal_wipe_buffer # A partial match also works: # export TEST_FILTER=wipe_buffer -$(NEW_TESTS): +$(NEW_TESTS) test_vim9: cd testdir; $(MAKE) $@ VIMPROG=../$(VIMTESTTARGET) $(GUI_TESTARG) SCRIPTSOURCE=../$(SCRIPTSOURCE) newtests: diff --git a/src/evalfunc.c b/src/evalfunc.c index a49c6bb858..375073761a 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -837,7 +837,7 @@ static funcentry_T global_functions[] = {"sign_undefine", 0, 1, FEARG_1, ret_number, SIGN_FUNC(f_sign_undefine)}, {"sign_unplace", 1, 2, FEARG_1, ret_number, SIGN_FUNC(f_sign_unplace)}, {"sign_unplacelist", 1, 2, FEARG_1, ret_list_number, SIGN_FUNC(f_sign_unplacelist)}, - {"simplify", 1, 1, 0, ret_string, f_simplify}, + {"simplify", 1, 1, FEARG_1, ret_string, f_simplify}, {"sin", 1, 1, FEARG_1, ret_float, FLOAT_FUNC(f_sin)}, {"sinh", 1, 1, FEARG_1, ret_float, FLOAT_FUNC(f_sinh)}, {"sort", 1, 3, FEARG_1, ret_list_any, f_sort}, @@ -4596,7 +4596,9 @@ f_has(typval_T *argvars, typval_T *rettv) if (x == TRUE && n == FALSE) { if (0) - ; + { + // intentionally empty + } #if defined(FEAT_BEVAL) && defined(FEAT_GUI_MSWIN) else if (STRICMP(name, "balloon_multiline") == 0) n = multiline_balloon_available(); diff --git a/src/evalvars.c b/src/evalvars.c index 693a5c4884..36563c6bb5 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -1917,15 +1917,17 @@ get_vimvar_dict(void) /* * Returns the index of a v:variable. Negative if not found. + * Returns DI_ flags in "di_flags". */ int -find_vim_var(char_u *name) +find_vim_var(char_u *name, int *di_flags) { - dictitem_T *di = find_var_in_ht(&vimvarht, 0, name, TRUE); - struct vimvar *vv; + dictitem_T *di = find_var_in_ht(&vimvarht, 0, name, TRUE); + struct vimvar *vv; if (di == NULL) return -1; + *di_flags = di->di_flags; vv = (struct vimvar *)((char *)di - offsetof(vimvar_T, vv_di)); return (int)(vv - vimvars); } @@ -1978,6 +1980,17 @@ set_vim_var_tv(int idx, typval_T *tv) clear_tv(tv); return FAIL; } + // VV_RO is also checked when compiling, but let's check here as well. + if (vimvars[idx].vv_flags & VV_RO) + { + semsg(_(e_readonlyvar), vimvars[idx].vv_name); + return FAIL; + } + if (sandbox && (vimvars[idx].vv_flags & VV_RO_SBX)) + { + semsg(_(e_readonlysbx), vimvars[idx].vv_name); + return FAIL; + } clear_tv(&vimvars[idx].vv_di.di_tv); vimvars[idx].vv_di.di_tv = *tv; return OK; diff --git a/src/list.c b/src/list.c index 9fe5384143..451e585910 100644 --- a/src/list.c +++ b/src/list.c @@ -368,12 +368,15 @@ list_equal( { listitem_T *item1, *item2; - if (l1 == NULL || l2 == NULL) - return FALSE; if (l1 == l2) return TRUE; if (list_len(l1) != list_len(l2)) return FALSE; + if (list_len(l1) == 0) + // empty and NULL list are considered equal + return TRUE; + if (l1 == NULL || l2 == NULL) + return FALSE; range_list_materialize(l1); range_list_materialize(l2); diff --git a/src/proto/evalvars.pro b/src/proto/evalvars.pro index 4338b20f73..352097d430 100644 --- a/src/proto/evalvars.pro +++ b/src/proto/evalvars.pro @@ -28,7 +28,7 @@ char *get_var_special_name(int nr); dict_T *get_globvar_dict(void); hashtab_T *get_globvar_ht(void); dict_T *get_vimvar_dict(void); -int find_vim_var(char_u *name); +int find_vim_var(char_u *name, int *di_flags); void set_vim_var_type(int idx, vartype_T type); void set_vim_var_nr(int idx, varnumber_T val); char *get_vim_var_name(int idx); diff --git a/src/structs.h b/src/structs.h index cdfb920c97..015d034368 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1290,6 +1290,10 @@ typedef long_u hash_T; // Type for hi_hash # endif #endif +// On rare systems "char" is unsigned, sometimes we really want a signed 8-bit +// value. +typedef signed char int8_T; + typedef double float_T; typedef struct listvar_S list_T; @@ -1342,7 +1346,7 @@ typedef enum typedef struct type_S type_T; struct type_S { vartype_T tt_type; - char tt_argcount; // for func, -1 for unknown + int8_T tt_argcount; // for func, -1 for unknown char tt_min_argcount; // number of non-optional arguments char tt_flags; // TTFLAG_ values type_T *tt_member; // for list, dict, func return type diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak index ae4cfdc133..c9b31d4535 100644 --- a/src/testdir/Make_all.mak +++ b/src/testdir/Make_all.mak @@ -43,6 +43,19 @@ SCRIPTS_WIN32 = # Tests for the GUI. SCRIPTS_GUI = +# Tests for Vim9 script. +TEST_VIM9 = \ + test_vim9_disassemble \ + test_vim9_expr \ + test_vim9_func \ + test_vim9_script + +TEST_VIM9_RES = \ + test_vim9_disassemble.res \ + test_vim9_expr.res \ + test_vim9_func.res \ + test_vim9_script.res + # Individual tests, including the ones part of test_alot. # Please keep sorted up to test_alot. NEW_TESTS = \ @@ -273,10 +286,7 @@ NEW_TESTS = \ test_utf8 \ test_utf8_comparisons \ test_vartabs \ - test_vim9_disassemble \ - test_vim9_expr \ - test_vim9_func \ - test_vim9_script \ + $(TEST_VIM9) \ test_viminfo \ test_vimscript \ test_virtualedit \ @@ -484,10 +494,7 @@ NEW_TESTS_RES = \ test_user_func.res \ test_usercommands.res \ test_vartabs.res \ - test_vim9_disassemble.res \ - test_vim9_expr.res \ - test_vim9_func.res \ - test_vim9_script.res \ + $(TEST_VIM9_RES) \ test_viminfo.res \ test_vimscript.res \ test_virtualedit.res \ diff --git a/src/testdir/Makefile b/src/testdir/Makefile index 746c849938..b2eaecbf40 100644 --- a/src/testdir/Makefile +++ b/src/testdir/Makefile @@ -79,6 +79,16 @@ $(NEW_TESTS): exit 1; \ fi +# Run only tests specific for Vim9 script +test_vim9: + rm -f test_vim9_*.res test.log messages + @MAKEFLAGS=--no-print-directory $(MAKE) -f Makefile $(TEST_VIM9_RES) VIMPROG=$(VIMPROG) XXDPROG=$(XXDPROG) SCRIPTSOURCE=$(SCRIPTSOURCE) + @cat messages + @MAKEFLAGS=--no-print-directory $(MAKE) -f Makefile report VIMPROG=$(VIMPROG) XXDPROG=$(XXDPROG) SCRIPTSOURCE=$(SCRIPTSOURCE) + @if test -f test.log; then \ + exit 1; \ + fi + RM_ON_RUN = test.out X* viminfo RM_ON_START = tiny.vim small.vim mbyte.vim mzscheme.vim test.ok benchmark.out RUN_VIM = VIMRUNTIME=$(SCRIPTSOURCE) $(VALGRIND) $(VIMPROG) -f $(GUI_FLAG) -u unix.vim $(NO_INITS) -s dotest.in diff --git a/src/testdir/term_util.vim b/src/testdir/term_util.vim index 32e2889140..715a4ac760 100644 --- a/src/testdir/term_util.vim +++ b/src/testdir/term_util.vim @@ -24,6 +24,21 @@ func StopShellInTerminal(buf) call WaitFor({-> job_status(job) == "dead"}) endfunc +" Wrapper around term_wait() to allow more time for re-runs of flaky tests +" The second argument is the minimum time to wait in msec, 10 if omitted. +func TermWait(buf, ...) + let wait_time = a:0 ? a:1 : 10 + if g:run_nr == 2 + let wait_time *= 4 + elseif g:run_nr > 2 + let wait_time *= 10 + endif + call term_wait(a:buf, wait_time) + + " In case it wasn't set yet. + let g:test_is_flaky = 1 +endfunc + " Run Vim with "arguments" in a new terminal window. " By default uses a size of 20 lines and 75 columns. " Returns the buffer number of the terminal. @@ -82,7 +97,7 @@ func RunVimInTerminal(arguments, options) let cols = term_getsize(buf)[1] endif - call term_wait(buf) + call TermWait(buf) " Wait for "All" or "Top" of the ruler to be shown in the last line or in " the status line of the last window. This can be quite slow (e.g. when diff --git a/src/testdir/test_arglist.vim b/src/testdir/test_arglist.vim index d73a3ccc27..aa81b57959 100644 --- a/src/testdir/test_arglist.vim +++ b/src/testdir/test_arglist.vim @@ -518,7 +518,7 @@ func Test_quit_with_arglist() call term_sendkeys(buf, ":set nomore\n") call term_sendkeys(buf, ":args a b c\n") call term_sendkeys(buf, ":quit\n") - call term_wait(buf) + call TermWait(buf) call WaitForAssert({-> assert_match('^E173:', term_getline(buf, 6))}) call StopVimInTerminal(buf) @@ -527,16 +527,16 @@ func Test_quit_with_arglist() call term_sendkeys(buf, ":set nomore\n") call term_sendkeys(buf, ":args a b c\n") call term_sendkeys(buf, ":confirm quit\n") - call term_wait(buf) + call TermWait(buf) call WaitForAssert({-> assert_match('^\[Y\]es, (N)o: *$', \ term_getline(buf, 6))}) call term_sendkeys(buf, "N") - call term_wait(buf) + call TermWait(buf) call term_sendkeys(buf, ":confirm quit\n") call WaitForAssert({-> assert_match('^\[Y\]es, (N)o: *$', \ term_getline(buf, 6))}) call term_sendkeys(buf, "Y") - call term_wait(buf) + call TermWait(buf) call WaitForAssert({-> assert_equal("finished", term_getstatus(buf))}) only! " When this test fails, swap files are left behind which breaks subsequent diff --git a/src/testdir/test_assert.vim b/src/testdir/test_assert.vim index 1b1f9e5151..762f12ff53 100644 --- a/src/testdir/test_assert.vim +++ b/src/testdir/test_assert.vim @@ -36,6 +36,9 @@ func Test_assert_equal() call assert_equal(0, assert_equal(4, n)) let l = [1, 2, 3] call assert_equal(0, assert_equal([1, 2, 3], l)) + call assert_equal(test_null_list(), test_null_list()) + call assert_equal(test_null_list(), []) + call assert_equal([], test_null_list()) let s = 'foo' call assert_equal(1, assert_equal('bar', s)) diff --git a/src/testdir/test_autocmd.vim b/src/testdir/test_autocmd.vim index 1de67c474b..326c682ffa 100644 --- a/src/testdir/test_autocmd.vim +++ b/src/testdir/test_autocmd.vim @@ -1761,9 +1761,9 @@ function s:Before_test_dirchanged() augroup END let s:li = [] let s:dir_this = getcwd() - let s:dir_foo = s:dir_this . '/foo' + let s:dir_foo = s:dir_this . '/Xfoo' call mkdir(s:dir_foo) - let s:dir_bar = s:dir_this . '/bar' + let s:dir_bar = s:dir_this . '/Xbar' call mkdir(s:dir_bar) endfunc @@ -2291,9 +2291,9 @@ func Test_autocmd_SafeState() call WaitForAssert({-> assert_match('^xxx', term_getline(buf, 6))}, 1000) call term_sendkeys(buf, ":let g:again = ''\:call CallTimer()\") - call term_wait(buf, 100) + call TermWait(buf, 50) call term_sendkeys(buf, ":\") - call term_wait(buf, 100) + call TermWait(buf, 50) call term_sendkeys(buf, ":echo g:again\") call WaitForAssert({-> assert_match('xtx', term_getline(buf, 6))}, 1000) @@ -2317,7 +2317,7 @@ func Test_autocmd_CmdWinEnter() let buf = RunVimInTerminal('-S '.filename, #{rows: 6}) call term_sendkeys(buf, "q:") - call term_wait(buf) + call TermWait(buf) call term_sendkeys(buf, ":echo b:dummy_var\") call WaitForAssert({-> assert_match('^This is a dummy', term_getline(buf, 6))}, 2000) call term_sendkeys(buf, ":echo &buftype\") diff --git a/src/testdir/test_balloon.vim b/src/testdir/test_balloon.vim index f32b73c0d4..bb22f7bf2e 100644 --- a/src/testdir/test_balloon.vim +++ b/src/testdir/test_balloon.vim @@ -32,14 +32,14 @@ func Test_balloon_eval_term() " Check that the balloon shows up after a mouse move let buf = RunVimInTerminal('-S XTest_beval', {'rows': 10, 'cols': 50}) - call term_wait(buf, 100) + call TermWait(buf, 50) call term_sendkeys(buf, 'll') call term_sendkeys(buf, ":call Trigger()\") call VerifyScreenDump(buf, 'Test_balloon_eval_term_01', {}) " Make sure the balloon still shows after 'updatetime' passed and CursorHold " was triggered. - call term_wait(buf, 300) + call TermWait(buf, 150) call VerifyScreenDump(buf, 'Test_balloon_eval_term_01a', {}) " clean up @@ -57,7 +57,7 @@ func Test_balloon_eval_term_visual() " Check that the balloon shows up after a mouse move let buf = RunVimInTerminal('-S XTest_beval_visual', {'rows': 10, 'cols': 50}) - call term_wait(buf, 100) + call TermWait(buf, 50) call VerifyScreenDump(buf, 'Test_balloon_eval_term_02', {}) " clean up diff --git a/src/testdir/test_bufline.vim b/src/testdir/test_bufline.vim index 3c3c89c618..a863ba5d3a 100644 --- a/src/testdir/test_bufline.vim +++ b/src/testdir/test_bufline.vim @@ -164,7 +164,7 @@ func Test_appendbufline_redraw() END call writefile(lines, 'XscriptMatchCommon') let buf = RunVimInTerminal('-S XscriptMatchCommon', #{rows: 10}) - call term_wait(buf) + call TermWait(buf) call VerifyScreenDump(buf, 'Test_appendbufline_1', {}) call StopVimInTerminal(buf) diff --git a/src/testdir/test_channel.vim b/src/testdir/test_channel.vim index dac90aa0e7..0cabd5c1af 100644 --- a/src/testdir/test_channel.vim +++ b/src/testdir/test_channel.vim @@ -1062,7 +1062,7 @@ func Test_write_to_buffer_and_scroll() END call writefile(lines, 'XtestBufferScroll') let buf = RunVimInTerminal('-S XtestBufferScroll', #{rows: 10}) - call term_wait(buf, 100) + call TermWait(buf, 50) call VerifyScreenDump(buf, 'Test_job_buffer_scroll_1', {}) " clean up diff --git a/src/testdir/test_clientserver.vim b/src/testdir/test_clientserver.vim index add6293bfc..94f10579c6 100644 --- a/src/testdir/test_clientserver.vim +++ b/src/testdir/test_clientserver.vim @@ -135,7 +135,7 @@ func Test_client_server() " Edit files in separate tab pages call system(cmd .. ' --remote-tab Xfile1 Xfile2 Xfile3') - call assert_equal('3', remote_expr(name, 'tabpagenr("$")')) + call WaitForAssert({-> assert_equal('3', remote_expr(name, 'tabpagenr("$")'))}) call assert_equal('Xfile2', remote_expr(name, 'bufname(tabpagebuflist(2)[0])')) eval name->remote_send(":%bw!\") diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim index e2b7fc298f..8aabaa859d 100644 --- a/src/testdir/test_cmdline.vim +++ b/src/testdir/test_cmdline.vim @@ -947,7 +947,7 @@ func Test_verbose_option() call writefile(lines, 'XTest_verbose') let buf = RunVimInTerminal('-S XTest_verbose', {'rows': 12}) - call term_wait(buf, 100) + call TermWait(buf, 50) call term_sendkeys(buf, ":DoSomething\") call VerifyScreenDump(buf, 'Test_verbose_option_1', {}) @@ -1024,7 +1024,7 @@ func Test_cmdwin_restore() call writefile(lines, 'XTest_restore') let buf = RunVimInTerminal('-S XTest_restore', {'rows': 12}) - call term_wait(buf, 100) + call TermWait(buf, 50) call term_sendkeys(buf, "q:") call VerifyScreenDump(buf, 'Test_cmdwin_restore_1', {}) @@ -1146,7 +1146,7 @@ func Test_cmdlineclear_tabenter() call writefile(lines, 'XtestCmdlineClearTabenter') let buf = RunVimInTerminal('-S XtestCmdlineClearTabenter', #{rows: 10}) - call term_wait(buf, 50) + call TermWait(buf, 25) " in one tab make the command line higher with CTRL-W - call term_sendkeys(buf, ":tabnew\\-\-gtgt") call VerifyScreenDump(buf, 'Test_cmdlineclear_tabenter', {}) diff --git a/src/testdir/test_conceal.vim b/src/testdir/test_conceal.vim index af0c3b8f79..bf942b7880 100644 --- a/src/testdir/test_conceal.vim +++ b/src/testdir/test_conceal.vim @@ -147,7 +147,7 @@ func Test_conceal_resize_term() call VerifyScreenDump(buf, 'Test_conceal_resize_01', {}) call win_execute(buf->win_findbuf()[0], 'wincmd +') - call term_wait(buf) + call TermWait(buf) call VerifyScreenDump(buf, 'Test_conceal_resize_02', {}) " clean up diff --git a/src/testdir/test_cursorline.vim b/src/testdir/test_cursorline.vim index d4a03afd38..03e7306d67 100644 --- a/src/testdir/test_cursorline.vim +++ b/src/testdir/test_cursorline.vim @@ -135,41 +135,41 @@ func Test_cursorline_screenline() call writefile(lines, filename) " basic test let buf = RunVimInTerminal('-S '. filename, #{rows: 20}) - call term_wait(buf) + call TermWait(buf) call VerifyScreenDump(buf, 'Test_'. filename. '_1', {}) call term_sendkeys(buf, "fagj") - call term_wait(buf) + call TermWait(buf) call VerifyScreenDump(buf, 'Test_'. filename. '_2', {}) call term_sendkeys(buf, "gj") - call term_wait(buf) + call TermWait(buf) call VerifyScreenDump(buf, 'Test_'. filename. '_3', {}) call term_sendkeys(buf, "gj") - call term_wait(buf) + call TermWait(buf) call VerifyScreenDump(buf, 'Test_'. filename. '_4', {}) call term_sendkeys(buf, "gj") - call term_wait(buf) + call TermWait(buf) call VerifyScreenDump(buf, 'Test_'. filename. '_5', {}) call term_sendkeys(buf, "gj") - call term_wait(buf) + call TermWait(buf) call VerifyScreenDump(buf, 'Test_'. filename. '_6', {}) " test with set list and cursorlineopt containing number call term_sendkeys(buf, "gg0") call term_sendkeys(buf, ":set list cursorlineopt+=number listchars=space:-\") call VerifyScreenDump(buf, 'Test_'. filename. '_7', {}) call term_sendkeys(buf, "fagj") - call term_wait(buf) + call TermWait(buf) call VerifyScreenDump(buf, 'Test_'. filename. '_8', {}) call term_sendkeys(buf, "gj") - call term_wait(buf) + call TermWait(buf) call VerifyScreenDump(buf, 'Test_'. filename. '_9', {}) call term_sendkeys(buf, "gj") - call term_wait(buf) + call TermWait(buf) call VerifyScreenDump(buf, 'Test_'. filename. '_10', {}) call term_sendkeys(buf, "gj") - call term_wait(buf) + call TermWait(buf) call VerifyScreenDump(buf, 'Test_'. filename. '_11', {}) call term_sendkeys(buf, "gj") - call term_wait(buf) + call TermWait(buf) call VerifyScreenDump(buf, 'Test_'. filename. '_12', {}) if exists("+foldcolumn") && exists("+signcolumn") && exists("+breakindent") " test with set foldcolumn signcoloumn and breakindent @@ -177,19 +177,19 @@ func Test_cursorline_screenline() call term_sendkeys(buf, ":set breakindent foldcolumn=2 signcolumn=yes\") call VerifyScreenDump(buf, 'Test_'. filename. '_13', {}) call term_sendkeys(buf, "fagj") - call term_wait(buf) + call TermWait(buf) call VerifyScreenDump(buf, 'Test_'. filename. '_14', {}) call term_sendkeys(buf, "gj") - call term_wait(buf) + call TermWait(buf) call VerifyScreenDump(buf, 'Test_'. filename. '_15', {}) call term_sendkeys(buf, "gj") - call term_wait(buf) + call TermWait(buf) call VerifyScreenDump(buf, 'Test_'. filename. '_16', {}) call term_sendkeys(buf, "gj") - call term_wait(buf) + call TermWait(buf) call VerifyScreenDump(buf, 'Test_'. filename. '_17', {}) call term_sendkeys(buf, "gj") - call term_wait(buf) + call TermWait(buf) call VerifyScreenDump(buf, 'Test_'. filename. '_18', {}) endif diff --git a/src/testdir/test_debugger.vim b/src/testdir/test_debugger.vim index 8ba3998f3f..a99154a5af 100644 --- a/src/testdir/test_debugger.vim +++ b/src/testdir/test_debugger.vim @@ -8,7 +8,7 @@ source check.vim " If the expected output argument is supplied, then check for it. func RunDbgCmd(buf, cmd, ...) call term_sendkeys(a:buf, a:cmd . "\r") - call term_wait(a:buf, 20) + call TermWait(a:buf) if a:0 != 0 " Verify the expected output diff --git a/src/testdir/test_diffmode.vim b/src/testdir/test_diffmode.vim index 07aa919f4c..a251d3fec2 100644 --- a/src/testdir/test_diffmode.vim +++ b/src/testdir/test_diffmode.vim @@ -801,7 +801,7 @@ func VerifyInternal(buf, dumpfile, extra) call term_sendkeys(a:buf, ":diffupdate!\") " trailing : for leaving the cursor on the command line call term_sendkeys(a:buf, ":set diffopt=internal,filler" . a:extra . "\:") - call term_wait(a:buf) + call TermWait(a:buf) call VerifyScreenDump(a:buf, a:dumpfile, {}) endfunc diff --git a/src/testdir/test_display.vim b/src/testdir/test_display.vim index f439bfe272..1093641783 100644 --- a/src/testdir/test_display.vim +++ b/src/testdir/test_display.vim @@ -174,7 +174,7 @@ func Test_scroll_CursorLineNr_update() call writefile(lines, filename) let buf = RunVimInTerminal('-S '.filename, #{rows: 5, cols: 50}) call term_sendkeys(buf, "k") - call term_wait(buf) + call TermWait(buf) call VerifyScreenDump(buf, 'Test_winline_rnu', {}) " clean up diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim index 427e404c87..3b9e34c191 100644 --- a/src/testdir/test_functions.vim +++ b/src/testdir/test_functions.vim @@ -450,7 +450,7 @@ func Test_simplify() call assert_equal('/', simplify('/.')) call assert_equal('/', simplify('/..')) call assert_equal('/...', simplify('/...')) - call assert_equal('./dir/file', simplify('./dir/file')) + call assert_equal('./dir/file', './dir/file'->simplify()) call assert_equal('./dir/file', simplify('.///dir//file')) call assert_equal('./dir/file', simplify('./dir/./file')) call assert_equal('./file', simplify('./dir/../file')) @@ -1858,15 +1858,6 @@ endfunc func Test_state() CheckRunVimInTerminal - " In the first run try a short wait time. If the test fails retry with a - " longer wait time. - if g:run_nr == 1 - let wait_time = 50 - elseif g:run_nr == 2 - let wait_time = 200 - else - let wait_time = 500 - endif let getstate = ":echo 'state: ' .. g:state .. '; mode: ' .. g:mode\" let lines =<< trim END @@ -1888,27 +1879,27 @@ func Test_state() " Using a timer callback call term_sendkeys(buf, ":call RunTimer()\") - call term_wait(buf, wait_time) + call TermWait(buf, 25) call term_sendkeys(buf, getstate) call WaitForAssert({-> assert_match('state: c; mode: n', term_getline(buf, 6))}, 1000) " Halfway a mapping call term_sendkeys(buf, ":call RunTimer()\;") - call term_wait(buf, wait_time) + call TermWait(buf, 25) call term_sendkeys(buf, ";") call term_sendkeys(buf, getstate) call WaitForAssert({-> assert_match('state: mSc; mode: n', term_getline(buf, 6))}, 1000) " Insert mode completion (bit slower on Mac) call term_sendkeys(buf, ":call RunTimer()\Got\") - call term_wait(buf, wait_time) + call TermWait(buf, 25) call term_sendkeys(buf, "\") call term_sendkeys(buf, getstate) call WaitForAssert({-> assert_match('state: aSc; mode: i', term_getline(buf, 6))}, 1000) " Autocommand executing call term_sendkeys(buf, ":set filetype=foobar\") - call term_wait(buf, wait_time) + call TermWait(buf, 25) call term_sendkeys(buf, getstate) call WaitForAssert({-> assert_match('state: xS; mode: n', term_getline(buf, 6))}, 1000) @@ -1916,7 +1907,7 @@ func Test_state() " messages scrolled call term_sendkeys(buf, ":call RunTimer()\:echo \"one\\ntwo\\nthree\"\") - call term_wait(buf, wait_time) + call TermWait(buf, 25) call term_sendkeys(buf, "\") call term_sendkeys(buf, getstate) call WaitForAssert({-> assert_match('state: Scs; mode: r', term_getline(buf, 6))}, 1000) diff --git a/src/testdir/test_highlight.vim b/src/testdir/test_highlight.vim index dfc9e24212..73b72289e6 100644 --- a/src/testdir/test_highlight.vim +++ b/src/testdir/test_highlight.vim @@ -542,9 +542,9 @@ func Test_cursorline_after_yank() \ 'call setline(1, ["","1","2","3",""])', \ ], 'Xtest_cursorline_yank') let buf = RunVimInTerminal('-S Xtest_cursorline_yank', {'rows': 8}) - call term_wait(buf) + call TermWait(buf) call term_sendkeys(buf, "Gy3k") - call term_wait(buf) + call TermWait(buf) call term_sendkeys(buf, "jj") call VerifyScreenDump(buf, 'Test_cursorline_yank_01', {}) @@ -582,7 +582,7 @@ func Test_cursorline_with_visualmode() \ 'call setline(1, repeat(["abc"], 50))', \ ], 'Xtest_cursorline_with_visualmode') let buf = RunVimInTerminal('-S Xtest_cursorline_with_visualmode', {'rows': 12}) - call term_wait(buf) + call TermWait(buf) call term_sendkeys(buf, "V\kkkjk") call VerifyScreenDump(buf, 'Test_cursorline_with_visualmode_01', {}) @@ -610,9 +610,9 @@ func Test_wincolor() END call writefile(lines, 'Xtest_wincolor') let buf = RunVimInTerminal('-S Xtest_wincolor', {'rows': 8}) - call term_wait(buf) + call TermWait(buf) call term_sendkeys(buf, "2G5lvj") - call term_wait(buf) + call TermWait(buf) call VerifyScreenDump(buf, 'Test_wincolor_01', {}) @@ -662,7 +662,7 @@ func Test_colorcolumn() call writefile(lines, 'Xtest_colorcolumn') let buf = RunVimInTerminal('-S Xtest_colorcolumn', {'rows': 10}) call term_sendkeys(buf, ":\") - call term_wait(buf) + call TermWait(buf) call VerifyScreenDump(buf, 'Test_colorcolumn_1', {}) " clean up diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim index b7893fffbe..a1c7b98f18 100644 --- a/src/testdir/test_ins_complete.vim +++ b/src/testdir/test_ins_complete.vim @@ -402,7 +402,7 @@ func Test_pum_with_folds_two_tabs() call writefile(lines, 'Xpumscript') let buf = RunVimInTerminal('-S Xpumscript', #{rows: 10}) - call term_wait(buf, 100) + call TermWait(buf, 50) call term_sendkeys(buf, "a\") call VerifyScreenDump(buf, 'Test_pum_with_folds_two_tabs', {}) @@ -427,9 +427,9 @@ func Test_pum_with_preview_win() call writefile(lines, 'Xpreviewscript') let buf = RunVimInTerminal('-S Xpreviewscript', #{rows: 12}) - call term_wait(buf, 100) + call TermWait(buf, 50) call term_sendkeys(buf, "Gi\\") - call term_wait(buf, 200) + call TermWait(buf, 100) call term_sendkeys(buf, "\") call VerifyScreenDump(buf, 'Test_pum_with_preview_win', {}) diff --git a/src/testdir/test_mapping.vim b/src/testdir/test_mapping.vim index 71f254a780..f6e712406c 100644 --- a/src/testdir/test_mapping.vim +++ b/src/testdir/test_mapping.vim @@ -430,9 +430,9 @@ func Test_error_in_map_expr() " GC must not run during map-expr processing, which can make Vim crash. call term_sendkeys(buf, '!') - call term_wait(buf, 100) + call TermWait(buf, 50) call term_sendkeys(buf, "\") - call term_wait(buf, 100) + call TermWait(buf, 50) call assert_equal('run', job_status(job)) call term_sendkeys(buf, ":qall!\") @@ -510,7 +510,7 @@ func Test_expr_map_restore_cursor() END call writefile(lines, 'XtestExprMap') let buf = RunVimInTerminal('-S XtestExprMap', #{rows: 10}) - call term_wait(buf) + call TermWait(buf) call term_sendkeys(buf, "\") call VerifyScreenDump(buf, 'Test_map_expr_1', {}) diff --git a/src/testdir/test_marks.vim b/src/testdir/test_marks.vim index 15be080137..fcae2ac137 100644 --- a/src/testdir/test_marks.vim +++ b/src/testdir/test_marks.vim @@ -207,6 +207,9 @@ func Test_mark_error() call assert_fails('mark xx', 'E488:') call assert_fails('mark _', 'E191:') call assert_beeps('normal! m~') + + call setpos("'k", [0, 100, 1, 0]) + call assert_fails("normal 'k", 'E19:') endfunc " Test for :lockmarks when pasting content diff --git a/src/testdir/test_match.vim b/src/testdir/test_match.vim index 59098f7136..cd8ae2eb56 100644 --- a/src/testdir/test_match.vim +++ b/src/testdir/test_match.vim @@ -289,7 +289,7 @@ func OtherWindowCommon() END call writefile(lines, 'XscriptMatchCommon') let buf = RunVimInTerminal('-S XscriptMatchCommon', #{rows: 12}) - call term_wait(buf) + call TermWait(buf) return buf endfunc diff --git a/src/testdir/test_matchadd_conceal.vim b/src/testdir/test_matchadd_conceal.vim index 7c02087e23..be154643e6 100644 --- a/src/testdir/test_matchadd_conceal.vim +++ b/src/testdir/test_matchadd_conceal.vim @@ -298,14 +298,14 @@ func Test_cursor_column_in_concealed_line_after_window_scroll() END call writefile(lines, 'Xcolesearch') let buf = RunVimInTerminal('Xcolesearch', {}) - call term_wait(buf, 100) + call TermWait(buf, 50) " Jump to something that is beyond the bottom of the window, " so there's a scroll down. call term_sendkeys(buf, ":so %\") - call term_wait(buf, 100) + call TermWait(buf, 50) call term_sendkeys(buf, "/expr\") - call term_wait(buf, 100) + call TermWait(buf, 50) " Are the concealed parts of the current line really hidden? let cursor_row = term_scrape(buf, '.')->map({_, e -> e.chars})->join('') @@ -335,7 +335,7 @@ func Test_cursor_column_in_concealed_line_after_leftcol_change() " Horizontal scroll would center the cursor in the screen line, but conceal " makes it go to screen column 1. call term_sendkeys(buf, "$") - call term_wait(buf) + call TermWait(buf) " Are the concealed parts of the current line really hidden? call WaitForAssert({-> assert_equal('c', term_getline(buf, '.'))}) diff --git a/src/testdir/test_messages.vim b/src/testdir/test_messages.vim index 23e7735cb0..90d0d201f7 100644 --- a/src/testdir/test_messages.vim +++ b/src/testdir/test_messages.vim @@ -114,7 +114,7 @@ func Test_mode_message_at_leaving_insert_by_ctrl_c() let rows = 10 let buf = term_start([GetVimProg(), '--clean', '-S', testfile], {'term_rows': rows}) - call term_wait(buf, 200) + call TermWait(buf, 100) call assert_equal('run', job_status(term_getjob(buf))) call term_sendkeys(buf, "i") @@ -143,7 +143,7 @@ func Test_mode_message_at_leaving_insert_with_esc_mapped() let rows = 10 let buf = term_start([GetVimProg(), '--clean', '-S', testfile], {'term_rows': rows}) - call term_wait(buf, 200) + call WaitForAssert({-> assert_match('0,0-1\s*All$', term_getline(buf, rows - 1))}) call assert_equal('run', job_status(term_getjob(buf))) call term_sendkeys(buf, "i") diff --git a/src/testdir/test_number.vim b/src/testdir/test_number.vim index fef187bf90..17a1e35117 100644 --- a/src/testdir/test_number.vim +++ b/src/testdir/test_number.vim @@ -280,7 +280,7 @@ func Test_relativenumber_colors() " Check that the balloon shows up after a mouse move let buf = RunVimInTerminal('-S XTest_relnr', {'rows': 10, 'cols': 50}) - call term_wait(buf, 100) + call TermWait(buf, 50) " Default colors call VerifyScreenDump(buf, 'Test_relnr_colors_1', {}) diff --git a/src/testdir/test_options.vim b/src/testdir/test_options.vim index ef3ae1ad41..e1b11e933e 100644 --- a/src/testdir/test_options.vim +++ b/src/testdir/test_options.vim @@ -677,6 +677,15 @@ func Test_buftype() bwipe! endfunc +" Test for the 'shell' option +func Test_shell() + CheckUnix + let save_shell = &shell + set shell= + call assert_fails('shell', 'E91:') + let &shell = save_shell +endfunc + " Test for the 'shellquote' option func Test_shellquote() CheckUnix diff --git a/src/testdir/test_popup.vim b/src/testdir/test_popup.vim index 4ca35b2568..e96d5fda50 100644 --- a/src/testdir/test_popup.vim +++ b/src/testdir/test_popup.vim @@ -683,11 +683,11 @@ func Test_popup_and_window_resize() call term_sendkeys(buf, "Gi\") call term_sendkeys(buf, "\") - call term_wait(buf, 100) + call TermWait(buf, 50) " popup first entry "!" must be at the top call WaitForAssert({-> assert_match('^!\s*$', term_getline(buf, 1))}) exe 'resize +' . (h - 1) - call term_wait(buf, 100) + call TermWait(buf, 50) redraw! " popup shifted down, first line is now empty call WaitForAssert({-> assert_equal('', term_getline(buf, 1))}) @@ -750,11 +750,11 @@ func Test_popup_and_previewwindow_dump() let buf = RunVimInTerminal('-S Xscript', {}) " wait for the script to finish - call term_wait(buf) + call TermWait(buf) " Test that popup and previewwindow do not overlap. call term_sendkeys(buf, "o") - call term_wait(buf, 100) + call TermWait(buf, 50) call term_sendkeys(buf, "\\") call VerifyScreenDump(buf, 'Test_popup_and_previewwindow_01', {}) diff --git a/src/testdir/test_popupwin.vim b/src/testdir/test_popupwin.vim index 478e9d49e9..03285f935c 100644 --- a/src/testdir/test_popupwin.vim +++ b/src/testdir/test_popupwin.vim @@ -65,9 +65,9 @@ func Test_simple_popup() " clear all popups after moving the cursor a bit, so that ruler is updated call term_sendkeys(buf, "axxx\") - call term_wait(buf) + call TermWait(buf) call term_sendkeys(buf, "0") - call term_wait(buf) + call TermWait(buf) call term_sendkeys(buf, ":call popup_clear()\") call VerifyScreenDump(buf, 'Test_popupwin_08', {}) @@ -1389,7 +1389,7 @@ func Test_popup_beval() END call writefile(lines, 'XtestPopupBeval') let buf = RunVimInTerminal('-S XtestPopupBeval', #{rows: 10}) - call term_wait(buf, 100) + call TermWait(buf, 50) call term_sendkeys(buf, 'j') call term_sendkeys(buf, ":call Hover()\") call VerifyScreenDump(buf, 'Test_popupwin_beval_1', {}) @@ -2958,7 +2958,7 @@ func Test_popupmenu_info_border() call writefile(lines, 'XtestInfoPopup') let buf = RunVimInTerminal('-S XtestInfoPopup', #{rows: 14}) - call term_wait(buf, 50) + call TermWait(buf, 25) call term_sendkeys(buf, "A\\") call VerifyScreenDump(buf, 'Test_popupwin_infopopup_1', {}) @@ -3006,7 +3006,7 @@ func Test_popupmenu_info_noborder() call writefile(lines, 'XtestInfoPopupNb') let buf = RunVimInTerminal('-S XtestInfoPopupNb', #{rows: 14}) - call term_wait(buf, 50) + call TermWait(buf, 25) call term_sendkeys(buf, "A\\") call VerifyScreenDump(buf, 'Test_popupwin_infopopup_nb_1', {}) @@ -3024,7 +3024,7 @@ func Test_popupmenu_info_align_menu() call writefile(lines, 'XtestInfoPopupNb') let buf = RunVimInTerminal('-S XtestInfoPopupNb', #{rows: 14}) - call term_wait(buf, 50) + call TermWait(buf, 25) call term_sendkeys(buf, "A\\") call term_sendkeys(buf, "\") @@ -3055,7 +3055,7 @@ func Test_popupmenu_info_hidden() call writefile(lines, 'XtestInfoPopupHidden') let buf = RunVimInTerminal('-S XtestInfoPopupHidden', #{rows: 14}) - call term_wait(buf, 50) + call TermWait(buf, 25) call term_sendkeys(buf, "A\\") call VerifyScreenDump(buf, 'Test_popupwin_infopopup_hidden_1', {}) @@ -3113,7 +3113,7 @@ func Test_popupmenu_info_too_wide() call writefile(lines, 'XtestInfoPopupWide') let buf = RunVimInTerminal('-S XtestInfoPopupWide', #{rows: 8}) - call term_wait(buf, 50) + call TermWait(buf, 25) call term_sendkeys(buf, "Ascr\\") call VerifyScreenDump(buf, 'Test_popupwin_infopopup_wide_1', {}) diff --git a/src/testdir/test_profile.vim b/src/testdir/test_profile.vim index 5f3f7cb726..7018ea5fbc 100644 --- a/src/testdir/test_profile.vim +++ b/src/testdir/test_profile.vim @@ -541,7 +541,7 @@ func Test_profile_typed_func() \ .. "endfunc\") call term_sendkeys(buf, ":profile func DoSomething\") call term_sendkeys(buf, ":call DoSomething()\") - call term_wait(buf, 200) + call TermWait(buf, 100) call StopVimInTerminal(buf) let lines = readfile('XprofileTypedFunc') call assert_equal("FUNCTION DoSomething()", lines[0]) diff --git a/src/testdir/test_regexp_latin.vim b/src/testdir/test_regexp_latin.vim index 501a5667ab..f2910f0646 100644 --- a/src/testdir/test_regexp_latin.vim +++ b/src/testdir/test_regexp_latin.vim @@ -147,7 +147,10 @@ endfunc " Tests for regexp patterns without multi-byte support. func Test_regexp_single_line_pat() " tl is a List of Lists with: - " regexp engine + " regexp engines to test + " 0 - test with 'regexpengine' values 0 and 1 + " 1 - test with 'regexpengine' values 0 and 2 + " 2 - test with 'regexpengine' values 0, 1 and 2 " regexp pattern " text to test the pattern on " expected match (optional) @@ -168,6 +171,8 @@ func Test_regexp_single_line_pat() call add(tl, [2, 'c*', 'abdef', '']) call add(tl, [2, 'bc\+', 'abccccdef', 'bcccc']) call add(tl, [2, 'bc\+', 'abdef']) " no match + " match newline character in a string + call add(tl, [2, 'o\nb', "foo\nbar", "o\nb"]) " operator \| call add(tl, [2, 'a\|ab', 'cabd', 'a']) " alternation is ordered @@ -591,6 +596,9 @@ func Test_regexp_single_line_pat() " Test \%V atom call add(tl, [2, '\%>70vGesamt', 'Jean-Michel Charlier & Victor Hubinon\Gesamtausgabe [Salleck] Buck Danny {Jean-Michel Charlier & Victor Hubinon}\Gesamtausgabe', 'Gesamt']) + " Test for ignoring case and matching repeated characters + call add(tl, [2, '\cb\+', 'aAbBbBcC', 'bBbB']) + " Run the tests for t in tl let re = t[0] @@ -650,6 +658,14 @@ endfunc " Tests for multi-line regexp patterns without multi-byte support. func Test_regexp_multiline_pat() + " tl is a List of Lists with: + " regexp engines to test + " 0 - test with 'regexpengine' values 0 and 1 + " 1 - test with 'regexpengine' values 0 and 2 + " 2 - test with 'regexpengine' values 0, 1 and 2 + " regexp pattern + " List with text to test the pattern on + " List with the expected match let tl = [] " back references @@ -659,6 +675,70 @@ func Test_regexp_multiline_pat() " line breaks call add(tl, [2, '\S.*\nx', ['abc', 'def', 'ghi', 'xjk', 'lmn'], ['abc', 'def', 'XXjk', 'lmn']]) + " Any single character or end-of-line + call add(tl, [2, '\_.\+', ['a', 'b', 'c'], ['XX']]) + " Any identifier or end-of-line + call add(tl, [2, '\_i\+', ['a', 'b', ';', '2'], ['XX;XX']]) + " Any identifier but excluding digits or end-of-line + call add(tl, [2, '\_I\+', ['a', 'b', ';', '2'], ['XX;XX2XX']]) + " Any keyword or end-of-line + call add(tl, [2, '\_k\+', ['a', 'b', '=', '2'], ['XX=XX']]) + " Any keyword but excluding digits or end-of-line + call add(tl, [2, '\_K\+', ['a', 'b', '=', '2'], ['XX=XX2XX']]) + " Any filename character or end-of-line + call add(tl, [2, '\_f\+', ['a', 'b', '.', '5'], ['XX']]) + " Any filename character but excluding digits or end-of-line + call add(tl, [2, '\_F\+', ['a', 'b', '.', '5'], ['XX5XX']]) + " Any printable character or end-of-line + call add(tl, [2, '\_p\+', ['a', 'b', '=', '4'], ['XX']]) + " Any printable character excluding digits or end-of-line + call add(tl, [2, '\_P\+', ['a', 'b', '=', '4'], ['XX4XX']]) + " Any whitespace character or end-of-line + call add(tl, [2, '\_s\+', [' ', ' ', 'a', 'b'], ['XXaXXbXX']]) + " Any non-whitespace character or end-of-line + call add(tl, [2, '\_S\+', [' ', ' ', 'a', 'b'], [' XX XX']]) + " Any decimal digit or end-of-line + call add(tl, [2, '\_d\+', ['1', 'a', '2', 'b', '3'], ['XXaXXbXX']]) + " Any non-decimal digit or end-of-line + call add(tl, [2, '\_D\+', ['1', 'a', '2', 'b', '3'], ['1XX2XX3XX']]) + " Any hexadecimal digit or end-of-line + call add(tl, [2, '\_x\+', ['1', 'a', 'g', '9', '8'], ['XXgXX']]) + " Any non-hexadecimal digit or end-of-line + call add(tl, [2, '\_X\+', ['1', 'a', 'g', '9', '8'], ['1XXaXX9XX8XX']]) + " Any octal digit or end-of-line + call add(tl, [2, '\_o\+', ['0', '7', '8', '9', '0'], ['XX8XX9XX']]) + " Any non-octal digit or end-of-line + call add(tl, [2, '\_O\+', ['0', '7', '8', '9', '0'], ['0XX7XX0XX']]) + " Any word character or end-of-line + call add(tl, [2, '\_w\+', ['A', 'B', '=', 'C', 'D'], ['XX=XX']]) + " Any non-word character or end-of-line + call add(tl, [2, '\_W\+', ['A', 'B', '=', 'C', 'D'], ['AXXBXXCXXDXX']]) + " Any head-of-word character or end-of-line + call add(tl, [2, '\_h\+', ['a', '1', 'b', '2', 'c'], ['XX1XX2XX']]) + " Any non-head-of-word character or end-of-line + call add(tl, [2, '\_H\+', ['a', '1', 'b', '2', 'c'], ['aXXbXXcXX']]) + " Any alphabetic character or end-of-line + call add(tl, [2, '\_a\+', ['a', '1', 'b', '2', 'c'], ['XX1XX2XX']]) + " Any non-alphabetic character or end-of-line + call add(tl, [2, '\_A\+', ['a', '1', 'b', '2', 'c'], ['aXXbXXcXX']]) + " Any lowercase character or end-of-line + call add(tl, [2, '\_l\+', ['a', 'A', 'b', 'B'], ['XXAXXBXX']]) + " Any non-lowercase character or end-of-line + call add(tl, [2, '\_L\+', ['a', 'A', 'b', 'B'], ['aXXbXX']]) + " Any uppercase character or end-of-line + call add(tl, [2, '\_u\+', ['a', 'A', 'b', 'B'], ['aXXbXX']]) + " Any non-uppercase character or end-of-line + call add(tl, [2, '\_U\+', ['a', 'A', 'b', 'B'], ['XXAXXBXX']]) + " Collection or end-of-line + call add(tl, [2, '\_[a-z]\+', ['a', 'A', 'b', 'B'], ['XXAXXBXX']]) + " start of line anywhere in the text + call add(tl, [2, 'one\zs\_s*\_^\zetwo', + \ ['', 'one', ' two', 'one', '', 'two'], + \ ['', 'one', ' two', 'oneXXtwo']]) + " end of line anywhere in the text + call add(tl, [2, 'one\zs\_$\_s*two', + \ ['', 'one', ' two', 'one', '', 'two'], ['', 'oneXX', 'oneXX']]) + " Check that \_[0-9] matching EOL does not break a following \> call add(tl, [2, '\<\(\(25\_[0-5]\|2\_[0-4]\_[0-9]\|\_[01]\?\_[0-9]\_[0-9]\?\)\.\)\{3\}\(25\_[0-5]\|2\_[0-4]\_[0-9]\|\_[01]\?\_[0-9]\_[0-9]\?\)\>', ['', 'localnet/192.168.0.1', ''], ['', 'localnet/XX', '']]) @@ -674,7 +754,7 @@ func Test_regexp_multiline_pat() let before = t[2] let after = t[3] for engine in [0, 1, 2] - if engine == 2 && re == 0 || engine == 1 && re ==1 + if engine == 2 && re == 0 || engine == 1 && re == 1 continue endif let ®expengine = engine @@ -722,9 +802,8 @@ func Test_lookbehind_across_line() bwipe! endfunc -" Check matching Visual area -func Test_matching_visual_area() - new +" Test for the \%V atom (match inside the visual area) +func Regex_Match_Visual_Area() call append(0, ['Visual:', 'thexe the thexethe', 'andaxand andaxand', \ 'oooxofor foroxooo', 'oooxofor foroxooo']) call cursor(1, 1) @@ -733,12 +812,22 @@ func Test_matching_visual_area() exe "normal jfx\fxj:s/\\%Vo/O/g\" call assert_equal(['Visual:', 'thexE thE thExethe', 'AndAxAnd AndAxAnd', \ 'oooxOfOr fOrOxooo', 'oooxOfOr fOrOxooo', ''], getline(1, '$')) + %d +endfunc + +" Check matching Visual area +func Test_matching_visual_area() + new + set regexpengine=1 + call Regex_Match_Visual_Area() + set regexpengine=2 + call Regex_Match_Visual_Area() + set regexpengine& bwipe! endfunc " Check matching marks -func Test_matching_marks() - new +func Regex_Mark() call append(0, ['', '', '', 'Marks:', 'asdfSasdfsadfEasdf', 'asdfSas', \ 'dfsadfEasdf', '', '', '', '', '']) call cursor(4, 1) @@ -746,6 +835,15 @@ func Test_matching_marks() exe "normal jfSmsj0fEme:.-4,.+6s/.\\%>'s\\_.*\\%<'e../again/\" call assert_equal(['', '', '', 'Marks:', 'asdfhereasdf', 'asdfagainasdf', \ '', '', '', '', '', ''], getline(1, '$')) + %d +endfunc + +func Test_matching_marks() + new + set regexpengine=1 + call Regex_Mark() + set regexpengine=2 + call Regex_Mark() bwipe! endfunc @@ -786,8 +884,7 @@ func Test_matching_curpos() endfunc " Test for matching the start and end of a buffer -func Test_start_end_of_buffer_match() - new +func Regex_start_end_buffer() call setline(1, repeat(['vim edit'], 20)) /\%^ call assert_equal([0, 1, 1, 0], getpos('.')) @@ -797,15 +894,34 @@ func Test_start_end_of_buffer_match() call assert_equal([0, 20, 8, 0], getpos('.')) exe "normal 6gg/..\\%$\" call assert_equal([0, 20, 7, 0], getpos('.')) + %d +endfunc + +func Test_start_end_of_buffer_match() + new + set regexpengine=1 + call Regex_start_end_buffer() + set regexpengine=2 + call Regex_start_end_buffer() bwipe! endfunc " Check for detecting error func Test_regexp_error() - set regexpengine=2 - call assert_fails("call matchlist('x x', ' \\ze*')", 'E888:') - call assert_fails("call matchlist('x x', ' \\zs*')", 'E888:') - set re& + call assert_fails("call matchlist('x x', '\\%#=1 \\zs*')", 'E888:') + call assert_fails("call matchlist('x x', '\\%#=1 \\ze*')", 'E888:') + call assert_fails("call matchlist('x x', '\\%#=2 \\zs*')", 'E888:') + call assert_fails("call matchlist('x x', '\\%#=2 \\ze*')", 'E888:') + call assert_fails('exe "normal /\\%#=1\\%[x\\%[x]]\"', 'E369:') +endfunc + +" Test for using the last substitute string pattern (~) +func Test_regexp_last_subst_string() + new + s/bar/baz/e + call assert_equal(matchstr("foo\nbaz\nbar", "\\%#=1\~"), "baz") + call assert_equal(matchstr("foo\nbaz\nbar", "\\%#=2\~"), "baz") + close! endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_search.vim b/src/testdir/test_search.vim index d57dbd7e5b..29943df99d 100644 --- a/src/testdir/test_search.vim +++ b/src/testdir/test_search.vim @@ -672,7 +672,7 @@ func Test_search_cmdline8() call term_sendkeys(buf, "/vim\") call term_sendkeys(buf, "/b\") call term_sendkeys(buf, "gg0") - call term_wait(buf, 500) + call TermWait(buf, 250) let screen_line = term_scrape(buf, 1) let [a0,a1,a2,a3] = [screen_line[3].attr, screen_line[4].attr, \ screen_line[18].attr, screen_line[19].attr] @@ -688,9 +688,7 @@ func Test_search_cmdline8() endfunc " Tests for regexp with various magic settings -func Test_search_regexp() - enew! - +func Run_search_regexp_magic_opt() put ='1 a aa abb abbccc' exe 'normal! /a*b\{2}c\+/e' . "\" call assert_equal([0, 2, 17, 0], getpos('.')) @@ -725,6 +723,18 @@ func Test_search_regexp() exe 'normal! /\V[ab]\(\[xy]\)\1' . "\" call assert_equal([0, 9, 7, 0], getpos('.')) + %d +endfunc + +func Test_search_regexp() + enew! + + set regexpengine=1 + call Run_search_regexp_magic_opt() + set regexpengine=2 + call Run_search_regexp_magic_opt() + set regexpengine& + set undolevels=100 put ='9 foobar' put ='' @@ -732,12 +742,12 @@ func Test_search_regexp() normal G exe 'normal! dv?bar?' . "\" call assert_equal('9 foo', getline('.')) - call assert_equal([0, 10, 5, 0], getpos('.')) - call assert_equal(10, line('$')) + call assert_equal([0, 2, 5, 0], getpos('.')) + call assert_equal(2, line('$')) normal u call assert_equal('9 foobar', getline('.')) - call assert_equal([0, 10, 6, 0], getpos('.')) - call assert_equal(11, line('$')) + call assert_equal([0, 2, 6, 0], getpos('.')) + call assert_equal(3, line('$')) set undolevels& enew! @@ -792,12 +802,12 @@ func Test_search_cmdline_incsearch_highlight_attr() call WaitForAssert({-> assert_equal(lines, [term_getline(buf, 1), term_getline(buf, 2)])}) " wait for vim to complete initialization - call term_wait(buf) + call TermWait(buf) " Get attr of normal(a0), incsearch(a1), hlsearch(a2) highlight call term_sendkeys(buf, ":set incsearch hlsearch\") call term_sendkeys(buf, '/b') - call term_wait(buf, 200) + call TermWait(buf, 100) let screen_line1 = term_scrape(buf, 1) call assert_true(len(screen_line1) > 2) " a0: attr_normal @@ -813,7 +823,7 @@ func Test_search_cmdline_incsearch_highlight_attr() " Test incremental highlight search call term_sendkeys(buf, "/vim") - call term_wait(buf, 200) + call TermWait(buf, 100) " Buffer: " abb vim vim vi " vimvivim @@ -825,7 +835,7 @@ func Test_search_cmdline_incsearch_highlight_attr() " Test call term_sendkeys(buf, "\\") - call term_wait(buf, 200) + call TermWait(buf, 100) let attr_line1 = [a0,a0,a0,a0,a2,a2,a2,a0,a2,a2,a2,a0,a0,a0] let attr_line2 = [a1,a1,a1,a0,a0,a2,a2,a2] call assert_equal(attr_line1, map(term_scrape(buf, 1)[:len(attr_line1)-1], 'v:val.attr')) @@ -833,7 +843,7 @@ func Test_search_cmdline_incsearch_highlight_attr() " Test call term_sendkeys(buf, "\") - call term_wait(buf, 200) + call TermWait(buf, 100) let attr_line1 = [a0,a0,a0,a0,a2,a2,a2,a0,a1,a1,a1,a0,a0,a0] let attr_line2 = [a2,a2,a2,a0,a0,a2,a2,a2] call assert_equal(attr_line1, map(term_scrape(buf, 1)[:len(attr_line1)-1], 'v:val.attr')) @@ -841,7 +851,7 @@ func Test_search_cmdline_incsearch_highlight_attr() " Type Enter and a1(incsearch highlight) should become a2(hlsearch highlight) call term_sendkeys(buf, "\") - call term_wait(buf, 200) + call TermWait(buf, 100) let attr_line1 = [a0,a0,a0,a0,a2,a2,a2,a0,a2,a2,a2,a0,a0,a0] let attr_line2 = [a2,a2,a2,a0,a0,a2,a2,a2] call assert_equal(attr_line1, map(term_scrape(buf, 1)[:len(attr_line1)-1], 'v:val.attr')) @@ -851,7 +861,7 @@ func Test_search_cmdline_incsearch_highlight_attr() call term_sendkeys(buf, ":1\") call term_sendkeys(buf, ":set nohlsearch\") call term_sendkeys(buf, "/vim") - call term_wait(buf, 200) + call TermWait(buf, 100) let attr_line1 = [a0,a0,a0,a0,a1,a1,a1,a0,a0,a0,a0,a0,a0,a0] let attr_line2 = [a0,a0,a0,a0,a0,a0,a0,a0] call assert_equal(attr_line1, map(term_scrape(buf, 1)[:len(attr_line1)-1], 'v:val.attr')) @@ -1543,4 +1553,44 @@ func Test_searchforward_var() close! endfunc +" Test for invalid regular expressions +func Test_invalid_regexp() + set regexpengine=1 + call assert_fails("call search(repeat('\\(.\\)', 10))", 'E51:') + call assert_fails("call search('\\%(')", 'E53:') + call assert_fails("call search('\\(')", 'E54:') + call assert_fails("call search('\\)')", 'E55:') + call assert_fails("call search('x\\@#')", 'E59:') + call assert_fails('call search(''\v%(%(%(%(%(%(%(%(%(%(%(a){1}){1}){1}){1}){1}){1}){1}){1}){1}){1}){1}'')', 'E60:') + call assert_fails("call search('a\\+*')", 'E61:') + call assert_fails("call search('\\_m')", 'E63:') + call assert_fails("call search('\\+')", 'E64:') + call assert_fails("call search('\\1')", 'E65:') + call assert_fails("call search('\\z\\(\\)')", 'E66:') + call assert_fails("call search('\\z2')", 'E67:') + call assert_fails("call search('\\zx')", 'E68:') + call assert_fails("call search('\\%[ab')", 'E69:') + call assert_fails("call search('\\%[]')", 'E70:') + call assert_fails("call search('\\%a')", 'E71:') + call assert_fails("call search('ab\\%[\\(cd\\)]')", 'E369:') + call assert_fails("call search('ab\\%[\\%(cd\\)]')", 'E369:') + set regexpengine=2 + call assert_fails("call search('\\_')", 'E865:') + call assert_fails("call search('\\+')", 'E866:') + call assert_fails("call search('\\zx')", 'E867:') + call assert_fails("call search('\\%a')", 'E867:') + call assert_fails("call search('x\\@#')", 'E869:') + call assert_fails("call search(repeat('\\(.\\)', 10))", 'E872:') + call assert_fails("call search('\\_m')", 'E877:') + call assert_fails("call search('\\%(')", 'E53:') + call assert_fails("call search('\\(')", 'E54:') + call assert_fails("call search('\\)')", 'E55:') + call assert_fails("call search('\\z\\(\\)')", 'E66:') + call assert_fails("call search('\\%[ab')", 'E69:') + call assert_fails("call search('\\%[]')", 'E70:') + call assert_fails("call search('\\%9999999999999999999999999999v')", 'E951:') + set regexpengine& + call assert_fails("call search('\\%#=3ab')", 'E864:') +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_search_stat.vim b/src/testdir/test_search_stat.vim index 3d60716ee7..9bd2404df0 100644 --- a/src/testdir/test_search_stat.vim +++ b/src/testdir/test_search_stat.vim @@ -202,12 +202,12 @@ func! Test_search_stat_screendump() END call writefile(lines, 'Xsearchstat') let buf = RunVimInTerminal('-S Xsearchstat', #{rows: 10}) - call term_wait(buf) + call TermWait(buf) call VerifyScreenDump(buf, 'Test_searchstat_1', {}) call term_sendkeys(buf, ":nnoremap n n\") call term_sendkeys(buf, "gg0n") - call term_wait(buf) + call TermWait(buf) call VerifyScreenDump(buf, 'Test_searchstat_2', {}) call StopVimInTerminal(buf) diff --git a/src/testdir/test_source.vim b/src/testdir/test_source.vim index ba6fd5ad95..b22e57cb03 100644 --- a/src/testdir/test_source.vim +++ b/src/testdir/test_source.vim @@ -87,4 +87,10 @@ func Test_source_autocmd_sfile() call delete('Xscript.vim') endfunc +func Test_source_error() + call assert_fails('scriptencoding utf-8', 'E167:') + call assert_fails('finish', 'E168:') + call assert_fails('scriptversion 2', 'E984:') +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_startup.vim b/src/testdir/test_startup.vim index 5341cdff0b..985a1b01b4 100644 --- a/src/testdir/test_startup.vim +++ b/src/testdir/test_startup.vim @@ -797,9 +797,9 @@ func Test_missing_vimrc() let cmd = GetVimCommandCleanTerm() . ' -u Xvimrc_missing -S Xafter' let buf = term_start(cmd, {'term_rows' : 10}) call WaitForAssert({-> assert_equal("running", term_getstatus(buf))}) - call term_wait(buf) + call TermWait(buf) call term_sendkeys(buf, "\n:") - call term_wait(buf) + call TermWait(buf) call WaitForAssert({-> assert_match(':', term_getline(buf, 10))}) call StopVimInTerminal(buf) call assert_equal([], readfile('Xtestout')) diff --git a/src/testdir/test_startup_utf8.vim b/src/testdir/test_startup_utf8.vim index 1b3d2184a0..8f969d3be0 100644 --- a/src/testdir/test_startup_utf8.vim +++ b/src/testdir/test_startup_utf8.vim @@ -74,7 +74,7 @@ func Test_detect_ambiwidth() \ 'redraw', \ ], 'Xscript') let buf = RunVimInTerminal('-S Xscript', {}) - call term_wait(buf) + call TermWait(buf) call term_sendkeys(buf, "S\=&ambiwidth\\") call WaitForAssert({-> assert_match('single', term_getline(buf, 1))}) diff --git a/src/testdir/test_statusline.vim b/src/testdir/test_statusline.vim index ebfe8aac66..449cf80de3 100644 --- a/src/testdir/test_statusline.vim +++ b/src/testdir/test_statusline.vim @@ -406,7 +406,7 @@ func Test_statusline_removed_group() call writefile(lines, 'XTest_statusline') let buf = RunVimInTerminal('-S XTest_statusline', {'rows': 10, 'cols': 50}) - call term_wait(buf, 100) + call TermWait(buf, 50) call VerifyScreenDump(buf, 'Test_statusline_1', {}) " clean up diff --git a/src/testdir/test_suspend.vim b/src/testdir/test_suspend.vim index 4b3bd5eadf..39ae32d4cc 100644 --- a/src/testdir/test_suspend.vim +++ b/src/testdir/test_suspend.vim @@ -53,7 +53,7 @@ func Test_suspend() " Quit gracefully to dump coverage information. call term_sendkeys(buf, ":qall!\") - call term_wait(buf) + call TermWait(buf) " Wait until Vim actually exited and shell shows a prompt call WaitForAssert({-> assert_match('[$#] $', term_getline(buf, '.'))}) call StopShellInTerminal(buf) diff --git a/src/testdir/test_swap.vim b/src/testdir/test_swap.vim index 612832c966..7889d4b480 100644 --- a/src/testdir/test_swap.vim +++ b/src/testdir/test_swap.vim @@ -363,14 +363,14 @@ func Test_swap_prompt_splitwin() call term_sendkeys(buf, ":set nomore\n") call term_sendkeys(buf, ":set noruler\n") call term_sendkeys(buf, ":split Xfile1\n") - call term_wait(buf) + call TermWait(buf) call WaitForAssert({-> assert_match('^\[O\]pen Read-Only, (E)dit anyway, (R)ecover, (Q)uit, (A)bort: $', term_getline(buf, 20))}) call term_sendkeys(buf, "q") - call term_wait(buf) + call TermWait(buf) call term_sendkeys(buf, ":\") call WaitForAssert({-> assert_match('^:$', term_getline(buf, 20))}) call term_sendkeys(buf, ":echomsg winnr('$')\") - call term_wait(buf) + call TermWait(buf) call WaitForAssert({-> assert_match('^1$', term_getline(buf, 20))}) call StopVimInTerminal(buf) %bwipe! diff --git a/src/testdir/test_syntax.vim b/src/testdir/test_syntax.vim index 8197f1af54..c7fefa95b1 100644 --- a/src/testdir/test_syntax.vim +++ b/src/testdir/test_syntax.vim @@ -332,6 +332,64 @@ func Test_syntax_invalid_arg() call assert_fails('syntax sync x', 'E404:') call assert_fails('syntax keyword Abc a[', 'E789:') call assert_fails('syntax keyword Abc a[bc]d', 'E890:') + + let caught_393 = 0 + try + syntax keyword cMyItem grouphere G1 + catch /E393:/ + let caught_393 = 1 + endtry + call assert_equal(1, caught_393) + + let caught_394 = 0 + try + syntax sync match Abc grouphere MyItem "abc"' + catch /E394:/ + let caught_394 = 1 + endtry + call assert_equal(1, caught_394) + + " Test for too many \z\( and unmatched \z\( + " Not able to use assert_fails() here because both E50:/E879: and E475: + " messages are emitted. + set regexpengine=1 + let caught_52 = 0 + try + syntax region MyRegion start='\z\(' end='\*/' + catch /E52:/ + let caught_52 = 1 + endtry + call assert_equal(1, caught_52) + + let caught_50 = 0 + try + let cmd = "syntax region MyRegion start='" + let cmd ..= repeat("\\z\\(.\\)", 10) .. "' end='\*/'" + exe cmd + catch /E50:/ + let caught_50 = 1 + endtry + call assert_equal(1, caught_50) + + set regexpengine=2 + let caught_54 = 0 + try + syntax region MyRegion start='\z\(' end='\*/' + catch /E54:/ + let caught_54 = 1 + endtry + call assert_equal(1, caught_54) + + let caught_879 = 0 + try + let cmd = "syntax region MyRegion start='" + let cmd ..= repeat("\\z\\(.\\)", 10) .. "' end='\*/'" + exe cmd + catch /E879:/ + let caught_879 = 1 + endtry + call assert_equal(1, caught_879) + set regexpengine& endfunc func Test_syn_sync() diff --git a/src/testdir/test_tagjump.vim b/src/testdir/test_tagjump.vim index 6b73239ed5..99526005e6 100644 --- a/src/testdir/test_tagjump.vim +++ b/src/testdir/test_tagjump.vim @@ -544,7 +544,7 @@ func Test_tselect() call writefile(lines, 'XTest_tselect') let buf = RunVimInTerminal('-S XTest_tselect', {'rows': 10, 'cols': 50}) - call term_wait(buf, 100) + call TermWait(buf, 50) call term_sendkeys(buf, ":tselect main\2\") call VerifyScreenDump(buf, 'Test_tselect_1', {}) diff --git a/src/testdir/test_terminal.vim b/src/testdir/test_terminal.vim index b6d0b40748..e6b6c2edde 100644 --- a/src/testdir/test_terminal.vim +++ b/src/testdir/test_terminal.vim @@ -44,7 +44,7 @@ func Test_terminal_basic() call assert_notmatch('%[^\n]*running]', execute('ls ?')) call StopShellInTerminal(buf) - call term_wait(buf) + call TermWait(buf) call assert_equal('n', mode()) call assert_match('%aF[^\n]*finished]', execute('ls')) call assert_match('%aF[^\n]*finished]', execute('ls F')) @@ -79,7 +79,7 @@ endfunc func Test_terminal_make_change() let buf = Run_shell_in_terminal({}) call StopShellInTerminal(buf) - call term_wait(buf) + call TermWait(buf) setlocal modifiable exe "normal Axxx\" @@ -117,10 +117,10 @@ endfunc func Test_terminal_split_quit() let buf = Run_shell_in_terminal({}) - call term_wait(buf) + call TermWait(buf) split quit! - call term_wait(buf) + call TermWait(buf) sleep 50m call assert_equal('run', job_status(g:job)) @@ -225,7 +225,7 @@ func Test_terminal_scrape_123() " Nothing happens with invalid buffer number call term_wait(1234) - call term_wait(buf) + call TermWait(buf) " On MS-Windows we first get a startup message of two lines, wait for the " "cls" to happen, after that we have one line with three characters. call WaitForAssert({-> assert_equal(3, len(term_scrape(buf, 1)))}) @@ -234,7 +234,7 @@ func Test_terminal_scrape_123() " Must still work after the job ended. let job = term_getjob(buf) call WaitForAssert({-> assert_equal("dead", job_status(job))}) - call term_wait(buf) + call TermWait(buf) call Check_123(buf) exe buf . 'bwipe' @@ -270,7 +270,7 @@ func Test_terminal_scrape_multibyte() let job = term_getjob(buf) call WaitForAssert({-> assert_equal("dead", job_status(job))}) - call term_wait(buf) + call TermWait(buf) exe buf . 'bwipe' call delete('Xtext') @@ -287,7 +287,7 @@ func Test_terminal_scroll() let job = term_getjob(buf) call WaitForAssert({-> assert_equal("dead", job_status(job))}) - call term_wait(buf) + call TermWait(buf) " wait until the scrolling stops while 1 @@ -325,7 +325,7 @@ func Test_terminal_scrollback() call assert_inrange(91, 100, lines) call StopShellInTerminal(buf) - call term_wait(buf) + call TermWait(buf) exe buf . 'bwipe' set termwinscroll& call delete('Xtext') @@ -359,10 +359,10 @@ func Test_terminal_postponed_scrollback() " stop "tail -f" call term_sendkeys(buf, "\") - call term_wait(buf, 50) + call TermWait(buf, 25) " stop shell call term_sendkeys(buf, "exit\") - call term_wait(buf, 100) + call TermWait(buf, 50) " close terminal window let tsk_ret = term_sendkeys(buf, ":q\") @@ -622,7 +622,7 @@ func s:test_environment(name, value) else call term_sendkeys(buf, "echo $" . a:name . "\r") endif - call term_wait(buf) + call TermWait(buf) call StopShellInTerminal(buf) call WaitForAssert({-> assert_equal(a:value, getline(2))}) @@ -639,7 +639,7 @@ func Test_terminal_env() else call term_sendkeys(buf, "echo $TESTENV\r") endif - eval buf->term_wait() + eval buf->TermWait() call StopShellInTerminal(buf) call WaitForAssert({-> assert_equal('correct', getline(2))}) @@ -688,7 +688,7 @@ func Test_terminal_noblock() let g:job = term_getjob(buf) call StopShellInTerminal(buf) - call term_wait(buf) + call TermWait(buf) unlet g:job bwipe endfunc @@ -813,7 +813,7 @@ endfunc func Test_terminal_redir_file() let cmd = Get_cat_123_cmd() let buf = term_start(cmd, {'out_io': 'file', 'out_name': 'Xfile'}) - call term_wait(buf) + call TermWait(buf) " ConPTY may precede escape sequence. There are things that are not so. if !has('conpty') call WaitForAssert({-> assert_notequal(0, len(readfile("Xfile")))}) @@ -827,7 +827,7 @@ func Test_terminal_redir_file() if has('unix') call writefile(['one line'], 'Xfile') let buf = term_start('cat', {'in_io': 'file', 'in_name': 'Xfile'}) - call term_wait(buf) + call TermWait(buf) call WaitForAssert({-> assert_equal('one line', term_getline(buf, 1))}) let g:job = term_getjob(buf) call WaitForAssert({-> assert_equal('dead', job_status(g:job))}) @@ -860,7 +860,7 @@ func TerminalTmap(remap) call term_sendkeys(buf, "\r") call StopShellInTerminal(buf) - call term_wait(buf) + call TermWait(buf) tunmap 123 tunmap 456 @@ -878,7 +878,7 @@ func Test_terminal_wall() let buf = Run_shell_in_terminal({}) wall call StopShellInTerminal(buf) - call term_wait(buf) + call TermWait(buf) exe buf . 'bwipe' unlet g:job endfunc @@ -887,7 +887,7 @@ func Test_terminal_wqall() let buf = Run_shell_in_terminal({}) call assert_fails('wqall', 'E948') call StopShellInTerminal(buf) - call term_wait(buf) + call TermWait(buf) exe buf . 'bwipe' unlet g:job endfunc @@ -908,7 +908,7 @@ func Test_terminal_composing_unicode() enew let buf = term_start(cmd, {'curwin': bufnr('')}) let g:job = term_getjob(buf) - call term_wait(buf, 50) + call TermWait(buf, 25) if has('win32') call assert_equal('cmd', job_info(g:job).cmd[0]) @@ -919,7 +919,7 @@ func Test_terminal_composing_unicode() " ascii + composing let txt = "a\u0308bc" call term_sendkeys(buf, "echo " . txt . "\r") - call term_wait(buf, 50) + call TermWait(buf, 25) call assert_match("echo " . txt, term_getline(buf, lnum[0])) call assert_equal(txt, term_getline(buf, lnum[0] + 1)) let l = term_scrape(buf, lnum[0] + 1) @@ -930,7 +930,7 @@ func Test_terminal_composing_unicode() " multibyte + composing let txt = "\u304b\u3099\u304e\u304f\u3099\u3052\u3053\u3099" call term_sendkeys(buf, "echo " . txt . "\r") - call term_wait(buf, 50) + call TermWait(buf, 25) call assert_match("echo " . txt, term_getline(buf, lnum[1])) call assert_equal(txt, term_getline(buf, lnum[1] + 1)) let l = term_scrape(buf, lnum[1] + 1) @@ -943,7 +943,7 @@ func Test_terminal_composing_unicode() " \u00a0 + composing let txt = "abc\u00a0\u0308" call term_sendkeys(buf, "echo " . txt . "\r") - call term_wait(buf, 50) + call TermWait(buf, 25) call assert_match("echo " . txt, term_getline(buf, lnum[2])) call assert_equal(txt, term_getline(buf, lnum[2] + 1)) let l = term_scrape(buf, lnum[2] + 1) @@ -1592,7 +1592,7 @@ func Test_terminal_ansicolors_default() let buf = Run_shell_in_terminal({}) call assert_equal(colors, term_getansicolors(buf)) call StopShellInTerminal(buf) - call term_wait(buf) + call TermWait(buf) exe buf . 'bwipe' endfunc @@ -1617,7 +1617,7 @@ func Test_terminal_ansicolors_global() let buf = Run_shell_in_terminal({}) call assert_equal(g:terminal_ansi_colors, term_getansicolors(buf)) call StopShellInTerminal(buf) - call term_wait(buf) + call TermWait(buf) exe buf . 'bwipe' unlet g:terminal_ansi_colors @@ -1651,7 +1651,7 @@ func Test_terminal_ansicolors_func() call assert_fails('call term_setansicolors(buf, colors)', 'E474:') call StopShellInTerminal(buf) - call term_wait(buf) + call TermWait(buf) exe buf . 'bwipe' endfunc @@ -1747,7 +1747,7 @@ func Test_terminal_termwinsize_option_zero() let win = bufwinid(buf) call assert_equal([winheight(win), winwidth(win)], term_getsize(buf)) call StopShellInTerminal(buf) - call term_wait(buf) + call TermWait(buf) exe buf . 'bwipe' set termwinsize=7x0 @@ -1755,7 +1755,7 @@ func Test_terminal_termwinsize_option_zero() let win = bufwinid(buf) call assert_equal([7, winwidth(win)], term_getsize(buf)) call StopShellInTerminal(buf) - call term_wait(buf) + call TermWait(buf) exe buf . 'bwipe' set termwinsize=0x33 @@ -1763,7 +1763,7 @@ func Test_terminal_termwinsize_option_zero() let win = bufwinid(buf) call assert_equal([winheight(win), 33], term_getsize(buf)) call StopShellInTerminal(buf) - call term_wait(buf) + call TermWait(buf) exe buf . 'bwipe' set termwinsize= @@ -1793,7 +1793,7 @@ func Test_terminal_termwinsize_minimum() call assert_equal(30, winwidth(win)) call StopShellInTerminal(buf) - call term_wait(buf) + call TermWait(buf) exe buf . 'bwipe' set termwinsize=0*0 @@ -1801,7 +1801,7 @@ func Test_terminal_termwinsize_minimum() let win = bufwinid(buf) call assert_equal([winheight(win), winwidth(win)], term_getsize(buf)) call StopShellInTerminal(buf) - call term_wait(buf) + call TermWait(buf) exe buf . 'bwipe' set termwinsize= @@ -1943,7 +1943,7 @@ func Test_zz1_terminal_in_gui() call assert_equal(1, winnr('$')) let buf = Run_shell_in_terminal({'term_finish': 'close'}) call StopShellInTerminal(buf) - call term_wait(buf) + call TermWait(buf) " closing window wipes out the terminal buffer a with finished job call WaitForAssert({-> assert_equal(1, winnr('$'))}) @@ -2030,7 +2030,7 @@ func Test_terminal_normal_mode() END call writefile(lines, 'XtermNormal') let buf = RunVimInTerminal('-S XtermNormal', {'rows': 8}) - call term_wait(buf) + call TermWait(buf) call term_sendkeys(buf, "\N") call term_sendkeys(buf, ":set number cursorline culopt=both\r") @@ -2220,7 +2220,7 @@ func Test_term_gettty() call assert_equal('', term_gettty(buf + 1)) call StopShellInTerminal(buf) - call term_wait(buf) + call TermWait(buf) exe buf . 'bwipe' endfunc @@ -2260,7 +2260,7 @@ func Test_terminal_getwinpos() \ 'echo getwinpos()', \ ], 'XTest_getwinpos') let buf = RunVimInTerminal('-S XTest_getwinpos', {'cols': 60}) - call term_wait(buf) + call TermWait(buf) " Find the output of getwinpos() in the bottom line. let rows = term_getsize(buf)[0] @@ -2283,7 +2283,7 @@ func Test_terminal_getwinpos() call assert_inrange(xroot + 2, xroot + xoff, xpos) call assert_inrange(yroot + 2, yroot + yoff, ypos) - call term_wait(buf) + call TermWait(buf) call term_sendkeys(buf, ":q\") call StopVimInTerminal(buf) call delete('XTest_getwinpos') @@ -2439,11 +2439,11 @@ func Test_terminal_in_popup() \ ] call writefile(lines, 'XtermPopup') let buf = RunVimInTerminal('-S XtermPopup', #{rows: 15}) - call term_wait(buf, 200) + call TermWait(buf, 100) call term_sendkeys(buf, ":call OpenTerm(0)\") - call term_wait(buf, 200) + call TermWait(buf, 100) call term_sendkeys(buf, ":\") - call term_wait(buf, 200) + call TermWait(buf, 100) call term_sendkeys(buf, "\:echo getwinvar(g:winid, \"&buftype\") win_gettype(g:winid)\") call VerifyScreenDump(buf, 'Test_terminal_popup_1', {}) @@ -2451,7 +2451,7 @@ func Test_terminal_in_popup() call VerifyScreenDump(buf, 'Test_terminal_popup_2', {}) call term_sendkeys(buf, ":call OpenTerm(1)\") - call term_wait(buf, 300) + call TermWait(buf, 150) call term_sendkeys(buf, ":set hlsearch\") call term_sendkeys(buf, "/edit\") call VerifyScreenDump(buf, 'Test_terminal_popup_3', {}) @@ -2459,7 +2459,7 @@ func Test_terminal_in_popup() call term_sendkeys(buf, "\:call HidePopup()\") call VerifyScreenDump(buf, 'Test_terminal_popup_4', {}) call term_sendkeys(buf, "\") - call term_wait(buf, 100) + call TermWait(buf, 50) call term_sendkeys(buf, "\:call ClosePopup()\") call VerifyScreenDump(buf, 'Test_terminal_popup_5', {}) @@ -2475,9 +2475,9 @@ func Test_terminal_in_popup() call term_sendkeys(buf, "A") call VerifyScreenDump(buf, 'Test_terminal_popup_8', {}) - call term_wait(buf, 100) + call TermWait(buf, 50) call term_sendkeys(buf, ":q\") - call term_wait(buf, 200) " wait for terminal to vanish + call TermWait(buf, 100) " wait for terminal to vanish call StopVimInTerminal(buf) call delete('Xtext') @@ -2504,16 +2504,16 @@ func Test_terminal_in_popup_min_size() \ ] call writefile(lines, 'XtermPopup') let buf = RunVimInTerminal('-S XtermPopup', #{rows: 15}) - call term_wait(buf, 200) + call TermWait(buf, 100) call term_sendkeys(buf, ":set noruler\") call term_sendkeys(buf, ":call OpenTerm()\") - call term_wait(buf, 100) + call TermWait(buf, 50) call term_sendkeys(buf, ":\") call VerifyScreenDump(buf, 'Test_terminal_popup_m1', {}) - call term_wait(buf, 100) + call TermWait(buf, 50) call term_sendkeys(buf, ":q\") - call term_wait(buf, 100) " wait for terminal to vanish + call TermWait(buf, 50) " wait for terminal to vanish call StopVimInTerminal(buf) call delete('Xtext') call delete('XtermPopup') @@ -2536,17 +2536,17 @@ func Terminal_in_popup_colored(group_name, highlight_cmd, highlight_opt) \ ] call writefile(lines, 'XtermPopup') let buf = RunVimInTerminal('-S XtermPopup', #{rows: 15}) - call term_wait(buf, 200) + call TermWait(buf, 100) call term_sendkeys(buf, ":set noruler\") call term_sendkeys(buf, ":call OpenTerm()\") - call term_wait(buf, 100) + call TermWait(buf, 50) call term_sendkeys(buf, "hello\") call VerifyScreenDump(buf, 'Test_terminal_popup_' .. a:group_name, {}) call term_sendkeys(buf, "\") - call term_wait(buf, 100) + call TermWait(buf, 50) call term_sendkeys(buf, ":q\") - call term_wait(buf, 100) " wait for terminal to vanish + call TermWait(buf, 50) " wait for terminal to vanish call StopVimInTerminal(buf) call delete('XtermPopup') endfunc @@ -2599,19 +2599,19 @@ func Test_term_nasty_callback() let g:buf1 = term_start('sh', #{hidden: 1, term_finish: 'close'}) call popup_create(g:buf1, {}) let g:buf2 = term_start(['sh', '-c'], #{curwin: 1, exit_cb: function('TermExit')}) - call term_wait(g:buf2, 100) + call TermWait(g:buf2, 50) call popup_close(win_getid()) endfunc func TermExit(...) let altbuf = bufnr('#') call term_sendkeys(altbuf, "exit\") - call term_wait(altbuf) + call TermWait(altbuf) call popup_close(win_getid()) endfunc call OpenTerms() call term_sendkeys(g:buf0, "exit\") - call term_wait(g:buf0, 100) + call TermWait(g:buf0, 50) exe g:buf0 .. 'bwipe!' set hidden& endfunc diff --git a/src/testdir/test_terminal_fail.vim b/src/testdir/test_terminal_fail.vim index f33ade6342..d621d03a19 100644 --- a/src/testdir/test_terminal_fail.vim +++ b/src/testdir/test_terminal_fail.vim @@ -10,7 +10,7 @@ source shared.vim func Test_terminal_redir_fails() if has('unix') let buf = term_start('xyzabc', {'err_io': 'file', 'err_name': 'Xfile'}) - call term_wait(buf) + call TermWait(buf) call WaitFor('len(readfile("Xfile")) > 0') call assert_match('executing job failed', readfile('Xfile')[0]) call WaitFor('!&modified') diff --git a/src/testdir/test_timers.vim b/src/testdir/test_timers.vim index 1a6391b9d9..546df1ff73 100644 --- a/src/testdir/test_timers.vim +++ b/src/testdir/test_timers.vim @@ -398,9 +398,9 @@ func Test_timer_error_in_timer_callback() call WaitForAssert({-> assert_notequal('', term_getline(buf, 8))}) " GC must not run during timer callback, which can make Vim crash. - call term_wait(buf, 100) + call TermWait(buf, 50) call term_sendkeys(buf, "\") - call term_wait(buf, 100) + call TermWait(buf, 50) call assert_equal('run', job_status(job)) call term_sendkeys(buf, ":qall!\") diff --git a/src/testdir/test_user_func.vim b/src/testdir/test_user_func.vim index c8f8d07fd0..aec3619e77 100644 --- a/src/testdir/test_user_func.vim +++ b/src/testdir/test_user_func.vim @@ -3,6 +3,9 @@ " Also test that a builtin function cannot be replaced. " Also test for regression when calling arbitrary expression. +source check.vim +source shared.vim + func Table(title, ...) let ret = a:title let idx = 1 @@ -83,6 +86,7 @@ func Test_user_func() normal o[(one again call assert_equal('1. one again', getline('.')) + " Try to overwrite a function in the global (g:) scope call assert_equal(3, max([1, 2, 3])) call assert_fails("call extend(g:, {'max': function('min')})", 'E704') call assert_equal(3, max([1, 2, 3])) @@ -175,4 +179,256 @@ func Test_function_list() call assert_fails("function Xabc", 'E123:') endfunc +" Test for , in a function +func Test_sfile_in_function() + func Xfunc() + call assert_match('..Test_sfile_in_function\[5]..Xfunc', expand('')) + call assert_equal('2', expand('')) + endfunc + call Xfunc() + delfunc Xfunc +endfunc + +" Test trailing text after :endfunction {{{1 +func Test_endfunction_trailing() + call assert_false(exists('*Xtest')) + + exe "func Xtest()\necho 'hello'\nendfunc\nlet done = 'yes'" + call assert_true(exists('*Xtest')) + call assert_equal('yes', done) + delfunc Xtest + unlet done + + exe "func Xtest()\necho 'hello'\nendfunc|let done = 'yes'" + call assert_true(exists('*Xtest')) + call assert_equal('yes', done) + delfunc Xtest + unlet done + + " trailing line break + exe "func Xtest()\necho 'hello'\nendfunc\n" + call assert_true(exists('*Xtest')) + delfunc Xtest + + set verbose=1 + exe "func Xtest()\necho 'hello'\nendfunc \" garbage" + call assert_notmatch('W22:', split(execute('1messages'), "\n")[0]) + call assert_true(exists('*Xtest')) + delfunc Xtest + + exe "func Xtest()\necho 'hello'\nendfunc garbage" + call assert_match('W22:', split(execute('1messages'), "\n")[0]) + call assert_true(exists('*Xtest')) + delfunc Xtest + set verbose=0 + + function Foo() + echo 'hello' + endfunction | echo 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' + delfunc Foo +endfunc + +func Test_delfunction_force() + delfunc! Xtest + delfunc! Xtest + func Xtest() + echo 'nothing' + endfunc + delfunc! Xtest + delfunc! Xtest + + " Try deleting the current function + call assert_fails('delfunc Test_delfunction_force', 'E131:') +endfunc + +func Test_function_defined_line() + CheckNotGui + + let lines =<< trim [CODE] + " F1 + func F1() + " F2 + func F2() + " + " + " + return + endfunc + " F3 + execute "func F3()\n\n\n\nreturn\nendfunc" + " F4 + execute "func F4()\n + \\n + \\n + \\n + \return\n + \endfunc" + endfunc + " F5 + execute "func F5()\n\n\n\nreturn\nendfunc" + " F6 + execute "func F6()\n + \\n + \\n + \\n + \return\n + \endfunc" + call F1() + verbose func F1 + verbose func F2 + verbose func F3 + verbose func F4 + verbose func F5 + verbose func F6 + qall! + [CODE] + + call writefile(lines, 'Xtest.vim') + let res = system(GetVimCommandClean() .. ' -es -X -S Xtest.vim') + call assert_equal(0, v:shell_error) + + let m = matchstr(res, 'function F1()[^[:print:]]*[[:print:]]*') + call assert_match(' line 2$', m) + + let m = matchstr(res, 'function F2()[^[:print:]]*[[:print:]]*') + call assert_match(' line 4$', m) + + let m = matchstr(res, 'function F3()[^[:print:]]*[[:print:]]*') + call assert_match(' line 11$', m) + + let m = matchstr(res, 'function F4()[^[:print:]]*[[:print:]]*') + call assert_match(' line 13$', m) + + let m = matchstr(res, 'function F5()[^[:print:]]*[[:print:]]*') + call assert_match(' line 21$', m) + + let m = matchstr(res, 'function F6()[^[:print:]]*[[:print:]]*') + call assert_match(' line 23$', m) + + call delete('Xtest.vim') +endfunc + +" Test for defining a function reference in the global scope +func Test_add_funcref_to_global_scope() + let x = g: + let caught_E862 = 0 + try + func x.Xfunc() + return 1 + endfunc + catch /E862:/ + let caught_E862 = 1 + endtry + call assert_equal(1, caught_E862) +endfunc + +func Test_funccall_garbage_collect() + func Func(x, ...) + call add(a:x, a:000) + endfunc + call Func([], []) + " Must not crash cause by invalid freeing + call test_garbagecollect_now() + call assert_true(v:true) + delfunc Func +endfunc + +" Test for script-local function +func DoLast() + call append(line('$'), "last line") +endfunc + +func s:DoNothing() + call append(line('$'), "nothing line") +endfunc + +func Test_script_local_func() + set nocp nomore viminfo+=nviminfo + new + nnoremap _x :call DoNothing()call DoLast()delfunc DoNothingdelfunc DoLast + + normal _x + call assert_equal('nothing line', getline(2)) + call assert_equal('last line', getline(3)) + close! + + " Try to call a script local function in global scope + let lines =<< trim [CODE] + :call assert_fails('call s:Xfunc()', 'E81:') + :call assert_fails('let x = call("Xfunc", [])', 'E120:') + :call writefile(v:errors, 'Xresult') + :qall + + [CODE] + call writefile(lines, 'Xscript') + if RunVim([], [], '-s Xscript') + call assert_equal([], readfile('Xresult')) + endif + call delete('Xresult') + call delete('Xscript') +endfunc + +" Test for errors in defining new functions +func Test_func_def_error() + call assert_fails('func Xfunc abc ()', 'E124:') + call assert_fails('func Xfunc(', 'E125:') + call assert_fails('func xfunc()', 'E128:') + + " Try to redefine a function that is in use + let caught_E127 = 0 + try + func! Test_func_def_error() + endfunc + catch /E127:/ + let caught_E127 = 1 + endtry + call assert_equal(1, caught_E127) + + " Try to define a function in a dict twice + let d = {} + let lines =<< trim END + func d.F1() + return 1 + endfunc + END + let l = join(lines, "\n") . "\n" + exe l + call assert_fails('exe l', 'E717:') + + " Define an autoload function with an incorrect file name + call writefile(['func foo#Bar()', 'return 1', 'endfunc'], 'Xscript') + call assert_fails('source Xscript', 'E746:') + call delete('Xscript') +endfunc + +" Test for deleting a function +func Test_del_func() + call assert_fails('delfunction Xabc', 'E130:') + let d = {'a' : 10} + call assert_fails('delfunc d.a', 'E718:') +endfunc + +" Test for calling return outside of a function +func Test_return_outside_func() + call writefile(['return 10'], 'Xscript') + call assert_fails('source Xscript', 'E133:') + call delete('Xscript') +endfunc + +" Test for errors in calling a function +func Test_func_arg_error() + " Too many arguments + call assert_fails("call call('min', range(1,20))", 'E118:') + call assert_fails("call call('min', range(1,21))", 'E699:') + call assert_fails('echo min(0,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,0,1)', + \ 'E740:') + + " Missing dict argument + func Xfunc() dict + return 1 + endfunc + call assert_fails('call Xfunc()', 'E725:') + delfunc Xfunc +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim index f11fc83893..f34041b5d2 100644 --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -711,12 +711,28 @@ def Test_expr7_string() call CheckDefFailure("let x = 'abc", 'E115:') enddef +def Test_expr7_vimvar() + let old: list = v:oldfiles + let compl: dict = v:completed_item + + call CheckDefFailure("let old: list = v:oldfiles", 'E1013: type mismatch, expected list but got list') + call CheckDefFailure("let old: dict = v:completed_item", 'E1013: type mismatch, expected dict but got dict') +enddef + def Test_expr7_special() " special constant assert_equal(g:special_true, true) assert_equal(g:special_false, false) + assert_equal(g:special_true, v:true) + assert_equal(g:special_false, v:false) assert_equal(g:special_null, v:null) assert_equal(g:special_none, v:none) + + call CheckDefFailure('v:true = true', 'E46:') + call CheckDefFailure('v:true = false', 'E46:') + call CheckDefFailure('v:false = true', 'E46:') + call CheckDefFailure('v:null = 11', 'E46:') + call CheckDefFailure('v:none = 22', 'E46:') enddef def Test_expr7_list() @@ -962,7 +978,7 @@ func Test_expr_fails() call CheckDefFailure("CallMe2('yes' , 'no')", 'E1068:') call CheckDefFailure("v:nosuch += 3", 'E1001:') - call CheckDefFailure("let v:version = 3", 'E1064:') + call CheckDefFailure("let v:statusmsg = ''", 'E1064:') call CheckDefFailure("let asdf = v:nosuch", 'E1001:') call CheckDefFailure("echo len('asdf'", 'E110:') diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index 5554b2d7e1..6f9aa0cca4 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -128,6 +128,20 @@ def Test_call_def_varargs() assert_equal('one,foo', MyDefVarargs('one')) assert_equal('one,two', MyDefVarargs('one', 'two')) assert_equal('one,two,three', MyDefVarargs('one', 'two', 'three')) + call CheckDefFailure(['MyDefVarargs("one", 22)'], 'E1013: argument 2: type mismatch, expected string but got number') +enddef + +" Only varargs +def MyVarargsOnly(...args: list): string + return join(args, ',') +enddef + +def Test_call_varargs_only() + assert_equal('', MyVarargsOnly()) + assert_equal('one', MyVarargsOnly('one')) + assert_equal('one,two', MyVarargsOnly('one', 'two')) + call CheckDefFailure(['MyVarargsOnly(1)'], 'E1013: argument 1: type mismatch, expected string but got number') + call CheckDefFailure(['MyVarargsOnly("one", 2)'], 'E1013: argument 2: type mismatch, expected string but got number') enddef def Test_using_var_as_arg() @@ -373,6 +387,11 @@ def FuncNoArgRetNumber(): number return 1234 enddef +def FuncNoArgRetString(): string + funcResult = 45 + return 'text' +enddef + def FuncOneArgNoRet(arg: number) funcResult = arg enddef @@ -382,6 +401,10 @@ def FuncOneArgRetNumber(arg: number): number return arg enddef +def FuncOneArgRetString(arg: string): string + return arg +enddef + def FuncOneArgRetAny(arg: any): any return arg enddef @@ -415,6 +438,32 @@ def Test_func_type() assert_equal(13, funcResult) enddef +def Test_func_type_part() + let RefVoid: func: void + RefVoid = FuncNoArgNoRet + RefVoid = FuncOneArgNoRet + CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func() but got func(): number') + CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetString'], 'E1013: type mismatch, expected func() but got func(): string') + + let RefAny: func(): any + RefAny = FuncNoArgRetNumber + RefAny = FuncNoArgRetString + CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): any but got func()') + CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncOneArgNoRet'], 'E1013: type mismatch, expected func(): any but got func(number)') + + let RefNr: func: number + RefNr = FuncNoArgRetNumber + RefNr = FuncOneArgRetNumber + CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): number but got func()') + CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgRetString'], 'E1013: type mismatch, expected func(): number but got func(): string') + + let RefStr: func: string + RefStr = FuncNoArgRetString + RefStr = FuncOneArgRetString + CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): string but got func()') + CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func(): string but got func(): number') +enddef + def Test_func_type_fails() CheckDefFailure(['let ref1: func()'], 'E704:') diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index cab9f86304..4e0dc1b2ca 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -170,6 +170,11 @@ def Test_assignment_default() assert_equal(5678, nr) enddef +def Mess(): string + v:foldstart = 123 + return 'xxx' +enddef + func Test_assignment_failure() call CheckDefFailure(['let var=234'], 'E1004:') call CheckDefFailure(['let var =234'], 'E1004:') @@ -207,6 +212,9 @@ func Test_assignment_failure() call CheckDefFailure(['let var: dict '], 'E1068:') call CheckDefFailure(['let var: dictDoLast() - call append(line('$'), "last line") -endfunc - -func s:DoNothing() - call append(line('$'), "nothing line") -endfunc - -func Test_script_local_func() - set nocp nomore viminfo+=nviminfo - new - nnoremap _x :call DoNothing()call DoLast()delfunc DoNothingdelfunc DoLast - - normal _x - call assert_equal('nothing line', getline(2)) - call assert_equal('last line', getline(3)) - enew! | close -endfunc - func Test_script_expand_sfile() let lines =<< trim END func s:snr() @@ -1888,84 +1816,6 @@ func Test_refcount() delfunc DictFunc endfunc -func Test_funccall_garbage_collect() - func Func(x, ...) - call add(a:x, a:000) - endfunc - call Func([], []) - " Must not crash cause by invalid freeing - call test_garbagecollect_now() - call assert_true(v:true) - delfunc Func -endfunc - -func Test_function_defined_line() - CheckNotGui - - let lines =<< trim [CODE] - " F1 - func F1() - " F2 - func F2() - " - " - " - return - endfunc - " F3 - execute "func F3()\n\n\n\nreturn\nendfunc" - " F4 - execute "func F4()\n - \\n - \\n - \\n - \return\n - \endfunc" - endfunc - " F5 - execute "func F5()\n\n\n\nreturn\nendfunc" - " F6 - execute "func F6()\n - \\n - \\n - \\n - \return\n - \endfunc" - call F1() - verbose func F1 - verbose func F2 - verbose func F3 - verbose func F4 - verbose func F5 - verbose func F6 - qall! - [CODE] - - call writefile(lines, 'Xtest.vim') - let res = system(GetVimCommandClean() .. ' -es -X -S Xtest.vim') - call assert_equal(0, v:shell_error) - - let m = matchstr(res, 'function F1()[^[:print:]]*[[:print:]]*') - call assert_match(' line 2$', m) - - let m = matchstr(res, 'function F2()[^[:print:]]*[[:print:]]*') - call assert_match(' line 4$', m) - - let m = matchstr(res, 'function F3()[^[:print:]]*[[:print:]]*') - call assert_match(' line 11$', m) - - let m = matchstr(res, 'function F4()[^[:print:]]*[[:print:]]*') - call assert_match(' line 13$', m) - - let m = matchstr(res, 'function F5()[^[:print:]]*[[:print:]]*') - call assert_match(' line 21$', m) - - let m = matchstr(res, 'function F6()[^[:print:]]*[[:print:]]*') - call assert_match(' line 23$', m) - - call delete('Xtest.vim') -endfunc - " Test for missing :endif, :endfor, :endwhile and :endtry {{{1 func Test_missing_end() call writefile(['if 2 > 1', 'echo ">"'], 'Xscript') @@ -2063,30 +1913,30 @@ func Test_deep_nest() " Deep nesting of if ... endif call term_sendkeys(buf, ":call Test1()\n") - call term_wait(buf) + call TermWait(buf) call WaitForAssert({-> assert_match('^E579:', term_getline(buf, 5))}) " Deep nesting of for ... endfor call term_sendkeys(buf, ":call Test2()\n") - call term_wait(buf) + call TermWait(buf) call WaitForAssert({-> assert_match('^E585:', term_getline(buf, 5))}) " Deep nesting of while ... endwhile call term_sendkeys(buf, ":call Test3()\n") - call term_wait(buf) + call TermWait(buf) call WaitForAssert({-> assert_match('^E585:', term_getline(buf, 5))}) " Deep nesting of try ... endtry call term_sendkeys(buf, ":call Test4()\n") - call term_wait(buf) + call TermWait(buf) call WaitForAssert({-> assert_match('^E601:', term_getline(buf, 5))}) " Deep nesting of function ... endfunction call term_sendkeys(buf, ":call Test5()\n") - call term_wait(buf) + call TermWait(buf) call WaitForAssert({-> assert_match('^E1058:', term_getline(buf, 4))}) call term_sendkeys(buf, "\\n") - call term_wait(buf) + call TermWait(buf) "let l = '' "for i in range(1, 6) @@ -2098,16 +1948,6 @@ func Test_deep_nest() call delete('Xscript') endfunc -" Test for , in a function {{{1 -func Test_sfile_in_function() - func Xfunc() - call assert_match('..Test_sfile_in_function\[5]..Xfunc', expand('')) - call assert_equal('2', expand('')) - endfunc - call Xfunc() - delfunc Xfunc -endfunc - " Test for errors in converting to float from various types {{{1 func Test_float_conversion_errors() if has('float') diff --git a/src/userfunc.c b/src/userfunc.c index f93c1492c4..316eac6aa0 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -3020,7 +3020,7 @@ ex_function(exarg_T *eap) if (eap->cmdidx == CMD_def) { - int lnum_save = SOURCING_LNUM; + int lnum_save = SOURCING_LNUM; // error messages are for the first function line SOURCING_LNUM = sourcing_lnum_top; @@ -3034,7 +3034,8 @@ ex_function(exarg_T *eap) // and uf_va_type. int len = argtypes.ga_len - (varargs ? 1 : 0); - fp->uf_arg_types = ALLOC_CLEAR_MULT(type_T *, len); + if (len > 0) + fp->uf_arg_types = ALLOC_CLEAR_MULT(type_T *, len); if (fp->uf_arg_types != NULL) { int i; @@ -3044,8 +3045,8 @@ ex_function(exarg_T *eap) { p = ((char_u **)argtypes.ga_data)[i]; if (p == NULL) - // todo: get type from default value - type = &t_any; + // will get the type from the default value + type = &t_unknown; else type = parse_type(&p, &fp->uf_type_list); if (type == NULL) diff --git a/src/version.c b/src/version.c index 5aa82f5380..0040ae753d 100644 --- a/src/version.c +++ b/src/version.c @@ -753,6 +753,34 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 539, +/**/ + 538, +/**/ + 537, +/**/ + 536, +/**/ + 535, +/**/ + 534, +/**/ + 533, +/**/ + 532, +/**/ + 531, +/**/ + 530, +/**/ + 529, +/**/ + 528, +/**/ + 527, +/**/ + 526, /**/ 525, /**/ diff --git a/src/vim9.h b/src/vim9.h index 0c59b06ced..57cbfead33 100644 --- a/src/vim9.h +++ b/src/vim9.h @@ -46,7 +46,6 @@ typedef enum { ISN_PUSHS, // push string isn_arg.string ISN_PUSHBLOB, // push blob isn_arg.blob ISN_PUSHFUNC, // push func isn_arg.string - ISN_PUSHPARTIAL, // push partial ? ISN_PUSHCHANNEL, // push channel isn_arg.channel ISN_PUSHJOB, // push channel isn_arg.job ISN_NEWLIST, // push list from stack items, size is isn_arg.number @@ -92,7 +91,6 @@ typedef enum { ISN_COMPARELIST, ISN_COMPAREDICT, ISN_COMPAREFUNC, - ISN_COMPAREPARTIAL, ISN_COMPAREANY, // expression operations diff --git a/src/vim9compile.c b/src/vim9compile.c index 359007a38a..90f7d28413 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -130,6 +130,8 @@ static int compile_expr1(char_u **arg, cctx_T *cctx); static int compile_expr2(char_u **arg, cctx_T *cctx); static int compile_expr3(char_u **arg, cctx_T *cctx); static void delete_def_function_contents(dfunc_T *dfunc); +static void arg_type_mismatch(type_T *expected, type_T *actual, int argidx); +static int check_type(type_T *expected, type_T *actual, int give_msg); /* * Lookup variable "name" in the local scope and return the index. @@ -314,6 +316,11 @@ get_func_type(type_T *ret_type, int argcount, garray_T *type_gap) // recognize commonly used types if (argcount <= 0) { + if (ret_type == &t_unknown) + { + // (argcount == 0) is not possible + return &t_func_unknown; + } if (ret_type == &t_void) { if (argcount == 0) @@ -350,6 +357,7 @@ get_func_type(type_T *ret_type, int argcount, garray_T *type_gap) return &t_any; type->tt_type = VAR_FUNC; type->tt_member = ret_type; + type->tt_argcount = argcount; type->tt_args = NULL; return type; } @@ -388,14 +396,14 @@ typval2type(typval_T *tv) if (tv->v_type == VAR_NUMBER) return &t_number; if (tv->v_type == VAR_BOOL) - return &t_bool; + return &t_bool; // not used if (tv->v_type == VAR_STRING) return &t_string; if (tv->v_type == VAR_LIST) // e.g. for v:oldfiles return &t_list_string; if (tv->v_type == VAR_DICT) // e.g. for v:completed_item return &t_dict_any; - return &t_any; + return &t_any; // not used } ///////////////////////////////////////////////////////////////////// @@ -634,7 +642,6 @@ generate_COMPARE(cctx_T *cctx, exptype_T exptype, int ic) case VAR_LIST: isntype = ISN_COMPARELIST; break; case VAR_DICT: isntype = ISN_COMPAREDICT; break; case VAR_FUNC: isntype = ISN_COMPAREFUNC; break; - case VAR_PARTIAL: isntype = ISN_COMPAREPARTIAL; break; default: isntype = ISN_COMPAREANY; break; } } @@ -871,23 +878,6 @@ generate_PUSHFUNC(cctx_T *cctx, char_u *name, type_T *type) return OK; } -/* - * Generate an ISN_PUSHPARTIAL instruction with partial "part". - * Consumes "part". - */ - static int -generate_PUSHPARTIAL(cctx_T *cctx, partial_T *part) -{ - isn_T *isn; - - RETURN_OK_IF_SKIP(cctx); - if ((isn = generate_instr_type(cctx, ISN_PUSHPARTIAL, &t_func_any)) == NULL) - return FAIL; - isn->isn_arg.partial = part; - - return OK; -} - /* * Generate an ISN_STORE instruction. */ @@ -966,7 +956,7 @@ generate_LOAD( } /* - * Generate an ISN_LOADV instruction. + * Generate an ISN_LOADV instruction for v:var. */ static int generate_LOADV( @@ -974,8 +964,9 @@ generate_LOADV( char_u *name, int error) { - // load v:var - int vidx = find_vim_var(name); + int di_flags; + int vidx = find_vim_var(name, &di_flags); + type_T *type; RETURN_OK_IF_SKIP(cctx); if (vidx < 0) @@ -984,9 +975,9 @@ generate_LOADV( semsg(_(e_var_notfound), name); return FAIL; } + type = typval2type(get_vim_var_tv(vidx)); - // TODO: get actual type - return generate_LOAD(cctx, ISN_LOADV, vidx, NULL, &t_any); + return generate_LOAD(cctx, ISN_LOADV, vidx, NULL, type); } /* @@ -1234,6 +1225,32 @@ generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount) return FAIL; } + if (ufunc->uf_dfunc_idx >= 0) + { + int i; + + for (i = 0; i < argcount; ++i) + { + type_T *expected; + type_T *actual; + + if (i < regular_args) + { + if (ufunc->uf_arg_types == NULL) + continue; + expected = ufunc->uf_arg_types[i]; + } + else + expected = ufunc->uf_va_type->tt_member; + actual = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i]; + if (check_type(expected, actual, FALSE) == FAIL) + { + arg_type_mismatch(expected, actual, i + 1); + return FAIL; + } + } + } + // Turn varargs into a list. if (ufunc->uf_va_name != NULL) { @@ -1589,7 +1606,7 @@ parse_type(char_u **arg, garray_T *type_gap) if (len == 4 && STRNCMP(*arg, "func", len) == 0) { type_T *type; - type_T *ret_type = &t_any; + type_T *ret_type = &t_unknown; int argcount = -1; int flags = 0; int first_optional = -1; @@ -1657,7 +1674,7 @@ parse_type(char_u **arg, garray_T *type_gap) { // parse return type ++*arg; - if (!VIM_ISWHITE(*p)) + if (!VIM_ISWHITE(**arg)) semsg(_(e_white_after), ":"); *arg = skipwhite(*arg); ret_type = parse_type(arg, type_gap); @@ -2397,6 +2414,18 @@ type_mismatch(type_T *expected, type_T *actual) vim_free(tofree2); } + static void +arg_type_mismatch(type_T *expected, type_T *actual, int argidx) +{ + char *tofree1, *tofree2; + + semsg(_("E1013: argument %d: type mismatch, expected %s but got %s"), + argidx, + type_name(expected, &tofree1), type_name(actual, &tofree2)); + vim_free(tofree1); + vim_free(tofree2); +} + /* * Check if the expected and actual types match. */ @@ -2405,7 +2434,10 @@ check_type(type_T *expected, type_T *actual, int give_msg) { int ret = OK; - if (expected->tt_type != VAR_UNKNOWN && expected->tt_type != VAR_ANY) + // When expected is "unknown" we accept any actual type. + // When expected is "any" we accept any actual type except "void". + if (expected->tt_type != VAR_UNKNOWN + && (expected->tt_type != VAR_ANY || actual->tt_type == VAR_VOID)) { if (expected->tt_type != actual->tt_type) { @@ -2421,8 +2453,7 @@ check_type(type_T *expected, type_T *actual, int give_msg) } else if (expected->tt_type == VAR_FUNC) { - if (expected->tt_member != &t_any - && expected->tt_member != &t_unknown) + if (expected->tt_member != &t_unknown) ret = check_type(expected->tt_member, actual->tt_member, FALSE); if (ret == OK && expected->tt_argcount != -1 && (actual->tt_argcount < expected->tt_min_argcount @@ -3859,14 +3890,18 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) } else if (STRNCMP(arg, "v:", 2) == 0) { - typval_T *vtv; + typval_T *vtv; + int di_flags; - vimvaridx = find_vim_var(name + 2); + vimvaridx = find_vim_var(name + 2, &di_flags); if (vimvaridx < 0) { semsg(_(e_var_notfound), arg); goto theend; } + // We use the current value of "sandbox" here, is that OK? + if (var_check_ro(di_flags, name, FALSE)) + goto theend; dest = dest_vimvar; vtv = get_vim_var_tv(vimvaridx); type = typval2type(vtv); @@ -4044,36 +4079,39 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) if (r == FAIL) goto theend; - stack = &cctx->ctx_type_stack; - stacktype = stack->ga_len == 0 ? &t_void - : ((type_T **)stack->ga_data)[stack->ga_len - 1]; - if (idx >= 0 && (is_decl || !has_type)) + if (cctx->ctx_skip != TRUE) { - lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx; - if (new_local && !has_type) + stack = &cctx->ctx_type_stack; + stacktype = stack->ga_len == 0 ? &t_void + : ((type_T **)stack->ga_data)[stack->ga_len - 1]; + if (idx >= 0 && (is_decl || !has_type)) { - if (stacktype->tt_type == VAR_VOID) + lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx; + if (new_local && !has_type) { - emsg(_("E1031: Cannot use void value")); - goto theend; - } - else - { - // An empty list or dict has a &t_void member, for a - // variable that implies &t_any. - if (stacktype == &t_list_empty) - lvar->lv_type = &t_list_any; - else if (stacktype == &t_dict_empty) - lvar->lv_type = &t_dict_any; + if (stacktype->tt_type == VAR_VOID) + { + emsg(_("E1031: Cannot use void value")); + goto theend; + } else - lvar->lv_type = stacktype; + { + // An empty list or dict has a &t_void member, for a + // variable that implies &t_any. + if (stacktype == &t_list_empty) + lvar->lv_type = &t_list_any; + else if (stacktype == &t_dict_empty) + lvar->lv_type = &t_dict_any; + else + lvar->lv_type = stacktype; + } } + else if (need_type(stacktype, lvar->lv_type, -1, cctx) == FAIL) + goto theend; } - else if (need_type(stacktype, lvar->lv_type, -1, cctx) == FAIL) + else if (*p != '=' && check_type(type, stacktype, TRUE) == FAIL) goto theend; } - else if (*p != '=' && check_type(type, stacktype, TRUE) == FAIL) - goto theend; } else if (cmdidx == CMD_const) { @@ -4109,9 +4147,6 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) case VAR_FUNC: generate_PUSHFUNC(cctx, NULL, &t_func_void); break; - case VAR_PARTIAL: - generate_PUSHPARTIAL(cctx, NULL); - break; case VAR_LIST: generate_NEWLIST(cctx, 0); break; @@ -4127,6 +4162,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) case VAR_NUMBER: case VAR_UNKNOWN: case VAR_ANY: + case VAR_PARTIAL: case VAR_VOID: case VAR_SPECIAL: // cannot happen generate_PUSHNR(cctx, 0); @@ -5497,6 +5533,7 @@ compile_def_function(ufunc_T *ufunc, int set_return_type) if (ufunc->uf_def_args.ga_len > 0) { int count = ufunc->uf_def_args.ga_len; + int first_def_arg = ufunc->uf_args.ga_len - count; int i; char_u *arg; int off = STACK_FRAME_SIZE + (ufunc->uf_va_name != NULL ? 1 : 0); @@ -5510,11 +5547,30 @@ compile_def_function(ufunc_T *ufunc, int set_return_type) goto erret; for (i = 0; i < count; ++i) { + garray_T *stack = &cctx.ctx_type_stack; + type_T *val_type; + int arg_idx = first_def_arg + i; + ufunc->uf_def_arg_idx[i] = instr->ga_len; arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i]; - if (compile_expr1(&arg, &cctx) == FAIL - || generate_STORE(&cctx, ISN_STORE, - i - count - off, NULL) == FAIL) + if (compile_expr1(&arg, &cctx) == FAIL) + goto erret; + + // If no type specified use the type of the default value. + // Otherwise check that the default value type matches the + // specified type. + val_type = ((type_T **)stack->ga_data)[stack->ga_len - 1]; + if (ufunc->uf_arg_types[arg_idx] == &t_unknown) + ufunc->uf_arg_types[arg_idx] = val_type; + else if (check_type(ufunc->uf_arg_types[i], val_type, FALSE) + == FAIL) + { + arg_type_mismatch(ufunc->uf_arg_types[arg_idx], val_type, + arg_idx + 1); + goto erret; + } + + if (generate_STORE(&cctx, ISN_STORE, i - count - off, NULL) == FAIL) goto erret; } @@ -5942,10 +5998,6 @@ delete_instr(isn_T *isn) blob_unref(isn->isn_arg.blob); break; - case ISN_PUSHPARTIAL: - partial_unref(isn->isn_arg.partial); - break; - case ISN_PUSHJOB: #ifdef FEAT_JOB_CHANNEL job_unref(isn->isn_arg.job); @@ -5978,7 +6030,6 @@ delete_instr(isn_T *isn) case ISN_COMPAREFUNC: case ISN_COMPARELIST: case ISN_COMPARENR: - case ISN_COMPAREPARTIAL: case ISN_COMPARESPECIAL: case ISN_COMPARESTRING: case ISN_CONCAT: diff --git a/src/vim9execute.c b/src/vim9execute.c index b7ec9798c3..d9b87c18dc 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -858,7 +858,6 @@ call_def_function( case ISN_PUSHS: case ISN_PUSHBLOB: case ISN_PUSHFUNC: - case ISN_PUSHPARTIAL: case ISN_PUSHCHANNEL: case ISN_PUSHJOB: if (ga_grow(&ectx.ec_stack, 1) == FAIL) @@ -896,12 +895,6 @@ call_def_function( tv->vval.v_string = vim_strsave(iptr->isn_arg.string); break; - case ISN_PUSHPARTIAL: - tv->v_type = VAR_PARTIAL; - tv->vval.v_partial = iptr->isn_arg.partial; - if (tv->vval.v_partial != NULL) - ++tv->vval.v_partial->pt_refcount; - break; case ISN_PUSHCHANNEL: #ifdef FEAT_JOB_CHANNEL tv->v_type = VAR_CHANNEL; @@ -1412,7 +1405,6 @@ call_def_function( case ISN_COMPARESTRING: case ISN_COMPAREDICT: case ISN_COMPAREFUNC: - case ISN_COMPAREPARTIAL: case ISN_COMPAREANY: { typval_T *tv1 = STACK_TV_BOT(-2); @@ -1932,14 +1924,6 @@ ex_disassemble(exarg_T *eap) name == NULL ? "[none]" : name); } break; - case ISN_PUSHPARTIAL: - { - partial_T *part = iptr->isn_arg.partial; - - smsg("%4d PUSHPARTIAL \"%s\"", current, - part == NULL ? "[none]" : (char *)partial_name(part)); - } - break; case ISN_PUSHCHANNEL: #ifdef FEAT_JOB_CHANNEL { @@ -2117,7 +2101,6 @@ ex_disassemble(exarg_T *eap) case ISN_COMPARELIST: case ISN_COMPAREDICT: case ISN_COMPAREFUNC: - case ISN_COMPAREPARTIAL: case ISN_COMPAREANY: { char *p; @@ -2154,8 +2137,6 @@ ex_disassemble(exarg_T *eap) case ISN_COMPARELIST: type = "COMPARELIST"; break; case ISN_COMPAREDICT: type = "COMPAREDICT"; break; case ISN_COMPAREFUNC: type = "COMPAREFUNC"; break; - case ISN_COMPAREPARTIAL: - type = "COMPAREPARTIAL"; break; case ISN_COMPAREANY: type = "COMPAREANY"; break; default: type = "???"; break; }