Compare commits

..

27 Commits

Author SHA1 Message Date
Bram Moolenaar
420952175a patch 8.2.1264: terminal getwinpos() test is a bit flaky
Problem:    Terminal getwinpos() test is a bit flaky.
Solution:   Call getwinpos() a bit later.
2020-07-21 21:48:58 +02:00
Bram Moolenaar
c71f36a889 patch 8.2.1263: Vim9: comperators use 'ignorecase' in Vim9 script
Problem:    Vim9: comperators use 'ignorecase' in Vim9 script.
Solution:   Ignore 'ignorecase'.  Use true and false instead of 1 and 0.
            (closes #6497)
2020-07-21 21:31:00 +02:00
Bram Moolenaar
f868ba8903 patch 8.2.1262: src/ex_cmds.c file is too big
Problem:    src/ex_cmds.c file is too big.
Solution:   Move help related code to src/help.c. (Yegappan Lakshmanan,
            closes #6506)
2020-07-21 21:07:20 +02:00
Bram Moolenaar
c7db57788b patch 8.2.1261: Vim9: common type of function not tested
Problem:    Vim9: common type of function not tested.
Solution:   Add a test.  Fix uncovered problems.
2020-07-21 20:55:50 +02:00
Bram Moolenaar
7591116acf patch 8.2.1260: there is no good test for CursorHold
Problem:    There is no good test for CursorHold.
Solution:   Add a test.  Remove duplicated test. (Yegappan Lakshmanan,
            closes #6503
2020-07-21 19:44:47 +02:00
Bram Moolenaar
f56c95fdad patch 8.2.1259: empty group in 'tabline' may cause using an invalid pointer
Problem:    Empty group in 'tabline' may cause using an invalid pointer.
Solution:   Set the group start position. (closes #6505)
2020-07-21 19:25:18 +02:00
Bram Moolenaar
08815a1d03 patch 8.2.1258: CursorHold does not work well
Problem:    CursorHold does not work well.a (Shane-XB-Qian)
Solution:   Only restore did_cursorhold when using :normal.
2020-07-20 23:10:56 +02:00
Bram Moolenaar
b31be3f909 patch 8.2.1257: Vim9: list unpack doesn't work at the script level
Problem:    Vim9: list unpack doesn't work at the script level.
Solution:   Detect unpack assignment better. (closes #6494)
2020-07-20 22:37:44 +02:00
Bram Moolenaar
7892b953e0 patch 8.2.1256: Vim9: type wrong after getting dict item in lambda
Problem:    Vim9: type wrong after getting dict item in lambda.
Solution:   Set the type to "any" after enforcing dict type. (closes #6491)
2020-07-20 22:09:34 +02:00
Bram Moolenaar
d43906d2e5 patch 8.2.1255: cannot use a lambda with quickfix functions
Problem:    Cannot use a lambda with quickfix functions.
Solution:   Add support for lambda. (Yegappan Lakshmanan, closes #6499)
2020-07-20 21:31:32 +02:00
Bram Moolenaar
470adb827f patch 8.2.1254: MS-Windows: regexp test may fail if 'iskeyword' set wrongly
Problem:    MS-Windows: regexp test may fail if 'iskeyword' set wrongly.
Solution:   Override the 'iskeyword' value. (Taro Muraoka, closes #6502)
2020-07-20 21:21:30 +02:00
Bram Moolenaar
b146e01a7e patch 8.2.1253: CTRL-K in Insert mode gets <CursorHold> inserted
Problem:    CTRL-K in Insert mode gets <CursorHold> inserted. (Roland
            Puntaier)
Solution:   Do not reset did_cursorhold, restore it. (closes #6447)
2020-07-19 23:06:05 +02:00
Bram Moolenaar
54c3fcd852 patch 8.2.1252: ":marks" may show '< and '> mixed up
Problem:    ":marks" may show '< and '> mixed up.
Solution:   Show the mark position as where '< and '> would jump.
2020-07-19 22:09:06 +02:00
Bram Moolenaar
682d0a1546 patch 8.2.1251: Vim9: warning for pointer usage, test failure undetected
Problem:    Vim9: warning for pointer usage, test failure undetected.
Solution:   Fix pointer indirection.  Give error when executing function
            failed for any reason.  Fix instruction names.
2020-07-19 20:48:59 +02:00
Bram Moolenaar
2f8ce0ae8a patch 8.2.1250: Vim9: cannot use the g:, b:, t: and w: namespaces
Problem:    Vim9: cannot use the g:, b:, t: and w: namespaces.
Solution:   Add instructions to push a dict for the namespaces. (closes #6480)
2020-07-19 19:47:35 +02:00
Bram Moolenaar
747f11ad6e patch 8.2.1249: Vim9: disassemble test fails
Problem:    Vim9: disassemble test fails.
Solution:   Change INDEX to LISTINDEX.  Add test for STRINDEX.
2020-07-19 18:38:37 +02:00
Bram Moolenaar
956501594e patch 8.2.1248: Netbeans test is flaky in the GUI
Problem:    Netbeans test is flaky in the GUI.
Solution:   Filter out geometry messages. (Taro Muraoka, closes #6487)
2020-07-19 18:24:32 +02:00
Bram Moolenaar
bf9d8c3765 patch 8.2.1247: Vim9: cannot index a character in a string
Problem:    Vim9: cannot index a character in a string.
Solution:   Add ISN_STRINDEX instruction. (closes #6478)
2020-07-19 17:55:44 +02:00
Bram Moolenaar
b209750b5e patch 8.2.1246: Vim9: comment after assignment doesn't work
Problem:    Vim9: comment after assignment doesn't work.
Solution:   Skip over white space. (closes #6481)
2020-07-19 17:17:02 +02:00
Bram Moolenaar
f398238a37 patch 8.2.1245: build failure in tiny version
Problem:    Build failure in tiny version.
Solution:   Add #ifdef.
2020-07-19 16:32:09 +02:00
Bram Moolenaar
6802cce407 patch 8.2.1244: Vim9: in lambda index assumes a list
Problem:    Vim9: in lambda index assumes a list.
Solution:   Use the value type to decide about list or dict. (closes #6479)
2020-07-19 15:49:49 +02:00
Bram Moolenaar
75783bd84e patch 8.2.1243: Vim9: cannot have a comment line halfway a list
Problem:    Vim9: cannot have a comment or empty line halfway a list at script
            level.
Solution:   Skip more than one line if needed.
2020-07-19 14:41:58 +02:00
Bram Moolenaar
65b9545f44 patch 8.2.1242: Vim9: no error if calling a function with wrong type
Problem:    Vim9: no error if calling a function with wrong argument type.
Solution:   Check types of arguments. (closes #6469)
2020-07-19 14:03:09 +02:00
Bram Moolenaar
6434fc574d patch 8.2.1241: cannot use getbufinfo() as a method
Problem:    Cannot use getbufinfo() as a method.
Solution:   Support using getbufinfo() as a method. (closes #6458)
2020-07-18 22:24:22 +02:00
Bram Moolenaar
10e1d01aaf patch 8.2.1240: GUI tests sometimes fail because of translations
Problem:    GUI tests sometimes fail because of translations.
Solution:   Reload the menus without translation. (Taro Muraoka, closes #6486)
2020-07-18 22:03:11 +02:00
Bram Moolenaar
de2396fc87 patch 8.2.1239: "maxwidth" in 'completepopup' not obeyed
Problem:    "maxwidth" in 'completepopup' not obeyed. (Jay Sitter)
Solution:   Add separate field for value from option. (closes #6470)
2020-07-18 21:40:41 +02:00
Bram Moolenaar
d032f34a51 patch 8.2.1238: Vim9: a few remaining errors not caught by try/catch
Problem:    Vim9: a few remaining errors not caught by try/catch.
Solution:   Do not bail out if an error is inside try/catch.
2020-07-18 18:13:02 +02:00
56 changed files with 2465 additions and 1727 deletions

View File

@@ -68,6 +68,7 @@ SRC_ALL = \
src/gui_beval.c \
src/hardcopy.c \
src/hashtab.c \
src/help.c \
src/highlight.c \
src/indent.c \
src/insexpand.c \
@@ -240,6 +241,7 @@ SRC_ALL = \
src/proto/gui_beval.pro \
src/proto/hardcopy.pro \
src/proto/hashtab.pro \
src/proto/help.pro \
src/proto/highlight.pro \
src/proto/indent.pro \
src/proto/insexpand.pro \

View File

@@ -1,4 +1,4 @@
*eval.txt* For Vim version 8.2. Last change: 2020 Jul 09
*eval.txt* For Vim version 8.2. Last change: 2020 Jul 19
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -94,8 +94,9 @@ the Number. Examples:
Number 0 --> String "0" ~
Number -1 --> String "-1" ~
*octal*
Conversion from a String to a Number is done by converting the first digits to
a number. Hexadecimal "0xf9", Octal "017" or "0o17", and Binary "0b10"
Conversion from a String to a Number only happens in legacy Vim script, not in
Vim9 script. It is done by converting the first digits to a number.
Hexadecimal "0xf9", Octal "017" or "0o17", and Binary "0b10"
numbers are recognized (NOTE: when using |scriptversion-4| octal with a
leading "0" is not recognized). If the String doesn't start with digits, the
result is zero.
@@ -2831,7 +2832,7 @@ stridx({haystack}, {needle} [, {start}])
string({expr}) String String representation of {expr} value
strlen({expr}) Number length of the String {expr}
strpart({str}, {start} [, {len}])
String {len} characters of {str} at {start}
String {len} bytes of {str} at byte {start}
strptime({format}, {timestring})
Number Convert {timestring} to unix timestamp
strridx({haystack}, {needle} [, {start}])
@@ -4929,8 +4930,11 @@ getbufinfo([{dict}])
<
To get buffer-local options use: >
getbufvar({bufnr}, '&option_name')
<
Can also be used as a |method|: >
GetBufnr()->getbufinfo()
<
*getbufline()*
getbufline({expr}, {lnum} [, {end}])
Return a |List| with the lines starting from {lnum} to {end}
@@ -9180,7 +9184,8 @@ setqflist({list} [, {action} [, {what}]]) *setqflist()*
the last quickfix list.
quickfixtextfunc
function to get the text to display in the
quickfix window. Refer to
quickfix window. The value can be the name of
a function or a funcref or a lambda. Refer to
|quickfix-window-function| for an explanation
of how to write the function and an example.
title quickfix list title text. See |quickfix-title|

View File

@@ -5913,7 +5913,8 @@ A jump table for the options with a short description can be found at |Q_op|.
customize the information displayed in the quickfix or location window
for each entry in the corresponding quickfix or location list. See
|quickfix-window-function| for an explanation of how to write the
function and an example.
function and an example. The value can be the name of a function or a
lambda.
This option cannot be set from a |modeline| or in the |sandbox|, for
security reasons.

View File

@@ -1964,7 +1964,10 @@ The function should return a single line of text to display in the quickfix
window for each entry from start_idx to end_idx. The function can obtain
information about the entries using the |getqflist()| function and specifying
the quickfix list identifier "id". For a location list, getloclist() function
can be used with the 'winid' argument.
can be used with the 'winid' argument. If an empty list is returned, then the
default format is used to display all the entries. If an item in the returned
list is an empty string, then the default format is used to display the
corresponding entry.
If a quickfix or location list specific customization is needed, then the
'quickfixtextfunc' attribute of the list can be set using the |setqflist()| or

View File

@@ -744,6 +744,7 @@ OBJ = \
$(OUTDIR)/gui_xim.o \
$(OUTDIR)/hardcopy.o \
$(OUTDIR)/hashtab.o \
$(OUTDIR)/help.o \
$(OUTDIR)/highlight.o \
$(OUTDIR)/if_cscope.o \
$(OUTDIR)/indent.o \

View File

@@ -64,6 +64,7 @@ SRC = arabic.c \
gui_xim.c \
hardcopy.c \
hashtab.c \
help.c \
highlight.c \
indent.c \
insexpand.c \

View File

@@ -766,6 +766,7 @@ OBJ = \
$(OUTDIR)\gui_xim.obj \
$(OUTDIR)\hardcopy.obj \
$(OUTDIR)\hashtab.obj \
$(OUTDIR)\help.obj \
$(OUTDIR)\highlight.obj \
$(OBJDIR)\if_cscope.obj \
$(OUTDIR)\indent.obj \
@@ -1608,6 +1609,8 @@ $(OUTDIR)/hardcopy.obj: $(OUTDIR) hardcopy.c $(INCL) version.h
$(OUTDIR)/hashtab.obj: $(OUTDIR) hashtab.c $(INCL)
$(OUTDIR)/help.obj: $(OUTDIR) help.c $(INCL)
$(OUTDIR)/highlight.obj: $(OUTDIR) highlight.c $(INCL)
$(OUTDIR)/indent.obj: $(OUTDIR) indent.c $(INCL)
@@ -1930,6 +1933,7 @@ proto.h: \
proto/gui_xim.pro \
proto/hardcopy.pro \
proto/hashtab.pro \
proto/help.pro \
proto/highlight.pro \
proto/indent.pro \
proto/insexpand.pro \

View File

@@ -337,6 +337,7 @@ SRC = \
gui_xim.c \
hardcopy.c \
hashtab.c \
help.c \
highlight.c \
if_cscope.c \
if_xcmdsrv.c \
@@ -450,6 +451,7 @@ OBJ = \
gui_xim.obj \
hardcopy.obj \
hashtab.obj \
help.obj \
highlight.obj \
if_cscope.obj \
if_mzsch.obj \
@@ -834,6 +836,10 @@ hashtab.obj : hashtab.c vim.h [.auto]config.h feature.h os_unix.h \
ascii.h keymap.h term.h macros.h structs.h regexp.h \
gui.h beval.h [.proto]gui_beval.pro option.h ex_cmds.h proto.h \
globals.h
help.obj : help.c vim.h [.auto]config.h feature.h os_unix.h \
ascii.h keymap.h term.h macros.h structs.h regexp.h \
gui.h beval.h [.proto]gui_beval.pro option.h ex_cmds.h proto.h \
globals.h
highlight.obj : highlight.c vim.h [.auto]config.h feature.h os_unix.h \
ascii.h keymap.h term.h macros.h structs.h regexp.h \
gui.h beval.h [.proto]gui_beval.pro option.h ex_cmds.h proto.h \

View File

@@ -404,7 +404,7 @@ CClink = $(CC)
# Use --with-luajit if you want to use LuaJIT instead of Lua.
# Set PATH environment variable to find lua or luajit executable.
# This requires at least "normal" features, "tiny" and "small" don't work.
#CONF_OPT_LUA = --enable-luainterp
CONF_OPT_LUA = --enable-luainterp
#CONF_OPT_LUA = --enable-luainterp=dynamic
#CONF_OPT_LUA = --enable-luainterp --with-luajit
#CONF_OPT_LUA = --enable-luainterp=dynamic --with-luajit
@@ -447,10 +447,10 @@ CClink = $(CC)
# dlopen(), dlsym(), dlclose(), i.e. pythonX.Y.so must be available
# However, this may still cause problems, such as "import termios" failing.
# Build two separate versions of Vim in that case.
#CONF_OPT_PYTHON = --enable-pythoninterp
CONF_OPT_PYTHON = --enable-pythoninterp
#CONF_OPT_PYTHON = --enable-pythoninterp --with-python-command=python2.7
#CONF_OPT_PYTHON = --enable-pythoninterp=dynamic
#CONF_OPT_PYTHON3 = --enable-python3interp
CONF_OPT_PYTHON3 = --enable-python3interp
#CONF_OPT_PYTHON3 = --enable-python3interp --with-python3-command=python3.6
#CONF_OPT_PYTHON3 = --enable-python3interp=dynamic
@@ -472,7 +472,7 @@ CClink = $(CC)
# CSCOPE
# Uncomment this when you want to include the Cscope interface.
#CONF_OPT_CSCOPE = --enable-cscope
CONF_OPT_CSCOPE = --enable-cscope
# NETBEANS - NetBeans interface. Only works with Motif, GTK, and gnome.
# Motif version must have XPM libraries (see |netbeans-xpm|).
@@ -540,7 +540,7 @@ CClink = $(CC)
#CONF_OPT_FEAT = --with-features=small
#CONF_OPT_FEAT = --with-features=normal
#CONF_OPT_FEAT = --with-features=big
#CONF_OPT_FEAT = --with-features=huge
CONF_OPT_FEAT = --with-features=huge
# COMPILED BY - For including a specific e-mail address for ":version".
#CONF_OPT_COMPBY = "--with-compiledby=John Doe <JohnDoe@yahoo.com>"
@@ -614,7 +614,7 @@ CClink = $(CC)
# Use this with GCC to check for mistakes, unused arguments, etc.
# Note: If you use -Wextra and get warnings in GTK code about function
# parameters, you can add -Wno-cast-function-type
#CFLAGS = -g -Wall -Wextra -Wshadow -Wmissing-prototypes -Wunreachable-code -Wno-cast-function-type -Wno-deprecated-declarations -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1
CFLAGS = -g -Wall -Wextra -Wshadow -Wmissing-prototypes -Wunreachable-code -Wno-cast-function-type -Wno-deprecated-declarations -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1
# Add -Wpedantic to find // comments and other C99 constructs.
# Better disable Perl and Python to avoid a lot of warnings.
#CFLAGS = -g -Wall -Wextra -Wshadow -Wmissing-prototypes -Wpedantic -Wunreachable-code -Wunused-result -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1
@@ -709,7 +709,7 @@ SANITIZER_LIBS = $(SANITIZER_CFLAGS)
# Configuration is in the .ccmalloc or ~/.ccmalloc file.
# Doesn't work very well, since memory linked to from global variables
# (in libraries) is also marked as leaked memory.
#LEAK_CFLAGS = -DEXITFREE
LEAK_CFLAGS = -DEXITFREE
#LEAK_LIBS = -lccmalloc
# Uncomment this line to have Vim call abort() when an internal error is
@@ -1639,6 +1639,7 @@ BASIC_SRC = \
gui_xim.c \
hardcopy.c \
hashtab.c \
help.c \
highlight.c \
if_cscope.c \
if_xcmdsrv.c \
@@ -1790,6 +1791,7 @@ OBJ_COMMON = \
objects/gui_xim.o \
objects/hardcopy.o \
objects/hashtab.o \
objects/help.o \
objects/highlight.o \
objects/if_cscope.o \
objects/if_xcmdsrv.o \
@@ -1958,6 +1960,7 @@ PRO_AUTO = \
gui_beval.pro \
hardcopy.pro \
hashtab.pro \
help.pro \
highlight.pro \
if_cscope.pro \
if_lua.pro \
@@ -3264,6 +3267,9 @@ objects/hardcopy.o: hardcopy.c
objects/hashtab.o: hashtab.c
$(CCC) -o $@ hashtab.c
objects/help.o: help.c
$(CCC) -o $@ help.c
objects/gui.o: gui.c
$(CCC) -o $@ gui.c
@@ -3930,6 +3936,10 @@ objects/hashtab.o: hashtab.c vim.h protodef.h auto/config.h feature.h os_unix.h
auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \
proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \
proto.h globals.h
objects/help.o: help.c vim.h protodef.h auto/config.h feature.h os_unix.h \
auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \
proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \
proto.h globals.h
objects/highlight.o: highlight.c vim.h protodef.h auto/config.h feature.h \
os_unix.h auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \
proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \

View File

@@ -48,6 +48,7 @@ filepath.c | dealing with file names and paths
findfile.c | search for files in 'path'
fold.c | folding
getchar.c | getting characters and key mapping
help.c | vim help related functions
highlight.c | syntax highlighting
indent.c | text indentation
insexpand.c | Insert mode completion

View File

@@ -4229,12 +4229,19 @@ build_stl_str_hl(
}
if (n == curitem && group_start_userhl == group_end_userhl)
{
// empty group
p = t;
l = 0;
// do not use the highlighting from the removed group
for (n = groupitem[groupdepth] + 1; n < curitem; n++)
{
// do not use the highlighting from the removed group
if (item[n].type == Highlight)
item[n].type = Empty;
// adjust the start position of TabPage to the next
// item position
if (item[n].type == TabPage)
item[n].start = p;
}
}
}
if (l > item[groupitem[groupdepth]].maxwid)

View File

@@ -1101,27 +1101,6 @@ channel_open(
return channel;
}
/*
* Copy callback from "src" to "dest", incrementing the refcounts.
*/
static void
copy_callback(callback_T *dest, callback_T *src)
{
dest->cb_partial = src->cb_partial;
if (dest->cb_partial != NULL)
{
dest->cb_name = src->cb_name;
dest->cb_free_name = FALSE;
++dest->cb_partial->pt_refcount;
}
else
{
dest->cb_name = vim_strsave(src->cb_name);
dest->cb_free_name = TRUE;
func_ref(src->cb_name);
}
}
static void
free_set_callback(callback_T *cbp, callback_T *callback)
{

View File

@@ -1887,62 +1887,6 @@ expand_cmdline(
return EXPAND_OK;
}
#ifdef FEAT_MULTI_LANG
/*
* Cleanup matches for help tags:
* Remove "@ab" if the top of 'helplang' is "ab" and the language of the first
* tag matches it. Otherwise remove "@en" if "en" is the only language.
*/
static void
cleanup_help_tags(int num_file, char_u **file)
{
int i, j;
int len;
char_u buf[4];
char_u *p = buf;
if (p_hlg[0] != NUL && (p_hlg[0] != 'e' || p_hlg[1] != 'n'))
{
*p++ = '@';
*p++ = p_hlg[0];
*p++ = p_hlg[1];
}
*p = NUL;
for (i = 0; i < num_file; ++i)
{
len = (int)STRLEN(file[i]) - 3;
if (len <= 0)
continue;
if (STRCMP(file[i] + len, "@en") == 0)
{
// Sorting on priority means the same item in another language may
// be anywhere. Search all items for a match up to the "@en".
for (j = 0; j < num_file; ++j)
if (j != i && (int)STRLEN(file[j]) == len + 3
&& STRNCMP(file[i], file[j], len + 1) == 0)
break;
if (j == num_file)
// item only exists with @en, remove it
file[i][len] = NUL;
}
}
if (*buf != NUL)
for (i = 0; i < num_file; ++i)
{
len = (int)STRLEN(file[i]) - 3;
if (len <= 0)
continue;
if (STRCMP(file[i] + len, buf) == 0)
{
// remove the default language
file[i][len] = NUL;
}
}
}
#endif
/*
* Function given to ExpandGeneric() to obtain the possible arguments of the
* ":behave {mswin,xterm}" command.

View File

@@ -1913,7 +1913,7 @@ eval_next_non_blank(char_u *arg, evalarg_T *evalarg, int *getnext)
&& evalarg != NULL
&& (evalarg->eval_cookie != NULL || evalarg->eval_cctx != NULL)
&& (*arg == NUL || (VIM_ISWHITE(arg[-1])
&& *arg == '#' && arg[1] != '{')))
&& vim9_comment_start(arg))))
{
char_u *p;
@@ -2413,13 +2413,11 @@ eval3(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
static int
eval4(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
{
typval_T var2;
char_u *p;
int getnext;
int i;
exptype_T type = EXPR_UNKNOWN;
int len = 2;
int ic;
/*
* Get the first variable.
@@ -2472,6 +2470,10 @@ eval4(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
*/
if (type != EXPR_UNKNOWN)
{
typval_T var2;
int ic;
int vim9script = in_vim9script();
if (getnext)
*arg = eval_next_line(evalarg);
@@ -2487,9 +2489,9 @@ eval4(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
ic = FALSE;
++len;
}
// nothing appended: use 'ignorecase'
// nothing appended: use 'ignorecase' if not in Vim script
else
ic = p_ic;
ic = vim9script ? FALSE : p_ic;
/*
* Get the second variable.
@@ -2504,8 +2506,7 @@ eval4(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
{
int ret;
if (in_vim9script() && check_compare_types(
type, rettv, &var2) == FAIL)
if (vim9script && check_compare_types(type, rettv, &var2) == FAIL)
{
ret = FAIL;
clear_tv(rettv);

View File

@@ -611,7 +611,7 @@ static funcentry_T global_functions[] =
{"function", 1, 3, FEARG_1, ret_f_function, f_function},
{"garbagecollect", 0, 1, 0, ret_void, f_garbagecollect},
{"get", 2, 3, FEARG_1, ret_any, f_get},
{"getbufinfo", 0, 1, 0, ret_list_dict_any, f_getbufinfo},
{"getbufinfo", 0, 1, FEARG_1, ret_list_dict_any, f_getbufinfo},
{"getbufline", 2, 3, FEARG_1, ret_list_string, f_getbufline},
{"getbufvar", 2, 3, FEARG_1, ret_any, f_getbufvar},
{"getchangelist", 0, 1, FEARG_1, ret_list_any, f_getchangelist},

View File

@@ -3848,6 +3848,27 @@ set_callback(callback_T *dest, callback_T *src)
dest->cb_partial = src->cb_partial;
}
/*
* Copy callback from "src" to "dest", incrementing the refcounts.
*/
void
copy_callback(callback_T *dest, callback_T *src)
{
dest->cb_partial = src->cb_partial;
if (dest->cb_partial != NULL)
{
dest->cb_name = src->cb_name;
dest->cb_free_name = FALSE;
++dest->cb_partial->pt_refcount;
}
else
{
dest->cb_name = vim_strsave(src->cb_name);
dest->cb_free_name = TRUE;
func_ref(src->cb_name);
}
}
/*
* Unref/free "callback" returned by get_callback() or set_callback().
*/

File diff suppressed because it is too large Load Diff

View File

@@ -3282,10 +3282,19 @@ find_ex_command(
// after the "]" by to_name_const_end(): check if a "=" follows.
// If "[...]" has a line break "p" still points at the "[" and it can't
// be an assignment.
if (*eap->cmd == '[' && (p == eap->cmd || *skipwhite(p) != '='))
if (*eap->cmd == '[')
{
eap->cmdidx = CMD_eval;
return eap->cmd;
p = to_name_const_end(eap->cmd);
if (p == eap->cmd || *skipwhite(p) != '=')
{
eap->cmdidx = CMD_eval;
return eap->cmd;
}
if (p > eap->cmd && *skipwhite(p) == '=')
{
eap->cmdidx = CMD_let;
return eap->cmd;
}
}
// Recognize an assignment if we recognize the variable name:

1295
src/help.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -704,6 +704,7 @@ ex_marks(exarg_T *eap)
char_u *arg = eap->arg;
int i;
char_u *name;
pos_T *posp, *startp, *endp;
if (arg != NULL && *arg == NUL)
arg = NULL;
@@ -731,8 +732,17 @@ ex_marks(exarg_T *eap)
show_one_mark(']', arg, &curbuf->b_op_end, NULL, TRUE);
show_one_mark('^', arg, &curbuf->b_last_insert, NULL, TRUE);
show_one_mark('.', arg, &curbuf->b_last_change, NULL, TRUE);
show_one_mark('<', arg, &curbuf->b_visual.vi_start, NULL, TRUE);
show_one_mark('>', arg, &curbuf->b_visual.vi_end, NULL, TRUE);
// Show the marks as where they will jump to.
startp = &curbuf->b_visual.vi_start;
endp = &curbuf->b_visual.vi_end;
if ((LT_POS(*startp, *endp) || endp->lnum == 0) && startp->lnum != 0)
posp = startp;
else
posp = endp;
show_one_mark('<', arg, posp, NULL, TRUE);
show_one_mark('>', arg, posp == startp ? endp : startp, NULL, TRUE);
show_one_mark(-1, arg, NULL, NULL, FALSE);
}

View File

@@ -499,6 +499,7 @@ normal_cmd(
#ifdef FEAT_EVAL
int set_prevcount = FALSE;
#endif
int save_did_cursorhold = did_cursorhold;
CLEAR_FIELD(ca); // also resets ca.retval
ca.oap = oap;
@@ -1025,7 +1026,12 @@ getcount:
out_flush();
#endif
if (ca.cmdchar != K_IGNORE)
did_cursorhold = FALSE;
{
if (ex_normal_busy)
did_cursorhold = save_did_cursorhold;
else
did_cursorhold = FALSE;
}
State = NORMAL;

View File

@@ -2255,6 +2255,14 @@ did_set_string_option(
# endif
#endif
#ifdef FEAT_QUICKFIX
else if (varp == &p_qftf)
{
if (qf_process_qftf_option() == FALSE)
errmsg = e_invarg;
}
#endif
// Options that are a list of flags.
else
{

View File

@@ -642,6 +642,7 @@ pum_position_info_popup(win_T *wp)
int col = pum_col + pum_width + pum_scrollbar + 1;
int row = pum_row;
int botpos = POPPOS_BOTLEFT;
int used_maxwidth_opt = FALSE;
wp->w_popup_pos = POPPOS_TOPLEFT;
if (Columns - col < 20 && Columns - col < pum_col)
@@ -654,6 +655,12 @@ pum_position_info_popup(win_T *wp)
else
wp->w_maxwidth = Columns - col + 1;
wp->w_maxwidth -= popup_extra_width(wp);
if (wp->w_maxwidth_opt > 0 && wp->w_maxwidth > wp->w_maxwidth_opt)
{
// option value overrules computed value
wp->w_maxwidth = wp->w_maxwidth_opt;
used_maxwidth_opt = TRUE;
}
row -= popup_top_extra(wp);
if (wp->w_popup_flags & POPF_INFO_MENU)
@@ -673,7 +680,7 @@ pum_position_info_popup(win_T *wp)
row += pum_selected - pum_first + 1;
wp->w_popup_flags &= ~POPF_HIDDEN;
if (wp->w_maxwidth < 10)
if (wp->w_maxwidth < 10 && !used_maxwidth_opt)
// The popup is not going to fit or will overlap with the cursor
// position, hide the popup.
wp->w_popup_flags |= POPF_HIDDEN;

View File

@@ -1620,6 +1620,7 @@ parse_popup_option(win_T *wp, int is_preview)
if (is_preview)
wp->w_minwidth = x;
wp->w_maxwidth = x;
wp->w_maxwidth_opt = x;
}
}
else if (STRNCMP(s, "highlight:", 10) == 0)

View File

@@ -95,6 +95,7 @@ extern int _stricoll(char *a, char *b);
# include "gui_xim.pro"
# include "hardcopy.pro"
# include "hashtab.pro"
# include "help.pro"
# include "highlight.pro"
# include "indent.pro"
# include "insexpand.pro"

View File

@@ -88,5 +88,6 @@ void f_setbufvar(typval_T *argvars, typval_T *rettv);
callback_T get_callback(typval_T *arg);
void put_callback(callback_T *cb, typval_T *tv);
void set_callback(callback_T *dest, callback_T *src);
void copy_callback(callback_T *dest, callback_T *src);
void free_callback(callback_T *callback);
/* vim: set ft=c : */

View File

@@ -35,15 +35,6 @@ char_u *get_old_sub(void);
void set_old_sub(char_u *val);
void free_old_sub(void);
int prepare_tagpreview(int undo_sync, int use_previewpopup, use_popup_T use_popup);
void ex_help(exarg_T *eap);
void ex_helpclose(exarg_T *eap);
char_u *check_help_lang(char_u *arg);
int help_heuristic(char_u *matched_string, int offset, int wrong_case);
int find_help_tags(char_u *arg, int *num_matches, char_u ***matches, int keep_lang);
void fix_help_buffer(void);
void ex_exusage(exarg_T *eap);
void ex_viusage(exarg_T *eap);
void ex_helptags(exarg_T *eap);
void ex_smile(exarg_T *eap);
void ex_drop(exarg_T *eap);
char_u *skip_vimgrep_pat(char_u *p, char_u **s, int *flags);

14
src/proto/help.pro Normal file
View File

@@ -0,0 +1,14 @@
/* help.c */
void ex_help(exarg_T *eap);
void ex_helpclose(exarg_T *eap);
char_u *check_help_lang(char_u *arg);
int help_heuristic(char_u *matched_string, int offset, int wrong_case);
int find_help_tags(char_u *arg, int *num_matches, char_u ***matches, int keep_lang);
void cleanup_help_tags(int num_file, char_u **file);
void prepare_help_buffer(void);
void fix_help_buffer(void);
void ex_exusage(exarg_T *eap);
void ex_viusage(exarg_T *eap);
void ex_helptags(exarg_T *eap);
/* vim: set ft=c : */

View File

@@ -15,6 +15,7 @@ void ex_cclose(exarg_T *eap);
void ex_copen(exarg_T *eap);
void ex_cbottom(exarg_T *eap);
linenr_T qf_current_entry(win_T *wp);
int qf_process_qftf_option(void);
int grep_internal(cmdidx_T cmdidx);
void ex_make(exarg_T *eap);
int qf_get_size(exarg_T *eap);

View File

@@ -22,6 +22,7 @@ int get_callback_depth(void);
int call_callback(callback_T *callback, int len, typval_T *rettv, int argcount, typval_T *argvars);
void user_func_error(int error, char_u *name);
int call_func(char_u *funcname, int len, typval_T *rettv, int argcount_in, typval_T *argvars_in, funcexe_T *funcexe);
char_u *printable_func_name(ufunc_T *fp);
char_u *trans_function_name(char_u **pp, int *is_global, int skip, int flags, funcdict_T *fdp, partial_T **partial);
char_u *untrans_function_name(char_u *name);
ufunc_T *def_function(exarg_T *eap, char_u *name_arg);

View File

@@ -3,6 +3,7 @@ int check_defined(char_u *p, size_t len, cctx_T *cctx);
void clear_type_list(garray_T *gap);
type_T *typval2type(typval_T *tv);
int check_type(type_T *expected, type_T *actual, int give_msg);
int check_argtype(type_T *expected, typval_T *actual_tv);
int check_compare_types(exptype_T type, typval_T *tv1, typval_T *tv2);
char_u *skip_type(char_u *start);
type_T *parse_type(char_u **arg, garray_T *type_gap);
@@ -10,6 +11,7 @@ char *vartype_name(vartype_T type);
char *type_name(type_T *type, char **tofree);
int get_script_item_idx(int sid, char_u *name, int check_writable);
imported_T *find_imported(char_u *name, size_t len, cctx_T *cctx);
int vim9_comment_start(char_u *p);
char_u *peek_next_line_from_context(cctx_T *cctx);
char_u *next_line_from_context(cctx_T *cctx, int skip_comment);
char_u *to_name_const_end(char_u *arg);

View File

@@ -82,7 +82,7 @@ typedef struct qf_list_S
char_u *qf_title; // title derived from the command that created
// the error list or set by setqflist
typval_T *qf_ctx; // context set by setqflist/setloclist
char_u *qf_qftf; // 'quickfixtextfunc' setting for this list
callback_T qftf_cb; // 'quickfixtextfunc' callback function
struct dir_stack_T *qf_dir_stack;
char_u *qf_directory;
@@ -161,6 +161,9 @@ static int quickfix_busy = 0;
static efm_T *fmt_start = NULL; // cached across qf_parse_line() calls
// callback function for 'quickfixtextfunc'
static callback_T qftf_cb;
static void qf_new_list(qf_info_T *qi, char_u *qf_title);
static int qf_add_entry(qf_list_T *qfl, char_u *dir, char_u *fname, char_u *module, int bufnum, char_u *mesg, long lnum, int col, int vis_col, char_u *pattern, int nr, int type, int valid);
static void qf_free(qf_list_T *qfl);
@@ -2279,10 +2282,10 @@ copy_loclist(qf_list_T *from_qfl, qf_list_T *to_qfl)
}
else
to_qfl->qf_ctx = NULL;
if (from_qfl->qf_qftf != NULL)
to_qfl->qf_qftf = vim_strsave(from_qfl->qf_qftf);
if (from_qfl->qftf_cb.cb_name != NULL)
copy_callback(&to_qfl->qftf_cb, &from_qfl->qftf_cb);
else
to_qfl->qf_qftf = NULL;
to_qfl->qftf_cb.cb_name = NULL;
if (from_qfl->qf_count)
if (copy_loclist_entries(from_qfl, to_qfl) == FAIL)
@@ -3818,7 +3821,7 @@ qf_free(qf_list_T *qfl)
VIM_CLEAR(qfl->qf_title);
free_tv(qfl->qf_ctx);
qfl->qf_ctx = NULL;
VIM_CLEAR(qfl->qf_qftf);
free_callback(&qfl->qftf_cb);
qfl->qf_id = 0;
qfl->qf_changedtick = 0L;
}
@@ -4348,6 +4351,49 @@ qf_find_buf(qf_info_T *qi)
return NULL;
}
/*
* Process the 'quickfixtextfunc' option value.
*/
int
qf_process_qftf_option(void)
{
typval_T *tv;
callback_T cb;
if (p_qftf == NULL || *p_qftf == NUL)
{
free_callback(&qftf_cb);
return TRUE;
}
if (*p_qftf == '{')
{
// Lambda expression
tv = eval_expr(p_qftf, NULL);
if (tv == NULL)
return FALSE;
}
else
{
// treat everything else as a function name string
tv = alloc_string_tv(vim_strsave(p_qftf));
if (tv == NULL)
return FALSE;
}
cb = get_callback(tv);
if (cb.cb_name == NULL)
{
free_tv(tv);
return FALSE;
}
free_callback(&qftf_cb);
set_callback(&qftf_cb, &cb);
free_tv(tv);
return TRUE;
}
/*
* Update the w:quickfix_title variable in the quickfix/location list window
*/
@@ -4424,7 +4470,9 @@ qf_buf_add_line(
int len;
buf_T *errbuf;
if (qftf_str != NULL)
// If the 'quickfixtextfunc' function returned an non-empty custom string
// for this entry, then use it.
if (qftf_str != NULL && *qftf_str != NUL)
vim_strncpy(IObuff, qftf_str, IOSIZE - 1);
else
{
@@ -4501,21 +4549,26 @@ qf_buf_add_line(
return OK;
}
/*
* Call the 'quickfixtextfunc' function to get the list of lines to display in
* the quickfix window for the entries 'start_idx' to 'end_idx'.
*/
static list_T *
call_qftf_func(qf_list_T *qfl, int qf_winid, long start_idx, long end_idx)
{
char_u *qftf = p_qftf;
callback_T *cb = &qftf_cb;
list_T *qftf_list = NULL;
// If 'quickfixtextfunc' is set, then use the user-supplied function to get
// the text to display. Use the local value of 'quickfixtextfunc' if it is
// set.
if (qfl->qf_qftf != NULL)
qftf = qfl->qf_qftf;
if (qftf != NULL && *qftf != NUL)
if (qfl->qftf_cb.cb_name != NULL)
cb = &qfl->qftf_cb;
if (cb != NULL && cb->cb_name != NULL)
{
typval_T args[1];
dict_T *d;
typval_T rettv;
// create the dict argument
if ((d = dict_alloc_lock(VAR_FIXED)) == NULL)
@@ -4529,8 +4582,17 @@ call_qftf_func(qf_list_T *qfl, int qf_winid, long start_idx, long end_idx)
args[0].v_type = VAR_DICT;
args[0].vval.v_dict = d;
qftf_list = call_func_retlist(qftf, 1, args);
--d->dv_refcount;
qftf_list = NULL;
if (call_callback(cb, 0, &rettv, 1, args) != FAIL)
{
if (rettv.v_type == VAR_LIST)
{
qftf_list = rettv.vval.v_list;
qftf_list->lv_refcount++;
}
clear_tv(&rettv);
}
dict_unref(d);
}
return qftf_list;
@@ -4569,6 +4631,7 @@ qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last, int qf_winid)
if (qfl != NULL)
{
char_u dirname[MAXPATHL];
int invalid_val = FALSE;
*dirname = NUL;
@@ -4593,9 +4656,15 @@ qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last, int qf_winid)
{
char_u *qftf_str = NULL;
if (qftf_li != NULL)
// Use the text supplied by the user defined function
// Use the text supplied by the user defined function (if any).
// If the returned value is not string, then ignore the rest
// of the returned values and use the default.
if (qftf_li != NULL && !invalid_val)
{
qftf_str = tv_get_string_chk(&qftf_li->li_tv);
if (qftf_str == NULL)
invalid_val = TRUE;
}
if (qf_buf_add_line(buf, lnum, qfp, dirname, qftf_str) == FAIL)
break;
@@ -6515,7 +6584,8 @@ enum {
QF_GETLIST_TICK = 0x100,
QF_GETLIST_FILEWINID = 0x200,
QF_GETLIST_QFBUFNR = 0x400,
QF_GETLIST_ALL = 0x7FF,
QF_GETLIST_QFTF = 0x800,
QF_GETLIST_ALL = 0xFFF,
};
/*
@@ -6644,6 +6714,9 @@ qf_getprop_keys2flags(dict_T *what, int loclist)
if (dict_find(what, (char_u *)"qfbufnr", -1) != NULL)
flags |= QF_GETLIST_QFBUFNR;
if (dict_find(what, (char_u *)"quickfixtextfunc", -1) != NULL)
flags |= QF_GETLIST_QFTF;
return flags;
}
@@ -6738,6 +6811,8 @@ qf_getprop_defaults(qf_info_T *qi, int flags, int locstack, dict_T *retdict)
status = dict_add_number(retdict, "filewinid", 0);
if ((status == OK) && (flags & QF_GETLIST_QFBUFNR))
status = qf_getprop_qfbufnr(qi, retdict);
if ((status == OK) && (flags & QF_GETLIST_QFTF))
status = dict_add_string(retdict, "quickfixtextfunc", (char_u *)"");
return status;
}
@@ -6836,6 +6911,28 @@ qf_getprop_idx(qf_list_T *qfl, int eidx, dict_T *retdict)
return dict_add_number(retdict, "idx", eidx);
}
/*
* Return the 'quickfixtextfunc' function of a quickfix/location list
*/
static int
qf_getprop_qftf(qf_list_T *qfl, dict_T *retdict)
{
int status;
if (qfl->qftf_cb.cb_name != NULL)
{
typval_T tv;
put_callback(&qfl->qftf_cb, &tv);
status = dict_add_tv(retdict, "quickfixtextfunc", &tv);
clear_tv(&tv);
}
else
status = dict_add_string(retdict, "quickfixtextfunc", (char_u *)"");
return status;
}
/*
* Return quickfix/location list details (title) as a
* dictionary. 'what' contains the details to return. If 'list_idx' is -1,
@@ -6899,6 +6996,8 @@ qf_get_properties(win_T *wp, dict_T *what, dict_T *retdict)
status = qf_getprop_filewinid(wp, qi, retdict);
if ((status == OK) && (flags & QF_GETLIST_QFBUFNR))
status = qf_getprop_qfbufnr(qi, retdict);
if ((status == OK) && (flags & QF_GETLIST_QFTF))
status = qf_getprop_qftf(qfl, retdict);
return status;
}
@@ -7260,10 +7359,12 @@ qf_setprop_curidx(qf_info_T *qi, qf_list_T *qfl, dictitem_T *di)
static int
qf_setprop_qftf(qf_info_T *qi UNUSED, qf_list_T *qfl, dictitem_T *di)
{
VIM_CLEAR(qfl->qf_qftf);
if (di->di_tv.v_type == VAR_STRING
&& di->di_tv.vval.v_string != NULL)
qfl->qf_qftf = vim_strsave(di->di_tv.vval.v_string);
callback_T cb;
free_callback(&qfl->qftf_cb);
cb = get_callback(&di->di_tv);
if (cb.cb_name != NULL && *cb.cb_name != NUL)
set_callback(&qfl->qftf_cb, &cb);
return OK;
}

View File

@@ -1763,10 +1763,16 @@ getsourceline(int c UNUSED, void *cookie, int indent UNUSED, int do_concat)
// backslash. We always need to read the next line, keep it in
// sp->nextline.
/* Also check for a comment in between continuation lines: "\ */
// Also check for a Vim9 comment and empty line.
sp->nextline = get_one_sourceline(sp);
if (sp->nextline != NULL
&& (*(p = skipwhite(sp->nextline)) == '\\'
|| (p[0] == '"' && p[1] == '\\' && p[2] == ' ')))
|| (p[0] == '"' && p[1] == '\\' && p[2] == ' ')
#ifdef FEAT_EVAL
|| (in_vim9script()
&& (*p == NUL || vim9_comment_start(p)))
#endif
))
{
garray_T ga;
@@ -1794,8 +1800,14 @@ getsourceline(int c UNUSED, void *cookie, int indent UNUSED, int do_concat)
}
ga_concat(&ga, p + 1);
}
else if (p[0] != '"' || p[1] != '\\' || p[2] != ' ')
else if (!(p[0] == '"' && p[1] == '\\' && p[2] == ' ')
#ifdef FEAT_EVAL
&& !(in_vim9script()
&& (*p == NUL || vim9_comment_start(p)))
#endif
)
break;
/* drop a # comment or "\ comment line */
}
ga_append(&ga, NUL);
vim_free(line);

View File

@@ -3302,6 +3302,7 @@ struct window_S
int w_minwidth; // "minwidth" for popup window
int w_maxheight; // "maxheight" for popup window
int w_maxwidth; // "maxwidth" for popup window
int w_maxwidth_opt; // maxwidth from option
int w_wantline; // "line" for popup window
int w_wantcol; // "col" for popup window
int w_firstline; // "firstline" for popup window

View File

@@ -0,0 +1,14 @@
|a+0&#ffffff0|w|o|r|d| @69
|t|e|s|a|w|o|r|d> @66
|~+0#4040ff13&| | +0#0000001#e0e0e08|w|r|d| @4|W| |e|x|t|r|a| |t|e|x|t| @1| +0#0000000#0000001| +0#0000001#e0e0e08|w|o|r|d|s| |a|r|e| @1| +0#4040ff13#ffffff0@36
|~| | +0#0000001#ffd7ff255|a|n|o|t|w|r|d| |W| |e|x|t|r|a| |t|e|x|t| @1| +0#0000000#0000001| +0#0000001#e0e0e08|c|o@1|l| @6| +0#4040ff13#ffffff0@36
|~| | +0#0000001#ffd7ff255|n|o|a|w|r|d| @1|W| |e|x|t|r|a| |t|e|x|t| @1| +0#0000000#a8a8a8255| +0#4040ff13#ffffff0@48
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|-+2#0000000&@1| |U|s|e|r| |d|e|f|i|n|e|d| |c|o|m|p|l|e|t|i|o|n| |(|^|U|^|N|^|P|)| |m+0#00e0003&|a|t|c|h| |1| |o|f| |4| +0#0000000&@26

View File

@@ -105,6 +105,13 @@ set nomore
" Output all messages in English.
lang mess C
" suppress menu translation
if has('gui_running') && exists('did_install_default_menus')
source $VIMRUNTIME/delmenu.vim
set langmenu=none
source $VIMRUNTIME/menu.vim
endif
" Always use forward slashes.
set shellslash

View File

@@ -19,6 +19,35 @@ func Test_vim_did_enter()
" becomes one.
endfunc
" Test for the CursorHold autocmd
func Test_CursorHold_autocmd()
CheckRunVimInTerminal
call writefile(['one', 'two', 'three'], 'Xfile')
let before =<< trim END
set updatetime=10
au CursorHold * call writefile([line('.')], 'Xoutput', 'a')
END
call writefile(before, 'Xinit')
let buf = RunVimInTerminal('-S Xinit Xfile', {})
call term_wait(buf)
call term_sendkeys(buf, "gg")
call term_wait(buf)
sleep 50m
call term_sendkeys(buf, "j")
call term_wait(buf)
sleep 50m
call term_sendkeys(buf, "j")
call term_wait(buf)
sleep 50m
call StopVimInTerminal(buf)
call assert_equal(['1', '2', '3'], readfile('Xoutput')[-3:-1])
call delete('Xinit')
call delete('Xoutput')
call delete('Xfile')
endfunc
if has('timers')
func ExitInsertMode(id)

View File

@@ -67,15 +67,6 @@ func Test_bunload_with_offset()
call assert_fails('1,4bunload', 'E16:')
call assert_fails(',100bunload', 'E16:')
" Use a try-catch for this test. When assert_fails() is used for this
" test, the command fails with E515: instead of E90:
let caught_E90 = 0
try
$bunload
catch /E90:/
let caught_E90 = 1
endtry
call assert_equal(1, caught_E90)
call assert_fails('$bunload', 'E90:')
endfunc

View File

@@ -23,6 +23,9 @@ func Test_getbufwintabinfo()
call assert_equal('vim', l[0].variables.editor)
call assert_notequal(-1, index(l[0].windows, '%'->bufwinid()))
let l = '%'->getbufinfo()
call assert_equal(bufnr('%'), l[0].bufnr)
" Test for getbufinfo() with 'bufmodified'
call assert_equal(0, len(getbufinfo({'bufmodified' : 1})))
call setbufline('Xtestfile1', 1, ["Line1"])

View File

@@ -105,33 +105,43 @@ func Test_marks_cmd()
new Xtwo
call setline(1, ['ccc', 'ddd'])
norm! $mcGmD
exe "norm! GVgg\<Esc>G"
w!
b Xone
let a = split(execute('marks'), "\n")
call assert_equal(9, len(a))
call assert_equal('mark line col file/text', a[0])
call assert_equal(" ' 2 0 bbb", a[1])
call assert_equal(' a 1 0 aaa', a[2])
call assert_equal(' B 2 2 bbb', a[3])
call assert_equal(' D 2 0 Xtwo', a[4])
call assert_equal(' " 1 0 aaa', a[5])
call assert_equal(' [ 1 0 aaa', a[6])
call assert_equal(' ] 2 0 bbb', a[7])
call assert_equal(' . 2 0 bbb', a[8])
call assert_equal(['mark line col file/text',
\ " ' 2 0 bbb",
\ ' a 1 0 aaa',
\ ' B 2 2 bbb',
\ ' D 2 0 Xtwo',
\ ' " 1 0 aaa',
\ ' [ 1 0 aaa',
\ ' ] 2 0 bbb',
\ ' . 2 0 bbb'], a)
b Xtwo
let a = split(execute('marks'), "\n")
call assert_equal(9, len(a))
call assert_equal('mark line col file/text', a[0])
call assert_equal(" ' 1 0 ccc", a[1])
call assert_equal(' c 1 2 ccc', a[2])
call assert_equal(' B 2 2 Xone', a[3])
call assert_equal(' D 2 0 ddd', a[4])
call assert_equal(' " 2 0 ddd', a[5])
call assert_equal(' [ 1 0 ccc', a[6])
call assert_equal(' ] 2 0 ddd', a[7])
call assert_equal(' . 2 0 ddd', a[8])
call assert_equal(11, len(a))
call assert_equal(['mark line col file/text',
\ " ' 1 0 ccc",
\ ' c 1 2 ccc',
\ ' B 2 2 Xone',
\ ' D 2 0 ddd',
\ ' " 2 0 ddd',
\ ' [ 1 0 ccc',
\ ' ] 2 0 ddd',
\ ' . 2 0 ddd',
\ ' < 1 0 ccc',
\ ' > 2 0 ddd'], a)
norm! Gdd
w!
let a = split(execute('marks <>'), "\n")
call assert_equal(3, len(a))
call assert_equal(['mark line col file/text',
\ ' < 1 0 ccc',
\ ' > 2 0 -invalid-'], a)
b Xone
delmarks aB

View File

@@ -31,6 +31,15 @@ func WaitForError(errcode)
call assert_match(a:errcode, save_exception)
endfunc
" Read the "Xnetbeans" file and filter out geometry messages.
func ReadXnetbeans()
let l = readfile("Xnetbeans")
" Xnetbeans may include '0:geometry=' messages on GUI environment if window
" position, size, or z order are changed. Remove these messages because
" will causes troubles on check.
return filter(l, 'v:val !~ "^0:geometry="')
endfunc
func Nb_basic(port)
call delete("Xnetbeans")
call writefile([], "Xnetbeans")
@@ -42,8 +51,8 @@ func Nb_basic(port)
" Establish the connection with the netbeans server
exe 'nbstart :localhost:' .. a:port .. ':bunny'
call assert_true(has("netbeans_enabled"))
call WaitFor('len(readfile("Xnetbeans")) > (g:last + 2)')
let l = readfile("Xnetbeans")
call WaitFor('len(ReadXnetbeans()) > (g:last + 2)')
let l = ReadXnetbeans()
call assert_equal(['AUTH bunny',
\ '0:version=0 "2.5"',
\ '0:startupDone=0'], l[-3:])
@@ -55,8 +64,8 @@ func Nb_basic(port)
" Open the command buffer to communicate with the server
split Xcmdbuf
let cmdbufnr = bufnr()
call WaitFor('len(readfile("Xnetbeans")) > (g:last + 2)')
let l = readfile("Xnetbeans")
call WaitFor('len(ReadXnetbeans()) > (g:last + 2)')
let l = ReadXnetbeans()
call assert_equal('0:fileOpened=0 "Xcmdbuf" T F',
\ substitute(l[-3], '".*/', '"', ''))
call assert_equal('send: 1:putBufferNumber!15 "Xcmdbuf"',
@@ -75,120 +84,120 @@ func Nb_basic(port)
call cursor(3, 4)
sleep 10m
call appendbufline(cmdbufnr, '$', 'getCursor_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 5)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 5)')
let l = ReadXnetbeans()
call assert_equal(['send: 0:getCursor/30', '30 -1 3 3 19'], l[-2:])
let g:last += 5
" Test for E627
call appendbufline(cmdbufnr, '$', 'E627_Test')
call WaitForError('E627:')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 0 setReadOnly!31', l[-1])
let g:last += 3
" Test for E628
call appendbufline(cmdbufnr, '$', 'E628_Test')
call WaitForError('E628:')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 0:setReadOnly 32', l[-1])
let g:last += 3
" Test for E632
call appendbufline(cmdbufnr, '$', 'E632_Test')
call WaitForError('E632:')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 4)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 4)')
let l = ReadXnetbeans()
call assert_equal(['send: 0:getLength/33', '33 0'], l[-2:])
let g:last += 4
" Test for E633
call appendbufline(cmdbufnr, '$', 'E633_Test')
call WaitForError('E633:')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 4)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 4)')
let l = ReadXnetbeans()
call assert_equal(['send: 0:getText/34', '34 '], l[-2:])
let g:last += 4
" Test for E634
call appendbufline(cmdbufnr, '$', 'E634_Test')
call WaitForError('E634:')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 4)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 4)')
let l = ReadXnetbeans()
call assert_equal(['send: 0:remove/35 1 1', '35'], l[-2:])
let g:last += 4
" Test for E635
call appendbufline(cmdbufnr, '$', 'E635_Test')
call WaitForError('E635:')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 4)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 4)')
let l = ReadXnetbeans()
call assert_equal(['send: 0:insert/36 0 "line1\n"', '36'], l[-2:])
let g:last += 4
" Test for E636
call appendbufline(cmdbufnr, '$', 'E636_Test')
call WaitForError('E636:')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 0:create!37', l[-1])
let g:last += 3
" Test for E637
call appendbufline(cmdbufnr, '$', 'E637_Test')
call WaitForError('E637:')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 0:startDocumentListen!38', l[-1])
let g:last += 3
" Test for E638
call appendbufline(cmdbufnr, '$', 'E638_Test')
call WaitForError('E638:')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 0:stopDocumentListen!39', l[-1])
let g:last += 3
" Test for E639
call appendbufline(cmdbufnr, '$', 'E639_Test')
call WaitForError('E639:')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 0:setTitle!40 "Title"', l[-1])
let g:last += 3
" Test for E640
call appendbufline(cmdbufnr, '$', 'E640_Test')
call WaitForError('E640:')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 0:initDone!41', l[-1])
let g:last += 3
" Test for E641
call appendbufline(cmdbufnr, '$', 'E641_Test')
call WaitForError('E641:')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 0:putBufferNumber!42 "XSomeBuf"', l[-1])
let g:last += 3
" Test for E642
call appendbufline(cmdbufnr, '$', 'E642_Test')
call WaitForError('E642:')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 9:putBufferNumber!43 "XInvalidBuf"', l[-1])
let g:last += 3
" Test for E643
call appendbufline(cmdbufnr, '$', 'E643_Test')
call WaitForError('E643:')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 0:setFullName!44 "XSomeBuf"', l[-1])
let g:last += 3
@@ -197,8 +206,8 @@ func Nb_basic(port)
" Test for E644
call appendbufline(cmdbufnr, '$', 'E644_Test')
call WaitForError('E644:')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 0:editFile!45 "Xfile3"', l[-1])
let g:last += 3
@@ -207,8 +216,8 @@ func Nb_basic(port)
set verbose=1
call WaitForError('E645:')
set verbose&
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 0:setVisible!46 T', l[-1])
let g:last += 3
@@ -217,56 +226,56 @@ func Nb_basic(port)
set verbose=1
call WaitForError('E646:')
set verbose&
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 0:setModified!47 T', l[-1])
let g:last += 3
" Test for E647
call appendbufline(cmdbufnr, '$', 'E647_Test')
call WaitForError('E647:')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 0:setDot!48 1/1', l[-1])
let g:last += 3
" Test for E648
call appendbufline(cmdbufnr, '$', 'E648_Test')
call WaitForError('E648:')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 0:close!49', l[-1])
let g:last += 3
" Test for E650
call appendbufline(cmdbufnr, '$', 'E650_Test')
call WaitForError('E650:')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 0:defineAnnoType!50 1 "abc" "a" "a" 1 1', l[-1])
let g:last += 3
" Test for E651
call appendbufline(cmdbufnr, '$', 'E651_Test')
call WaitForError('E651:')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 0:addAnno!51 1 1 1 1', l[-1])
let g:last += 3
" Test for E652
call appendbufline(cmdbufnr, '$', 'E652_Test')
call WaitForError('E652:')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 4)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 4)')
let l = ReadXnetbeans()
call assert_equal(['send: 0:getAnno/52 8', '52 0'], l[-2:])
let g:last += 4
" editFile test
call writefile(['foo bar1', 'foo bar2', 'foo bar3'], 'Xfile3')
call appendbufline(cmdbufnr, '$', 'editFile_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 4)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 4)')
let l = ReadXnetbeans()
call assert_equal('send: 2:editFile!53 "Xfile3"', l[-2])
call assert_match('0:fileOpened=0 ".*/Xfile3" T F', l[-1])
call assert_equal('Xfile3', bufname())
@@ -274,37 +283,37 @@ func Nb_basic(port)
" getLength test
call appendbufline(cmdbufnr, '$', 'getLength_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 4)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 4)')
let l = ReadXnetbeans()
call assert_equal(['send: 2:getLength/54', '54 27'], l[-2:])
let g:last += 4
" getModified test
call appendbufline(cmdbufnr, '$', 'getModified_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 4)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 4)')
let l = ReadXnetbeans()
call assert_equal(['send: 2:getModified/55', '55 0'], l[-2:])
let g:last += 4
" getText test
call appendbufline(cmdbufnr, '$', 'getText_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 4)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 4)')
let l = ReadXnetbeans()
call assert_equal(['send: 2:getText/56',
\ '56 "foo bar1\nfoo bar2\nfoo bar3\n"'], l[-2:])
let g:last += 4
" setDot test
call appendbufline(cmdbufnr, '$', 'setDot_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 2:setDot!57 3/6', l[-1])
let g:last += 3
" startDocumentListen test
call appendbufline(cmdbufnr, '$', 'startDocumentListen_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 2:startDocumentListen!58', l[-1])
let g:last += 3
@@ -312,8 +321,8 @@ func Nb_basic(port)
" received the notifications
call append(2, 'blue sky')
1d
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_match('2:insert=\d\+ 18 "blue sky"', l[-3])
call assert_match('2:insert=\d\+ 26 "\\n"', l[-2])
call assert_match('2:remove=\d\+ 0 9', l[-1])
@@ -321,8 +330,8 @@ func Nb_basic(port)
" stopDocumentListen test
call appendbufline(cmdbufnr, '$', 'stopDocumentListen_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 2:stopDocumentListen!59', l[-1])
let g:last += 3
@@ -335,8 +344,8 @@ func Nb_basic(port)
" defineAnnoType test
call appendbufline(cmdbufnr, '$', 'define_anno_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 2:defineAnnoType!60 1 "s1" "x" "=>" blue none', l[-1])
sleep 1m
call assert_equal({'name': '1', 'texthl': 'NB_s1', 'text': '=>'},
@@ -346,15 +355,15 @@ func Nb_basic(port)
" defineAnnoType with a long color name
call appendbufline(cmdbufnr, '$', 'E532_Test')
call WaitForError('E532:')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 2:defineAnnoType!61 1 "s1" "x" "=>" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa none', l[-1])
let g:last += 3
" addAnno test
call appendbufline(cmdbufnr, '$', 'add_anno_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 2:addAnno!62 1 1 2/1 0', l[-1])
sleep 1m
call assert_equal([{'lnum': 2, 'id': 1, 'name': '1', 'priority': 10,
@@ -363,15 +372,15 @@ func Nb_basic(port)
" getAnno test
call appendbufline(cmdbufnr, '$', 'get_anno_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 4)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 4)')
let l = ReadXnetbeans()
call assert_equal(['send: 2:getAnno/63 1', '63 2'], l[-2:])
let g:last += 4
" removeAnno test
call appendbufline(cmdbufnr, '$', 'remove_anno_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 2:removeAnno!64 1', l[-1])
sleep 1m
call assert_equal([], sign_getplaced())
@@ -379,8 +388,8 @@ func Nb_basic(port)
" getModified test to get the number of modified buffers
call appendbufline(cmdbufnr, '$', 'getModifiedAll_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 4)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 4)')
let l = ReadXnetbeans()
call assert_equal(['send: 0:getModified/65', '65 2'], l[-2:])
let g:last += 4
@@ -388,8 +397,8 @@ func Nb_basic(port)
" create test to create a new buffer
call appendbufline(cmdbufnr, '$', 'create_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 3:create!66', l[-1])
" Wait for vim to process the previous netbeans message
sleep 10m
@@ -398,15 +407,15 @@ func Nb_basic(port)
" setTitle test
call appendbufline(cmdbufnr, '$', 'setTitle_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 3:setTitle!67 "Xfile4"', l[-1])
let g:last += 3
" setFullName test
call appendbufline(cmdbufnr, '$', 'setFullName_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 5)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 5)')
let l = ReadXnetbeans()
call assert_equal('send: 3:setFullName!68 "Xfile4"', l[-3])
call assert_match('0:fileOpened=0 ".*/Xfile4" T F', l[-1])
call assert_equal('Xfile4', bufname())
@@ -414,65 +423,65 @@ func Nb_basic(port)
" initDone test
call appendbufline(cmdbufnr, '$', 'initDone_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 3:initDone!69', l[-1])
let g:last += 3
" setVisible test
hide enew
call appendbufline(cmdbufnr, '$', 'setVisible_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 3:setVisible!70 T', l[-1])
let g:last += 3
" setModtime test
call appendbufline(cmdbufnr, '$', 'setModtime_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 3:setModtime!71 6', l[-1])
let g:last += 3
" insert test
call appendbufline(cmdbufnr, '$', 'insert_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 4)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 4)')
let l = ReadXnetbeans()
call assert_equal(['send: 3:insert/72 0 "line1\nline2\n"', '72'], l[-2:])
call assert_equal(['line1', 'line2'], getline(1, '$'))
let g:last += 4
" remove test
call appendbufline(cmdbufnr, '$', 'remove_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 4)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 4)')
let l = ReadXnetbeans()
call assert_equal(['send: 3:remove/73 3 4', '73'], l[-2:])
call assert_equal(['linine2'], getline(1, '$'))
let g:last += 4
" remove with invalid offset
call appendbufline(cmdbufnr, '$', 'remove_invalid_offset_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 4)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 4)')
let l = ReadXnetbeans()
call assert_equal(['send: 3:remove/74 900 4', '74 !bad position'], l[-2:])
let g:last += 4
" remove with invalid count
call appendbufline(cmdbufnr, '$', 'remove_invalid_count_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 4)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 4)')
let l = ReadXnetbeans()
call assert_equal(['send: 3:remove/75 1 800', '75 !bad count'], l[-2:])
let g:last += 4
" guard test
%d
call setline(1, ['foo bar', 'foo bar', 'foo bar'])
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 8)')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 8)')
let g:last += 8
call appendbufline(cmdbufnr, '$', 'guard_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 3:guard!76 8 7', l[-1])
sleep 1m
" second line is guarded. Try modifying the line
@@ -488,8 +497,8 @@ func Nb_basic(port)
" setModified test
call appendbufline(cmdbufnr, '$', 'setModified_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 3:setModified!77 T', l[-1])
call assert_equal(1, &modified)
let g:last += 3
@@ -497,8 +506,8 @@ func Nb_basic(port)
" insertDone test
let v:statusmsg = ''
call appendbufline(cmdbufnr, '$', 'insertDone_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 3:insertDone!78 T F', l[-1])
sleep 1m
call assert_match('.*/Xfile4" 3L, 0B', v:statusmsg)
@@ -507,8 +516,8 @@ func Nb_basic(port)
" saveDone test
let v:statusmsg = ''
call appendbufline(cmdbufnr, '$', 'saveDone_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 3:saveDone!79', l[-1])
sleep 1m
call assert_match('.*/Xfile4" 3L, 0B', v:statusmsg)
@@ -516,51 +525,51 @@ func Nb_basic(port)
" unimplemented command test
call appendbufline(cmdbufnr, '$', 'invalidcmd_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 3:invalidcmd!80', l[-1])
let g:last += 3
" unimplemented function test
call appendbufline(cmdbufnr, '$', 'invalidfunc_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 4)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 4)')
let l = ReadXnetbeans()
call assert_equal(['send: 3:invalidfunc/81', '81'], l[-2:])
let g:last += 4
" Test for removeAnno cmd failure
call appendbufline(cmdbufnr, '$', 'removeAnno_fail_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 4)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 4)')
let l = ReadXnetbeans()
call assert_equal(['send: 0:removeAnno/82 1', '82'], l[-2:])
let g:last += 4
" Test for guard cmd failure
call appendbufline(cmdbufnr, '$', 'guard_fail_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 4)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 4)')
let l = ReadXnetbeans()
call assert_equal(['send: 0:guard/83 1 1', '83'], l[-2:])
let g:last += 4
" Test for save cmd failure
call appendbufline(cmdbufnr, '$', 'save_fail_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 4)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 4)')
let l = ReadXnetbeans()
call assert_equal(['send: 0:save/84', '84'], l[-2:])
let g:last += 4
" Test for netbeansBuffer cmd failure
call appendbufline(cmdbufnr, '$', 'netbeansBuffer_fail_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 4)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 4)')
let l = ReadXnetbeans()
call assert_equal(['send: 0:netbeansBuffer/85 T', '85'], l[-2:])
let g:last += 4
" nbkey test
call cursor(3, 3)
nbkey "\<C-F2>"
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal(['3:newDotAndMark=85 18 18',
\ '3:keyCommand=85 ""\<C-F2>""',
\ '3:keyAtPos=85 ""\<C-F2>"" 18 3/2'], l[-3:])
@@ -568,22 +577,22 @@ func Nb_basic(port)
" setExitDelay test
call appendbufline(cmdbufnr, '$', 'setExitDelay_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 0:setExitDelay!86 2', l[-1])
let g:last += 3
" setReadonly test
call appendbufline(cmdbufnr, '$', 'setReadOnly_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 3:setReadOnly!87', l[-1])
let g:last += 3
" close test. Don't use buffer 10 after this
call appendbufline(cmdbufnr, '$', 'close_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 4)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 4)')
let l = ReadXnetbeans()
call assert_equal('send: 3:close!88', l[-2])
call assert_equal('3:killed=88', l[-1])
call assert_equal(1, winnr('$'))
@@ -591,8 +600,8 @@ func Nb_basic(port)
" specialKeys test
call appendbufline(cmdbufnr, '$', 'specialKeys_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 3)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 3)')
let l = ReadXnetbeans()
call assert_equal('send: 0:specialKeys!89 "F12 F13"', l[-1])
sleep 1m
call assert_equal(':nbkey F12<CR>', maparg('<F12>', 'n'))
@@ -602,25 +611,25 @@ func Nb_basic(port)
" Open a buffer not monitored by netbeans
enew | only!
nbkey "\<C-F3>"
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 1)')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 1)')
let l = ReadXnetbeans()
call assert_equal('0:fileOpened=0 "" T F', l[-1])
let g:last += 1
" Test for writing a netbeans buffer
call appendbufline(cmdbufnr, '$', 'nbbufwrite_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 5)')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 5)')
call assert_fails('write', 'E656:')
call setline(1, ['one', 'two'])
call assert_fails('1write!', 'E657:')
write
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 10)')
call WaitFor('len(ReadXnetbeans()) >= (g:last + 10)')
let g:last += 10
" detach
call appendbufline(cmdbufnr, '$', 'detach_Test')
call WaitFor('len(readfile("Xnetbeans")) >= (g:last + 8)')
call WaitForAssert({-> assert_equal('0:disconnect=93', readfile("Xnetbeans")[-1])})
call WaitFor('len(ReadXnetbeans()) >= (g:last + 8)')
call WaitForAssert({-> assert_equal('0:disconnect=93', ReadXnetbeans()[-1])})
" the connection was closed
call assert_false(has("netbeans_enabled"))
@@ -649,9 +658,9 @@ func Nb_file_auth(port)
exe 'nbstart =Xnbauth'
call assert_true(has("netbeans_enabled"))
call WaitFor('len(readfile("Xnetbeans")) > 2')
call WaitFor('len(ReadXnetbeans()) > 2')
nbclose
let lines = readfile("Xnetbeans")
let lines = ReadXnetbeans()
call assert_equal('AUTH bunny', lines[0])
call assert_equal('0:version=0 "2.5"', lines[1])
call assert_equal('0:startupDone=0', lines[2])
@@ -672,19 +681,24 @@ func Nb_quit_with_conn(port)
let after =<< trim END
source shared.vim
func ReadXnetbeans()
let l = readfile("Xnetbeans")
return filter(l, 'v:val !~ "^0:geometry="')
endfunc
" Establish the connection with the netbeans server
exe 'nbstart :localhost:' .. g:port .. ':star'
call assert_true(has("netbeans_enabled"))
call WaitFor('len(readfile("Xnetbeans")) >= 3')
let l = readfile("Xnetbeans")
call WaitFor('len(ReadXnetbeans()) >= 3')
let l = ReadXnetbeans()
call assert_equal(['AUTH star',
\ '0:version=0 "2.5"',
\ '0:startupDone=0'], l[-3:])
" Open the command buffer to communicate with the server
split Xcmdbuf
call WaitFor('len(readfile("Xnetbeans")) >= 6')
let l = readfile("Xnetbeans")
call WaitFor('len(ReadXnetbeans()) >= 6')
let l = ReadXnetbeans()
call assert_equal('0:fileOpened=0 "Xcmdbuf" T F',
\ substitute(l[-3], '".*/', '"', ''))
call assert_equal('send: 1:putBufferNumber!15 "Xcmdbuf"',
@@ -696,8 +710,8 @@ func Nb_quit_with_conn(port)
quit!
END
if RunVim(['let g:port = ' .. a:port], after, '')
call WaitFor('len(readfile("Xnetbeans")) >= 9')
let l = readfile('Xnetbeans')
call WaitFor('len(ReadXnetbeans()) >= 9')
let l = ReadXnetbeans()
call assert_equal('1:unmodified=16', l[-3])
call assert_equal('1:killed=16', l[-2])
call assert_equal('0:disconnect=16', l[-1])

View File

@@ -2506,24 +2506,6 @@ func Test_normal47_visual_buf_wipe()
set nomodified
endfunc
func Test_normal47_autocmd()
" disabled, does not seem to be possible currently
throw "Skipped: not possible to test cursorhold autocmd while waiting for input in normal_cmd"
new
call append(0, repeat('-',20))
au CursorHold * call feedkeys('2l', '')
1
set updatetime=20
" should delete 12 chars (d12l)
call feedkeys('d1', '!')
call assert_equal('--------', getline(1))
" clean up
au! CursorHold
set updatetime=4000
bw!
endfunc
func Test_normal48_wincmd()
new
exe "norm! \<c-w>c"

View File

@@ -3490,13 +3490,13 @@ func Xgetlist_empty_tests(cchar)
if a:cchar == 'c'
call assert_equal({'context' : '', 'id' : 0, 'idx' : 0,
\ 'items' : [], 'nr' : 0, 'size' : 0, 'qfbufnr' : 0,
\ 'title' : '', 'winid' : 0, 'changedtick': 0},
\ g:Xgetlist({'all' : 0}))
\ 'title' : '', 'winid' : 0, 'changedtick': 0,
\ 'quickfixtextfunc' : ''}, g:Xgetlist({'all' : 0}))
else
call assert_equal({'context' : '', 'id' : 0, 'idx' : 0,
\ 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '',
\ 'winid' : 0, 'changedtick': 0, 'filewinid' : 0,
\ 'qfbufnr' : 0},
\ 'qfbufnr' : 0, 'quickfixtextfunc' : ''},
\ g:Xgetlist({'all' : 0}))
endif
@@ -3535,12 +3535,13 @@ func Xgetlist_empty_tests(cchar)
if a:cchar == 'c'
call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
\ 'qfbufnr' : qfbufnr,
\ 'qfbufnr' : qfbufnr, 'quickfixtextfunc' : '',
\ 'changedtick' : 0}, g:Xgetlist({'id' : qfid, 'all' : 0}))
else
call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
\ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0},
\ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0,
\ 'quickfixtextfunc' : ''},
\ g:Xgetlist({'id' : qfid, 'all' : 0}))
endif
@@ -3557,13 +3558,13 @@ func Xgetlist_empty_tests(cchar)
if a:cchar == 'c'
call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
\ 'changedtick' : 0, 'qfbufnr' : qfbufnr},
\ g:Xgetlist({'nr' : 5, 'all' : 0}))
\ 'changedtick' : 0, 'qfbufnr' : qfbufnr,
\ 'quickfixtextfunc' : ''}, g:Xgetlist({'nr' : 5, 'all' : 0}))
else
call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
\ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0},
\ g:Xgetlist({'nr' : 5, 'all' : 0}))
\ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0,
\ 'quickfixtextfunc' : ''}, g:Xgetlist({'nr' : 5, 'all' : 0}))
endif
endfunc
@@ -4865,6 +4866,9 @@ func Xtest_qftextfunc(cchar)
set efm=%f:%l:%c:%m
set quickfixtextfunc=Tqfexpr
call assert_equal('Tqfexpr', &quickfixtextfunc)
call assert_equal('',
\ g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc)
Xexpr ['F1:10:2:green', 'F1:20:4:blue']
Xwindow
call assert_equal('F1-L10C2-green', getline(1))
@@ -4901,12 +4905,15 @@ func Xtest_qftextfunc(cchar)
call assert_equal('Line 10, Col 2', getline(1))
call assert_equal('Line 20, Col 4', getline(2))
Xclose
call assert_equal(function('PerQfText'),
\ g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc)
" Add entries to the list when the quickfix buffer is hidden
Xaddexpr ['F1:30:6:red']
Xwindow
call assert_equal('Line 30, Col 6', getline(3))
Xclose
call g:Xsetlist([], 'r', {'quickfixtextfunc' : ''})
call assert_equal('', g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc)
set quickfixtextfunc&
delfunc PerQfText
@@ -4941,12 +4948,53 @@ func Xtest_qftextfunc(cchar)
call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue', 'F1:30:6:red']",
\ 'E730:')
call assert_fails('Xwindow', 'E730:')
call assert_equal(['one', 'F1|20 col 4| blue', 'two'], getline(1, '$'))
call assert_equal(['one', 'F1|20 col 4| blue', 'F1|30 col 6| red'],
\ getline(1, '$'))
Xclose
set quickfixtextfunc&
delfunc Xqftext
delfunc Xqftext2
" set the global option to a lambda function
set quickfixtextfunc={d\ ->\ map(g:Xgetlist({'id'\ :\ d.id,\ 'items'\ :\ 1}).items[d.start_idx-1:d.end_idx-1],\ 'v:val.text')}
Xexpr ['F1:10:2:green', 'F1:20:4:blue']
Xwindow
call assert_equal(['green', 'blue'], getline(1, '$'))
Xclose
call assert_equal("{d -> map(g:Xgetlist({'id' : d.id, 'items' : 1}).items[d.start_idx-1:d.end_idx-1], 'v:val.text')}", &quickfixtextfunc)
set quickfixtextfunc&
" use a lambda function that returns an empty list
set quickfixtextfunc={d\ ->\ []}
Xexpr ['F1:10:2:green', 'F1:20:4:blue']
Xwindow
call assert_equal(['F1|10 col 2| green', 'F1|20 col 4| blue'],
\ getline(1, '$'))
Xclose
set quickfixtextfunc&
" use a lambda function that returns a list with empty strings
set quickfixtextfunc={d\ ->\ ['',\ '']}
Xexpr ['F1:10:2:green', 'F1:20:4:blue']
Xwindow
call assert_equal(['F1|10 col 2| green', 'F1|20 col 4| blue'],
\ getline(1, '$'))
Xclose
set quickfixtextfunc&
" set the per-quickfix list text function to a lambda function
call g:Xsetlist([], ' ',
\ {'quickfixtextfunc' :
\ {d -> map(g:Xgetlist({'id' : d.id, 'items' : 1}).items[d.start_idx-1:d.end_idx-1],
\ "'Line ' .. v:val.lnum .. ', Col ' .. v:val.col")}})
Xaddexpr ['F1:10:2:green', 'F1:20:4:blue']
Xwindow
call assert_equal('Line 10, Col 2', getline(1))
call assert_equal('Line 20, Col 4', getline(2))
Xclose
call assert_match("function('<lambda>\\d\\+')", string(g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc))
call g:Xsetlist([], 'f')
endfunc
func Test_qftextfunc()

View File

@@ -32,6 +32,9 @@ func Test_equivalence_re2()
endfunc
func s:classes_test()
if has('win32')
set iskeyword=@,48-57,_,192-255
endif
set isprint=@,161-255
call assert_equal('Motörhead', matchstr('Motörhead', '[[:print:]]\+'))

View File

@@ -112,4 +112,27 @@ func Test_tabline_flags()
%bw!
endfunc
function EmptyTabname()
return ""
endfunction
function MakeTabLine() abort
let titles = map(range(1, tabpagenr('$')), '"%( %" . v:val . "T%{EmptyTabname()}%T %)"')
let sep = 'あ'
let tabpages = join(titles, sep)
return tabpages .. sep .. '%=%999X X'
endfunction
func Test_tabline_empty_group()
" this was reading invalid memory
set tabline=%!MakeTabLine()
tabnew
redraw!
tabclose
set tabline=
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@@ -527,11 +527,9 @@ func Test_terminal_getwinpos()
wincmd j
set splitright
call writefile([
\ 'echo getwinpos()',
\ ], 'XTest_getwinpos')
let buf = RunVimInTerminal('-S XTest_getwinpos', {'cols': 60})
call TermWait(buf)
let buf = RunVimInTerminal('', {'cols': 60})
call TermWait(buf, 100)
call term_sendkeys(buf, ":echo getwinpos(500)\<CR>")
" Find the output of getwinpos() in the bottom line.
let rows = term_getsize(buf)[0]
@@ -557,7 +555,6 @@ func Test_terminal_getwinpos()
call TermWait(buf)
call term_sendkeys(buf, ":q\<CR>")
call StopVimInTerminal(buf)
call delete('XTest_getwinpos')
exe buf . 'bwipe!'
set splitright&
only!

View File

@@ -21,9 +21,13 @@ def s:ScriptFuncLoad(arg: string)
echo v:version
echo s:scriptvar
echo g:globalvar
echo get(g:, "global")
echo b:buffervar
echo get(b:, "buffer")
echo w:windowvar
echo get(w:, "window")
echo t:tabpagevar
echo get(t:, "tab")
echo &tabstop
echo $ENVVAR
echo @z
@@ -47,9 +51,25 @@ def Test_disassemble_load()
' LOADV v:version.*' ..
' LOADS s:scriptvar from .*test_vim9_disassemble.vim.*' ..
' LOADG g:globalvar.*' ..
'echo get(g:, "global")\_s*' ..
'\d\+ LOAD g:\_s*' ..
'\d\+ PUSHS "global"\_s*' ..
'\d\+ BCALL get(argc 2).*' ..
' LOADB b:buffervar.*' ..
'echo get(b:, "buffer")\_s*' ..
'\d\+ LOAD b:\_s*' ..
'\d\+ PUSHS "buffer"\_s*' ..
'\d\+ BCALL get(argc 2).*' ..
' LOADW w:windowvar.*' ..
'echo get(w:, "window")\_s*' ..
'\d\+ LOAD w:\_s*' ..
'\d\+ PUSHS "window"\_s*' ..
'\d\+ BCALL get(argc 2).*' ..
' LOADT t:tabpagevar.*' ..
'echo get(t:, "tab")\_s*' ..
'\d\+ LOAD t:\_s*' ..
'\d\+ PUSHS "tab"\_s*' ..
'\d\+ BCALL get(argc 2).*' ..
' LOADENV $ENVVAR.*' ..
' LOADREG @z.*',
res)
@@ -898,6 +918,27 @@ def Test_disassemble_concat()
assert_equal('aabb', ConcatString())
enddef
def StringIndex(): number
let s = "abcd"
let res = s[1]
return res
enddef
def Test_disassemble_string_index()
let instr = execute('disassemble StringIndex')
assert_match('StringIndex\_s*' ..
'let s = "abcd"\_s*' ..
'\d PUSHS "abcd"\_s*' ..
'\d STORE $0\_s*' ..
'let res = s\[1]\_s*' ..
'\d LOAD $0\_s*' ..
'\d PUSHNR 1\_s*' ..
'\d STRINDEX\_s*' ..
'\d STORE $1\_s*',
instr)
assert_equal('b', StringIndex())
enddef
def ListIndex(): number
let l = [1, 2, 3]
let res = l[1]
@@ -916,7 +957,7 @@ def Test_disassemble_list_index()
'let res = l\[1]\_s*' ..
'\d LOAD $0\_s*' ..
'\d PUSHNR 1\_s*' ..
'\d INDEX\_s*' ..
'\d LISTINDEX\_s*' ..
'\d STORE $1\_s*',
instr)
assert_equal(2, ListIndex())

View File

@@ -3,6 +3,15 @@
source check.vim
source vim9.vim
let g:cond = v:false
def FuncOne(arg: number): string
return 'yes'
enddef
def FuncTwo(arg: number): number
return 123
enddef
" test cond ? expr : expr
def Test_expr1()
assert_equal('one', true ? 'one' : 'two')
@@ -43,6 +52,11 @@ def Test_expr1()
let RetTwo: func(string): number = function('winnr')
let RetThat: func = g:atrue ? RetOne : RetTwo
assert_equal(function('len'), RetThat)
let x = FuncOne
let y = FuncTwo
let Z = g:cond ? FuncOne : FuncTwo
assert_equal(123, Z(3))
enddef
def Test_expr1_vimscript()
@@ -88,6 +102,13 @@ func Test_expr1_fails()
call CheckDefFailure(["let x = 1 ? 'one': 'two'"], msg)
call CheckDefFailure(["let x = 1 ? 'one' :'two'"], msg)
call CheckDefFailure(["let x = 1 ? 'one':'two'"], msg)
" missing argument detected even when common type is used
call CheckDefFailure([
\ 'let x = FuncOne',
\ 'let y = FuncTwo',
\ 'let Z = g:cond ? FuncOne : FuncTwo',
\ 'Z()'], 'E119:')
endfunc
" TODO: define inside test function
@@ -630,7 +651,7 @@ def Test_expr4_vimscript()
vim9script
let var = 0
< 1
assert_equal(1, var)
assert_equal(true, var)
END
CheckScriptSuccess(lines)
@@ -638,7 +659,7 @@ def Test_expr4_vimscript()
vim9script
let var = 123
!= 123
assert_equal(0, var)
assert_equal(false, var)
END
CheckScriptSuccess(lines)
@@ -646,7 +667,7 @@ def Test_expr4_vimscript()
vim9script
let var = 123 ==
123
assert_equal(1, var)
assert_equal(true, var)
END
CheckScriptSuccess(lines)
@@ -655,7 +676,7 @@ def Test_expr4_vimscript()
let list = [1, 2, 3]
let var = list
is list
assert_equal(1, var)
assert_equal(true, var)
END
CheckScriptSuccess(lines)
@@ -664,7 +685,7 @@ def Test_expr4_vimscript()
let myblob = 0z1234
let var = myblob
isnot 0z11
assert_equal(1, var)
assert_equal(true, var)
END
CheckScriptSuccess(lines)
@@ -686,6 +707,25 @@ def Test_expr4_vimscript()
echo 123 is 123
END
CheckScriptFailure(lines, 'Cannot use "is" with number')
# check 'ignorecase' not being used
lines =<< trim END
vim9script
set ignorecase
assert_equal(false, 'abc' == 'ABC')
assert_equal(false, 'abc' ==# 'ABC')
assert_equal(true, 'abc' ==? 'ABC')
assert_equal(true, 'abc' != 'ABC')
assert_equal(true, 'abc' !=# 'ABC')
assert_equal(false, 'abc' !=? 'ABC')
assert_equal(false, 'abc' =~ 'ABC')
assert_equal(false, 'abc' =~# 'ABC')
assert_equal(true, 'abc' =~? 'ABC')
set noignorecase
END
CheckScriptSuccess(lines)
enddef
func Test_expr4_fails()
@@ -1115,7 +1155,7 @@ def Test_expr7_list()
call CheckDefExecFailure(["let x = g:anint[3]"], 'E714:')
call CheckDefFailure(["let x = g:list_mixed[xxx]"], 'E1001:')
call CheckDefFailure(["let x = [1,2,3]"], 'E1069:')
call CheckDefExecFailure(["let x = g:list_mixed['xx']"], 'E39:')
call CheckDefExecFailure(["let x = g:list_mixed['xx']"], 'E1029:')
call CheckDefFailure(["let x = g:list_mixed["], 'E1097:')
call CheckDefFailure(["let x = g:list_mixed[0"], 'E1097:')
call CheckDefExecFailure(["let x = g:list_empty[3]"], 'E684:')
@@ -1173,6 +1213,13 @@ def Test_expr7_lambda()
})
assert_equal([111, 222, 111], ll)
let dl = [{'key': 0}, {'key': 22}]->filter({ _, v -> v['key'] })
assert_equal([{'key': 22}], dl)
dl = [{'key': 12}, {'foo': 34}]
assert_equal([{'key': 12}], filter(dl,
{_, v -> has_key(v, 'key') ? v['key'] == 12 : 0}))
call CheckDefFailure(["filter([1, 2], {k,v -> 1})"], 'E1069:')
enddef
@@ -1342,6 +1389,32 @@ def Test_expr7_register()
assert_equal('register a', @a)
enddef
def Test_expr7_namespace()
g:some_var = 'some'
assert_equal('some', get(g:, 'some_var'))
assert_equal('some', get(g:, 'some_var', 'xxx'))
assert_equal('xxx', get(g:, 'no_var', 'xxx'))
unlet g:some_var
b:some_var = 'some'
assert_equal('some', get(b:, 'some_var'))
assert_equal('some', get(b:, 'some_var', 'xxx'))
assert_equal('xxx', get(b:, 'no_var', 'xxx'))
unlet b:some_var
w:some_var = 'some'
assert_equal('some', get(w:, 'some_var'))
assert_equal('some', get(w:, 'some_var', 'xxx'))
assert_equal('xxx', get(w:, 'no_var', 'xxx'))
unlet w:some_var
t:some_var = 'some'
assert_equal('some', get(t:, 'some_var'))
assert_equal('some', get(t:, 'some_var', 'xxx'))
assert_equal('xxx', get(t:, 'no_var', 'xxx'))
unlet t:some_var
enddef
def Test_expr7_parens()
# (expr)
assert_equal(4, (6 * 4) / 6)
@@ -1506,6 +1579,15 @@ def Test_expr7_trailing()
assert_equal(123, d.key)
enddef
def Test_expr7_subscript()
let text = 'abcdef'
assert_equal('', text[-1])
assert_equal('a', text[0])
assert_equal('e', text[4])
assert_equal('f', text[5])
assert_equal('', text[6])
enddef
def Test_expr7_subscript_linebreak()
let range = range(
3)

View File

@@ -407,6 +407,17 @@ def Test_vim9script_call_fail_decl()
delete('Xcall_decl.vim')
enddef
def Test_vim9script_call_fail_type()
let lines =<< trim END
vim9script
def MyFunc(arg: string)
echo arg
enddef
MyFunc(1234)
END
CheckScriptFailure(lines, 'E1013: type mismatch, expected string but got number')
enddef
def Test_vim9script_call_fail_const()
let lines =<< trim END
vim9script

View File

@@ -29,7 +29,7 @@ def Test_assignment()
call CheckDefFailure(['let x:string = "x"'], 'E1069:')
call CheckDefFailure(['let a:string = "x"'], 'E1069:')
let a: number = 6
let a: number = 6 #comment
assert_equal(6, a)
if has('channel')
@@ -44,7 +44,7 @@ def Test_assignment()
let Funky2: func = function('len')
let Party2: func = funcref('g:Test_syntax')
g:newvar = 'new'
g:newvar = 'new' #comment
assert_equal('new', g:newvar)
assert_equal('yes', g:existing)
@@ -169,6 +169,18 @@ def Test_assignment_list()
let somelist = rand() > 0 ? [1, 2, 3] : ['a', 'b', 'c']
enddef
def Test_assignment_list_vim9script()
let lines =<< trim END
vim9script
let v1: number
let v2: number
let v3: number
[v1, v2, v3] = [1, 2, 3]
assert_equal([1, 2, 3], [v1, v2, v3])
END
call CheckScriptSuccess(lines)
enddef
def Test_assignment_dict()
let dict1: dict<bool> = #{one: false, two: true}
let dict2: dict<number> = #{one: 1, two: 2}
@@ -498,6 +510,10 @@ def Test_cmd_modifier()
call CheckDefFailure(['5tab echo 3'], 'E16:')
enddef
func g:NoSuchFunc()
echo 'none'
endfunc
def Test_try_catch()
let l = []
try # comment
@@ -656,6 +672,57 @@ def Test_try_catch()
n = 344
endtry
assert_equal(344, n)
try
echo len(v:true)
catch /E701:/
n = 355
endtry
assert_equal(355, n)
let P = function('g:NoSuchFunc')
delfunc g:NoSuchFunc
try
echo P()
catch /E117:/
n = 366
endtry
assert_equal(366, n)
try
echo g:NoSuchFunc()
catch /E117:/
n = 377
endtry
assert_equal(377, n)
try
echo g:alist + 4
catch /E745:/
n = 388
endtry
assert_equal(388, n)
try
echo 4 + g:alist
catch /E745:/
n = 399
endtry
assert_equal(399, n)
try
echo g:alist.member
catch /E715:/
n = 400
endtry
assert_equal(400, n)
try
echo d.member
catch /E716:/
n = 411
endtry
assert_equal(411, n)
enddef
def DeletedFunc(): list<any>
@@ -766,6 +833,22 @@ def Test_cexpr_vimscript()
set errorformat&
enddef
def Test_list_vimscript()
# checks line continuation and comments
let lines =<< trim END
vim9script
let mylist = [
'one',
# comment
'two', # empty line follows
'three',
]
assert_equal(['one', 'two', 'three'], mylist)
END
CheckScriptSuccess(lines)
enddef
if has('channel')
let someJob = test_null_job()
@@ -2029,7 +2112,7 @@ def Test_vim9_comment()
CheckScriptFailure([
'vim9script',
'syntax region Word start=/pat/ end=/pat/# comment',
], 'E475:')
], 'E402:')
CheckScriptSuccess([
'vim9script',

View File

@@ -790,8 +790,16 @@ typval_compare(
}
}
clear_tv(typ1);
typ1->v_type = VAR_NUMBER;
typ1->vval.v_number = n1;
if (in_vim9script())
{
typ1->v_type = VAR_BOOL;
typ1->vval.v_number = n1 ? VVAL_TRUE : VVAL_FALSE;
}
else
{
typ1->v_type = VAR_NUMBER;
typ1->vval.v_number = n1;
}
return OK;
}

View File

@@ -2122,7 +2122,7 @@ theend:
return ret;
}
static char_u *
char_u *
printable_func_name(ufunc_T *fp)
{
return fp->uf_name_exp != NULL ? fp->uf_name_exp : fp->uf_name;

View File

@@ -754,6 +754,60 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1264,
/**/
1263,
/**/
1262,
/**/
1261,
/**/
1260,
/**/
1259,
/**/
1258,
/**/
1257,
/**/
1256,
/**/
1255,
/**/
1254,
/**/
1253,
/**/
1252,
/**/
1251,
/**/
1250,
/**/
1249,
/**/
1248,
/**/
1247,
/**/
1246,
/**/
1245,
/**/
1244,
/**/
1243,
/**/
1242,
/**/
1241,
/**/
1240,
/**/
1239,
/**/
1238,
/**/
1237,
/**/

View File

@@ -26,6 +26,10 @@ typedef enum {
ISN_LOADB, // push b: variable isn_arg.string
ISN_LOADW, // push w: variable isn_arg.string
ISN_LOADT, // push t: variable isn_arg.string
ISN_LOADGDICT, // push g: dict
ISN_LOADBDICT, // push b: dict
ISN_LOADWDICT, // push w: dict
ISN_LOADTDICT, // push t: dict
ISN_LOADS, // push s: variable isn_arg.loadstore
ISN_LOADOUTER, // push variable from outer scope isn_arg.number
ISN_LOADSCRIPT, // push script-local variable isn_arg.script.
@@ -111,7 +115,8 @@ typedef enum {
// expression operations
ISN_CONCAT,
ISN_INDEX, // [expr] list index
ISN_STRINDEX, // [expr] string index
ISN_LISTINDEX, // [expr] list index
ISN_SLICE, // drop isn_arg.number items from start of list
ISN_GETITEM, // push list item, isn_arg.number is the index
ISN_MEMBER, // dict[member]

View File

@@ -147,6 +147,7 @@ static char e_var_notfound[] = N_("E1001: variable not found: %s");
static char e_syntax_at[] = N_("E1002: Syntax error at %s");
static char e_used_as_arg[] = N_("E1006: %s is used as an argument");
static char e_cannot_use_void[] = N_("E1031: Cannot use void value");
static char e_namespace[] = N_("E1075: Namespace not supported: %s");
static void delete_def_function_contents(dfunc_T *dfunc);
static void arg_type_mismatch(type_T *expected, type_T *actual, int argidx);
@@ -560,6 +561,50 @@ check_type(type_T *expected, type_T *actual, int give_msg)
return ret;
}
/*
* Return FAIl if "expected" and "actual" don't match.
* TODO: better type comparison
*/
int
check_argtype(type_T *expected, typval_T *actual_tv)
{
type_T actual;
type_T member;
// TODO: should should be done with more levels
CLEAR_FIELD(actual);
actual.tt_type = actual_tv->v_type;
if (actual_tv->v_type == VAR_LIST
&& actual_tv->vval.v_list != NULL
&& actual_tv->vval.v_list->lv_first != NULL)
{
// Use the type of the first member, it is the most specific.
CLEAR_FIELD(member);
member.tt_type = actual_tv->vval.v_list->lv_first->li_tv.v_type;
member.tt_member = &t_any;
actual.tt_member = &member;
}
else if (actual_tv->v_type == VAR_DICT
&& actual_tv->vval.v_dict != NULL
&& actual_tv->vval.v_dict->dv_hashtab.ht_used > 0)
{
dict_iterator_T iter;
typval_T *value;
// Use the type of the first value, it is the most specific.
dict_iterate_start(actual_tv, &iter);
dict_iterate_next(&iter, &value);
CLEAR_FIELD(member);
member.tt_type = value->v_type;
member.tt_member = &t_any;
actual.tt_member = &member;
}
else
actual.tt_member = &t_any;
return check_type(expected, &actual, TRUE);
}
/////////////////////////////////////////////////////////////////////
// Following generate_ functions expect the caller to call ga_grow().
@@ -1098,13 +1143,13 @@ generate_GETITEM(cctx_T *cctx, int index)
RETURN_OK_IF_SKIP(cctx);
if (type->tt_type == VAR_LIST)
item_type = type->tt_member;
else if (type->tt_type != VAR_ANY)
if (type->tt_type != VAR_LIST)
{
// cannot happen, caller has checked the type
emsg(_(e_listreq));
return FAIL;
}
item_type = type->tt_member;
if ((isn = generate_instr(cctx, ISN_GETITEM)) == NULL)
return FAIL;
isn->isn_arg.number = index;
@@ -2419,7 +2464,7 @@ free_imported(cctx_T *cctx)
/*
* Return TRUE if "p" points at a "#" but not at "#{".
*/
static int
int
vim9_comment_start(char_u *p)
{
return p[0] == '#' && p[1] != '{';
@@ -2737,7 +2782,7 @@ generate_funcref(cctx_T *cctx, char_u *name)
compile_load(char_u **arg, char_u *end_arg, cctx_T *cctx, int error)
{
type_T *type;
char_u *name;
char_u *name = NULL;
char_u *end = end_arg;
int res = FAIL;
int prev_called_emsg = called_emsg;
@@ -2746,48 +2791,52 @@ compile_load(char_u **arg, char_u *end_arg, cctx_T *cctx, int error)
{
// load namespaced variable
if (end <= *arg + 2)
name = vim_strsave((char_u *)"[empty]");
else
name = vim_strnsave(*arg + 2, end - (*arg + 2));
if (name == NULL)
return FAIL;
{
isntype_T isn_type;
if (**arg == 'v')
{
res = generate_LOADV(cctx, name, error);
}
else if (**arg == 'g')
{
// Global variables can be defined later, thus we don't check if it
// exists, give error at runtime.
res = generate_LOAD(cctx, ISN_LOADG, 0, name, &t_any);
}
else if (**arg == 's')
{
res = compile_load_scriptvar(cctx, name, NULL, NULL, error);
}
else if (**arg == 'b')
{
// Buffer-local variables can be defined later, thus we don't check
// if it exists, give error at runtime.
res = generate_LOAD(cctx, ISN_LOADB, 0, name, &t_any);
}
else if (**arg == 'w')
{
// Window-local variables can be defined later, thus we don't check
// if it exists, give error at runtime.
res = generate_LOAD(cctx, ISN_LOADW, 0, name, &t_any);
}
else if (**arg == 't')
{
// Tabpage-local variables can be defined later, thus we don't
// check if it exists, give error at runtime.
res = generate_LOAD(cctx, ISN_LOADT, 0, name, &t_any);
switch (**arg)
{
case 'g': isn_type = ISN_LOADGDICT; break;
case 'w': isn_type = ISN_LOADWDICT; break;
case 't': isn_type = ISN_LOADTDICT; break;
case 'b': isn_type = ISN_LOADBDICT; break;
default:
semsg(_(e_namespace), *arg);
goto theend;
}
if (generate_instr_type(cctx, isn_type, &t_dict_any) == NULL)
goto theend;
res = OK;
}
else
{
semsg("E1075: Namespace not supported: %s", *arg);
goto theend;
isntype_T isn_type = ISN_DROP;
name = vim_strnsave(*arg + 2, end - (*arg + 2));
if (name == NULL)
return FAIL;
switch (**arg)
{
case 'v': res = generate_LOADV(cctx, name, error);
break;
case 's': res = compile_load_scriptvar(cctx, name,
NULL, NULL, error);
break;
case 'g': isn_type = ISN_LOADG; break;
case 'w': isn_type = ISN_LOADW; break;
case 't': isn_type = ISN_LOADT; break;
case 'b': isn_type = ISN_LOADB; break;
default: semsg(_(e_namespace), *arg);
goto theend;
}
if (isn_type != ISN_DROP)
{
// Global, Buffer-local, Window-local and Tabpage-local
// variables can be defined later, thus we don't check if it
// exists, give error at runtime.
res = generate_LOAD(cctx, isn_type, 0, name, &t_any);
}
}
}
else
@@ -3704,9 +3753,11 @@ compile_subscript(
{
garray_T *stack = &cctx->ctx_type_stack;
type_T **typep;
vartype_T vtype;
// list index: list[123]
// dict member: dict[key]
// string index: text[123]
// TODO: blob index
// TODO: more arguments
// TODO: recognize list or dict at runtime
@@ -3729,22 +3780,47 @@ compile_subscript(
}
*arg = *arg + 1;
// We can index a list and a dict. If we don't know the type
// we can use the index value type.
// TODO: If we don't know use an instruction to figure it out at
// runtime.
typep = ((type_T **)stack->ga_data) + stack->ga_len - 2;
if ((*typep)->tt_type == VAR_LIST || (*typep) == &t_any)
vtype = (*typep)->tt_type;
if (*typep == &t_any)
{
if ((*typep)->tt_type == VAR_LIST)
*typep = (*typep)->tt_member;
if (generate_instr_drop(cctx, ISN_INDEX, 1) == FAIL)
return FAIL;
type_T *valtype = ((type_T **)stack->ga_data)
[stack->ga_len - 1];
if (valtype == &t_string)
vtype = VAR_DICT;
}
else if ((*typep)->tt_type == VAR_DICT)
if (vtype == VAR_DICT)
{
*typep = (*typep)->tt_member;
if ((*typep)->tt_type == VAR_DICT)
*typep = (*typep)->tt_member;
else
{
if (need_type(*typep, &t_dict_any, -2, cctx, FALSE) == FAIL)
return FAIL;
*typep = &t_any;
}
if (may_generate_2STRING(-1, cctx) == FAIL)
return FAIL;
if (generate_instr_drop(cctx, ISN_MEMBER, 1) == FAIL)
return FAIL;
}
else if (vtype == VAR_STRING)
{
*typep = &t_number;
if (generate_instr_drop(cctx, ISN_STRINDEX, 1) == FAIL)
return FAIL;
}
else if (vtype == VAR_LIST || *typep == &t_any)
{
if ((*typep)->tt_type == VAR_LIST)
*typep = (*typep)->tt_member;
if (generate_instr_drop(cctx, ISN_LISTINDEX, 1) == FAIL)
return FAIL;
}
else
{
emsg(_(e_listdictblobreq));
@@ -4893,6 +4969,8 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
if (var_count > 0 && is_decl)
{
// TODO: should we allow this, and figure out type inference from list
// members?
emsg(_("E1092: Cannot use a list for a declaration"));
return NULL;
}
@@ -5342,7 +5420,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
}
stacktype = stack->ga_len == 0 ? &t_void
: ((type_T **)stack->ga_data)[stack->ga_len - 1];
: ((type_T **)stack->ga_data)[stack->ga_len - 1];
if (lvar != NULL && (is_decl || !has_type))
{
if (new_local && !has_type)
@@ -5645,7 +5723,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
goto theend;
}
ret = end;
ret = skipwhite(end);
theend:
vim_free(name);
@@ -7481,16 +7559,21 @@ delete_instr(isn_T *isn)
case ISN_EXECCONCAT:
case ISN_EXECUTE:
case ISN_FOR:
case ISN_INDEX:
case ISN_LISTINDEX:
case ISN_STRINDEX:
case ISN_GETITEM:
case ISN_SLICE:
case ISN_MEMBER:
case ISN_JUMP:
case ISN_LOAD:
case ISN_LOADBDICT:
case ISN_LOADGDICT:
case ISN_LOADOUTER:
case ISN_LOADSCRIPT:
case ISN_LOADREG:
case ISN_LOADSCRIPT:
case ISN_LOADTDICT:
case ISN_LOADV:
case ISN_LOADWDICT:
case ISN_NEGATENR:
case ISN_NEWDICT:
case ISN_NEWLIST:

View File

@@ -714,8 +714,7 @@ call_def_function(
{
if (called_emsg == called_emsg_before)
semsg(_("E1091: Function is not compiled: %s"),
ufunc->uf_name_exp == NULL
? ufunc->uf_name : ufunc->uf_name_exp);
printable_func_name(ufunc));
return FAIL;
}
@@ -737,6 +736,9 @@ call_def_function(
// Put arguments on the stack.
for (idx = 0; idx < argc; ++idx)
{
if (ufunc->uf_arg_types != NULL && idx < ufunc->uf_args.ga_len
&& check_argtype(ufunc->uf_arg_types[idx], &argv[idx]) == FAIL)
goto failed_early;
copy_tv(&argv[idx], STACK_TV_BOT(0));
++ectx.ec_stack.ga_len;
}
@@ -1086,6 +1088,7 @@ call_def_function(
dictitem_T *di = NULL;
hashtab_T *ht = NULL;
char namespace;
switch (iptr->isn_type)
{
case ISN_LOADG:
@@ -1125,6 +1128,33 @@ call_def_function(
}
break;
// load g:/b:/w:/t: namespace
case ISN_LOADGDICT:
case ISN_LOADBDICT:
case ISN_LOADWDICT:
case ISN_LOADTDICT:
{
dict_T *d = NULL;
switch (iptr->isn_type)
{
case ISN_LOADGDICT: d = get_globvar_dict(); break;
case ISN_LOADBDICT: d = curbuf->b_vars; break;
case ISN_LOADWDICT: d = curwin->w_vars; break;
case ISN_LOADTDICT: d = curtab->tp_vars; break;
default: // Cannot reach here
goto failed;
}
if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
goto failed;
tv = STACK_TV_BOT(0);
tv->v_type = VAR_DICT;
tv->v_lock = 0;
tv->vval.v_dict = d;
++ectx.ec_stack.ga_len;
}
break;
// load &option
case ISN_LOADOPT:
{
@@ -1163,6 +1193,7 @@ call_def_function(
goto failed;
tv = STACK_TV_BOT(0);
tv->v_type = VAR_STRING;
tv->v_lock = 0;
tv->vval.v_string = get_reg_contents(
iptr->isn_arg.number, GREG_EXPR_SRC);
++ectx.ec_stack.ga_len;
@@ -1408,6 +1439,7 @@ call_def_function(
if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
goto failed;
tv = STACK_TV_BOT(0);
tv->v_lock = 0;
++ectx.ec_stack.ga_len;
switch (iptr->isn_type)
{
@@ -1512,6 +1544,7 @@ call_def_function(
item->di_tv.v_lock = 0;
if (dict_add(dict, item) == FAIL)
{
// can this ever happen?
dict_unref(dict);
goto failed;
}
@@ -1525,6 +1558,7 @@ call_def_function(
++ectx.ec_stack.ga_len;
tv = STACK_TV_BOT(-1);
tv->v_type = VAR_DICT;
tv->v_lock = 0;
tv->vval.v_dict = dict;
++dict->dv_refcount;
}
@@ -1544,7 +1578,7 @@ call_def_function(
if (call_bfunc(iptr->isn_arg.bfunc.cbf_idx,
iptr->isn_arg.bfunc.cbf_argcount,
&ectx) == FAIL)
goto failed;
goto on_error;
break;
// call a funcref or partial
@@ -1571,7 +1605,7 @@ call_def_function(
if (tv == &partial_tv)
clear_tv(&partial_tv);
if (r == FAIL)
goto failed;
goto on_error;
}
break;
@@ -1592,7 +1626,7 @@ call_def_function(
SOURCING_LNUM = iptr->isn_lnum;
if (call_eval_func(cufunc->cuf_name,
cufunc->cuf_argcount, &ectx, iptr) == FAIL)
goto failed;
goto on_error;
}
break;
@@ -1614,19 +1648,7 @@ call_def_function(
trycmd->tcd_return = TRUE;
}
else
{
// Restore previous function. If the frame pointer
// is zero then there is none and we are done.
if (ectx.ec_frame_idx == initial_frame_idx)
{
if (handle_closure_in_use(&ectx, FALSE) == FAIL)
goto failed;
goto done;
}
if (func_return(&ectx) == FAIL)
goto failed;
}
goto func_return;
}
break;
@@ -1681,6 +1703,7 @@ call_def_function(
++ectx.ec_stack.ga_len;
tv->vval.v_partial = pt;
tv->v_type = VAR_PARTIAL;
tv->v_lock = 0;
}
break;
@@ -1727,6 +1750,7 @@ call_def_function(
// non-materialized range() list
tv = STACK_TV_BOT(0);
tv->v_type = VAR_NUMBER;
tv->v_lock = 0;
tv->vval.v_number = list_find_nr(
list, idxtv->vval.v_number, NULL);
++ectx.ec_stack.ga_len;
@@ -1735,8 +1759,6 @@ call_def_function(
{
listitem_T *li = list_find(list, idxtv->vval.v_number);
if (li == NULL)
goto failed;
copy_tv(&li->li_tv, STACK_TV_BOT(0));
++ectx.ec_stack.ga_len;
}
@@ -1772,6 +1794,7 @@ call_def_function(
tv = STACK_TV_BOT(0);
++ectx.ec_stack.ga_len;
tv->v_type = VAR_STRING;
tv->v_lock = 0;
tv->vval.v_string = vim_strsave(
(char_u *)current_exception->value);
break;
@@ -1814,19 +1837,7 @@ call_def_function(
}
if (trycmd->tcd_return)
{
// Restore previous function. If the frame pointer
// is zero then there is none and we are done.
if (ectx.ec_frame_idx == initial_frame_idx)
{
if (handle_closure_in_use(&ectx, FALSE) == FAIL)
goto failed;
goto done;
}
if (func_return(&ectx) == FAIL)
goto failed;
}
goto func_return;
}
}
break;
@@ -2006,9 +2017,6 @@ call_def_function(
typval_compare(tv1, tv2, exptype, ic);
clear_tv(tv2);
tv1->v_type = VAR_BOOL;
tv1->vval.v_number = tv1->vval.v_number
? VVAL_TRUE : VVAL_FALSE;
--ectx.ec_stack.ga_len;
}
break;
@@ -2068,7 +2076,7 @@ call_def_function(
{
n1 = tv_get_number_chk(tv1, &error);
if (error)
goto failed;
goto on_error;
#ifdef FEAT_FLOAT
if (tv2->v_type == VAR_FLOAT)
f1 = n1;
@@ -2085,7 +2093,7 @@ call_def_function(
{
n2 = tv_get_number_chk(tv2, &error);
if (error)
goto failed;
goto on_error;
#ifdef FEAT_FLOAT
if (tv1->v_type == VAR_FLOAT)
f2 = n2;
@@ -2144,7 +2152,44 @@ call_def_function(
}
break;
case ISN_INDEX:
case ISN_STRINDEX:
{
char_u *s;
varnumber_T n;
char_u *res;
// string index: string is at stack-2, index at stack-1
tv = STACK_TV_BOT(-2);
if (tv->v_type != VAR_STRING)
{
emsg(_(e_stringreq));
goto on_error;
}
s = tv->vval.v_string;
tv = STACK_TV_BOT(-1);
if (tv->v_type != VAR_NUMBER)
{
emsg(_(e_number_exp));
goto on_error;
}
n = tv->vval.v_number;
// The resulting variable is a string of a single
// character. If the index is too big or negative the
// result is empty.
if (n < 0 || n >= (varnumber_T)STRLEN(s))
res = NULL;
else
res = vim_strnsave(s + n, 1);
--ectx.ec_stack.ga_len;
tv = STACK_TV_BOT(-1);
vim_free(tv->vval.v_string);
tv->vval.v_string = res;
}
break;
case ISN_LISTINDEX:
{
list_T *list;
varnumber_T n;
@@ -2268,7 +2313,7 @@ call_def_function(
if (tv->v_type != VAR_DICT || tv->vval.v_dict == NULL)
{
emsg(_(e_dictreq));
goto failed;
goto on_error;
}
dict = tv->vval.v_dict;
@@ -2276,7 +2321,7 @@ call_def_function(
== NULL)
{
semsg(_(e_dictkey), iptr->isn_arg.string);
goto failed;
goto on_error;
}
// Clear the dict after getting the item, to avoid that it
// make the item invalid.
@@ -2409,6 +2454,21 @@ call_def_function(
}
continue;
func_return:
// Restore previous function. If the frame pointer is zero then there
// is none and we are done.
if (ectx.ec_frame_idx == initial_frame_idx)
{
if (handle_closure_in_use(&ectx, FALSE) == FAIL)
// only fails when out of memory
goto failed;
goto done;
}
if (func_return(&ectx) == FAIL)
// only fails when out of memory
goto failed;
continue;
on_error:
if (trylevel == 0)
goto failed;
@@ -2434,6 +2494,10 @@ failed_early:
vim_free(ectx.ec_stack.ga_data);
vim_free(ectx.ec_trystack.ga_data);
if (ret != OK && called_emsg == called_emsg_before)
semsg(_("E1099: Unknown error while executing %s"),
printable_func_name(ufunc));
return ret;
}
@@ -2597,6 +2661,18 @@ ex_disassemble(exarg_T *eap)
case ISN_LOADT:
smsg("%4d LOADT t:%s", current, iptr->isn_arg.string);
break;
case ISN_LOADGDICT:
smsg("%4d LOAD g:", current);
break;
case ISN_LOADBDICT:
smsg("%4d LOAD b:", current);
break;
case ISN_LOADWDICT:
smsg("%4d LOAD w:", current);
break;
case ISN_LOADTDICT:
smsg("%4d LOAD t:", current);
break;
case ISN_LOADOPT:
smsg("%4d LOADOPT %s", current, iptr->isn_arg.string);
break;
@@ -2955,7 +3031,8 @@ ex_disassemble(exarg_T *eap)
// expression operations
case ISN_CONCAT: smsg("%4d CONCAT", current); break;
case ISN_INDEX: smsg("%4d INDEX", current); break;
case ISN_STRINDEX: smsg("%4d STRINDEX", current); break;
case ISN_LISTINDEX: smsg("%4d LISTINDEX", current); break;
case ISN_SLICE: smsg("%4d SLICE %lld",
current, iptr->isn_arg.number); break;
case ISN_GETITEM: smsg("%4d ITEM %lld",