aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmake.deps/CMakeLists.txt4
-rw-r--r--runtime/doc/usr_05.txt4
-rw-r--r--runtime/queries/help/highlights.scm2
-rwxr-xr-xscripts/vim-patch.sh9
-rwxr-xr-xsrc/nvim/CMakeLists.txt5
-rw-r--r--src/nvim/eval.c25
-rw-r--r--src/nvim/eval/funcs.c2
-rw-r--r--src/nvim/eval/typval.c14
-rw-r--r--src/nvim/eval/userfunc.c22
-rw-r--r--src/nvim/generators/gen_options.lua1
-rw-r--r--src/nvim/globals.h2
-rw-r--r--src/nvim/memline.c6
-rw-r--r--src/nvim/option.c4
-rw-r--r--src/nvim/option_defs.h1
-rw-r--r--src/nvim/options.lua4
-rw-r--r--src/nvim/po/CMakeLists.txt3
-rw-r--r--src/nvim/regexp.c2
-rw-r--r--src/nvim/spellfile.c2
-rw-r--r--src/nvim/spellsuggest.c2
-rw-r--r--src/nvim/tag.c2
-rw-r--r--src/nvim/testdir/Makefile2
-rw-r--r--src/nvim/testdir/check.vim16
-rw-r--r--src/nvim/testdir/test_blob.vim6
-rw-r--r--src/nvim/testdir/test_breakindent.vim5
-rw-r--r--src/nvim/testdir/test_bufline.vim6
-rw-r--r--src/nvim/testdir/test_clientserver.vim2
-rw-r--r--src/nvim/testdir/test_cmdline.vim34
-rw-r--r--src/nvim/testdir/test_const.vim10
-rw-r--r--src/nvim/testdir/test_diffmode.vim27
-rw-r--r--src/nvim/testdir/test_eval_stuff.vim12
-rw-r--r--src/nvim/testdir/test_excmd.vim15
-rw-r--r--src/nvim/testdir/test_expr.vim8
-rw-r--r--src/nvim/testdir/test_filter_map.vim7
-rw-r--r--src/nvim/testdir/test_fold.vim5
-rw-r--r--src/nvim/testdir/test_functions.vim303
-rw-r--r--src/nvim/testdir/test_highlight.vim8
-rw-r--r--src/nvim/testdir/test_lambda.vim18
-rw-r--r--src/nvim/testdir/test_let.vim102
-rw-r--r--src/nvim/testdir/test_listdict.vim139
-rw-r--r--src/nvim/testdir/test_mapping.vim4
-rw-r--r--src/nvim/testdir/test_marks.vim9
-rw-r--r--src/nvim/testdir/test_match.vim5
-rw-r--r--src/nvim/testdir/test_method.vim1
-rw-r--r--src/nvim/testdir/test_normal.vim1
-rw-r--r--src/nvim/testdir/test_options.vim34
-rw-r--r--src/nvim/testdir/test_popup.vim12
-rw-r--r--src/nvim/testdir/test_signals.vim8
-rw-r--r--src/nvim/testdir/test_sort.vim2
-rw-r--r--src/nvim/testdir/test_source.vim6
-rw-r--r--src/nvim/testdir/test_spell.vim29
-rw-r--r--src/nvim/testdir/test_startup.vim44
-rw-r--r--src/nvim/testdir/test_syntax.vim87
-rw-r--r--src/nvim/testdir/test_timers.vim7
-rw-r--r--src/nvim/testdir/test_unlet.vim25
-rw-r--r--src/nvim/testdir/test_user_func.vim317
-rw-r--r--src/nvim/testdir/test_usercommands.vim21
-rw-r--r--src/nvim/testdir/test_utf8.vim6
-rw-r--r--src/nvim/testdir/test_vimscript.vim269
-rw-r--r--src/nvim/testdir/test_window_cmd.vim5
-rw-r--r--src/nvim/testing.c9
-rw-r--r--test/functional/legacy/eval_spec.lua2
-rw-r--r--test/functional/ui/tabline_spec.lua36
-rw-r--r--test/functional/vimscript/exepath_spec.lua2
-rw-r--r--test/unit/eval/typval_spec.lua8
64 files changed, 1493 insertions, 297 deletions
diff --git a/cmake.deps/CMakeLists.txt b/cmake.deps/CMakeLists.txt
index 54a70aaa65..68ac102864 100644
--- a/cmake.deps/CMakeLists.txt
+++ b/cmake.deps/CMakeLists.txt
@@ -203,8 +203,8 @@ set(TREESITTER_LUA_SHA256 564594fe0ffd2f2fb3578a15019b723e1bc94ac82cb6a0103a6b3b
set(TREESITTER_VIM_URL https://github.com/vigoux/tree-sitter-viml/archive/v0.2.0.tar.gz)
set(TREESITTER_VIM_SHA256 608dcc31a7948cb66ae7f45494620e2e9face1af75598205541f80d782ec4501)
-set(TREESITTER_HELP_URL https://github.com/neovim/tree-sitter-vimdoc/archive/v1.2.4.tar.gz)
-set(TREESITTER_HELP_SHA256 e1595148092c082f6d50989a0f096182b39fd684449d09c4975ed403bfa42f10)
+set(TREESITTER_HELP_URL https://github.com/neovim/tree-sitter-vimdoc/archive/v1.2.5.tar.gz)
+set(TREESITTER_HELP_SHA256 379d764937a0e3a38e3f9ce9a62c93ba24211a236c74181dd04ee3b4631472a8)
set(TREESITTER_URL https://github.com/tree-sitter/tree-sitter/archive/v0.20.7.tar.gz)
set(TREESITTER_SHA256 b355e968ec2d0241bbd96748e00a9038f83968f85d822ecb9940cbe4c42e182e)
diff --git a/runtime/doc/usr_05.txt b/runtime/doc/usr_05.txt
index 63714595eb..944eb1fc80 100644
--- a/runtime/doc/usr_05.txt
+++ b/runtime/doc/usr_05.txt
@@ -127,8 +127,8 @@ Display matches for a search pattern while you type.
This defines a key mapping. More about that in the next section. This
defines the "Q" command to do formatting with the "gq" operator. This is how
-it worked before Vim 5.0. Otherwise the "Q" command starts Ex mode, but you
-will not need it.
+it worked before Vim 5.0. Otherwise the "Q" command repeats the last recorded
+register.
>
vnoremap _g y:exe "grep /" .. escape(@", '\\/') .. "/ *.c *.h"<CR>
diff --git a/runtime/queries/help/highlights.scm b/runtime/queries/help/highlights.scm
index 50beeed8b9..b2ed390336 100644
--- a/runtime/queries/help/highlights.scm
+++ b/runtime/queries/help/highlights.scm
@@ -2,6 +2,8 @@
(h2) @text.title
(h3) @text.title
(column_heading) @text.title
+(column_heading
+ "~" @conceal (#set! conceal ""))
(tag
"*" @conceal (#set! conceal "")
text: (_) @label)
diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh
index 0a2b1df197..c2fac658a9 100755
--- a/scripts/vim-patch.sh
+++ b/scripts/vim-patch.sh
@@ -315,12 +315,11 @@ uncrustify_patch() {
local before=$patch_path/before/$basename
local after=$patch_path/after/$basename
local patchfile="$patch_path"/patch/"$basename".patch
- if [[ ! -e $before ]] || [[ ! -e $after ]]; then
- continue
- fi
+ [[ ! -e $before ]] && before=/dev/null
+ [[ ! -e $after ]] && after=/dev/null
git --no-pager diff --no-index --patch --unified=5 --color=never "$before" "$after" > "$patchfile"
- sed -E "s|$before|/$file|g" -i "$patchfile"
- sed -E "s|$after|/$file|g" -i "$patchfile"
+ [[ "$before" != /dev/null ]] && sed -E "s|$before|/$file|g" -i "$patchfile"
+ [[ "$after" != /dev/null ]] && sed -E "s|$after|/$file|g" -i "$patchfile"
done
cat "$patch_path"/patch/*.patch
diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt
index ac27f46bfb..aee6319770 100755
--- a/src/nvim/CMakeLists.txt
+++ b/src/nvim/CMakeLists.txt
@@ -571,7 +571,10 @@ file(MAKE_DIRECTORY ${BINARY_LIB_DIR})
# install treesitter parser if bundled
if(EXISTS ${DEPS_PREFIX}/lib/nvim/parser)
- file(COPY ${DEPS_PREFIX}/lib/nvim/parser DESTINATION ${BINARY_LIB_DIR})
+ glob_wrapper(TREESITTER_PARSERS ${DEPS_PREFIX}/lib/nvim/parser/*)
+ foreach(parser_lib ${TREESITTER_PARSERS})
+ file(COPY ${parser_lib} DESTINATION ${BINARY_LIB_DIR}/parser)
+ endforeach()
endif()
install(DIRECTORY ${BINARY_LIB_DIR}
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 69bc26b82e..0e4dbeaea6 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -65,6 +65,7 @@ static char *e_nowhitespace
= N_("E274: No white space allowed before parenthesis");
static char *e_write2 = N_("E80: Error while writing: %s");
static char *e_string_list_or_blob_required = N_("E1098: String, List or Blob required");
+static char e_expression_too_recursive_str[] = N_("E1169: Expression too recursive: %s");
static char * const namespace_char = "abglstvw";
@@ -1449,6 +1450,7 @@ char *get_lval(char *const name, typval_T *const rettv, lval_T *const lp, const
key[len] = prevval;
}
if (wrong) {
+ tv_clear(&var1);
return NULL;
}
}
@@ -2910,6 +2912,7 @@ static int eval7(char **arg, typval_T *rettv, int evaluate, int want_string)
const char *start_leader, *end_leader;
int ret = OK;
char *alias;
+ static int recurse = 0;
// Initialise variable so that tv_clear() can't mistake this for a
// string and free a string that isn't there.
@@ -2922,6 +2925,20 @@ static int eval7(char **arg, typval_T *rettv, int evaluate, int want_string)
}
end_leader = *arg;
+ // Limit recursion to 1000 levels. At least at 10000 we run out of stack
+ // and crash. With MSVC the stack is smaller.
+ if (recurse ==
+#ifdef _MSC_VER
+ 300
+#else
+ 1000
+#endif
+ ) {
+ semsg(_(e_expression_too_recursive_str), *arg);
+ return FAIL;
+ }
+ recurse++;
+
switch (**arg) {
// Number constant.
case '0':
@@ -3126,6 +3143,8 @@ static int eval7(char **arg, typval_T *rettv, int evaluate, int want_string)
if (ret == OK && evaluate && end_leader > start_leader) {
ret = eval7_leader(rettv, (char *)start_leader, &end_leader);
}
+
+ recurse--;
return ret;
}
@@ -4785,20 +4804,20 @@ void filter_map(typval_T *argvars, typval_T *rettv, int map)
int save_did_emsg;
int idx = 0;
+ // Always return the first argument, also on failure.
+ tv_copy(&argvars[0], rettv);
+
if (argvars[0].v_type == VAR_BLOB) {
- tv_copy(&argvars[0], rettv);
if ((b = argvars[0].vval.v_blob) == NULL) {
return;
}
} else if (argvars[0].v_type == VAR_LIST) {
- tv_copy(&argvars[0], rettv);
if ((l = argvars[0].vval.v_list) == NULL
|| (!map
&& var_check_lock(tv_list_locked(l), arg_errmsg, TV_TRANSLATE))) {
return;
}
} else if (argvars[0].v_type == VAR_DICT) {
- tv_copy(&argvars[0], rettv);
if ((d = argvars[0].vval.v_dict) == NULL
|| (!map && var_check_lock(d->dv_lock, arg_errmsg, TV_TRANSLATE))) {
return;
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index f66ff7b5bb..b475ff1096 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -5921,7 +5921,7 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
for (p = buf, start = buf;
p < buf + readlen || (readlen <= 0 && (prevlen > 0 || binary));
p++) {
- if (*p == '\n' || readlen <= 0) {
+ if (readlen <= 0 || *p == '\n') {
char *s = NULL;
size_t len = (size_t)(p - start);
diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c
index 6bb390d793..fb601c4307 100644
--- a/src/nvim/eval/typval.c
+++ b/src/nvim/eval/typval.c
@@ -43,7 +43,7 @@
static char e_string_required_for_argument_nr[]
= N_("E1174: String required for argument %d");
static char e_non_empty_string_required_for_argument_nr[]
- = N_("E1142: Non-empty string required for argument %d");
+ = N_("E1175: Non-empty string required for argument %d");
static char e_number_required_for_argument_nr[]
= N_("E1210: Number required for argument %d");
@@ -1094,7 +1094,9 @@ static int item_compare2(const void *s1, const void *s2, bool keep_zero)
tv_clear(&argv[1]);
if (res == FAIL) {
+ // XXX: ITEM_COMPARE_FAIL is unused
res = ITEM_COMPARE_FAIL;
+ sortinfo->item_compare_func_err = true;
} else {
res = (int)tv_get_number_chk(&rettv, &sortinfo->item_compare_func_err);
if (res > 0) {
@@ -1257,7 +1259,7 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort)
} else {
li = TV_LIST_ITEM_NEXT(l, li);
}
- if (info.item_compare_func_err) { // -V547
+ if (info.item_compare_func_err) {
emsg(_("E882: Uniq compare function failed"));
break;
}
@@ -2488,10 +2490,14 @@ bool tv_dict_equal(dict_T *const d1, dict_T *const d2, const bool ic, const bool
if (d1 == d2) {
return true;
}
- if (d1 == NULL || d2 == NULL) {
+ if (tv_dict_len(d1) != tv_dict_len(d2)) {
return false;
}
- if (tv_dict_len(d1) != tv_dict_len(d2)) {
+ if (tv_dict_len(d1) == 0) {
+ // empty and NULL dicts are considered equal
+ return true;
+ }
+ if (d1 == NULL || d2 == NULL) {
return false;
}
diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c
index 4a62b4bf8d..147beb78ad 100644
--- a/src/nvim/eval/userfunc.c
+++ b/src/nvim/eval/userfunc.c
@@ -48,6 +48,8 @@ static char *e_funcexts = N_("E122: Function %s already exists, add ! to replace
static char *e_funcdict = N_("E717: Dictionary entry already exists");
static char *e_funcref = N_("E718: Funcref required");
static char *e_nofunc = N_("E130: Unknown function: %s");
+static char e_no_white_space_allowed_before_str_str[]
+ = N_("E1068: No white space allowed before '%s': %s");
void func_init(void)
{
@@ -149,6 +151,15 @@ static int get_function_args(char **argp, char_u endchar, garray_T *newargs, int
emsg(_("E989: Non-default argument follows default argument"));
mustend = true;
}
+
+ if (ascii_iswhite(*p) && *skipwhite(p) == ',') {
+ // Be tolerant when skipping
+ if (!skip) {
+ semsg(_(e_no_white_space_allowed_before_str_str), ",", p);
+ goto err_ret;
+ }
+ p = skipwhite(p);
+ }
if (*p == ',') {
p++;
} else {
@@ -1335,10 +1346,10 @@ void free_all_functions(void)
/// @param[in] len length of "name", or -1 for NUL terminated.
///
/// @return true if "name" looks like a builtin function name: starts with a
-/// lower case letter and doesn't contain AUTOLOAD_CHAR.
+/// lower case letter and doesn't contain AUTOLOAD_CHAR or ':'.
static bool builtin_function(const char *name, int len)
{
- if (!ASCII_ISLOWER(name[0])) {
+ if (!ASCII_ISLOWER(name[0]) || name[1] == ':') {
return false;
}
@@ -2693,6 +2704,13 @@ void ex_delfunction(exarg_T *eap)
*p = NUL;
}
+ if (isdigit(*name) && fudi.fd_dict == NULL) {
+ if (!eap->skip) {
+ semsg(_(e_invarg2), eap->arg);
+ }
+ xfree(name);
+ return;
+ }
if (!eap->skip) {
fp = find_func(name);
}
diff --git a/src/nvim/generators/gen_options.lua b/src/nvim/generators/gen_options.lua
index 6dba6552b3..4e4dd83367 100644
--- a/src/nvim/generators/gen_options.lua
+++ b/src/nvim/generators/gen_options.lua
@@ -30,6 +30,7 @@ local type_flags={
local redraw_flags={
statuslines='P_RSTAT',
+ tabline = 'P_RTABL',
current_window='P_RWIN',
current_window_only='P_RWINONLY',
current_buffer='P_RBUF',
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 5a38585bb1..f6fbd6ffe9 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -997,8 +997,6 @@ EXTERN char e_luv_api_disabled[] INIT(= N_("E5560: %s must not be called in a lu
EXTERN char e_floatonly[] INIT(= N_("E5601: Cannot close window, only floating window would remain"));
EXTERN char e_floatexchange[] INIT(= N_("E5602: Cannot exchange or rotate float"));
-EXTERN char e_non_empty_string_required[] INIT(= N_("E1142: Non-empty string required"));
-
EXTERN char e_cannot_define_autocommands_for_all_events[] INIT(= N_("E1155: Cannot define autocommands for ALL events"));
EXTERN char e_resulting_text_too_long[] INIT(= N_("E1240: Resulting text too long"));
diff --git a/src/nvim/memline.c b/src/nvim/memline.c
index da31235e74..225e2aeab1 100644
--- a/src/nvim/memline.c
+++ b/src/nvim/memline.c
@@ -169,7 +169,7 @@ struct block0 {
char_u b0_fname[B0_FNAME_SIZE_ORG]; // name of file being edited
long b0_magic_long; // check for byte order of long
int b0_magic_int; // check for byte order of int
- short b0_magic_short; // check for byte order of short
+ int16_t b0_magic_short; // check for byte order of short
char_u b0_magic_char; // check for last char
};
@@ -272,7 +272,7 @@ int ml_open(buf_T *buf)
b0p->b0_id[1] = BLOCK0_ID1;
b0p->b0_magic_long = B0_MAGIC_LONG;
b0p->b0_magic_int = (int)B0_MAGIC_INT;
- b0p->b0_magic_short = (short)B0_MAGIC_SHORT;
+ b0p->b0_magic_short = (int16_t)B0_MAGIC_SHORT;
b0p->b0_magic_char = B0_MAGIC_CHAR;
xstrlcpy(xstpcpy((char *)b0p->b0_version, "VIM "), Version, 6);
long_to_char((long)mfp->mf_page_size, b0p->b0_page_size);
@@ -3376,7 +3376,7 @@ static int b0_magic_wrong(ZERO_BL *b0p)
{
return b0p->b0_magic_long != B0_MAGIC_LONG
|| b0p->b0_magic_int != (int)B0_MAGIC_INT
- || b0p->b0_magic_short != (short)B0_MAGIC_SHORT
+ || b0p->b0_magic_short != (int16_t)B0_MAGIC_SHORT
|| b0p->b0_magic_char != B0_MAGIC_CHAR;
}
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 1a6cd0c1af..06662afd08 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -2648,6 +2648,10 @@ void check_redraw(uint32_t flags)
status_redraw_all();
}
+ if ((flags & P_RTABL) || all) { // mark tablines dirty
+ redraw_tabline = true;
+ }
+
if ((flags & P_RBUF) || (flags & P_RWIN) || all) {
changed_window_setting();
}
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index c4333a6f61..19e4780e0a 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -24,6 +24,7 @@
#define P_NO_MKRC 0x200U ///< don't include in :mkvimrc output
// when option changed, what to display:
+#define P_RTABL 0x800U ///< redraw tabline
#define P_RSTAT 0x1000U ///< redraw status lines
#define P_RWIN 0x2000U ///< redraw current window and recompute text
#define P_RBUF 0x4000U ///< redraw current buffer and recompute text
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index 8a883a09c3..ba483d3714 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -19,7 +19,7 @@
-- types: bool, number, string
-- lists: (nil), comma, onecomma, flags, flagscomma
-- scopes: global, buffer, window
--- redraw options: statuslines, current_window, curent_window_only,
+-- redraw options: statuslines, tabline, current_window, curent_window_only,
-- current_buffer, all_windows, curswant
-- defaults: {condition=#if condition, if_true=default, if_false=default}
-- #if condition:
@@ -2407,7 +2407,7 @@ return {
short_desc=N_("custom format for the console tab pages line"),
type='string', scope={'global'},
modelineexpr=true,
- redraw={'statuslines'},
+ redraw={'tabline'},
varname='p_tal',
defaults={if_true=""}
},
diff --git a/src/nvim/po/CMakeLists.txt b/src/nvim/po/CMakeLists.txt
index 57896b74ce..74d9901bad 100644
--- a/src/nvim/po/CMakeLists.txt
+++ b/src/nvim/po/CMakeLists.txt
@@ -49,7 +49,8 @@ if(HAVE_WORKING_LIBINTL AND GETTEXT_FOUND AND XGETTEXT_PRG AND ICONV_PRG)
add_custom_command(
OUTPUT ${NVIM_POT}
COMMAND ${XGETTEXT_PRG} -o ${NVIM_POT} --default-domain=nvim
- --add-comments --keyword=_ --keyword=N_ -D ${CMAKE_CURRENT_SOURCE_DIR}
+ --add-comments --keyword=_ --keyword=N_ --keyword=NGETTEXT:1,2
+ -D ${CMAKE_CURRENT_SOURCE_DIR}
${NVIM_RELATIVE_SOURCES}
DEPENDS ${NVIM_SOURCES})
diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c
index e87382ff7c..6bd15fdbbe 100644
--- a/src/nvim/regexp.c
+++ b/src/nvim/regexp.c
@@ -240,7 +240,7 @@ static int get_char_class(char **pp)
* Specific version of character class functions.
* Using a table to keep this fast.
*/
-static short class_tab[256];
+static int16_t class_tab[256];
#define RI_DIGIT 0x01
#define RI_HEX 0x02
diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c
index 793985f45d..d5fbbaff1f 100644
--- a/src/nvim/spellfile.c
+++ b/src/nvim/spellfile.c
@@ -415,7 +415,7 @@ struct wordnode_S {
// "wn_region" the LSW of the wordnr.
char_u wn_affixID; // supported/required prefix ID or 0
uint16_t wn_flags; // WF_ flags
- short wn_region; // region mask
+ int16_t wn_region; // region mask
#ifdef SPELL_PRINTTREE
int wn_nr; // sequence nr for printing
diff --git a/src/nvim/spellsuggest.c b/src/nvim/spellsuggest.c
index fbe2ec837b..400579a233 100644
--- a/src/nvim/spellsuggest.c
+++ b/src/nvim/spellsuggest.c
@@ -2250,7 +2250,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
ftp = (fromto_T *)gap->ga_data + sp->ts_curi++;
if (*ftp->ft_from != *p) {
// past possible matching entries
- sp->ts_curi = (char_u)gap->ga_len;
+ sp->ts_curi = (int16_t)gap->ga_len;
break;
}
if (STRNCMP(ftp->ft_from, p, STRLEN(ftp->ft_from)) == 0
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index 8c0c2e8f57..90b21320d2 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -3289,10 +3289,12 @@ int set_tagstack(win_T *wp, const dict_T *d, int action)
if ((di = tv_dict_find(d, "curidx", -1)) != NULL) {
tagstack_set_curidx(wp, (int)tv_get_number(&di->di_tv) - 1);
}
+
if (action == 't') { // truncate the stack
taggy_T *const tagstack = wp->w_tagstack;
const int tagstackidx = wp->w_tagstackidx;
int tagstacklen = wp->w_tagstacklen;
+
// delete all the tag stack entries above the current entry
while (tagstackidx < tagstacklen) {
tagstack_clear_entry(&tagstack[--tagstacklen]);
diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile
index 4641408069..a6d1cf1003 100644
--- a/src/nvim/testdir/Makefile
+++ b/src/nvim/testdir/Makefile
@@ -179,4 +179,4 @@ newtestssilent: $(NEW_TESTS_RES)
@echo "[OLDTEST] Running" $*
@rm -rf $*.failed test.ok $(RM_ON_RUN)
@mkdir -p $(TMPDIR)
- @/bin/sh runnvim.sh $(ROOT) $(NVIM_PRG) $* $(RUN_VIMTEST) $(NO_INITS) -u NONE -S runtest.vim $*.vim
+ @/bin/sh runnvim.sh $(ROOT) $(NVIM_PRG) $* $(RUN_VIMTEST) $(NO_INITS) -u NONE --cmd "set shortmess-=F" -S runtest.vim $*.vim
diff --git a/src/nvim/testdir/check.vim b/src/nvim/testdir/check.vim
index 4107df99d6..92a51d4371 100644
--- a/src/nvim/testdir/check.vim
+++ b/src/nvim/testdir/check.vim
@@ -39,6 +39,22 @@ func CheckFunction(name)
endif
endfunc
+" Command to check for the presence of an Ex command
+command -nargs=1 CheckCommand call CheckCommand(<f-args>)
+func CheckCommand(name)
+ if !exists(':' .. a:name)
+ throw 'Skipped: ' .. a:name .. ' command not supported'
+ endif
+endfunc
+
+" Command to check for the presence of a shell command
+command -nargs=1 CheckExecutable call CheckExecutable(<f-args>)
+func CheckExecutable(name)
+ if !executable(a:name)
+ throw 'Skipped: ' .. a:name .. ' program not executable'
+ endif
+endfunc
+
" Command to check for the presence of python. Argument should have been
" obtained with PythonProg()
func CheckPython(name)
diff --git a/src/nvim/testdir/test_blob.vim b/src/nvim/testdir/test_blob.vim
index 70529c14d5..770b2d16ef 100644
--- a/src/nvim/testdir/test_blob.vim
+++ b/src/nvim/testdir/test_blob.vim
@@ -88,6 +88,7 @@ func Test_blob_get_range()
call assert_equal(0z0011223344, b[:])
call assert_equal(0z0011223344, b[:-1])
call assert_equal(0z, b[5:6])
+ call assert_equal(0z0011, b[-10:1])
endfunc
func Test_blob_get()
@@ -208,6 +209,7 @@ func Test_blob_add()
call assert_equal(0z001122, b)
call add(b, '51')
call assert_equal(0z00112233, b)
+ call assert_equal(1, add(v:_null_blob, 0x22))
call assert_fails('call add(b, [9])', 'E745:')
call assert_fails('call add("", 0x01)', 'E897:')
@@ -272,6 +274,7 @@ endfunc
" filter() item in blob
func Test_blob_filter()
+ call assert_equal(v:_null_blob, filter(v:_null_blob, '0'))
call assert_equal(0z, filter(0zDEADBEEF, '0'))
call assert_equal(0zADBEEF, filter(0zDEADBEEF, 'v:val != 0xDE'))
call assert_equal(0zDEADEF, filter(0zDEADBEEF, 'v:val != 0xBE'))
@@ -313,6 +316,9 @@ func Test_blob_insert()
call assert_fails('call insert(b, -1)', 'E475:')
call assert_fails('call insert(b, 257)', 'E475:')
call assert_fails('call insert(b, 0, [9])', 'E745:')
+ call assert_fails('call insert(b, 0, -20)', 'E475:')
+ call assert_fails('call insert(b, 0, 20)', 'E475:')
+ call assert_fails('call insert(b, [])', 'E745:')
call assert_equal(0, insert(v:_null_blob, 0x33))
" Translated from v8.2.3284
diff --git a/src/nvim/testdir/test_breakindent.vim b/src/nvim/testdir/test_breakindent.vim
index a37751e748..ed4d886fd1 100644
--- a/src/nvim/testdir/test_breakindent.vim
+++ b/src/nvim/testdir/test_breakindent.vim
@@ -4,9 +4,8 @@
" while the test is run, the breakindent caching gets in its way.
" It helps to change the tabstop setting and force a redraw (e.g. see
" Test_breakindent08())
-if !exists('+breakindent')
- throw 'Skipped: breakindent option not supported'
-endif
+source check.vim
+CheckOption breakindent
source view_util.vim
diff --git a/src/nvim/testdir/test_bufline.vim b/src/nvim/testdir/test_bufline.vim
index 3b5bcbce89..8f853fe44e 100644
--- a/src/nvim/testdir/test_bufline.vim
+++ b/src/nvim/testdir/test_bufline.vim
@@ -2,6 +2,7 @@
source shared.vim
source screendump.vim
+source check.vim
func Test_setbufline_getbufline()
new
@@ -130,9 +131,8 @@ func Test_deletebufline()
endfunc
func Test_appendbufline_redraw()
- if !CanRunVimInTerminal()
- throw 'Skipped: cannot make screendumps'
- endif
+ CheckScreendump
+
let lines =<< trim END
new foo
let winnr = 'foo'->bufwinnr()
diff --git a/src/nvim/testdir/test_clientserver.vim b/src/nvim/testdir/test_clientserver.vim
index a4ebce5af9..943f79d98f 100644
--- a/src/nvim/testdir/test_clientserver.vim
+++ b/src/nvim/testdir/test_clientserver.vim
@@ -147,7 +147,7 @@ func Test_client_server()
" Edit files in separate tab pages
call system(cmd .. ' --remote-tab Xfile1 Xfile2 Xfile3')
- call assert_equal('3', remote_expr(name, 'tabpagenr("$")'))
+ call WaitForAssert({-> assert_equal('3', remote_expr(name, 'tabpagenr("$")'))})
call assert_equal('Xfile2', remote_expr(name, 'bufname(tabpagebuflist(2)[0])'))
eval name->remote_send(":%bw!\<CR>")
diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim
index f37e8be59a..00bfadec93 100644
--- a/src/nvim/testdir/test_cmdline.vim
+++ b/src/nvim/testdir/test_cmdline.vim
@@ -854,7 +854,7 @@ func Test_cmdline_complete_bang()
endif
endfunc
-funct Test_cmdline_complete_languages()
+func Test_cmdline_complete_languages()
let lang = substitute(execute('language time'), '.*"\(.*\)"$', '\1', '')
call assert_equal(lang, v:lc_time)
@@ -891,10 +891,8 @@ endfunc
func Test_cmdline_complete_env_variable()
let $X_VIM_TEST_COMPLETE_ENV = 'foo'
-
call feedkeys(":edit $X_VIM_TEST_COMPLETE_E\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_match('"edit $X_VIM_TEST_COMPLETE_ENV', @:)
-
unlet $X_VIM_TEST_COMPLETE_ENV
endfunc
@@ -1074,9 +1072,25 @@ func Test_cmdline_complete_various()
call feedkeys(":e `a1b2c\t\<C-B>\"\<CR>", 'xt')
call assert_equal('"e `a1b2c', @:)
- " completion for the expression register
- call feedkeys(":\"\<C-R>=float2\t\"\<C-B>\"\<CR>", 'xt')
- call assert_equal('"float2nr("', @=)
+ " completion for :language command with an invalid argument
+ call feedkeys(":language dummy \t\<C-B>\"\<CR>", 'xt')
+ call assert_equal("\"language dummy \t", @:)
+
+ " completion for commands after a :global command
+ call feedkeys(":g/a\\xb/clearj\t\<C-B>\"\<CR>", 'xt')
+ call assert_equal('"g/a\xb/clearjumps', @:)
+
+ " completion with ambiguous user defined commands
+ com TCmd1 echo 'TCmd1'
+ com TCmd2 echo 'TCmd2'
+ call feedkeys(":TCmd \t\<C-B>\"\<CR>", 'xt')
+ call assert_equal('"TCmd ', @:)
+ delcom TCmd1
+ delcom TCmd2
+
+ " completion after a range followed by a pipe (|) character
+ call feedkeys(":1,10 | chist\t\<C-B>\"\<CR>", 'xt')
+ call assert_equal('"1,10 | chistory', @:)
endfunc
func Test_cmdline_write_alternatefile()
@@ -1682,16 +1696,16 @@ func Test_wildmode()
" Test for wildmode=longest with 'fileignorecase' set
set wildmode=longest
set fileignorecase
- argadd AA AAA AAAA
- call feedkeys(":buffer \t\<C-B>\"\<CR>", 'xt')
- call assert_equal('"buffer AA', @:)
+ argadd AAA AAAA AAAAA
+ call feedkeys(":buffer a\t\<C-B>\"\<CR>", 'xt')
+ call assert_equal('"buffer AAA', @:)
set fileignorecase&
" Test for listing files with wildmode=list
set wildmode=list
let g:Sline = ''
call feedkeys(":b A\t\t\<F2>\<C-B>\"\<CR>", 'xt')
- call assert_equal('AA AAA AAAA', g:Sline)
+ call assert_equal('AAA AAAA AAAAA', g:Sline)
call assert_equal('"b A', @:)
%argdelete
diff --git a/src/nvim/testdir/test_const.vim b/src/nvim/testdir/test_const.vim
index 0d064617a5..7f19085b16 100644
--- a/src/nvim/testdir/test_const.vim
+++ b/src/nvim/testdir/test_const.vim
@@ -231,6 +231,14 @@ func Test_const_with_special_variables()
call assert_fails('const &filetype = "vim"', 'E996:')
call assert_fails('const &l:filetype = "vim"', 'E996:')
call assert_fails('const &g:encoding = "utf-8"', 'E996:')
+
+ call assert_fails('const [a, $CONST_FOO] = [369, "abc"]', 'E996:')
+ call assert_equal(369, a)
+ call assert_equal(v:null, getenv("CONST_FOO"))
+
+ call assert_fails('const [b; $CONST_FOO] = [246, 2, "abc"]', 'E996:')
+ call assert_equal(246, b)
+ call assert_equal(v:null, getenv("CONST_FOO"))
endfunc
func Test_const_with_eval_name()
@@ -274,3 +282,5 @@ func Test_lock_depth_is_2()
const d2 = #{a: 0, b: lvar, c: 4}
let d2.b[1] = 'd'
endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_diffmode.vim b/src/nvim/testdir/test_diffmode.vim
index 1cb71664bd..831efdbfc2 100644
--- a/src/nvim/testdir/test_diffmode.vim
+++ b/src/nvim/testdir/test_diffmode.vim
@@ -1198,6 +1198,33 @@ func Test_diff_maintains_change_mark()
delfunc DiffMaintainsChangeMark
endfunc
+" Test for 'patchexpr'
+func Test_patchexpr()
+ let g:patch_args = []
+ func TPatch()
+ call add(g:patch_args, readfile(v:fname_in))
+ call add(g:patch_args, readfile(v:fname_diff))
+ call writefile(['output file'], v:fname_out)
+ endfunc
+ set patchexpr=TPatch()
+
+ call writefile(['input file'], 'Xinput')
+ call writefile(['diff file'], 'Xdiff')
+ %bwipe!
+ edit Xinput
+ diffpatch Xdiff
+ call assert_equal('output file', getline(1))
+ call assert_equal('Xinput.new', bufname())
+ call assert_equal(2, winnr('$'))
+ call assert_true(&diff)
+
+ call delete('Xinput')
+ call delete('Xdiff')
+ set patchexpr&
+ delfunc TPatch
+ %bwipe!
+endfunc
+
func Test_diff_rnu()
CheckScreendump
diff --git a/src/nvim/testdir/test_eval_stuff.vim b/src/nvim/testdir/test_eval_stuff.vim
index dc110af356..851048ec5b 100644
--- a/src/nvim/testdir/test_eval_stuff.vim
+++ b/src/nvim/testdir/test_eval_stuff.vim
@@ -120,6 +120,13 @@ func Test_readfile_binary()
call delete('XReadfile_bin')
endfunc
+func Test_readfile_binary_empty()
+ call writefile([], 'Xempty-file')
+ " This used to compare uninitialized memory in Vim <= 8.2.4065
+ call assert_equal([''], readfile('Xempty-file', 'b'))
+ call delete('Xempty-file')
+endfunc
+
func Test_readfile_bom()
call writefile(["\ufeffFOO", "FOO\ufeffBAR"], 'XReadfile_bom')
call assert_equal(['FOO', 'FOOBAR'], readfile('XReadfile_bom'))
@@ -360,6 +367,11 @@ func Test_curly_assignment()
unlet g:gvar
endfunc
+func Test_deep_recursion()
+ " this was running out of stack
+ call assert_fails("exe 'if ' .. repeat('(', 1002)", 'E1169: Expression too recursive: ((')
+endfunc
+
" K_SPECIAL in the modified character used be escaped, which causes
" double-escaping with feedkeys() or as the return value of an <expr> mapping,
" and doesn't match what getchar() returns,
diff --git a/src/nvim/testdir/test_excmd.vim b/src/nvim/testdir/test_excmd.vim
index 7692d4fc55..04ab8e288f 100644
--- a/src/nvim/testdir/test_excmd.vim
+++ b/src/nvim/testdir/test_excmd.vim
@@ -479,12 +479,21 @@ endfunc
func Test_redir_cmd()
call assert_fails('redir @@', 'E475:')
call assert_fails('redir abc', 'E475:')
+ call assert_fails('redir => 1abc', 'E474:')
+ call assert_fails('redir => a b', 'E488:')
+ call assert_fails('redir => abc[1]', 'E475:')
+ let b=0zFF
+ call assert_fails('redir =>> b', 'E734:')
+ unlet b
+
if has('unix')
+ " Redirecting to a directory name
call mkdir('Xdir')
call assert_fails('redir > Xdir', 'E17:')
call delete('Xdir', 'd')
endif
if !has('bsd')
+ " Redirecting to a read-only file
call writefile([], 'Xfile')
call setfperm('Xfile', 'r--r--r--')
call assert_fails('redir! > Xfile', 'E190:')
@@ -674,6 +683,12 @@ func Test_sandbox()
sandbox call Sandbox_tests()
endfunc
+func Test_command_not_implemented_E319()
+ if !has('mzscheme')
+ call assert_fails('mzscheme', 'E319:')
+ endif
+endfunc
+
func Test_not_break_expression_register()
call setreg('=', '1+1')
if 0
diff --git a/src/nvim/testdir/test_expr.vim b/src/nvim/testdir/test_expr.vim
index c63a969e50..66660ab75e 100644
--- a/src/nvim/testdir/test_expr.vim
+++ b/src/nvim/testdir/test_expr.vim
@@ -46,6 +46,7 @@ func Test_dict()
call assert_equal('zero', d[0])
call assert_true(has_key(d, ''))
call assert_true(has_key(d, 'a'))
+ call assert_fails("let i = has_key([], 'a')", 'E715:')
let d[''] = 'none'
let d['a'] = 'aaa'
@@ -98,13 +99,6 @@ func Test_loop_over_null_list()
endfor
endfunc
-func Test_compare_null_dict()
- call assert_fails('let x = v:_null_dict[10]')
- call assert_equal({}, {})
- call assert_equal(v:_null_dict, v:_null_dict)
- call assert_notequal({}, v:_null_dict)
-endfunc
-
func Test_set_reg_null_list()
call setreg('x', v:_null_list)
endfunc
diff --git a/src/nvim/testdir/test_filter_map.vim b/src/nvim/testdir/test_filter_map.vim
index 1cd3a2287b..c75177ea39 100644
--- a/src/nvim/testdir/test_filter_map.vim
+++ b/src/nvim/testdir/test_filter_map.vim
@@ -86,6 +86,13 @@ func Test_map_filter_fails()
call assert_fails('call filter([1], "42 +")', 'E15:')
call assert_fails("let l = map('abc', '\"> \" . v:val')", 'E896:')
call assert_fails("let l = filter('abc', '\"> \" . v:val')", 'E896:')
+ call assert_fails("let l = filter([1, 2, 3], '{}')", 'E728:')
+ call assert_fails("let l = filter({'k' : 10}, '{}')", 'E728:')
+ call assert_fails("let l = filter([1, 2], {})", 'E731:')
+ call assert_equal(v:_null_list, filter(v:_null_list, 0))
+ call assert_equal(v:_null_dict, filter(v:_null_dict, 0))
+ call assert_equal(v:_null_list, map(v:_null_list, '"> " .. v:val'))
+ call assert_equal(v:_null_dict, map(v:_null_dict, '"> " .. v:val'))
endfunc
func Test_map_and_modify()
diff --git a/src/nvim/testdir/test_fold.vim b/src/nvim/testdir/test_fold.vim
index 327f0f73f2..0a9be310ff 100644
--- a/src/nvim/testdir/test_fold.vim
+++ b/src/nvim/testdir/test_fold.vim
@@ -1,5 +1,6 @@
" Test for folding
+source check.vim
source view_util.vim
source screendump.vim
@@ -727,9 +728,7 @@ func Test_fold_last_line_with_pagedown()
endfunc
func Test_folds_with_rnu()
- if !CanRunVimInTerminal()
- throw 'Skipped: cannot make screendumps'
- endif
+ CheckScreendump
call writefile([
\ 'set fdm=marker rnu foldcolumn=2',
diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim
index 7ad0cb5884..fa79aaf6d7 100644
--- a/src/nvim/testdir/test_functions.vim
+++ b/src/nvim/testdir/test_functions.vim
@@ -67,9 +67,11 @@ func Test_len()
call assert_equal(2, len('ab'))
call assert_equal(0, len([]))
+ call assert_equal(0, len(v:_null_list))
call assert_equal(2, len([2, 1]))
call assert_equal(0, len({}))
+ call assert_equal(0, len(v:_null_dict))
call assert_equal(2, len({'a': 1, 'b': 2}))
" call assert_fails('call len(v:none)', 'E701:')
@@ -771,6 +773,9 @@ func Test_append()
split
only
undo
+
+ " Using $ instead of '$' must give an error
+ call assert_fails("call append($, 'foobar')", 'E116:')
endfunc
func Test_getbufvar()
@@ -804,6 +809,10 @@ func Test_getbufvar()
call assert_equal(0, getbufvar(bnr, '&autoindent'))
call assert_equal(0, getbufvar(bnr, '&autoindent', 1))
+ " Set and get a buffer-local variable
+ call setbufvar(bnr, 'bufvar_test', ['one', 'two'])
+ call assert_equal(['one', 'two'], getbufvar(bnr, 'bufvar_test'))
+
" Open new window with forced option values
set fileformats=unix,dos
new ++ff=dos ++bin ++enc=iso-8859-2
@@ -1009,7 +1018,9 @@ func Test_charidx()
call assert_equal(2, charidx(a, 4))
call assert_equal(3, charidx(a, 7))
call assert_equal(-1, charidx(a, 8))
+ call assert_equal(-1, charidx(a, -1))
call assert_equal(-1, charidx('', 0))
+ call assert_equal(-1, charidx(v:_null_string, 0))
" count composing characters
call assert_equal(0, charidx(a, 0, 1))
@@ -1195,6 +1206,7 @@ func Test_col()
norm gg4|mx6|mY2|
call assert_equal(2, col('.'))
call assert_equal(7, col('$'))
+ call assert_equal(2, col('v'))
call assert_equal(4, col("'x"))
call assert_equal(6, col("'Y"))
call assert_equal(2, [1, 2]->col())
@@ -1205,6 +1217,19 @@ func Test_col()
call assert_equal(0, col([2, '$']))
call assert_equal(0, col([1, 100]))
call assert_equal(0, col([1]))
+
+ " test for getting the visual start column
+ func T()
+ let g:Vcol = col('v')
+ return ''
+ endfunc
+ let g:Vcol = 0
+ xmap <expr> <F2> T()
+ exe "normal gg3|ve\<F2>"
+ call assert_equal(3, g:Vcol)
+ xunmap <F2>
+ delfunc T
+
bw!
endfunc
@@ -1302,6 +1327,9 @@ func Test_balloon_show()
" This won't do anything but must not crash either.
call balloon_show('hi!')
+ if !has('gui_running')
+ call balloon_show(range(3))
+ endif
endfunc
func Test_shellescape()
@@ -1633,6 +1661,10 @@ func Test_func_sandbox()
call assert_fails('call Fsandbox()', 'E48:')
delfunc Fsandbox
+
+ " From a sandbox try to set a predefined variable (which cannot be modified
+ " from a sandbox)
+ call assert_fails('sandbox let v:lnum = 10', 'E794:')
endfunc
func EditAnotherFile()
@@ -1715,9 +1747,8 @@ endfunc
func Test_confirm()
" requires a UI to be active
throw 'Skipped: use test/functional/vimscript/input_spec.lua'
- if !has('unix') || has('gui_running')
- return
- endif
+ CheckUnix
+ CheckNotGui
call feedkeys('o', 'L')
let a = confirm('Press O to proceed')
@@ -1834,6 +1865,7 @@ func Test_call()
let mydict = {'data': [0, 1, 2, 3], 'len': function("Mylen")}
eval mydict.len->call([], mydict)->assert_equal(4)
call assert_fails("call call('Mylen', [], 0)", 'E715:')
+ call assert_fails('call foo', 'E107:')
endfunc
func Test_char2nr()
@@ -1915,6 +1947,271 @@ func Test_bufadd_bufload()
call delete('XotherName')
endfunc
+func Test_range()
+ " destructuring
+ let [x, y] = range(2)
+ call assert_equal([0, 1], [x, y])
+
+ " index
+ call assert_equal(4, range(1, 10)[3])
+
+ " add()
+ call assert_equal([0, 1, 2, 3], add(range(3), 3))
+ call assert_equal([0, 1, 2, [0, 1, 2]], add([0, 1, 2], range(3)))
+ call assert_equal([0, 1, 2, [0, 1, 2]], add(range(3), range(3)))
+
+ " append()
+ new
+ call append('.', range(5))
+ call assert_equal(['', '0', '1', '2', '3', '4'], getline(1, '$'))
+ bwipe!
+
+ " appendbufline()
+ new
+ call appendbufline(bufnr(''), '.', range(5))
+ call assert_equal(['0', '1', '2', '3', '4', ''], getline(1, '$'))
+ bwipe!
+
+ " call()
+ func TwoArgs(a, b)
+ return [a:a, a:b]
+ endfunc
+ call assert_equal([0, 1], call('TwoArgs', range(2)))
+
+ " col()
+ new
+ call setline(1, ['foo', 'bar'])
+ call assert_equal(2, col(range(1, 2)))
+ bwipe!
+
+ " complete()
+ execute "normal! a\<C-r>=[complete(col('.'), range(10)), ''][1]\<CR>"
+ " complete_info()
+ execute "normal! a\<C-r>=[complete(col('.'), range(10)), ''][1]\<CR>\<C-r>=[complete_info(range(5)), ''][1]\<CR>"
+
+ " copy()
+ call assert_equal([1, 2, 3], copy(range(1, 3)))
+
+ " count()
+ call assert_equal(0, count(range(0), 3))
+ call assert_equal(0, count(range(2), 3))
+ call assert_equal(1, count(range(5), 3))
+
+ " cursor()
+ new
+ call setline(1, ['aaa', 'bbb', 'ccc'])
+ call cursor(range(1, 2))
+ call assert_equal([2, 1], [col('.'), line('.')])
+ bwipe!
+
+ " deepcopy()
+ call assert_equal([1, 2, 3], deepcopy(range(1, 3)))
+
+ " empty()
+ call assert_true(empty(range(0)))
+ call assert_false(empty(range(2)))
+
+ " execute()
+ new
+ call setline(1, ['aaa', 'bbb', 'ccc'])
+ call execute(range(3))
+ call assert_equal(2, line('.'))
+ bwipe!
+
+ " extend()
+ call assert_equal([1, 2, 3, 4], extend([1], range(2, 4)))
+ call assert_equal([1, 2, 3, 4], extend(range(1, 1), range(2, 4)))
+ call assert_equal([1, 2, 3, 4], extend(range(1, 1), [2, 3, 4]))
+
+ " filter()
+ call assert_equal([1, 3], filter(range(5), 'v:val % 2'))
+
+ " funcref()
+ call assert_equal([0, 1], funcref('TwoArgs', range(2))())
+
+ " function()
+ call assert_equal([0, 1], function('TwoArgs', range(2))())
+
+ " garbagecollect()
+ let thelist = [1, range(2), 3]
+ let otherlist = range(3)
+ call test_garbagecollect_now()
+
+ " get()
+ call assert_equal(4, get(range(1, 10), 3))
+ call assert_equal(-1, get(range(1, 10), 42, -1))
+
+ " index()
+ call assert_equal(1, index(range(1, 5), 2))
+
+ " inputlist()
+ call feedkeys(":let result = inputlist(range(10))\<CR>1\<CR>", 'x')
+ call assert_equal(1, result)
+ call feedkeys(":let result = inputlist(range(3, 10))\<CR>1\<CR>", 'x')
+ call assert_equal(1, result)
+
+ " insert()
+ call assert_equal([42, 1, 2, 3, 4, 5], insert(range(1, 5), 42))
+ call assert_equal([42, 1, 2, 3, 4, 5], insert(range(1, 5), 42, 0))
+ call assert_equal([1, 42, 2, 3, 4, 5], insert(range(1, 5), 42, 1))
+ call assert_equal([1, 2, 3, 4, 42, 5], insert(range(1, 5), 42, 4))
+ call assert_equal([1, 2, 3, 4, 42, 5], insert(range(1, 5), 42, -1))
+ call assert_equal([1, 2, 3, 4, 5, 42], insert(range(1, 5), 42, 5))
+
+ " join()
+ call assert_equal('0 1 2 3 4', join(range(5)))
+
+ " json_encode()
+ " call assert_equal('[0,1,2,3]', json_encode(range(4)))
+ call assert_equal('[0, 1, 2, 3]', json_encode(range(4)))
+
+ " len()
+ call assert_equal(0, len(range(0)))
+ call assert_equal(2, len(range(2)))
+ call assert_equal(5, len(range(0, 12, 3)))
+ call assert_equal(4, len(range(3, 0, -1)))
+
+ " list2str()
+ call assert_equal('ABC', list2str(range(65, 67)))
+ call assert_fails('let s = list2str(5)', 'E474:')
+
+ " lock()
+ let thelist = range(5)
+ lockvar thelist
+
+ " map()
+ call assert_equal([0, 2, 4, 6, 8], map(range(5), 'v:val * 2'))
+
+ " match()
+ call assert_equal(3, match(range(5), 3))
+
+ " matchaddpos()
+ highlight MyGreenGroup ctermbg=green guibg=green
+ call matchaddpos('MyGreenGroup', range(line('.'), line('.')))
+
+ " matchend()
+ call assert_equal(4, matchend(range(5), '4'))
+ call assert_equal(3, matchend(range(1, 5), '4'))
+ call assert_equal(-1, matchend(range(1, 5), '42'))
+
+ " matchstrpos()
+ call assert_equal(['4', 4, 0, 1], matchstrpos(range(5), '4'))
+ call assert_equal(['4', 3, 0, 1], matchstrpos(range(1, 5), '4'))
+ call assert_equal(['', -1, -1, -1], matchstrpos(range(1, 5), '42'))
+
+ " max() reverse()
+ call assert_equal(0, max(range(0)))
+ call assert_equal(0, max(range(10, 9)))
+ call assert_equal(9, max(range(10)))
+ call assert_equal(18, max(range(0, 20, 3)))
+ call assert_equal(20, max(range(20, 0, -3)))
+ call assert_equal(99999, max(range(100000)))
+ call assert_equal(99999, max(range(99999, 0, -1)))
+ call assert_equal(99999, max(reverse(range(100000))))
+ call assert_equal(99999, max(reverse(range(99999, 0, -1))))
+
+ " min() reverse()
+ call assert_equal(0, min(range(0)))
+ call assert_equal(0, min(range(10, 9)))
+ call assert_equal(5, min(range(5, 10)))
+ call assert_equal(5, min(range(5, 10, 3)))
+ call assert_equal(2, min(range(20, 0, -3)))
+ call assert_equal(0, min(range(100000)))
+ call assert_equal(0, min(range(99999, 0, -1)))
+ call assert_equal(0, min(reverse(range(100000))))
+ call assert_equal(0, min(reverse(range(99999, 0, -1))))
+
+ " remove()
+ call assert_equal(1, remove(range(1, 10), 0))
+ call assert_equal(2, remove(range(1, 10), 1))
+ call assert_equal(9, remove(range(1, 10), 8))
+ call assert_equal(10, remove(range(1, 10), 9))
+ call assert_equal(10, remove(range(1, 10), -1))
+ call assert_equal([3, 4, 5], remove(range(1, 10), 2, 4))
+
+ " repeat()
+ call assert_equal([0, 1, 2, 0, 1, 2], repeat(range(3), 2))
+ call assert_equal([0, 1, 2], repeat(range(3), 1))
+ call assert_equal([], repeat(range(3), 0))
+ call assert_equal([], repeat(range(5, 4), 2))
+ call assert_equal([], repeat(range(5, 4), 0))
+
+ " reverse()
+ call assert_equal([2, 1, 0], reverse(range(3)))
+ call assert_equal([0, 1, 2, 3], reverse(range(3, 0, -1)))
+ call assert_equal([9, 8, 7, 6, 5, 4, 3, 2, 1, 0], reverse(range(10)))
+ call assert_equal([20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10], reverse(range(10, 20)))
+ call assert_equal([16, 13, 10], reverse(range(10, 18, 3)))
+ call assert_equal([19, 16, 13, 10], reverse(range(10, 19, 3)))
+ call assert_equal([19, 16, 13, 10], reverse(range(10, 20, 3)))
+ call assert_equal([11, 14, 17, 20], reverse(range(20, 10, -3)))
+ call assert_equal([], reverse(range(0)))
+
+ " TODO: setpos()
+ " new
+ " call setline(1, repeat([''], bufnr('')))
+ " call setline(bufnr('') + 1, repeat('x', bufnr('') * 2 + 6))
+ " call setpos('x', range(bufnr(''), bufnr('') + 3))
+ " bwipe!
+
+ " setreg()
+ call setreg('a', range(3))
+ call assert_equal("0\n1\n2\n", getreg('a'))
+
+ " settagstack()
+ call settagstack(1, #{items : range(4)})
+
+ " sign_define()
+ call assert_fails("call sign_define(range(5))", "E715:")
+ call assert_fails("call sign_placelist(range(5))", "E715:")
+
+ " sign_undefine()
+ " call assert_fails("call sign_undefine(range(5))", "E908:")
+ call assert_fails("call sign_undefine(range(5))", "E155:")
+
+ " sign_unplacelist()
+ call assert_fails("call sign_unplacelist(range(5))", "E715:")
+
+ " sort()
+ call assert_equal([0, 1, 2, 3, 4, 5], sort(range(5, 0, -1)))
+
+ " string()
+ call assert_equal('[0, 1, 2, 3, 4]', string(range(5)))
+
+ " taglist() with 'tagfunc'
+ func TagFunc(pattern, flags, info)
+ return range(10)
+ endfunc
+ set tagfunc=TagFunc
+ call assert_fails("call taglist('asdf')", 'E987:')
+ set tagfunc=
+
+ " term_start()
+ if has('terminal') && has('termguicolors')
+ call assert_fails('call term_start(range(3, 4))', 'E474:')
+ let g:terminal_ansi_colors = range(16)
+ if has('win32')
+ let cmd = "cmd /c dir"
+ else
+ let cmd = "ls"
+ endif
+ call assert_fails('call term_start("' .. cmd .. '", #{term_finish: "close"})', 'E475:')
+ unlet g:terminal_ansi_colors
+ endif
+
+ " type()
+ call assert_equal(v:t_list, type(range(5)))
+
+ " uniq()
+ call assert_equal([0, 1, 2, 3, 4], uniq(range(5)))
+endfunc
+
+func Test_garbagecollect_now_fails()
+ let v:testing = 0
+ call assert_fails('call test_garbagecollect_now()', 'E1142:')
+ let v:testing = 1
+endfunc
+
" Test for the eval() function
func Test_eval()
call assert_fails("call eval('5 a')", 'E488:')
diff --git a/src/nvim/testdir/test_highlight.vim b/src/nvim/testdir/test_highlight.vim
index e84c45c635..2be82f4e3c 100644
--- a/src/nvim/testdir/test_highlight.vim
+++ b/src/nvim/testdir/test_highlight.vim
@@ -536,9 +536,7 @@ func Test_termguicolors()
endfunc
func Test_cursorline_after_yank()
- if !CanRunVimInTerminal()
- throw 'Skipped: cannot make screendumps'
- endif
+ CheckScreendump
call writefile([
\ 'set cul rnu',
@@ -578,9 +576,7 @@ func Test_put_before_cursorline()
endfunc
func Test_cursorline_with_visualmode()
- if !CanRunVimInTerminal()
- throw 'Skipped: cannot make screendumps'
- endif
+ CheckScreendump
call writefile([
\ 'set cul',
diff --git a/src/nvim/testdir/test_lambda.vim b/src/nvim/testdir/test_lambda.vim
index c178c87d3e..ce15243993 100644
--- a/src/nvim/testdir/test_lambda.vim
+++ b/src/nvim/testdir/test_lambda.vim
@@ -63,6 +63,7 @@ function Test_lambda_fails()
call assert_equal(3, {a, b -> a + b}(1, 2))
call assert_fails('echo {a, a -> a + a}(1, 2)', 'E853:')
call assert_fails('echo {a, b -> a + b)}(1, 2)', 'E15:')
+ echo assert_fails('echo 10->{a -> a + 2}', 'E107:')
endfunc
func Test_not_lambda()
@@ -125,7 +126,7 @@ func Test_lambda_closure_counter()
endfunc
let l:F = s:foo()
- call garbagecollect()
+ call test_garbagecollect_now()
call assert_equal(1, l:F())
call assert_equal(2, l:F())
call assert_equal(3, l:F())
@@ -208,9 +209,9 @@ func Test_lambda_circular_reference()
endfunc
call s:Foo()
- call garbagecollect()
+ call test_garbagecollect_now()
let i = 0 | while i < 10000 | call s:Foo() | let i+= 1 | endwhile
- call garbagecollect()
+ call test_garbagecollect_now()
endfunc
func Test_lambda_combination()
@@ -239,11 +240,16 @@ func Test_closure_counter()
endfunc
let l:F = s:foo()
- call garbagecollect()
+ call test_garbagecollect_now()
call assert_equal(1, l:F())
call assert_equal(2, l:F())
call assert_equal(3, l:F())
call assert_equal(4, l:F())
+
+ call assert_match("^\n function <SNR>\\d\\+_bar() closure"
+ \ .. "\n1 let x += 1"
+ \ .. "\n2 return x"
+ \ .. "\n endfunction$", execute('func s:bar'))
endfunc
func Test_closure_unlet()
@@ -257,7 +263,7 @@ func Test_closure_unlet()
endfunc
call assert_false(has_key(s:foo(), 'x'))
- call garbagecollect()
+ call test_garbagecollect_now()
endfunc
func LambdaFoo()
@@ -294,7 +300,7 @@ func Test_named_function_closure()
endfunc
call Afoo()
call assert_equal(14, s:Abar())
- call garbagecollect()
+ call test_garbagecollect_now()
call assert_equal(14, s:Abar())
endfunc
diff --git a/src/nvim/testdir/test_let.vim b/src/nvim/testdir/test_let.vim
index 6cb736a38a..937076aa2a 100644
--- a/src/nvim/testdir/test_let.vim
+++ b/src/nvim/testdir/test_let.vim
@@ -25,9 +25,62 @@ func Test_let()
let s = "\na #1\nb #2"
call assert_equal(s, out)
+ " Test for displaying a string variable
+ let s = 'vim'
+ let out = execute('let s')
+ let s = "\ns vim"
+ call assert_equal(s, out)
+
+ " Test for displaying a list variable
+ let l = [1, 2]
+ let out = execute('let l')
+ let s = "\nl [1, 2]"
+ call assert_equal(s, out)
+
+ " Test for displaying a dict variable
+ let d = {'k' : 'v'}
+ let out = execute('let d')
+ let s = "\nd {'k': 'v'}"
+ call assert_equal(s, out)
+
+ " Test for displaying a function reference variable
+ let F = function('min')
+ let out = execute('let F')
+ let s = "\nF *min()"
+ call assert_equal(s, out)
+
let x = 0
if 0 | let x = 1 | endif
call assert_equal(0, x)
+
+ " Display a list item using an out of range index
+ let l = [10]
+ call assert_fails('let l[1]', 'E684:')
+
+ " List special variable dictionaries
+ let g:Test_Global_Var = 5
+ call assert_match("\nTest_Global_Var #5", execute('let g:'))
+ unlet g:Test_Global_Var
+
+ let b:Test_Buf_Var = 8
+ call assert_match("\nb:Test_Buf_Var #8", execute('let b:'))
+ unlet b:Test_Buf_Var
+
+ let w:Test_Win_Var = 'foo'
+ call assert_equal("\nw:Test_Win_Var foo", execute('let w:'))
+ unlet w:Test_Win_Var
+
+ let t:Test_Tab_Var = 'bar'
+ call assert_equal("\nt:Test_Tab_Var bar", execute('let t:'))
+ unlet t:Test_Tab_Var
+
+ let s:Test_Script_Var = [7]
+ call assert_match("\ns:Test_Script_Var \\[7]", execute('let s:'))
+ unlet s:Test_Script_Var
+
+ let l:Test_Local_Var = {'k' : 5}
+ call assert_match("\nl:Test_Local_Var {'k': 5}", execute('let l:'))
+ call assert_match("v:errors []", execute('let v:'))
endfunc
func s:set_arg1(a) abort
@@ -201,16 +254,59 @@ func Test_let_option_error()
let &fillchars = _w
endfunc
+" Errors with the :let statement
func Test_let_errors()
let s = 'abcd'
call assert_fails('let s[1] = 5', 'E689:')
let l = [1, 2, 3]
call assert_fails('let l[:] = 5', 'E709:')
+
+ call assert_fails('let x:lnum=5', 'E488:')
+ call assert_fails('let v:=5', 'E461:')
+ call assert_fails('let [a]', 'E474:')
+ call assert_fails('let [a, b] = [', 'E697:')
+ call assert_fails('let [a, b] = [10, 20', 'E696:')
+ call assert_fails('let [a, b] = 10', 'E714:')
+ call assert_fails('let [a, , b] = [10, 20]', 'E475:')
+ call assert_fails('let [a, b&] = [10, 20]', 'E475:')
+ call assert_fails('let $ = 10', 'E475:')
+ call assert_fails('let $FOO[1] = "abc"', 'E18:')
+ call assert_fails('let &buftype[1] = "nofile"', 'E18:')
+ let s = "var"
+ let var = 1
+ call assert_fails('let var += [1,2]', 'E734:')
+ call assert_fails('let {s}.1 = 2', 'E18:')
+ call assert_fails('let a[1] = 5', 'E121:')
+ let l = [[1,2]]
+ call assert_fails('let l[:][0] = [5]', 'E708:')
+ let d = {'k' : 4}
+ call assert_fails('let d.# = 5', 'E713:')
+ call assert_fails('let d.m += 5', 'E734:')
+ let l = [1, 2]
+ call assert_fails('let l[2] = 0', 'E684:')
+ call assert_fails('let l[0:1] = [1, 2, 3]', 'E710:')
+ call assert_fails('let l[-2:-3] = [3, 4]', 'E684:')
+ call assert_fails('let l[0:4] = [5, 6]', 'E711:')
+ call assert_fails('let g:["a;b"] = 10', 'E461:')
+ call assert_fails('let g:.min = function("max")', 'E704:')
+
+ " This test works only when the language is English
+ if v:lang == "C" || v:lang =~ '^[Ee]n'
+ call assert_fails('let [a ; b;] = [10, 20]',
+ \ 'Double ; in list of variables')
+ endif
endfunc
func Test_let_heredoc_fails()
call assert_fails('let v =<< marker', 'E991:')
+ try
+ exe "let v =<< TEXT | abc | TEXT"
+ call assert_report('No exception thrown')
+ catch /E488:/
+ catch
+ call assert_report("Caught exception: " .. v:exception)
+ endtry
let text =<< trim END
func WrongSyntax()
@@ -243,6 +339,10 @@ func Test_let_heredoc_fails()
call writefile(text, 'XheredocBadMarker')
call assert_fails('source XheredocBadMarker', 'E221:')
call delete('XheredocBadMarker')
+
+ call writefile(['let v =<< TEXT', 'abc'], 'XheredocMissingMarker')
+ call assert_fails('source XheredocMissingMarker', 'E990:')
+ call delete('XheredocMissingMarker')
endfunc
func Test_let_heredoc_trim_no_indent_marker()
@@ -361,3 +461,5 @@ E
END
call assert_equal([' x', ' \y', ' z'], [a, b, c])
endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_listdict.vim b/src/nvim/testdir/test_listdict.vim
index 9cef6905a5..f7261b2055 100644
--- a/src/nvim/testdir/test_listdict.vim
+++ b/src/nvim/testdir/test_listdict.vim
@@ -31,6 +31,12 @@ func Test_list_slice()
call assert_equal([1, 'as''d', [1, 2, function('strlen')]], l[:-2])
call assert_equal([1, 'as''d', [1, 2, function('strlen')], {'a': 1}], l[0:8])
call assert_equal([], l[8:-1])
+ call assert_equal([], l[0:-10])
+ " perform an operation on a list slice
+ let l = [1, 2, 3]
+ let l[:1] += [1, 2]
+ let l[2:] -= [1]
+ call assert_equal([2, 4, 2], l)
endfunc
" List identity
@@ -104,6 +110,8 @@ func Test_list_range_assign()
let l = [0]
let l[:] = [1, 2]
call assert_equal([1, 2], l)
+ let l[-4:-1] = [5, 6]
+ call assert_equal([5, 6], l)
endfunc
" Test removing items in list
@@ -143,6 +151,20 @@ func Test_list_func_remove()
call assert_fails("call remove(l, l)", 'E745:')
endfunc
+" List add() function
+func Test_list_add()
+ let l = []
+ call add(l, 1)
+ call add(l, [2, 3])
+ call add(l, [])
+ call add(l, v:_null_list)
+ call add(l, {'k' : 3})
+ call add(l, {})
+ call add(l, v:_null_dict)
+ call assert_equal([1, [2, 3], [], [], {'k' : 3}, {}, {}], l)
+ " call assert_equal(1, add(v:_null_list, 4))
+endfunc
+
" Tests for Dictionary type
func Test_dict()
@@ -166,6 +188,19 @@ func Test_dict()
call filter(d, 'v:key =~ ''[ac391]''')
call assert_equal({'c': 'ccc', '1': 99, '3': 33, '-1': {'a': 1}}, d)
+ " duplicate key
+ call assert_fails("let d = {'k' : 10, 'k' : 20}", 'E721:')
+ " missing comma
+ call assert_fails("let d = {'k' : 10 'k' : 20}", 'E722:')
+ " missing curly brace
+ call assert_fails("let d = {'k' : 10,", 'E723:')
+ " invalid key
+ call assert_fails('let d = #{++ : 10}', 'E15:')
+ " wrong type for key
+ call assert_fails('let d={[] : 10}', 'E730:')
+ " undefined variable as value
+ call assert_fails("let d={'k' : i}", 'E121:')
+
" allow key starting with number at the start, not a curly expression
call assert_equal({'1foo': 77}, #{1foo: 77})
@@ -266,7 +301,7 @@ func Test_script_local_dict_func()
unlet g:dict
endfunc
-" Test removing items in la dictionary
+" Test removing items in a dictionary
func Test_dict_func_remove()
let d = {1:'a', 2:'b', 3:'c'}
call assert_equal('b', remove(d, 2))
@@ -574,6 +609,18 @@ func Test_let_lock_list()
unlet l
endfunc
+" Locking part of the list
+func Test_let_lock_list_items()
+ let l = [1, 2, 3, 4]
+ lockvar l[2:]
+ call assert_equal(0, islocked('l[0]'))
+ call assert_equal(1, islocked('l[2]'))
+ call assert_equal(1, islocked('l[3]'))
+ call assert_fails('let l[2] = 10', 'E741:')
+ call assert_fails('let l[3] = 20', 'E741:')
+ unlet l
+endfunc
+
" lockvar/islocked() triggering script autoloading
func Test_lockvar_script_autoload()
let old_rtp = &rtp
@@ -628,6 +675,9 @@ func Test_reverse_sort_uniq()
call assert_fails('call reverse("")', 'E899:')
call assert_fails('call uniq([1, 2], {x, y -> []})', 'E882:')
+ call assert_fails("call sort([1, 2], function('min'), 1)", "E715:")
+ call assert_fails("call sort([1, 2], function('invalid_func'))", "E700:")
+ call assert_fails("call sort([1, 2], function('min'))", "E702:")
endfunc
" reduce a list or a blob
@@ -675,7 +725,7 @@ func Test_reduce()
call assert_equal(42, reduce(v:_null_blob, function('add'), 42))
endfunc
-" splitting a string to a List
+" splitting a string to a List using split()
func Test_str_split()
call assert_equal(['aa', 'bb'], split(' aa bb '))
call assert_equal(['aa', 'bb'], split(' aa bb ', '\W\+', 0))
@@ -697,6 +747,12 @@ func Test_listdict_compare()
call assert_true(d == d)
call assert_false(l != deepcopy(l))
call assert_false(d != deepcopy(d))
+
+ " comparison errors
+ call assert_fails('echo [1, 2] =~ {}', 'E691:')
+ call assert_fails('echo [1, 2] =~ [1, 2]', 'E692:')
+ call assert_fails('echo {} =~ 5', 'E735:')
+ call assert_fails('echo {} =~ {}', 'E736:')
endfunc
" compare complex recursively linked list and dict
@@ -870,6 +926,67 @@ func Test_scope_dict()
call s:check_scope_dict('v', v:true)
endfunc
+" Test for deep nesting of lists (> 100)
+func Test_deep_nested_list()
+ let deep_list = []
+ let l = deep_list
+ for i in range(102)
+ let newlist = []
+ call add(l, newlist)
+ let l = newlist
+ endfor
+ call add(l, 102)
+
+ call assert_fails('let m = deepcopy(deep_list)', 'E698:')
+ call assert_fails('lockvar 110 deep_list', 'E743:')
+ call assert_fails('unlockvar 110 deep_list', 'E743:')
+ " Nvim implements :echo very differently
+ " call assert_fails('let x = execute("echo deep_list")', 'E724:')
+ call test_garbagecollect_now()
+ unlet deep_list
+endfunc
+
+" Test for deep nesting of dicts (> 100)
+func Test_deep_nested_dict()
+ let deep_dict = {}
+ let d = deep_dict
+ for i in range(102)
+ let newdict = {}
+ let d.k = newdict
+ let d = newdict
+ endfor
+ let d.k = 'v'
+
+ call assert_fails('let m = deepcopy(deep_dict)', 'E698:')
+ call assert_fails('lockvar 110 deep_dict', 'E743:')
+ call assert_fails('unlockvar 110 deep_dict', 'E743:')
+ " Nvim implements :echo very differently
+ " call assert_fails('let x = execute("echo deep_dict")', 'E724:')
+ call test_garbagecollect_now()
+ unlet deep_dict
+endfunc
+
+" List and dict indexing tests
+func Test_listdict_index()
+ call assert_fails('echo function("min")[0]', 'E695:')
+ call assert_fails('echo v:true[0]', 'E909:')
+ let d = {'k' : 10}
+ call assert_fails('echo d.', 'E15:')
+ call assert_fails('echo d[1:2]', 'E719:')
+ call assert_fails("let v = [4, 6][{-> 1}]", 'E729:')
+ call assert_fails("let v = range(5)[2:[]]", 'E730:')
+ call assert_fails("let v = range(5)[2:{-> 2}(]", 'E116:')
+ call assert_fails("let v = range(5)[2:3", 'E111:')
+ call assert_fails("let l = insert([1,2,3], 4, 10)", 'E684:')
+ call assert_fails("let l = insert([1,2,3], 4, -10)", 'E684:')
+ call assert_fails("let l = insert([1,2,3], 4, [])", 'E745:')
+ let l = [1, 2, 3]
+ call assert_fails("let l[i] = 3", 'E121:')
+ call assert_fails("let l[1.1] = 4", 'E806:')
+ call assert_fails("let l[:i] = [4, 5]", 'E121:')
+ call assert_fails("let l[:3.2] = [4, 5]", 'E806:')
+endfunc
+
" Test for a null list
func Test_null_list()
let l = v:_null_list
@@ -906,3 +1023,21 @@ func Test_null_list()
call assert_equal(1, islocked('l'))
unlockvar l
endfunc
+
+" Test for a null dict
+func Test_null_dict()
+ call assert_equal(v:_null_dict, v:_null_dict)
+ let d = v:_null_dict
+ call assert_equal({}, d)
+ call assert_equal(0, len(d))
+ call assert_equal(1, empty(d))
+ call assert_equal(0, items(d))
+ call assert_equal(0, keys(d))
+ call assert_equal(0, values(d))
+ call assert_false(has_key(d, 'k'))
+ call assert_equal('{}', string(d))
+ call assert_fails('let x = v:_null_dict[10]')
+ call assert_equal({}, {})
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_mapping.vim b/src/nvim/testdir/test_mapping.vim
index bde3624adf..2d8c45210b 100644
--- a/src/nvim/testdir/test_mapping.vim
+++ b/src/nvim/testdir/test_mapping.vim
@@ -395,7 +395,9 @@ func Test_motionforce_omap()
endfunc
func Test_error_in_map_expr()
- if !has('terminal') || (has('win32') && has('gui_running'))
+ " Unlike CheckRunVimInTerminal this does work in a win32 console
+ CheckFeature terminal
+ if has('win32') && has('gui_running')
throw 'Skipped: cannot run Vim in a terminal window'
endif
diff --git a/src/nvim/testdir/test_marks.vim b/src/nvim/testdir/test_marks.vim
index 74e63d9d69..054ebf1218 100644
--- a/src/nvim/testdir/test_marks.vim
+++ b/src/nvim/testdir/test_marks.vim
@@ -91,6 +91,15 @@ func Test_setpos()
call assert_equal([0, 1, 21341234, 0], getpos("'a"))
call assert_equal(4, virtcol("'a"))
+ " Test with invalid buffer number, line number and column number
+ call cursor(2, 2)
+ call setpos('.', [-1, 1, 1, 0])
+ call assert_equal([2, 2], [line('.'), col('.')])
+ call setpos('.', [0, -1, 1, 0])
+ call assert_equal([2, 2], [line('.'), col('.')])
+ call setpos('.', [0, 1, -1, 0])
+ call assert_equal([2, 2], [line('.'), col('.')])
+
bwipe!
call win_gotoid(twowin)
bwipe!
diff --git a/src/nvim/testdir/test_match.vim b/src/nvim/testdir/test_match.vim
index 4f22e54563..fe931fefb2 100644
--- a/src/nvim/testdir/test_match.vim
+++ b/src/nvim/testdir/test_match.vim
@@ -322,9 +322,8 @@ func OtherWindowCommon()
endfunc
func Test_matchdelete_other_window()
- if !CanRunVimInTerminal()
- throw 'Skipped: cannot make screendumps'
- endif
+ CheckScreendump
+
let buf = OtherWindowCommon()
call term_sendkeys(buf, ":call matchdelete(mid, winid)\<CR>")
call VerifyScreenDump(buf, 'Test_matchdelete_1', {})
diff --git a/src/nvim/testdir/test_method.vim b/src/nvim/testdir/test_method.vim
index cdf688b857..e035b3ef50 100644
--- a/src/nvim/testdir/test_method.vim
+++ b/src/nvim/testdir/test_method.vim
@@ -35,6 +35,7 @@ func Test_list_method()
call assert_equal(v:t_list, l->type())
call assert_equal([1, 2, 3], [1, 1, 2, 3, 3]->uniq())
call assert_fails('eval l->values()', 'E715:')
+ call assert_fails('echo []->len', 'E107:')
endfunc
func Test_dict_method()
diff --git a/src/nvim/testdir/test_normal.vim b/src/nvim/testdir/test_normal.vim
index 4f842189b6..5730085c78 100644
--- a/src/nvim/testdir/test_normal.vim
+++ b/src/nvim/testdir/test_normal.vim
@@ -514,6 +514,7 @@ func Test_normal10_expand()
" Test expand(`=...`) i.e. backticks expression expansion
call assert_equal('5', expand('`=2+3`'))
+ call assert_equal('3.14', expand('`=3.14`'))
" clean up
bw!
diff --git a/src/nvim/testdir/test_options.vim b/src/nvim/testdir/test_options.vim
index ada6d2406b..2836e81c4a 100644
--- a/src/nvim/testdir/test_options.vim
+++ b/src/nvim/testdir/test_options.vim
@@ -432,9 +432,8 @@ endfunc
" Must be executed before other tests that set 'term'.
func Test_000_term_option_verbose()
- if has('nvim') || has('gui_running')
- return
- endif
+ throw "Skipped: Nvim does not support setting 'term'"
+ CheckNotGui
call CheckWasNotSet('t_cm')
@@ -1117,6 +1116,35 @@ func Test_opt_reset_scroll()
call delete('Xscroll')
endfunc
+" Check that VIM_POSIX env variable influences default value of 'cpo' and 'shm'
+func Test_VIM_POSIX()
+ throw 'Skipped: Nvim does not support $VIM_POSIX'
+ let saved_VIM_POSIX = getenv("VIM_POSIX")
+
+ call setenv('VIM_POSIX', "1")
+ let after =<< trim [CODE]
+ call writefile([&cpo, &shm], 'X_VIM_POSIX')
+ qall
+ [CODE]
+ if RunVim([], after, '')
+ call assert_equal(['aAbBcCdDeEfFgHiIjJkKlLmMnoOpPqrRsStuvwWxXyZ$!%*-+<>#{|&/\.;',
+ \ 'AS'], readfile('X_VIM_POSIX'))
+ endif
+
+ call setenv('VIM_POSIX', v:null)
+ let after =<< trim [CODE]
+ call writefile([&cpo, &shm], 'X_VIM_POSIX')
+ qall
+ [CODE]
+ if RunVim([], after, '')
+ call assert_equal(['aAbBcCdDeEfFgHiIjJkKlLmMnoOpPqrRsStuvwWxXyZ$!%*-+<>;',
+ \ 'S'], readfile('X_VIM_POSIX'))
+ endif
+
+ call delete('X_VIM_POSIX')
+ call setenv('VIM_POSIX', saved_VIM_POSIX)
+endfunc
+
" Test for setting an option to a Vi or Vim default
func Test_opt_default()
throw 'Skipped: Nvim has different defaults'
diff --git a/src/nvim/testdir/test_popup.vim b/src/nvim/testdir/test_popup.vim
index 067e5d14e5..7f183f0849 100644
--- a/src/nvim/testdir/test_popup.vim
+++ b/src/nvim/testdir/test_popup.vim
@@ -677,9 +677,9 @@ func Test_complete_CTRLN_startofbuffer()
endfunc
func Test_popup_and_window_resize()
- if !has('terminal') || has('gui_running')
- return
- endif
+ CheckFeature terminal
+ CheckNotGui
+
let h = winheight(0)
if h < 15
return
@@ -948,9 +948,9 @@ func Test_complete_o_tab()
endfunc
func Test_menu_only_exists_in_terminal()
- if !exists(':tlmenu') || has('gui_running')
- return
- endif
+ CheckCommand tlmenu
+ CheckNotGui
+
tlnoremenu &Edit.&Paste<Tab>"+gP <C-W>"+
aunmenu *
try
diff --git a/src/nvim/testdir/test_signals.vim b/src/nvim/testdir/test_signals.vim
index 338c0d79ff..e1c6e5d11f 100644
--- a/src/nvim/testdir/test_signals.vim
+++ b/src/nvim/testdir/test_signals.vim
@@ -16,8 +16,9 @@ endfunc
" Test signal WINCH (window resize signal)
func Test_signal_WINCH()
throw 'skipped: Nvim cannot avoid terminal resize'
- if has('gui_running') || !HasSignal('WINCH')
- return
+ CheckNotGui
+ if !HasSignal('WINCH')
+ throw 'Skipped: WINCH signal not supported'
endif
" We do not actually want to change the size of the terminal.
@@ -128,8 +129,7 @@ func Test_deadly_signal_TERM()
call assert_equal(['foo'], getline(1, '$'))
let result = readfile('XautoOut')
- call assert_match('VimLeavePre triggered', result[0])
- call assert_match('VimLeave triggered', result[1])
+ call assert_equal(["VimLeavePre triggered", "VimLeave triggered"], result)
%bwipe!
call delete('.Xsig_TERM.swp')
diff --git a/src/nvim/testdir/test_sort.vim b/src/nvim/testdir/test_sort.vim
index 9895ad754c..c3e7788164 100644
--- a/src/nvim/testdir/test_sort.vim
+++ b/src/nvim/testdir/test_sort.vim
@@ -80,7 +80,7 @@ func Test_sort_default()
call assert_equal(['2', 'A', 'AA', 'a', 1, 3.3], sort([3.3, 1, "2", "A", "a", "AA"], ''))
call assert_equal(['2', 'A', 'AA', 'a', 1, 3.3], sort([3.3, 1, "2", "A", "a", "AA"], 0))
call assert_equal(['2', 'A', 'a', 'AA', 1, 3.3], sort([3.3, 1, "2", "A", "a", "AA"], 1))
- call assert_fails('call sort([3.3, 1, "2"], 3)', "E474")
+ call assert_fails('call sort([3.3, 1, "2"], 3)', "E474:")
endfunc
" Tests for the ":sort" command.
diff --git a/src/nvim/testdir/test_source.vim b/src/nvim/testdir/test_source.vim
index ba6fd5ad95..0fd923abf2 100644
--- a/src/nvim/testdir/test_source.vim
+++ b/src/nvim/testdir/test_source.vim
@@ -87,4 +87,10 @@ func Test_source_autocmd_sfile()
call delete('Xscript.vim')
endfunc
+func Test_source_error()
+ call assert_fails('scriptencoding utf-8', 'E167:')
+ call assert_fails('finish', 'E168:')
+ " call assert_fails('scriptversion 2', 'E984:')
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_spell.vim b/src/nvim/testdir/test_spell.vim
index e421d21de1..4af02d3d31 100644
--- a/src/nvim/testdir/test_spell.vim
+++ b/src/nvim/testdir/test_spell.vim
@@ -474,6 +474,35 @@ func Test_spellsuggest_option_expr()
bwipe!
endfunc
+" Test for 'spellsuggest' expr errrors
+func Test_spellsuggest_expr_errors()
+ " 'spellsuggest'
+ func MySuggest()
+ return range(3)
+ endfunc
+ set spell spellsuggest=expr:MySuggest()
+ call assert_equal([], spellsuggest('baord', 3))
+
+ " Test for 'spellsuggest' expression returning a non-list value
+ func! MySuggest2()
+ return 'good'
+ endfunc
+ set spellsuggest=expr:MySuggest2()
+ call assert_equal([], spellsuggest('baord'))
+
+ " Test for 'spellsuggest' expression returning a list with dict values
+ func! MySuggest3()
+ return [[{}, {}]]
+ endfunc
+ set spellsuggest=expr:MySuggest3()
+ call assert_fails("call spellsuggest('baord')", 'E728:')
+
+ set nospell spellsuggest&
+ delfunc MySuggest
+ delfunc MySuggest2
+ delfunc MySuggest3
+endfunc
+
func Test_spellsuggest_timeout()
set spellsuggest=timeout:30
set spellsuggest=timeout:-123
diff --git a/src/nvim/testdir/test_startup.vim b/src/nvim/testdir/test_startup.vim
index b30a5e7edb..b8aad1bc46 100644
--- a/src/nvim/testdir/test_startup.vim
+++ b/src/nvim/testdir/test_startup.vim
@@ -267,10 +267,9 @@ endfunc
" Test the -V[N] argument to set the 'verbose' option to [N]
func Test_V_arg()
- if has('gui_running')
- " Can't catch the output of gvim.
- return
- endif
+ " Can't catch the output of gvim.
+ CheckNotGui
+
let out = system(GetVimCommand() . ' --clean -es -X -V0 -c "set verbose?" -cq')
call assert_equal(" verbose=0\n", out)
@@ -543,10 +542,9 @@ endfunc
func Test_invalid_args()
- if !has('unix') || has('gui_running')
- " can't get output of Vim.
- return
- endif
+ " must be able to get the output of Vim.
+ CheckUnix
+ CheckNotGui
for opt in ['-Y', '--does-not-exist']
let out = split(system(GetVimCommand() .. ' ' .. opt), "\n")
@@ -622,6 +620,12 @@ func Test_invalid_args()
endfor
if has('gui_gtk')
+ let out = split(system(GetVimCommand() .. ' --socketid'), "\n")
+ call assert_equal(1, v:shell_error)
+ call assert_match('^VIM - Vi IMproved .* (.*)$', out[0])
+ call assert_equal('Argument missing after: "--socketid"', out[1])
+ call assert_equal('More info with: "vim -h"', out[2])
+
for opt in ['--socketid x', '--socketid 0xg']
let out = split(system(GetVimCommand() .. ' ' .. opt), "\n")
call assert_equal(1, v:shell_error)
@@ -629,6 +633,7 @@ func Test_invalid_args()
call assert_equal('Invalid argument for: "--socketid"', out[1])
call assert_equal('More info with: "vim -h"', out[2])
endfor
+
endif
endfunc
@@ -747,10 +752,9 @@ func Test_progpath()
endfunc
func Test_silent_ex_mode()
- if !has('unix') || has('gui_running')
- " can't get output of Vim.
- return
- endif
+ " must be able to get the output of Vim.
+ CheckUnix
+ CheckNotGui
" This caused an ml_get error.
let out = system(GetVimCommand() . ' -u NONE -es -c''set verbose=1|h|exe "%norm\<c-y>\<c-d>"'' -c cq')
@@ -758,10 +762,9 @@ func Test_silent_ex_mode()
endfunc
func Test_default_term()
- if !has('unix') || has('gui_running')
- " can't get output of Vim.
- return
- endif
+ " must be able to get the output of Vim.
+ CheckUnix
+ CheckNotGui
let save_term = $TERM
let $TERM = 'unknownxxx'
@@ -796,6 +799,15 @@ func Test_zzz_startinsert()
call delete('Xtestout')
endfunc
+func Test_issue_3969()
+ " Can't catch the output of gvim.
+ CheckNotGui
+
+ " Check that message is not truncated.
+ let out = system(GetVimCommand() . ' -es -X -V1 -c "echon ''hello''" -cq')
+ call assert_equal('hello', out)
+endfunc
+
func Test_start_with_tabs()
if !CanRunVimInTerminal()
return
diff --git a/src/nvim/testdir/test_syntax.vim b/src/nvim/testdir/test_syntax.vim
index ccff01486e..d686ad7e96 100644
--- a/src/nvim/testdir/test_syntax.vim
+++ b/src/nvim/testdir/test_syntax.vim
@@ -113,6 +113,9 @@ func Test_syntime()
let a = execute('syntime report')
call assert_equal("\nNo Syntax items defined for this buffer", a)
+ let a = execute('syntime clear')
+ call assert_equal("\nNo Syntax items defined for this buffer", a)
+
view samples/memfile_test.c
setfiletype cpp
redraw
@@ -171,6 +174,10 @@ func Test_syntax_list()
let a = execute('syntax list')
call assert_equal("\nNo Syntax items defined for this buffer", a)
+ syntax keyword Type int containedin=g1 skipwhite skipempty skipnl nextgroup=Abc
+ let exp = "Type xxx containedin=g1 nextgroup=Abc skipnl skipwhite skipempty int"
+ call assert_equal(exp, split(execute("syntax list"), "\n")[1])
+
bd
endfunc
@@ -347,6 +354,18 @@ func Test_syntax_arg_skipped()
syn clear
endfunc
+" Check for an error. Used when multiple errors are thrown and we are checking
+" for an earliest error.
+func AssertFails(cmd, errcode)
+ let save_exception = ''
+ try
+ exe a:cmd
+ catch
+ let save_exception = v:exception
+ endtry
+ call assert_match(a:errcode, save_exception)
+endfunc
+
func Test_syntax_invalid_arg()
call assert_fails('syntax case asdf', 'E390:')
if has('conceal')
@@ -354,11 +373,49 @@ func Test_syntax_invalid_arg()
endif
call assert_fails('syntax spell asdf', 'E390:')
call assert_fails('syntax clear @ABCD', 'E391:')
- call assert_fails('syntax include @Xxx', 'E397:')
- call assert_fails('syntax region X start="{"', 'E399:')
+ call assert_fails('syntax include random_file', 'E484:')
+ call assert_fails('syntax include <afile>', 'E495:')
call assert_fails('syntax sync x', 'E404:')
call assert_fails('syntax keyword Abc a[', 'E789:')
call assert_fails('syntax keyword Abc a[bc]d', 'E890:')
+ call assert_fails('syntax cluster Abc add=A add=', 'E475:')
+
+ " Test for too many \z\( and unmatched \z\(
+ " Not able to use assert_fails() here because both E50:/E879: and E475:
+ " messages are emitted.
+ set regexpengine=1
+ call AssertFails("syntax region MyRegion start='\\z\\(' end='\\*/'", 'E52:')
+
+ let cmd = "syntax region MyRegion start='"
+ let cmd ..= repeat("\\z\\(.\\)", 10) .. "' end='\*/'"
+ call AssertFails(cmd, 'E50:')
+
+ set regexpengine=2
+ call AssertFails("syntax region MyRegion start='\\z\\(' end='\\*/'", 'E54:')
+
+ let cmd = "syntax region MyRegion start='"
+ let cmd ..= repeat("\\z\\(.\\)", 10) .. "' end='\*/'"
+ call AssertFails(cmd, 'E879:')
+ set regexpengine&
+
+ call AssertFails('syntax keyword cMyItem grouphere G1', 'E393:')
+ call AssertFails('syntax sync match Abc grouphere MyItem "abc"', 'E394:')
+ call AssertFails('syn keyword Type contains int', 'E395:')
+ call assert_fails('syntax include @Xxx', 'E397:')
+ call AssertFails('syntax region X start', 'E398:')
+ call assert_fails('syntax region X start="{"', 'E399:')
+ call AssertFails('syntax cluster contains=Abc', 'E400:')
+ call AssertFails("syntax match Character /'.'", 'E401:')
+ call AssertFails("syntax match Character /'.'/a", 'E402:')
+ call assert_fails('syntax sync linecont /pat', 'E404:')
+ call assert_fails('syntax sync linecont', 'E404:')
+ call assert_fails('syntax sync linecont /pat1/ linecont /pat2/', 'E403:')
+ call assert_fails('syntax sync minlines=a', 'E404:')
+ call AssertFails('syntax match ABC /x/ contains=', 'E406:')
+ call AssertFails("syntax match Character contains /'.'/", 'E405:')
+ call AssertFails('syntax match ccFoo "Foo" nextgroup=ALLBUT,F', 'E407:')
+ call AssertFails('syntax region Block start="{" contains=F,ALLBUT', 'E408:')
+ call AssertFails("syntax match Characters contains=a.*x /'.'/", 'E409:')
endfunc
func Test_syn_sync()
@@ -386,6 +443,7 @@ func Test_syn_clear()
hi clear Foo
call assert_equal('Foo', synIDattr(hlID("Foo"), "name"))
hi clear Bar
+ call assert_fails('syntax clear invalid_syngroup', 'E28:')
endfunc
func Test_invalid_name()
@@ -479,15 +537,16 @@ func Test_conceal()
call assert_match('16 ', ScreenLines(2, 7)[0])
call assert_equal([[0, '', 0], [1, '', 1], [1, '', 1], [1, '', 2], [1, '', 2], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)'))
+ call AssertFails("syntax match Entity '&amp;' conceal cchar=\<Tab>", 'E844:')
+
syn clear
set conceallevel&
bw!
endfunc
func Test_bg_detection()
- if has('gui_running')
- return
- endif
+ CheckNotGui
+
" auto-detection of &bg, make sure sure it isn't set anywhere before
" this test
hi Normal ctermbg=0
@@ -607,6 +666,24 @@ func Test_syntax_c()
call delete('Xtest.c')
endfun
+" Test \z(...) along with \z1
+func Test_syn_zsub()
+ new
+ syntax on
+ call setline(1, 'xxx start foo xxx not end foo xxx end foo xxx')
+ let l:expected = ' ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ '
+
+ for l:re in [0, 1, 2]
+ " Example taken from :help :syn-ext-match
+ syntax region Z start="start \z(\I\i*\)" skip="not end \z1" end="end \z1"
+ eval AssertHighlightGroups(1, 1, l:expected, 1, 'regexp=' .. l:re)
+ syntax clear Z
+ endfor
+
+ set re&
+ bw!
+endfunc
+
" Using \z() in a region with NFA failing should not crash.
func Test_syn_wrong_z_one()
new
diff --git a/src/nvim/testdir/test_timers.vim b/src/nvim/testdir/test_timers.vim
index 771f61442d..3a6abb3968 100644
--- a/src/nvim/testdir/test_timers.vim
+++ b/src/nvim/testdir/test_timers.vim
@@ -264,8 +264,9 @@ endfunc
func Test_timer_peek_and_get_char()
if !has('unix') && !has('gui_running')
- return
+ throw 'Skipped: cannot feed low-level input'
endif
+
call timer_start(0, 'FeedAndPeek')
let intr = timer_start(100, 'Interrupt')
let c = getchar()
@@ -275,9 +276,9 @@ endfunc
func Test_timer_getchar_zero()
if has('win32') && !has('gui_running')
- " Console: no low-level input
- return
+ throw 'Skipped: cannot feed low-level input'
endif
+ CheckFunction reltimefloat
" Measure the elapsed time to avoid a hang when it fails.
let start = reltime()
diff --git a/src/nvim/testdir/test_unlet.vim b/src/nvim/testdir/test_unlet.vim
index b02bdaab3b..4779d17906 100644
--- a/src/nvim/testdir/test_unlet.vim
+++ b/src/nvim/testdir/test_unlet.vim
@@ -1,12 +1,9 @@
" Tests for :unlet
func Test_read_only()
- try
- " this caused a crash
- unlet v:count
- catch
- call assert_true(v:exception =~ ':E795:')
- endtry
+ " these caused a crash
+ call assert_fails('unlet v:count', 'E795:')
+ call assert_fails('unlet v:errmsg', 'E795:')
endfunc
func Test_existing()
@@ -18,15 +15,19 @@ endfunc
func Test_not_existing()
unlet! does_not_exist
- try
- unlet does_not_exist
- catch
- call assert_true(v:exception =~ ':E108:')
- endtry
+ call assert_fails('unlet does_not_exist', 'E108:')
endfunc
func Test_unlet_fails()
call assert_fails('unlet v:["count"]', 'E46:')
+ call assert_fails('unlet $', 'E475:')
+ let v = {}
+ call assert_fails('unlet v[:]', 'E719:')
+ let l = []
+ call assert_fails("unlet l['k'", 'E111:')
+ let d = {'k' : 1}
+ call assert_fails("unlet d.k2", 'E716:')
+ call assert_fails("unlet {a};", 'E488:')
endfunc
func Test_unlet_env()
@@ -62,3 +63,5 @@ func Test_unlet_complete()
call feedkeys(":unlet $FOO\t\n", 'tx')
call assert_true(!exists('$FOOBAR') || empty($FOOBAR))
endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_user_func.vim b/src/nvim/testdir/test_user_func.vim
index c14624f5b4..7aa21d7816 100644
--- a/src/nvim/testdir/test_user_func.vim
+++ b/src/nvim/testdir/test_user_func.vim
@@ -3,6 +3,9 @@
" Also test that a builtin function cannot be replaced.
" Also test for regression when calling arbitrary expression.
+source check.vim
+source shared.vim
+
func Table(title, ...)
let ret = a:title
let idx = 1
@@ -83,10 +86,14 @@ func Test_user_func()
normal o[(one again
call assert_equal('1. one again', getline('.'))
+ " Try to overwrite a function in the global (g:) scope
call assert_equal(3, max([1, 2, 3]))
call assert_fails("call extend(g:, {'max': function('min')})", 'E704')
call assert_equal(3, max([1, 2, 3]))
+ " Try to overwrite an user defined function with a function reference
+ call assert_fails("let Expr1 = function('min')", 'E705:')
+
" Regression: the first line below used to throw ?E110: Missing ')'?
" Second is here just to prove that this line is correct when not skipping
" rhs of &&.
@@ -142,8 +149,8 @@ func Test_default_arg()
call assert_equal(res.optional, 2)
call assert_equal(res['0'], 1)
- call assert_fails("call MakeBadFunc()", 'E989')
- call assert_fails("fu F(a=1 ,) | endf", 'E475')
+ call assert_fails("call MakeBadFunc()", 'E989:')
+ call assert_fails("fu F(a=1 ,) | endf", 'E1068:')
" Since neovim does not have v:none, the ability to use the default
" argument with the intermediate argument set to v:none has been omitted.
@@ -175,4 +182,310 @@ func Test_function_list()
call assert_fails("function Xabc", 'E123:')
endfunc
+" Test for <sfile>, <slnum> in a function
+func Test_sfile_in_function()
+ func Xfunc()
+ call assert_match('..Test_sfile_in_function\[5]..Xfunc', expand('<sfile>'))
+ call assert_equal('2', expand('<slnum>'))
+ endfunc
+ call Xfunc()
+ delfunc Xfunc
+endfunc
+
+" Test trailing text after :endfunction {{{1
+func Test_endfunction_trailing()
+ call assert_false(exists('*Xtest'))
+
+ exe "func Xtest()\necho 'hello'\nendfunc\nlet done = 'yes'"
+ call assert_true(exists('*Xtest'))
+ call assert_equal('yes', done)
+ delfunc Xtest
+ unlet done
+
+ exe "func Xtest()\necho 'hello'\nendfunc|let done = 'yes'"
+ call assert_true(exists('*Xtest'))
+ call assert_equal('yes', done)
+ delfunc Xtest
+ unlet done
+
+ " trailing line break
+ exe "func Xtest()\necho 'hello'\nendfunc\n"
+ call assert_true(exists('*Xtest'))
+ delfunc Xtest
+
+ set verbose=1
+ exe "func Xtest()\necho 'hello'\nendfunc \" garbage"
+ call assert_notmatch('W22:', split(execute('1messages'), "\n")[0])
+ call assert_true(exists('*Xtest'))
+ delfunc Xtest
+
+ exe "func Xtest()\necho 'hello'\nendfunc garbage"
+ call assert_match('W22:', split(execute('1messages'), "\n")[0])
+ call assert_true(exists('*Xtest'))
+ delfunc Xtest
+ set verbose=0
+
+ func Xtest(a1, a2)
+ echo a:a1 .. a:a2
+ endfunc
+ set verbose=15
+ redir @a
+ call Xtest(123, repeat('x', 100))
+ redir END
+ call assert_match('calling Xtest(123, ''xxxxxxx.*x\.\.\.x.*xxxx'')', getreg('a'))
+ delfunc Xtest
+ set verbose=0
+
+ function Foo()
+ echo 'hello'
+ endfunction | echo 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
+ delfunc Foo
+endfunc
+
+func Test_delfunction_force()
+ delfunc! Xtest
+ delfunc! Xtest
+ func Xtest()
+ echo 'nothing'
+ endfunc
+ delfunc! Xtest
+ delfunc! Xtest
+
+ " Try deleting the current function
+ call assert_fails('delfunc Test_delfunction_force', 'E131:')
+endfunc
+
+func Test_function_defined_line()
+ CheckNotGui
+
+ let lines =<< trim [CODE]
+ " F1
+ func F1()
+ " F2
+ func F2()
+ "
+ "
+ "
+ return
+ endfunc
+ " F3
+ execute "func F3()\n\n\n\nreturn\nendfunc"
+ " F4
+ execute "func F4()\n
+ \\n
+ \\n
+ \\n
+ \return\n
+ \endfunc"
+ endfunc
+ " F5
+ execute "func F5()\n\n\n\nreturn\nendfunc"
+ " F6
+ execute "func F6()\n
+ \\n
+ \\n
+ \\n
+ \return\n
+ \endfunc"
+ call F1()
+ verbose func F1
+ verbose func F2
+ verbose func F3
+ verbose func F4
+ verbose func F5
+ verbose func F6
+ qall!
+ [CODE]
+
+ call writefile(lines, 'Xtest.vim')
+ let res = system(GetVimCommandClean() .. ' -es -X -S Xtest.vim')
+ call assert_equal(0, v:shell_error)
+
+ let m = matchstr(res, 'function F1()[^[:print:]]*[[:print:]]*')
+ call assert_match(' line 2$', m)
+
+ let m = matchstr(res, 'function F2()[^[:print:]]*[[:print:]]*')
+ call assert_match(' line 4$', m)
+
+ let m = matchstr(res, 'function F3()[^[:print:]]*[[:print:]]*')
+ call assert_match(' line 11$', m)
+
+ let m = matchstr(res, 'function F4()[^[:print:]]*[[:print:]]*')
+ call assert_match(' line 13$', m)
+
+ let m = matchstr(res, 'function F5()[^[:print:]]*[[:print:]]*')
+ call assert_match(' line 21$', m)
+
+ let m = matchstr(res, 'function F6()[^[:print:]]*[[:print:]]*')
+ call assert_match(' line 23$', m)
+
+ call delete('Xtest.vim')
+endfunc
+
+" Test for defining a function reference in the global scope
+func Test_add_funcref_to_global_scope()
+ let x = g:
+ let caught_E862 = 0
+ try
+ func x.Xfunc()
+ return 1
+ endfunc
+ catch /E862:/
+ let caught_E862 = 1
+ endtry
+ call assert_equal(1, caught_E862)
+endfunc
+
+func Test_funccall_garbage_collect()
+ func Func(x, ...)
+ call add(a:x, a:000)
+ endfunc
+ call Func([], [])
+ " Must not crash cause by invalid freeing
+ call test_garbagecollect_now()
+ call assert_true(v:true)
+ delfunc Func
+endfunc
+
+" Test for script-local function
+func <SID>DoLast()
+ call append(line('$'), "last line")
+endfunc
+
+func s:DoNothing()
+ call append(line('$'), "nothing line")
+endfunc
+
+func Test_script_local_func()
+ set nocp nomore viminfo+=nviminfo
+ new
+ nnoremap <buffer> _x :call <SID>DoNothing()<bar>call <SID>DoLast()<bar>delfunc <SID>DoNothing<bar>delfunc <SID>DoLast<cr>
+
+ normal _x
+ call assert_equal('nothing line', getline(2))
+ call assert_equal('last line', getline(3))
+ close!
+
+ " Try to call a script local function in global scope
+ let lines =<< trim [CODE]
+ :call assert_fails('call s:Xfunc()', 'E81:')
+ :call assert_fails('let x = call("<SID>Xfunc", [])', 'E120:')
+ :call writefile(v:errors, 'Xresult')
+ :qall
+
+ [CODE]
+ call writefile(lines, 'Xscript')
+ if RunVim([], [], '-s Xscript')
+ call assert_equal([], readfile('Xresult'))
+ endif
+ call delete('Xresult')
+ call delete('Xscript')
+endfunc
+
+" Test for errors in defining new functions
+func Test_func_def_error()
+ call assert_fails('func Xfunc abc ()', 'E124:')
+ call assert_fails('func Xfunc(', 'E125:')
+ call assert_fails('func xfunc()', 'E128:')
+
+ " Try to redefine a function that is in use
+ let caught_E127 = 0
+ try
+ func! Test_func_def_error()
+ endfunc
+ catch /E127:/
+ let caught_E127 = 1
+ endtry
+ call assert_equal(1, caught_E127)
+
+ " Try to define a function in a dict twice
+ let d = {}
+ let lines =<< trim END
+ func d.F1()
+ return 1
+ endfunc
+ END
+ let l = join(lines, "\n") . "\n"
+ exe l
+ call assert_fails('exe l', 'E717:')
+
+ " Define an autoload function with an incorrect file name
+ call writefile(['func foo#Bar()', 'return 1', 'endfunc'], 'Xscript')
+ call assert_fails('source Xscript', 'E746:')
+ call delete('Xscript')
+endfunc
+
+" Test for deleting a function
+func Test_del_func()
+ call assert_fails('delfunction Xabc', 'E130:')
+ let d = {'a' : 10}
+ call assert_fails('delfunc d.a', 'E718:')
+ func d.fn()
+ return 1
+ endfunc
+
+ " cannot delete the dict function by number
+ let nr = substitute(execute('echo d'), '.*function(''\(\d\+\)'').*', '\1', '')
+ call assert_fails('delfunction g:' .. nr, 'E475: Invalid argument: g:')
+
+ delfunc d.fn
+ call assert_equal({'a' : 10}, d)
+endfunc
+
+" Test for calling return outside of a function
+func Test_return_outside_func()
+ call writefile(['return 10'], 'Xscript')
+ call assert_fails('source Xscript', 'E133:')
+ call delete('Xscript')
+endfunc
+
+" Test for errors in calling a function
+func Test_func_arg_error()
+ " Too many arguments
+ call assert_fails("call call('min', range(1,20))", 'E118:')
+ call assert_fails("call call('min', range(1,21))", 'E699:')
+ call assert_fails('echo min(0,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,0,1)',
+ \ 'E740:')
+
+ " Missing dict argument
+ func Xfunc() dict
+ return 1
+ endfunc
+ call assert_fails('call Xfunc()', 'E725:')
+ delfunc Xfunc
+endfunc
+
+func Test_func_dict()
+ let mydict = {'a': 'b'}
+ function mydict.somefunc() dict
+ return len(self)
+ endfunc
+
+ call assert_equal("{'a': 'b', 'somefunc': function('3')}", string(mydict))
+ call assert_equal(2, mydict.somefunc())
+ call assert_match("^\n function \\d\\\+() dict"
+ \ .. "\n1 return len(self)"
+ \ .. "\n endfunction$", execute('func mydict.somefunc'))
+ call assert_fails('call mydict.nonexist()', 'E716:')
+endfunc
+
+func Test_func_range()
+ new
+ call setline(1, range(1, 8))
+ func FuncRange() range
+ echo a:firstline
+ echo a:lastline
+ endfunc
+ 3
+ call assert_equal("\n3\n3", execute('call FuncRange()'))
+ call assert_equal("\n4\n6", execute('4,6 call FuncRange()'))
+ call assert_equal("\n function FuncRange() range"
+ \ .. "\n1 echo a:firstline"
+ \ .. "\n2 echo a:lastline"
+ \ .. "\n endfunction",
+ \ execute('function FuncRange'))
+
+ bwipe!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_usercommands.vim b/src/nvim/testdir/test_usercommands.vim
index 12fe39851d..5b8b384bae 100644
--- a/src/nvim/testdir/test_usercommands.vim
+++ b/src/nvim/testdir/test_usercommands.vim
@@ -617,6 +617,27 @@ func Test_command_list()
call assert_equal("\nNo user-defined commands found", execute('command'))
endfunc
+" Test for a custom user completion returning the wrong value type
+func Test_usercmd_custom()
+ func T1(a, c, p)
+ return "a\nb\n"
+ endfunc
+ command -nargs=* -complete=customlist,T1 TCmd1
+ call feedkeys(":TCmd1 \<C-A>\<C-B>\"\<CR>", 'xt')
+ call assert_equal('"TCmd1 ', @:)
+ delcommand TCmd1
+ delfunc T1
+
+ func T2(a, c, p)
+ return {}
+ endfunc
+ command -nargs=* -complete=customlist,T2 TCmd2
+ call feedkeys(":TCmd2 \<C-A>\<C-B>\"\<CR>", 'xt')
+ call assert_equal('"TCmd2 ', @:)
+ delcommand TCmd2
+ delfunc T2
+endfunc
+
func Test_delcommand_buffer()
command Global echo 'global'
command -buffer OneBuffer echo 'one'
diff --git a/src/nvim/testdir/test_utf8.vim b/src/nvim/testdir/test_utf8.vim
index ab3503c282..7145d303cc 100644
--- a/src/nvim/testdir/test_utf8.vim
+++ b/src/nvim/testdir/test_utf8.vim
@@ -131,9 +131,13 @@ func Test_list2str_str2list_latin1()
let save_encoding = &encoding
" set encoding=latin1
-
+
let lres = str2list(s, 1)
let sres = list2str(l, 1)
+ call assert_equal([65, 66, 67], str2list("ABC"))
+
+ " Try converting a list to a string in latin-1 encoding
+ call assert_equal([1, 2, 3], str2list(list2str([1, 2, 3])))
let &encoding = save_encoding
call assert_equal(l, lres)
diff --git a/src/nvim/testdir/test_vimscript.vim b/src/nvim/testdir/test_vimscript.vim
index 3487a028ca..f20fd12ed3 100644
--- a/src/nvim/testdir/test_vimscript.vim
+++ b/src/nvim/testdir/test_vimscript.vim
@@ -1495,55 +1495,6 @@ func Test_bitwise_functions()
call assert_fails("call invert({})", 'E728:')
endfunc
-" Test trailing text after :endfunction {{{1
-func Test_endfunction_trailing()
- call assert_false(exists('*Xtest'))
-
- exe "func Xtest()\necho 'hello'\nendfunc\nlet done = 'yes'"
- call assert_true(exists('*Xtest'))
- call assert_equal('yes', done)
- delfunc Xtest
- unlet done
-
- exe "func Xtest()\necho 'hello'\nendfunc|let done = 'yes'"
- call assert_true(exists('*Xtest'))
- call assert_equal('yes', done)
- delfunc Xtest
- unlet done
-
- " trailing line break
- exe "func Xtest()\necho 'hello'\nendfunc\n"
- call assert_true(exists('*Xtest'))
- delfunc Xtest
-
- set verbose=1
- exe "func Xtest()\necho 'hello'\nendfunc \" garbage"
- call assert_notmatch('W22:', split(execute('1messages'), "\n")[0])
- call assert_true(exists('*Xtest'))
- delfunc Xtest
-
- exe "func Xtest()\necho 'hello'\nendfunc garbage"
- call assert_match('W22:', split(execute('1messages'), "\n")[0])
- call assert_true(exists('*Xtest'))
- delfunc Xtest
- set verbose=0
-
- function Foo()
- echo 'hello'
- endfunction | echo 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
- delfunc Foo
-endfunc
-
-func Test_delfunction_force()
- delfunc! Xtest
- delfunc! Xtest
- func Xtest()
- echo 'nothing'
- endfunc
- delfunc! Xtest
- delfunc! Xtest
-endfunc
-
" Test using bang after user command {{{1
func Test_user_command_with_bang()
command -bang Nieuw let nieuw = 1
@@ -1553,26 +1504,6 @@ func Test_user_command_with_bang()
delcommand Nieuw
endfunc
-" Test for script-local function
-func <SID>DoLast()
- call append(line('$'), "last line")
-endfunc
-
-func s:DoNothing()
- call append(line('$'), "nothing line")
-endfunc
-
-func Test_script_local_func()
- set nocp nomore viminfo+=nviminfo
- new
- nnoremap <buffer> _x :call <SID>DoNothing()<bar>call <SID>DoLast()<bar>delfunc <SID>DoNothing<bar>delfunc <SID>DoLast<cr>
-
- normal _x
- call assert_equal('nothing line', getline(2))
- call assert_equal('last line', getline(3))
- enew! | close
-endfunc
-
func Test_script_expand_sfile()
let lines =<< trim END
func s:snr()
@@ -1653,6 +1584,22 @@ func Test_compound_assignment_operators()
call assert_equal(4.2, x)
call assert_fails('let x %= 0.5', 'E734')
call assert_fails('let x .= "f"', 'E734')
+ let x = !3.14
+ call assert_equal(0.0, x)
+
+ " integer and float operations
+ let x = 1
+ let x *= 2.1
+ call assert_equal(2.1, x)
+ let x = 1
+ let x /= 0.25
+ call assert_equal(4.0, x)
+ let x = 1
+ call assert_fails('let x %= 0.25', 'E734:')
+ let x = 1
+ call assert_fails('let x .= 0.25', 'E734:')
+ let x = 1.0
+ call assert_fails('let x += [1.1]', 'E734:')
endif
" Test for environment variable
@@ -1716,87 +1663,6 @@ func Test_unlet_env()
call assert_equal('', $TESTVAR)
endfunc
-func Test_funccall_garbage_collect()
- func Func(x, ...)
- call add(a:x, a:000)
- endfunc
- call Func([], [])
- " Must not crash cause by invalid freeing
- call test_garbagecollect_now()
- call assert_true(v:true)
- delfunc Func
-endfunc
-
-func Test_function_defined_line()
- if has('gui_running')
- " Can't catch the output of gvim.
- return
- endif
-
- let lines =<< trim [CODE]
- " F1
- func F1()
- " F2
- func F2()
- "
- "
- "
- return
- endfunc
- " F3
- execute "func F3()\n\n\n\nreturn\nendfunc"
- " F4
- execute "func F4()\n
- \\n
- \\n
- \\n
- \return\n
- \endfunc"
- endfunc
- " F5
- execute "func F5()\n\n\n\nreturn\nendfunc"
- " F6
- execute "func F6()\n
- \\n
- \\n
- \\n
- \return\n
- \endfunc"
- call F1()
- verbose func F1
- verbose func F2
- verbose func F3
- verbose func F4
- verbose func F5
- verbose func F6
- qall!
- [CODE]
-
- call writefile(lines, 'Xtest.vim')
- let res = system(GetVimCommandClean() .. ' -es -X -S Xtest.vim')
- call assert_equal(0, v:shell_error)
-
- let m = matchstr(res, 'function F1()[^[:print:]]*[[:print:]]*')
- call assert_match(' line 2$', m)
-
- let m = matchstr(res, 'function F2()[^[:print:]]*[[:print:]]*')
- call assert_match(' line 4$', m)
-
- let m = matchstr(res, 'function F3()[^[:print:]]*[[:print:]]*')
- call assert_match(' line 11$', m)
-
- let m = matchstr(res, 'function F4()[^[:print:]]*[[:print:]]*')
- call assert_match(' line 13$', m)
-
- let m = matchstr(res, 'function F5()[^[:print:]]*[[:print:]]*')
- call assert_match(' line 21$', m)
-
- let m = matchstr(res, 'function F6()[^[:print:]]*[[:print:]]*')
- call assert_match(' line 23$', m)
-
- call delete('Xtest.vim')
-endfunc
-
" Test for missing :endif, :endfor, :endwhile and :endtry {{{1
func Test_missing_end()
call writefile(['if 2 > 1', 'echo ">"'], 'Xscript')
@@ -1834,6 +1700,9 @@ func Test_missing_end()
" Missing 'in' in a :for statement
call assert_fails('for i range(1) | endfor', 'E690:')
+
+ " Incorrect number of variables in for
+ call assert_fails('for [i,] in range(3) | endfor', 'E475:')
endfunc
" Test for deep nesting of if/for/while/try statements {{{1
@@ -1929,14 +1798,98 @@ func Test_deep_nest()
call delete('Xscript')
endfunc
-" Test for <sfile>, <slnum> in a function {{{1
-func Test_sfile_in_function()
- func Xfunc()
- call assert_match('..Test_sfile_in_function\[5]..Xfunc', expand('<sfile>'))
- call assert_equal('2', expand('<slnum>'))
- endfunc
- call Xfunc()
- delfunc Xfunc
+" Test for errors in converting to float from various types {{{1
+func Test_float_conversion_errors()
+ if has('float')
+ call assert_fails('let x = 4.0 % 2.0', 'E804')
+ call assert_fails('echo 1.1[0]', 'E806')
+ call assert_fails('echo sort([function("min"), 1], "f")', 'E891:')
+ call assert_fails('echo 3.2 == "vim"', 'E892:')
+ call assert_fails('echo sort([[], 1], "f")', 'E893:')
+ call assert_fails('echo sort([{}, 1], "f")', 'E894:')
+ call assert_fails('echo 3.2 == v:true', 'E362:')
+ " call assert_fails('echo 3.2 == v:none', 'E907:')
+ endif
+endfunc
+
+func Test_invalid_function_names()
+ " function name not starting with capital
+ let caught_e128 = 0
+ try
+ func! g:test()
+ echo "test"
+ endfunc
+ catch /E128:/
+ let caught_e128 = 1
+ endtry
+ call assert_equal(1, caught_e128)
+
+ " function name includes a colon
+ let caught_e884 = 0
+ try
+ func! b:test()
+ echo "test"
+ endfunc
+ catch /E884:/
+ let caught_e884 = 1
+ endtry
+ call assert_equal(1, caught_e884)
+
+ " function name folowed by #
+ let caught_e128 = 0
+ try
+ func! test2() "#
+ echo "test2"
+ endfunc
+ catch /E128:/
+ let caught_e128 = 1
+ endtry
+ call assert_equal(1, caught_e128)
+
+ " function name starting with/without "g:", buffer-local funcref.
+ function! g:Foo(n)
+ return 'called Foo(' . a:n . ')'
+ endfunction
+ let b:my_func = function('Foo')
+ call assert_equal('called Foo(1)', b:my_func(1))
+ call assert_equal('called Foo(2)', g:Foo(2))
+ call assert_equal('called Foo(3)', Foo(3))
+ delfunc g:Foo
+
+ " script-local function used in Funcref must exist.
+ let lines =<< trim END
+ func s:Testje()
+ return "foo"
+ endfunc
+ let Bar = function('s:Testje')
+ call assert_equal(0, exists('s:Testje'))
+ call assert_equal(1, exists('*s:Testje'))
+ call assert_equal(1, exists('Bar'))
+ call assert_equal(1, exists('*Bar'))
+ END
+ call writefile(lines, 'Xscript')
+ source Xscript
+ call delete('Xscript')
+endfunc
+
+" substring and variable name
+func Test_substring_var()
+ let str = 'abcdef'
+ let n = 3
+ call assert_equal('def', str[n:])
+ call assert_equal('abcd', str[:n])
+ call assert_equal('d', str[n:n])
+ unlet n
+ let nn = 3
+ call assert_equal('def', str[nn:])
+ call assert_equal('abcd', str[:nn])
+ call assert_equal('d', str[nn:nn])
+ unlet nn
+ let b:nn = 4
+ call assert_equal('ef', str[b:nn:])
+ call assert_equal('abcde', str[:b:nn])
+ call assert_equal('e', str[b:nn:b:nn])
+ unlet b:nn
endfunc
func Test_for_over_string()
diff --git a/src/nvim/testdir/test_window_cmd.vim b/src/nvim/testdir/test_window_cmd.vim
index c4ce4d638c..e01993b99c 100644
--- a/src/nvim/testdir/test_window_cmd.vim
+++ b/src/nvim/testdir/test_window_cmd.vim
@@ -592,6 +592,11 @@ func Test_window_contents()
call assert_equal(59, line("w0"))
call assert_equal('59 ', s3)
+ %d
+ call setline(1, ['one', 'two', 'three'])
+ call assert_equal(1, line('w0'))
+ call assert_equal(3, line('w$'))
+
bwipeout!
call test_garbagecollect_now()
endfunc
diff --git a/src/nvim/testing.c b/src/nvim/testing.c
index 348d5c6e29..45134db14f 100644
--- a/src/nvim/testing.c
+++ b/src/nvim/testing.c
@@ -14,6 +14,9 @@
# include "testing.c.generated.h"
#endif
+static char e_calling_test_garbagecollect_now_while_v_testing_is_not_set[]
+ = N_("E1142: Calling test_garbagecollect_now() while v:testing is not set");
+
/// Prepare "gap" for an assert error and add the sourcing position.
static void prepare_assert_error(garray_T *gap)
{
@@ -614,7 +617,11 @@ void f_test_garbagecollect_now(typval_T *argvars, typval_T *rettv, EvalFuncData
{
// This is dangerous, any Lists and Dicts used internally may be freed
// while still in use.
- garbage_collect(true);
+ if (!get_vim_var_nr(VV_TESTING)) {
+ emsg(_(e_calling_test_garbagecollect_now_while_v_testing_is_not_set));
+ } else {
+ garbage_collect(true);
+ }
}
/// "test_write_list_log()" function
diff --git a/test/functional/legacy/eval_spec.lua b/test/functional/legacy/eval_spec.lua
index 05d853622e..b5e45a86c1 100644
--- a/test/functional/legacy/eval_spec.lua
+++ b/test/functional/legacy/eval_spec.lua
@@ -639,7 +639,7 @@ describe('eval', function()
end)
it('function name includes a colon', function()
- eq('Vim(function):E128: Function name must start with a capital or "s:": b:test()\\nendfunction',
+ eq('Vim(function):E884: Function name cannot contain a colon: b:test()\\nendfunction',
exc_exec(dedent([[
function! b:test()
endfunction]])))
diff --git a/test/functional/ui/tabline_spec.lua b/test/functional/ui/tabline_spec.lua
index 809486d4db..0e35a03557 100644
--- a/test/functional/ui/tabline_spec.lua
+++ b/test/functional/ui/tabline_spec.lua
@@ -84,3 +84,39 @@ describe('ui/ext_tabline', function()
end}
end)
end)
+
+describe("tabline", function()
+ local screen
+
+ before_each(function()
+ clear()
+ screen = Screen.new(42, 5)
+ screen:attach()
+ end)
+
+ it('redraws when tabline option is set', function()
+ command('set tabline=asdf')
+ command('set showtabline=2')
+ screen:expect{grid=[[
+ {1:asdf }|
+ ^ |
+ {2:~ }|
+ {2:~ }|
+ |
+ ]], attr_ids={
+ [1] = {reverse = true};
+ [2] = {bold = true, foreground = Screen.colors.Blue1};
+ }}
+ command('set tabline=jkl')
+ screen:expect{grid=[[
+ {1:jkl }|
+ ^ |
+ {2:~ }|
+ {2:~ }|
+ |
+ ]], attr_ids={
+ [1] = {reverse = true};
+ [2] = {bold = true, foreground = Screen.colors.Blue};
+ }}
+ end)
+end)
diff --git a/test/functional/vimscript/exepath_spec.lua b/test/functional/vimscript/exepath_spec.lua
index 439dd96fcd..db96b79743 100644
--- a/test/functional/vimscript/exepath_spec.lua
+++ b/test/functional/vimscript/exepath_spec.lua
@@ -23,7 +23,7 @@ describe('exepath()', function()
for _, input in ipairs({'v:null', 'v:true', 'v:false', '{}', '[]'}) do
eq('Vim(call):E1174: String required for argument 1', exc_exec('call exepath('..input..')'))
end
- eq('Vim(call):E1142: Non-empty string required for argument 1', exc_exec('call exepath("")'))
+ eq('Vim(call):E1175: Non-empty string required for argument 1', exc_exec('call exepath("")'))
command('let $PATH = fnamemodify("./test/functional/fixtures/bin", ":p")')
for _, input in ipairs({'v:null', 'v:true', 'v:false'}) do
eq('Vim(call):E1174: String required for argument 1', exc_exec('call exepath('..input..')'))
diff --git a/test/unit/eval/typval_spec.lua b/test/unit/eval/typval_spec.lua
index 6387f89fe4..34dbf592a5 100644
--- a/test/unit/eval/typval_spec.lua
+++ b/test/unit/eval/typval_spec.lua
@@ -2253,8 +2253,8 @@ describe('typval.c', function()
local d1 = dict()
alloc_log:check({a.dict(d1)})
eq(1, d1.dv_refcount)
- eq(false, tv_dict_equal(nil, d1))
- eq(false, tv_dict_equal(d1, nil))
+ eq(true, tv_dict_equal(nil, d1))
+ eq(true, tv_dict_equal(d1, nil))
eq(true, tv_dict_equal(d1, d1))
eq(1, d1.dv_refcount)
alloc_log:check({})
@@ -2721,8 +2721,8 @@ describe('typval.c', function()
local d1 = lua2typvalt({})
alloc_log:check({a.dict(d1.vval.v_dict)})
eq(1, d1.vval.v_dict.dv_refcount)
- eq(false, tv_equal(nd, d1))
- eq(false, tv_equal(d1, nd))
+ eq(true, tv_equal(nd, d1))
+ eq(true, tv_equal(d1, nd))
eq(true, tv_equal(d1, d1))
eq(1, d1.vval.v_dict.dv_refcount)
alloc_log:check({})