Merge remote-tracking branch 'vim/master'

This commit is contained in:
ichizok
2022-02-24 09:19:26 +09:00
35 changed files with 685 additions and 146 deletions
+7 -7
View File
@@ -83,7 +83,7 @@ export def FTbas()
setf freebasic
elseif match(lines, qb64_preproc) > -1
setf qb64
elseif match(lines, s:ft_visual_basic_content) > -1
elseif match(lines, ft_visual_basic_content) > -1
setf vb
else
setf basic
@@ -241,7 +241,7 @@ export def FTfrm()
var lines = getline(1, min([line("$"), 5]))
if match(lines, s:ft_visual_basic_content) > -1
if match(lines, ft_visual_basic_content) > -1
setf vb
else
setf form
@@ -434,7 +434,7 @@ export def FTinc()
setf php
# Pascal supports // comments but they're vary rarely used for file
# headers so assume POV-Ray
elseif lines =~ '^\s*\%({\|(\*\)' || lines =~? s:ft_pascal_keywords
elseif lines =~ '^\s*\%({\|(\*\)' || lines =~? ft_pascal_keywords
setf pascal
else
FTasmsyntax()
@@ -496,7 +496,7 @@ export def FTprogress_pascal()
var lnum = 1
while lnum <= 10 && lnum < line('$')
var line = getline(lnum)
if line =~ s:ft_pascal_comments || line =~? s:ft_pascal_keywords
if line =~ ft_pascal_comments || line =~? ft_pascal_keywords
setf pascal
return
elseif line !~ '^\s*$' || line =~ '^/\*'
@@ -514,7 +514,7 @@ export def FTpp()
exe "setf " .. g:filetype_pp
else
var line = getline(nextnonblank(1))
if line =~ s:ft_pascal_comments || line =~? s:ft_pascal_keywords
if line =~ ft_pascal_comments || line =~? ft_pascal_keywords
setf pascal
else
setf puppet
@@ -685,8 +685,8 @@ export def FTRules()
endtry
var dir = expand('<amatch>:p:h')
for line in config_lines
if line =~ s:ft_rules_udev_rules_pattern
var udev_rules = substitute(line, s:ft_rules_udev_rules_pattern, '\1', "")
if line =~ ft_rules_udev_rules_pattern
var udev_rules = substitute(line, ft_rules_udev_rules_pattern, '\1', "")
if dir == udev_rules
setf udevrules
endif
+12 -11
View File
@@ -539,8 +539,8 @@ sin({expr}) Float sine of {expr}
sinh({expr}) Float hyperbolic sine of {expr}
slice({expr}, {start} [, {end}]) String, List or Blob
slice of a String, List or Blob
sort({list} [, {func} [, {dict}]])
List sort {list}, using {func} to compare
sort({list} [, {how} [, {dict}]])
List sort {list}, compare with {how}
sound_clear() none stop playing all sounds
sound_playevent({name} [, {callback}])
Number play an event sound
@@ -8033,21 +8033,22 @@ slice({expr}, {start} [, {end}]) *slice()*
GetList()->slice(offset)
sort({list} [, {func} [, {dict}]]) *sort()* *E702*
sort({list} [, {how} [, {dict}]]) *sort()* *E702*
Sort the items in {list} in-place. Returns {list}.
If you want a list to remain unmodified make a copy first: >
:let sortedlist = sort(copy(mylist))
< When {func} is omitted, is empty or zero, then sort() uses the
< When {how} is omitted or is an string, then sort() uses the
string representation of each item to sort on. Numbers sort
after Strings, |Lists| after Numbers. For sorting text in the
current buffer use |:sort|.
When {func} is given and it is '1' or 'i' then case is
ignored.
When {how} is given and it is 'i' then case is ignored.
In legacy script, for backwards compatibility, the value one
can be used to ignore case. Zero means to not ignore case.
When {func} is given and it is 'l' then the current collation
When {how} is given and it is 'l' then the current collation
locale is used for ordering. Implementation details: strcoll()
is used to compare strings. See |:language| check or set the
collation locale. |v:collate| can also be used to check the
@@ -8064,19 +8065,19 @@ sort({list} [, {func} [, {dict}]]) *sort()* *E702*
< ['n', 'o', 'O', 'p', 'z', 'ö'] ~
This does not work properly on Mac.
When {func} is given and it is 'n' then all items will be
When {how} is given and it is 'n' then all items will be
sorted numerical (Implementation detail: this uses the
strtod() function to parse numbers, Strings, Lists, Dicts and
Funcrefs will be considered as being 0).
When {func} is given and it is 'N' then all items will be
When {how} is given and it is 'N' then all items will be
sorted numerical. This is like 'n' but a string containing
digits will be used as the number they represent.
When {func} is given and it is 'f' then all items will be
When {how} is given and it is 'f' then all items will be
sorted numerical. All values must be a Number or a Float.
When {func} is a |Funcref| or a function name, this function
When {how} is a |Funcref| or a function name, this function
is called to compare items. The function is invoked with two
items as argument and must return zero if they are equal, 1 or
bigger if the first one sorts after the second one, -1 or
+1
View File
@@ -411,6 +411,7 @@ T *+mouse* Mouse handling |mouse-using|
N *+mouseshape* |'mouseshape'|
B *+mouse_dec* Unix only: Dec terminal mouse handling |dec-mouse|
N *+mouse_gpm* Unix only: Linux console mouse handling |gpm-mouse|
m *+mouse_gpm/dyn* Same as |+mouse_gpm| with optional library dependency |/dyn|
N *+mouse_jsbterm* JSB mouse handling |jsbterm-mouse|
B *+mouse_netterm* Unix only: netterm mouse handling |netterm-mouse|
N *+mouse_pterm* QNX only: pterm mouse handling |qnx-terminal|
+7 -5
View File
@@ -1,4 +1,4 @@
*vim9.txt* For Vim version 8.2. Last change: 2022 Feb 18
*vim9.txt* For Vim version 8.2. Last change: 2022 Feb 22
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -245,9 +245,11 @@ that the name interferes with builtin functions.
*vim9-s-namespace*
The use of the "s:" prefix is not supported at the Vim9 script level. All
functions and variables without a prefix are script-local.
In :def functions the use of "s:" is optional. This is because in legacy
script the "s:" might be needed. Disallowing the use of "s:" only in a :def
function in Vim9 script would be a bit confusing.
In :def functions the use of "s:" depends on the script: Script-local
variables and functions in a legacy script do use "s:", while in a Vim9 script
they do not use "s:". This matches what you see in the rest of the file.
In legacy functions the use of "s:" for script items is required, as before.
In all cases the function must be defined before used. That is when it is
@@ -1467,7 +1469,7 @@ strings: >
# typename(mylist) == "list<string>", no error
There is a subtle difference between using a list constant directly and
through a variable declaraiton. Because of type inference, when using a list
through a variable declaration. Because of type inference, when using a list
constant to initialize a variable, this also sets the declared type: >
var mylist = [1, 2, 3]
# typename(mylist) == "list<number>"
+2 -2
View File
@@ -2,7 +2,7 @@
" You can also use this as a start for your own set of menus.
"
" Maintainer: Bram Moolenaar <Bram@vim.org>
" Last Change: 2022 Feb 04
" Last Change: 2022 Feb 23
" Note that ":an" (short for ":anoremenu") is often used to make a menu work
" in all modes and avoid side effects from mappings defined by the user.
@@ -443,7 +443,7 @@ def s:SetupColorSchemes()
n += globpath(&packpath, "pack/*/opt/*/colors/*.vim", 1, 1)
# Ignore case for VMS and windows, sort on name
var names = sort(map(n, 'substitute(v:val, "\\c.*[/\\\\:\\]]\\([^/\\\\:]*\\)\\.vim", "\\1", "")'), 1)
var names = sort(map(n, 'substitute(v:val, "\\c.*[/\\\\:\\]]\\([^/\\\\:]*\\)\\.vim", "\\1", "")'), 'i')
# define all the submenu entries
var idx = 100
+2
View File
@@ -526,6 +526,8 @@ CClink = $(CC)
# though you have gpm libraries and includes.
# For Debian/Ubuntu gpm support requires the libgpm-dev package.
#CONF_OPT_GPM = --disable-gpm
# Use this to enable dynamic loading of the GPM library.
#CONF_OPT_GPM = --enable-gpm=dynamic
# sysmouse - For mouse support on FreeBSD and DragonFly console via sysmouse
# Uncomment this when you do not want do include sysmouse support, even
+3
View File
@@ -507,3 +507,6 @@
/* Define if _SC_SIGSTKSZ is available via sysconf() */
#undef HAVE_SYSCONF_SIGSTKSZ
/* Define if you want to load libgpm dynamically */
#undef DYNAMIC_GPM
+10 -6
View File
@@ -4294,13 +4294,13 @@ if test "x$GTK_CFLAGS" != "x"; then
LIBS="$ac_save_LIBS"
fi
AC_MSG_CHECKING(--disable-gpm argument)
AC_MSG_CHECKING(--enable-gpm argument)
AC_ARG_ENABLE(gpm,
[ --disable-gpm Don't use gpm (Linux mouse daemon).], ,
[ --enable-gpm=OPTS Use gpm (Linux mouse daemon). default=yes OPTS=yes/no/dynamic], ,
[enable_gpm="yes"])
if test "$enable_gpm" = "yes"; then
AC_MSG_RESULT(no)
if test "$enable_gpm" = "yes" -o "$enable_gpm" = "dynamic"; then
AC_MSG_RESULT($enable_gpm)
dnl Checking if gpm support can be compiled
AC_CACHE_CHECK([for gpm], vi_cv_have_gpm,
[olibs="$LIBS" ; LIBS="-lgpm"]
@@ -4315,11 +4315,15 @@ if test "$enable_gpm" = "yes"; then
[LIBS="$olibs"]
)
if test $vi_cv_have_gpm = yes; then
LIBS="$LIBS -lgpm"
if test "$enable_gpm" = "yes"; then
LIBS="$LIBS -lgpm"
else
AC_DEFINE(DYNAMIC_GPM)
fi
AC_DEFINE(HAVE_GPM)
fi
else
AC_MSG_RESULT(yes)
AC_MSG_RESULT(no)
fi
AC_MSG_CHECKING(--disable-sysmouse argument)
+2 -1
View File
@@ -3015,7 +3015,8 @@ EXTERN char e_variable_arguments_type_must_be_list_str[]
INIT(= N_("E1180: Variable arguments type must be a list: %s"));
EXTERN char e_cannot_use_underscore_here[]
INIT(= N_("E1181: Cannot use an underscore here"));
// E1182 unused
EXTERN char e_cannot_define_dict_func_in_vim9_script_str[]
INIT(= N_("E1182: Cannot define a dict function in Vim9 script: %s"));
EXTERN char e_cannot_use_range_with_assignment_operator_str[]
INIT(= N_("E1183: Cannot use a range with an assignment operator: %s"));
#endif
+116 -77
View File
@@ -485,6 +485,82 @@ arg_list_or_dict_or_blob_or_string(type_T *type, type_T *decl_type UNUSED, argco
return FAIL;
}
/*
* Check second argument of map() or filter().
*/
static int
check_map_filter_arg2(type_T *type, argcontext_T *context, int is_map)
{
type_T *expected_member = NULL;
type_T *(args[2]);
type_T t_func_exp = {VAR_FUNC, 2, 0, 0, NULL, args};
if (context->arg_types[0].type_curr->tt_type == VAR_LIST
|| context->arg_types[0].type_curr->tt_type == VAR_DICT)
{
// Use the declared type if possible, so that an error is given if
// a declared list changes type, but not if a constant list changes
// type.
if (context->arg_types[0].type_decl->tt_type == VAR_LIST
|| context->arg_types[0].type_decl->tt_type == VAR_DICT)
expected_member = context->arg_types[0].type_decl->tt_member;
else
expected_member = context->arg_types[0].type_curr->tt_member;
}
else if (context->arg_types[0].type_curr->tt_type == VAR_STRING)
expected_member = &t_string;
else if (context->arg_types[0].type_curr->tt_type == VAR_BLOB)
expected_member = &t_number;
args[0] = NULL;
args[1] = &t_unknown;
if (type->tt_argcount != -1)
{
if (!(type->tt_argcount == 2 || (type->tt_argcount == 1
&& (type->tt_flags & TTFLAG_VARARGS))))
{
emsg(_(e_invalid_number_of_arguments));
return FAIL;
}
if (type->tt_flags & TTFLAG_VARARGS)
// check the argument types at runtime
t_func_exp.tt_argcount = -1;
else
{
if (context->arg_types[0].type_curr->tt_type == VAR_STRING
|| context->arg_types[0].type_curr->tt_type == VAR_BLOB
|| context->arg_types[0].type_curr->tt_type == VAR_LIST)
args[0] = &t_number;
else if (context->arg_types[0].type_decl->tt_type == VAR_DICT)
args[0] = &t_string;
if (args[0] != NULL)
args[1] = expected_member;
}
}
if ((type->tt_member != &t_any && type->tt_member != &t_unknown)
|| args[0] != NULL)
{
where_T where = WHERE_INIT;
if (is_map)
t_func_exp.tt_member = expected_member == NULL
|| type->tt_member == &t_any
|| type->tt_member == &t_unknown
? &t_any : expected_member;
else
t_func_exp.tt_member = &t_bool;
if (args[0] == NULL)
args[0] = &t_unknown;
if (type->tt_argcount == -1)
t_func_exp.tt_argcount = -1;
where.wt_index = 2;
return check_type(&t_func_exp, type, TRUE, where);
}
return OK;
}
/*
* Check second argument of filter(): func must return a bool.
*/
@@ -498,22 +574,9 @@ arg_filter_func(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
return OK;
if (type->tt_type == VAR_FUNC)
{
if (!(type->tt_member->tt_type == VAR_BOOL
|| type->tt_member->tt_type == VAR_NUMBER
|| type->tt_member->tt_type == VAR_UNKNOWN
|| type->tt_member->tt_type == VAR_ANY))
{
arg_type_mismatch(&t_func_bool, type, context->arg_idx + 1);
return FAIL;
}
}
else
{
semsg(_(e_string_or_function_required_for_argument_nr), 2);
return FAIL;
}
return OK;
return check_map_filter_arg2(type, context, FALSE);
semsg(_(e_string_or_function_required_for_argument_nr), 2);
return FAIL;
}
/*
@@ -521,6 +584,24 @@ arg_filter_func(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
*/
static int
arg_map_func(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
{
if (type->tt_type == VAR_STRING
|| type->tt_type == VAR_PARTIAL
|| type == &t_unknown
|| type == &t_any)
return OK;
if (type->tt_type == VAR_FUNC)
return check_map_filter_arg2(type, context, TRUE);
semsg(_(e_string_or_function_required_for_argument_nr), 2);
return FAIL;
}
/*
* Check second argument of sort() and uniq(), the "how" argument.
*/
static int
arg_sort_how(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
{
if (type->tt_type == VAR_STRING
|| type->tt_type == VAR_PARTIAL
@@ -530,75 +611,29 @@ arg_map_func(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
if (type->tt_type == VAR_FUNC)
{
type_T *expected_ret = NULL;
type_T *(args[2]);
type_T t_func_exp = {VAR_FUNC, 2, 0, 0, NULL, args};
if (context->arg_types[0].type_curr->tt_type == VAR_LIST
|| context->arg_types[0].type_curr->tt_type == VAR_DICT)
{
// Use the declared type if possible, so that an error is given if
// a declared list changes type, but not if a constant list changes
// type.
if (context->arg_types[0].type_decl->tt_type == VAR_LIST
|| context->arg_types[0].type_decl->tt_type == VAR_DICT)
expected_ret = context->arg_types[0].type_decl->tt_member;
else
expected_ret = context->arg_types[0].type_curr->tt_member;
}
else if (context->arg_types[0].type_curr->tt_type == VAR_STRING)
expected_ret = &t_string;
else if (context->arg_types[0].type_curr->tt_type == VAR_BLOB)
expected_ret = &t_number;
args[0] = NULL;
args[1] = &t_unknown;
if (type->tt_argcount != -1)
{
if (!(type->tt_argcount == 2 || (type->tt_argcount == 1
&& (type->tt_flags & TTFLAG_VARARGS))))
{
emsg(_(e_invalid_number_of_arguments));
return FAIL;
}
if (type->tt_flags & TTFLAG_VARARGS)
// check the argument types at runtime
t_func_exp.tt_argcount = -1;
else
{
if (context->arg_types[0].type_curr->tt_type == VAR_STRING
|| context->arg_types[0].type_curr->tt_type == VAR_BLOB
|| context->arg_types[0].type_curr->tt_type == VAR_LIST)
args[0] = &t_number;
else if (context->arg_types[0].type_decl->tt_type == VAR_DICT)
args[0] = &t_string;
if (args[0] != NULL)
args[1] = expected_ret;
}
}
type_T t_func_exp = {VAR_FUNC, 2, 0, 0, &t_number, args};
if (context->arg_types[0].type_curr->tt_type == VAR_LIST)
args[0] = context->arg_types[0].type_curr->tt_member;
else
args[0] = &t_unknown;
if ((type->tt_member != &t_any && type->tt_member != &t_unknown)
|| args[0] != NULL)
|| args[0] != &t_unknown)
{
where_T where = WHERE_INIT;
t_func_exp.tt_member = expected_ret == NULL
|| type->tt_member == &t_any
|| type->tt_member == &t_unknown
? &t_any : expected_ret;
if (args[0] == NULL)
args[0] = &t_unknown;
args[1] = args[0];
if (type->tt_argcount == -1)
t_func_exp.tt_argcount = -1;
where.wt_index = 2;
return check_type(&t_func_exp, type, TRUE, where);
}
return OK;
}
else
{
semsg(_(e_string_or_function_required_for_argument_nr), 2);
return FAIL;
}
return OK;
semsg(_(e_string_or_function_required_for_argument_nr), 2);
return FAIL;
}
/*
@@ -1012,7 +1047,7 @@ static argcheck_T arg23_settagstack[] = {arg_number, arg_dict_any, arg_string};
static argcheck_T arg02_sign_getplaced[] = {arg_buffer, arg_dict_any};
static argcheck_T arg45_sign_place[] = {arg_number, arg_string, arg_string, arg_buffer, arg_dict_any};
static argcheck_T arg23_slice[] = {arg_slice1, arg_number, arg_number};
static argcheck_T arg13_sortuniq[] = {arg_list_any, NULL, arg_dict_any};
static argcheck_T arg13_sortuniq[] = {arg_list_any, arg_sort_how, arg_dict_any};
static argcheck_T arg24_strpart[] = {arg_string, arg_number, arg_number, arg_bool};
static argcheck_T arg12_system[] = {arg_string, arg_str_or_nr_or_list};
static argcheck_T arg23_win_execute[] = {arg_number, arg_string_or_list_string, arg_string};
@@ -5769,7 +5804,7 @@ f_has(typval_T *argvars, typval_T *rettv)
#endif
},
{"mouse_gpm",
#if (defined(UNIX) || defined(VMS)) && defined(FEAT_MOUSE_GPM)
#if (defined(UNIX) || defined(VMS)) && defined(FEAT_MOUSE_GPM) && !defined(DYNAMIC_GPM)
1
#else
0
@@ -6395,6 +6430,10 @@ f_has(typval_T *argvars, typval_T *rettv)
#if defined(FEAT_TERMINAL) && defined(MSWIN)
else if (STRICMP(name, "terminal") == 0)
n = terminal_enabled();
#endif
#ifdef DYNAMIC_GPM
else if (STRICMP(name, "mouse_gpm") == 0)
n = gpm_available();
#endif
}
+6
View File
@@ -964,6 +964,12 @@
*/
#if defined(FEAT_NORMAL) && defined(HAVE_GPM)
# define FEAT_MOUSE_GPM
/*
* +mouse_gpm/dyn Load libgpm dynamically.
*/
# ifndef DYNAMIC_GPM
// # define DYNAMIC_GPM
# endif
#endif
#if defined(FEAT_NORMAL) && defined(HAVE_SYSMOUSE)
+2 -1
View File
@@ -2198,7 +2198,8 @@ do_sort_uniq(typval_T *argvars, typval_T *rettv, int sort)
if (in_vim9script()
&& (check_for_list_arg(argvars, 0) == FAIL
|| (argvars[1].v_type != VAR_UNKNOWN
&& check_for_opt_dict_arg(argvars, 2) == FAIL)))
&& (check_for_string_or_func_arg(argvars, 1) == FAIL
|| check_for_opt_dict_arg(argvars, 2) == FAIL))))
return;
if (argvars[0].v_type != VAR_LIST)
+2 -1
View File
@@ -318,6 +318,7 @@ enc_alias_table[] =
{
{"ansi", IDX_LATIN_1},
{"iso-8859-1", IDX_LATIN_1},
{"iso-8859", IDX_LATIN_1},
{"latin2", IDX_ISO_2},
{"latin3", IDX_ISO_3},
{"latin4", IDX_ISO_4},
@@ -4523,7 +4524,7 @@ enc_canonize(char_u *enc)
}
// "iso-8859n" -> "iso-8859-n"
if (STRNCMP(p, "iso-8859", 8) == 0 && p[8] != '-')
if (STRNCMP(p, "iso-8859", 8) == 0 && isdigit(p[8]))
{
STRMOVE(p + 9, p + 8);
p[8] = '-';
+8
View File
@@ -4587,6 +4587,14 @@ get_encoding_default(void)
return (char_u *)NULL;
}
int
is_option_allocated(char *name)
{
int idx = findoption((char_u *)name);
return idx >= 0 && (options[idx].flags & P_ALLOCED);
}
/*
* Translate a string like "t_xx", "<t_xx>" or "<S-Tab>" to a key number.
* When "has_lt" is true there is a '<' before "*arg_arg".
+67 -1
View File
@@ -55,7 +55,25 @@ static int selinux_enabled = -1;
#endif
#ifdef FEAT_MOUSE_GPM
# include <gpm.h>
# ifdef DYNAMIC_GPM
# define Gpm_Open (*dll_Gpm_Open)
# define Gpm_Close (*dll_Gpm_Close)
# define Gpm_GetEvent (*dll_Gpm_GetEvent)
# define gpm_flag (dll_gpm_flag != NULL ? *dll_gpm_flag : 0)
# define gpm_fd (dll_gpm_fd != NULL ? *dll_gpm_fd : -1)
static int (*dll_Gpm_Open) (Gpm_Connect *, int);
static int (*dll_Gpm_Close) (void);
static int (*dll_Gpm_GetEvent) (Gpm_Event *);
static int *dll_gpm_flag;
static int *dll_gpm_fd;
static void *libgpm_hinst;
# endif
// <linux/keyboard.h> contains defines conflicting with "keymap.h",
// I just copied relevant defines here. A cleaner solution would be to put gpm
// code into separate file and include there linux/keyboard.h
@@ -6468,7 +6486,7 @@ select_eintr:
}
# endif
# ifdef FEAT_MOUSE_GPM
if (ret > 0 && gpm_flag && check_for_gpm != NULL && gpm_fd >= 0)
if (ret > 0 && check_for_gpm != NULL && gpm_flag && gpm_fd >= 0)
{
if (FD_ISSET(gpm_fd, &efds))
gpm_close();
@@ -7194,6 +7212,49 @@ mch_rename(const char *src, const char *dest)
#endif // !HAVE_RENAME
#if defined(FEAT_MOUSE_GPM) || defined(PROTO)
# if defined(DYNAMIC_GPM) || defined(PROTO)
/*
* Initialize Gpm's symbols for dynamic linking.
* Must be called only if libgpm_hinst is NULL.
*/
static int
load_libgpm(void)
{
libgpm_hinst = dlopen("libgpm.so", RTLD_LAZY|RTLD_GLOBAL);
if (libgpm_hinst == NULL)
{
if (p_verbose > 0)
smsg_attr(HL_ATTR(HLF_W),
_("Could not load gpm library: %s"), dlerror());
return FAIL;
}
if (
(dll_Gpm_Open = dlsym(libgpm_hinst, "Gpm_Open")) == NULL
|| (dll_Gpm_Close = dlsym(libgpm_hinst, "Gpm_Close")) == NULL
|| (dll_Gpm_GetEvent = dlsym(libgpm_hinst, "Gpm_GetEvent")) == NULL
|| (dll_gpm_flag = dlsym(libgpm_hinst, "gpm_flag")) == NULL
|| (dll_gpm_fd = dlsym(libgpm_hinst, "gpm_fd")) == NULL
)
{
semsg(_(e_could_not_load_library_str_str), "gpm", dlerror());
dlclose(libgpm_hinst);
libgpm_hinst = NULL;
dll_gpm_flag = NULL;
dll_gpm_fd = NULL;
return FAIL;
}
return OK;
}
int
gpm_available(void)
{
return libgpm_hinst != NULL || load_libgpm() == OK;
}
# endif // DYNAMIC_GPM
/*
* Initializes connection with gpm (if it isn't already opened)
* Return 1 if succeeded (or connection already opened), 0 if failed
@@ -7203,6 +7264,11 @@ gpm_open(void)
{
static Gpm_Connect gpm_connect; // Must it be kept till closing ?
#ifdef DYNAMIC_GPM
if (!gpm_available())
return 0;
#endif
if (!gpm_flag)
{
gpm_connect.eventMask = (GPM_UP | GPM_DRAG | GPM_DOWN);
+1
View File
@@ -41,6 +41,7 @@ char *set_option_value(char_u *name, long number, char_u *string, int opt_flags)
char_u *get_term_code(char_u *tname);
char_u *get_highlight_default(void);
char_u *get_encoding_default(void);
int is_option_allocated(char *name);
int makeset(FILE *fd, int opt_flags, int local_only);
int makefoldset(FILE *fd);
void clear_termoptions(void);
+1
View File
@@ -85,4 +85,5 @@ void clip_xterm_set_selection(Clipboard_T *cbd);
int xsmp_handle_requests(void);
void xsmp_init(void);
void xsmp_close(void);
int gpm_available(void);
/* vim: set ft=c : */
+4 -1
View File
@@ -8235,6 +8235,7 @@ ex_helpgrep(exarg_T *eap)
{
regmatch_T regmatch;
char_u *save_cpo;
int save_cpo_allocated;
qf_info_T *qi = &ql_info;
int new_qi = FALSE;
char_u *au_name = NULL;
@@ -8265,6 +8266,7 @@ ex_helpgrep(exarg_T *eap)
// Make 'cpoptions' empty, the 'l' flag should not be used here.
save_cpo = p_cpo;
save_cpo_allocated = is_option_allocated("cpo");
p_cpo = empty_option;
incr_quickfix_busy();
@@ -8302,7 +8304,8 @@ ex_helpgrep(exarg_T *eap)
// changed and restored, need to restore in the complicated way.
if (*p_cpo == NUL)
set_option_value((char_u *)"cpo", 0L, save_cpo, 0);
free_string_option(save_cpo);
if (save_cpo_allocated)
free_string_option(save_cpo);
}
if (updated)
+5
View File
@@ -4615,6 +4615,11 @@ regmatch(
if (rex.input == rex.line)
{
// backup to last char of previous line
if (rex.lnum == 0)
{
status = RA_NOMATCH;
break;
}
--rex.lnum;
rex.line = reg_getline(rex.lnum);
// Just in case regrepeat() didn't count
+18
View File
@@ -1,6 +1,7 @@
" Tests for exiting Vim.
source shared.vim
source check.vim
func Test_exiting()
let after =<< trim [CODE]
@@ -109,4 +110,21 @@ func Test_exit_code()
call delete('Xtestout')
endfunc
func Test_exit_error_reading_input()
CheckNotGui
CheckNotMSWindows
" The early exit causes memory not to be freed somehow
CheckNotAsan
call writefile([":au VimLeave * call writefile(['l = ' .. v:exiting], 'Xtestout')", ":tabnew", "q:"], 'Xscript', 'b')
if RunVim([], [], '<Xscript')
call assert_equal(1, v:shell_error)
call assert_equal(['l = 1'], readfile('Xtestout'))
endif
call delete('Xscript')
call delete('Xtestout')
endfun
" vim: shiftwidth=2 sts=2 expandtab
+11 -1
View File
@@ -949,7 +949,7 @@ func Test_reverse_sort_uniq()
call assert_equal([-1, 'one', 'two', 'three', 'four', 1.0e-15, 0.22, 7, 9, 12, 18, 22, 255], sort(copy(l), 'n'))
LET l = [7, 9, 18, 12, 22, 10.0e-16, -1, 0xff, 0, -0, 0.22, 'bar', 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', {}, []]
call assert_equal(['bar', 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}], sort(copy(l), 1))
call assert_equal(['bar', 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}], sort(copy(l), 'i'))
call assert_equal(['bar', 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}], sort(copy(l), 'i'))
call assert_equal(['BAR', 'Bar', 'FOO', 'FOOBAR', 'Foo', 'bar', 'foo', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}], sort(copy(l)))
endif
@@ -961,6 +961,16 @@ func Test_reverse_sort_uniq()
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'))", "E118:")
let lines =<< trim END
call sort(['a', 'b'], 0)
END
call v9.CheckDefAndScriptFailure(lines, 'E1256: String or function required for argument 2')
let lines =<< trim END
call sort(['a', 'b'], 1)
END
call v9.CheckDefAndScriptFailure(lines, 'E1256: String or function required for argument 2')
endfunc
" reduce a list, blob or string
+25
View File
@@ -445,6 +445,31 @@ func Test_set_errors()
call assert_fails('set t_#-&', 'E522:')
endfunc
func Test_set_encoding()
let save_encoding = &encoding
set enc=iso8859-1
call assert_equal('latin1', &enc)
set enc=iso8859_1
call assert_equal('latin1', &enc)
set enc=iso-8859-1
call assert_equal('latin1', &enc)
set enc=iso_8859_1
call assert_equal('latin1', &enc)
set enc=iso88591
call assert_equal('latin1', &enc)
set enc=iso8859
call assert_equal('latin1', &enc)
set enc=iso-8859
call assert_equal('latin1', &enc)
set enc=iso_8859
call assert_equal('latin1', &enc)
call assert_fails('set enc=iso8858', 'E474:')
call assert_equal('latin1', &enc)
let &encoding = save_encoding
endfunc
func CheckWasSet(name)
let verb_cm = execute('verbose set ' .. a:name .. '?')
call assert_match('Last set from.*test_options.vim', verb_cm)
+27
View File
@@ -745,6 +745,33 @@ def Test_helpgrep_vim9_restore_cpo()
helpclose
enddef
func Test_helpgrep_restore_cpo_aucmd()
let save_cpo = &cpo
augroup QF_Test
au!
autocmd BufNew * set cpo=acd
augroup END
helpgrep quickfix
call assert_equal('acd', &cpo)
%bw!
set cpo&vim
augroup QF_Test
au!
autocmd BufReadPost * set cpo=
augroup END
helpgrep buffer
call assert_equal('', &cpo)
augroup QF_Test
au!
augroup END
%bw!
let &cpo = save_cpo
endfunc
def Test_vim9_cexpr()
var text = 'somefile:95:error'
cexpr text
+10 -2
View File
@@ -508,7 +508,6 @@ endfunc
" Check that [[:upper:]] matches for automatic engine
func Test_match_char_class_upper()
new
let _engine=&regexpengine
" Test 1: [[:upper:]]\{2,\}
set regexpengine=0
@@ -549,7 +548,7 @@ func Test_match_char_class_upper()
call assert_equal(4, searchcount().total, 'TEST 3 lower')
" clean up
let &regexpengine=_engine
set regexpengine=0
bwipe!
endfunc
@@ -561,4 +560,13 @@ func Test_match_invalid_byte()
call delete('Xinvalid')
endfunc
func Test_match_too_complicated()
set regexpengine=1
exe "noswapfile vsplit \xeb\xdb\x99"
silent! buf \&\zs*\zs*0
bwipe!
set regexpengine=0
endfunc
" vim: shiftwidth=2 sts=2 expandtab
+2 -1
View File
@@ -715,7 +715,8 @@ endfunction
func Test_terminal_noblock()
let g:test_is_flaky = 1
let buf = term_start(&shell)
let wait_time = 5000
" Starting a terminal can be slow, esp. on busy CI machines.
let wait_time = 7500
let letters = 'abcdefghijklmnopqrstuvwxyz'
if has('bsd') || has('mac') || has('sun')
" The shell or something else has a problem dealing with more than 1000
+4 -3
View File
@@ -445,12 +445,13 @@ endfunc
func Test_vartabstop_latin1()
let save_encoding = &encoding
new
set encoding=iso8859
silent norm :se 
set encoding=iso8859-1
set compatible linebreak list revins smarttab
set vartabstop=400
norm i00 
exe "norm i00\t\<C-D>"
bwipe!
let &encoding = save_encoding
set nocompatible linebreak& list& revins& smarttab& vartabstop&
endfunc
+44 -1
View File
@@ -220,7 +220,7 @@ def Test_assignment()
enddef
defcompile
END
v9.CheckScriptFailure(lines, 'E1089:')
v9.CheckScriptFailure(lines, 'E1268:')
g:inc_counter += 1
assert_equal(2, g:inc_counter)
@@ -2460,6 +2460,49 @@ def Run_Test_declare_command_line()
g:StopVimInTerminal(buf)
enddef
def Test_using_s_var_in_function()
var lines =<< trim END
vim9script
var scriptlevel = 123
def SomeFunc()
echo s:scriptlevel
enddef
SomeFunc()
END
v9.CheckScriptFailure(lines, 'E1268:')
# OK in legacy script
lines =<< trim END
let s:scriptlevel = 123
def s:SomeFunc()
echo s:scriptlevel
enddef
call s:SomeFunc()
END
v9.CheckScriptSuccess(lines)
lines =<< trim END
vim9script
var scriptlevel = 123
def SomeFunc()
s:scriptlevel = 456
enddef
SomeFunc()
END
v9.CheckScriptFailure(lines, 'E1268:')
# OK in legacy script
lines =<< trim END
let s:scriptlevel = 123
def s:SomeFunc()
s:scriptlevel = 456
enddef
call s:SomeFunc()
call assert_equal(456, s:scriptlevel)
END
v9.CheckScriptSuccess(lines)
enddef
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
+117 -14
View File
@@ -427,6 +427,21 @@ def Test_call_call()
call('reverse', [l])
l->assert_equal([1, 2, 3])
var lines =<< trim END
vim9script
def Outer()
def g:Inner()
g:done = 'Inner'
enddef
call(g:Inner, [])
enddef
Outer()
assert_equal('Inner', g:done)
unlet g:done
END
v9.CheckScriptSuccess(lines)
delfunc g:Inner
v9.CheckDefExecAndScriptFailure(['call(123, [2])'], 'E1256: String or function required for argument 1')
v9.CheckDefExecAndScriptFailure(['call(true, [2])'], 'E1256: String or function required for argument 1')
v9.CheckDefAndScriptFailure(['call("reverse", 2)'], ['E1013: Argument 2: type mismatch, expected list<any> but got number', 'E1211: List required for argument 2'])
@@ -1315,17 +1330,6 @@ def Wrong_dict_key_type(items: list<number>): list<number>
enddef
def Test_filter()
v9.CheckDefAndScriptFailure(['filter(1.1, "1")'], ['E1013: Argument 1: type mismatch, expected list<any> but got float', 'E1251: List, Dictionary, Blob or String required for argument 1'])
v9.CheckDefAndScriptFailure(['filter([1, 2], 4)'], ['E1256: String or function required for argument 2', 'E1024: Using a Number as a String'])
var lines =<< trim END
def F(i: number, v: any): string
return 'bad'
enddef
echo filter([1, 2, 3], F)
END
v9.CheckDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(...): bool', 'E1135: Using a String as a Bool:'])
assert_equal([], filter([1, 2, 3], '0'))
assert_equal([1, 2, 3], filter([1, 2, 3], '1'))
assert_equal({b: 20}, filter({a: 10, b: 20}, 'v:val == 20'))
@@ -1335,6 +1339,72 @@ def Test_filter()
return range(3)->filter(Odd)
enddef
assert_equal([1], GetFiltered())
var lines =<< trim END
vim9script
def Func(): list<string>
var MatchWord: func: bool = (_, v) => true
var l = ['xxx']
return l->filter(MatchWord)
enddef
assert_equal(['xxx'], Func())
END
v9.CheckScriptSuccess(lines)
v9.CheckDefAndScriptFailure(['filter(1.1, "1")'], ['E1013: Argument 1: type mismatch, expected list<any> but got float', 'E1251: List, Dictionary, Blob or String required for argument 1'])
v9.CheckDefAndScriptFailure(['filter([1, 2], 4)'], ['E1256: String or function required for argument 2', 'E1024: Using a Number as a String'])
lines =<< trim END
def F(i: number, v: any): string
return 'bad'
enddef
echo filter([1, 2, 3], F)
END
v9.CheckDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?any): bool but got func(number, any): string', 'E1135: Using a String as a Bool:'])
# check first function argument type
lines =<< trim END
var l = [1, 2, 3]
filter(l, (i: string, v: number) => true)
END
v9.CheckDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?number): bool but got func(string, number): bool', 'E1013: Argument 1: type mismatch, expected string but got number'])
lines =<< trim END
var d = {a: 1}
filter(d, (i: number, v: number) => true)
END
v9.CheckDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?string, ?number): bool but got func(number, number): bool', 'E1013: Argument 1: type mismatch, expected number but got string'])
lines =<< trim END
var b = 0z1122
filter(b, (i: string, v: number) => true)
END
v9.CheckDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?number): bool but got func(string, number): bool', 'E1013: Argument 1: type mismatch, expected string but got number'])
lines =<< trim END
var s = 'text'
filter(s, (i: string, v: string) => true)
END
v9.CheckDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?string): bool but got func(string, string): bool', 'E1013: Argument 1: type mismatch, expected string but got number'])
# check second function argument type
lines =<< trim END
var l = [1, 2, 3]
filter(l, (i: number, v: string) => true)
END
v9.CheckDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?number): bool but got func(number, string): bool', 'E1013: Argument 2: type mismatch, expected string but got number'])
lines =<< trim END
var d = {a: 1}
filter(d, (i: string, v: string) => true)
END
v9.CheckDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?string, ?number): bool but got func(string, string): bool', 'E1013: Argument 2: type mismatch, expected string but got number'])
lines =<< trim END
var b = 0z1122
filter(b, (i: number, v: string) => true)
END
v9.CheckDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?number): bool but got func(number, string): bool', 'E1013: Argument 2: type mismatch, expected string but got number'])
lines =<< trim END
var s = 'text'
filter(s, (i: number, v: number) => true)
END
v9.CheckDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?string): bool but got func(number, number): bool', 'E1013: Argument 2: type mismatch, expected number but got string'])
enddef
def Test_filter_wrong_dict_key_type()
@@ -3737,19 +3807,52 @@ def Test_sort_argument()
assert_equal([1, 2, 3, 4, 5, 6, 7, 8], l)
END
v9.CheckDefAndScriptSuccess(lines)
v9.CheckDefAndScriptFailure(['sort("a")'], ['E1013: Argument 1: type mismatch, expected list<any> but got string', 'E1211: List required for argument 1'])
v9.CheckDefAndScriptFailure(['sort([1], "", [1])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 3'])
lines =<< trim END
sort([1, 2, 3], (a: any, b: any) => 1)
END
v9.CheckDefAndScriptSuccess(lines)
lines =<< trim END
vim9script
def SortedList(): list<number>
var Lambda: func: number = (a, b): number => a - b
var l = [3, 2, 1]
return l->sort(Lambda)
enddef
SortedList()->assert_equal([1, 2, 3])
END
v9.CheckScriptSuccess(lines)
enddef
def Test_sort_compare_func_fails()
v9.CheckDefAndScriptFailure(['sort("a")'], ['E1013: Argument 1: type mismatch, expected list<any> but got string', 'E1211: List required for argument 1'])
v9.CheckDefAndScriptFailure(['sort([1], "", [1])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 3'])
var lines =<< trim END
vim9script
echo ['a', 'b', 'c']->sort((a: number, b: number) => 0)
END
writefile(lines, 'Xbadsort')
assert_fails('source Xbadsort', ['E1013:', 'E702:'])
delete('Xbadsort')
lines =<< trim END
var l = [1, 2, 3]
sort(l, (a: string, b: number) => 1)
END
v9.CheckDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?number): number but got func(string, number): number', 'E1013: Argument 1: type mismatch, expected string but got number'])
lines =<< trim END
var l = ['a', 'b', 'c']
sort(l, (a: string, b: number) => 1)
END
v9.CheckDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?string, ?string): number but got func(string, number): number', 'E1013: Argument 2: type mismatch, expected number but got string'])
lines =<< trim END
sort([1, 2, 3], (a: number, b: number) => true)
END
v9.CheckDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?number): number but got func(number, number): bool', 'E1138: Using a Bool as a Number'])
enddef
def Test_spellbadword()
+57
View File
@@ -106,6 +106,63 @@ def Test_wrong_function_name()
enddef
END
v9.CheckScriptFailure(lines, 'E1267:')
lines =<< trim END
vim9script
var Object = {}
function Object.Method()
endfunction
END
v9.CheckScriptFailure(lines, 'E1182:')
lines =<< trim END
vim9script
var Object = {}
def Object.Method()
enddef
END
v9.CheckScriptFailure(lines, 'E1182:')
lines =<< trim END
vim9script
g:Object = {}
function g:Object.Method()
endfunction
END
v9.CheckScriptFailure(lines, 'E1182:')
lines =<< trim END
let s:Object = {}
def Define()
function s:Object.Method()
endfunction
enddef
defcompile
END
v9.CheckScriptFailure(lines, 'E1182:')
delfunc g:Define
lines =<< trim END
let s:Object = {}
def Define()
def Object.Method()
enddef
enddef
defcompile
END
v9.CheckScriptFailure(lines, 'E1182:')
delfunc g:Define
lines =<< trim END
let g:Object = {}
def Define()
function g:Object.Method()
endfunction
enddef
defcompile
END
v9.CheckScriptFailure(lines, 'E1182:')
delfunc g:Define
enddef
def Test_autoload_name_mismatch()
+14 -3
View File
@@ -4268,10 +4268,21 @@ define_function(exarg_T *eap, char_u *name_arg, garray_T *lines_to_free)
}
else
{
if (vim9script && p[0] == 's' && p[1] == ':')
if (vim9script)
{
semsg(_(e_cannot_use_s_colon_in_vim9_script_str), p);
return NULL;
if (p[0] == 's' && p[1] == ':')
{
semsg(_(e_cannot_use_s_colon_in_vim9_script_str), p);
return NULL;
}
p = to_name_end(p, TRUE);
if (*skipwhite(p) == '.' && vim_strchr(p, '(') != NULL)
{
semsg(_(e_cannot_define_dict_func_in_vim9_script_str),
eap->arg);
return NULL;
}
p = eap->arg;
}
name = save_function_name(&p, &is_global, eap->skip,
+52
View File
@@ -380,7 +380,11 @@ static char *(features[]) =
"-mouse_dec",
# endif
# ifdef FEAT_MOUSE_GPM
# ifdef DYNAMIC_GPM
"+mouse_gpm/dyn",
# else
"+mouse_gpm",
# endif
# else
"-mouse_gpm",
# endif
@@ -765,6 +769,54 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
4460,
/**/
4459,
/**/
4458,
/**/
4457,
/**/
4456,
/**/
4455,
/**/
4454,
/**/
4453,
/**/
4452,
/**/
4451,
/**/
4450,
/**/
4449,
/**/
4448,
/**/
4447,
/**/
4446,
/**/
4445,
/**/
4444,
/**/
4443,
/**/
4442,
/**/
4441,
/**/
4440,
/**/
4439,
/**/
4438,
/**/
4437,
/**/
4436,
/**/
+11 -1
View File
@@ -831,7 +831,11 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx, garray_T *lines_to_free)
{
if (!ends_excmd2(name_start, name_end))
{
semsg(_(e_invalid_command_str), eap->cmd);
if (*skipwhite(name_end) == '.')
semsg(_(e_cannot_define_dict_func_in_vim9_script_str),
eap->cmd);
else
semsg(_(e_invalid_command_str), eap->cmd);
return NULL;
}
@@ -1331,6 +1335,12 @@ compile_lhs(
char_u *rawname = lhs->lhs_name
+ (lhs->lhs_name[1] == ':' ? 2 : 0);
if (script_namespace && current_script_is_vim9())
{
semsg(_(e_cannot_use_s_colon_in_vim9_script_str),
var_start);
return FAIL;
}
if (is_decl)
{
if (script_namespace)
+22 -5
View File
@@ -2333,16 +2333,33 @@ load_namespace_var(ectx_T *ectx, isntype_T isn_type, isn_T *iptr)
if (di == NULL)
{
if (isn_type == ISN_LOADG)
{
ufunc_T *ufunc = find_func(iptr->isn_arg.string, TRUE);
// g:Something could be a function
if (ufunc != NULL)
{
typval_T *tv = STACK_TV_BOT(0);
++ectx->ec_stack.ga_len;
tv->v_type = VAR_FUNC;
tv->vval.v_string = alloc(STRLEN(iptr->isn_arg.string) + 3);
if (tv->vval.v_string == NULL)
return FAIL;
STRCPY(tv->vval.v_string, "g:");
STRCPY(tv->vval.v_string + 2, iptr->isn_arg.string);
return OK;
}
}
SOURCING_LNUM = iptr->isn_lnum;
if (vim_strchr(iptr->isn_arg.string,
AUTOLOAD_CHAR) != NULL)
if (vim_strchr(iptr->isn_arg.string, AUTOLOAD_CHAR) != NULL)
// no check if the item exists in the script but
// isn't exported, it is too complicated
semsg(_(e_item_not_found_in_script_str),
iptr->isn_arg.string);
semsg(_(e_item_not_found_in_script_str), iptr->isn_arg.string);
else
semsg(_(e_undefined_variable_char_str),
namespace, iptr->isn_arg.string);
namespace, iptr->isn_arg.string);
return FAIL;
}
else
+9 -2
View File
@@ -422,8 +422,15 @@ compile_load(
{
case 'v': res = generate_LOADV(cctx, name, error);
break;
case 's': if (is_expr && ASCII_ISUPPER(*name)
&& find_func(name, FALSE) != NULL)
case 's': if (current_script_is_vim9())
{
semsg(_(e_cannot_use_s_colon_in_vim9_script_str),
*arg);
vim_free(name);
return FAIL;
}
if (is_expr && ASCII_ISUPPER(*name)
&& find_func(name, FALSE) != NULL)
res = generate_funcref(cctx, name, FALSE);
else
res = compile_load_scriptvar(cctx, name,
+4
View File
@@ -2861,6 +2861,10 @@ win_free_all(void)
{
int dummy;
#ifdef FEAT_CMDWIN
// avoid an error for switching tabpage with the cmdline window open
cmdwin_type = 0;
#endif
while (first_tabpage->tp_next != NULL)
tabpage_close(TRUE);