Merge remote-tracking branch 'vim/master'

This commit is contained in:
ichizok
2021-07-19 13:03:24 +09:00
54 changed files with 2332 additions and 634 deletions
+1 -1
View File
@@ -852,7 +852,7 @@ available.
job_getchannel({job}) *job_getchannel()*
Get the channel handle that {job} is using.
To check if the job has no channel: >
if string(job_getchannel()) == 'channel fail'
if string(job_getchannel(job)) == 'channel fail'
<
Can also be used as a |method|: >
GetJob()->job_getchannel()
+4 -1
View File
@@ -1331,7 +1331,10 @@ A jump table for the options with a short description can be found at |Q_op|.
continuation (positive).
sbr Display the 'showbreak' value before applying the
additional indent.
The default value for min is 20 and shift is 0.
list:{n} Adds an additional indent for lines that match a
numbered or bulleted list (using the
'formatlistpat' setting).
The default value for min is 20, shift and list is 0.
*'browsedir'* *'bsdir'*
'browsedir' 'bsdir' string (default: "last")
+4
View File
@@ -1354,6 +1354,9 @@ script file to avoid confusion.
`:import` can also be used in legacy Vim script. The imported items still
become script-local, even when the "s:" prefix is not given.
`:import` can not be used in a function. Imported items are intended to exist
at the script level and only imported once.
The script name after `import` can be:
- A relative path, starting "." or "..". This finds a file relative to the
location of the script file itself. This is useful to split up a large
@@ -1363,6 +1366,7 @@ The script name after `import` can be:
- A path not being relative or absolute. This will be found in the
"import" subdirectories of 'runtimepath' entries. The name will usually be
longer and unique, to avoid loading the wrong file.
Note that "after/import" is not used.
Once a vim9 script file has been imported, the result is cached and used the
next time the same script is imported. It will not be read again.
+6 -3
View File
@@ -563,9 +563,12 @@ changed_common(
changed_cline_bef_curs_win(wp);
if (wp->w_botline >= lnum)
{
// Assume that botline doesn't change (inserted lines make
// other lines scroll down below botline).
approximate_botline_win(wp);
if (xtra < 0)
invalidate_botline_win(wp);
else
// Assume that botline doesn't change (inserted lines make
// other lines scroll down below botline).
approximate_botline_win(wp);
}
// Check if any w_lines[] entries have become invalid.
+8 -1
View File
@@ -896,8 +896,15 @@ f_remote_read(typval_T *argvars UNUSED, typval_T *rettv)
char_u *r = NULL;
#ifdef FEAT_CLIENTSERVER
char_u *serverid = tv_get_string_chk(&argvars[0]);
char_u *serverid;
if (in_vim9script()
&& (check_for_string_arg(argvars, 0) == FAIL
|| (argvars[1].v_type != VAR_UNKNOWN
&& check_for_number_arg(argvars, 1) == FAIL)))
return;
serverid = tv_get_string_chk(&argvars[0]);
if (serverid != NULL && !check_restricted() && !check_secure())
{
int timeout = 0;
+6
View File
@@ -597,6 +597,12 @@ f_histget(typval_T *argvars UNUSED, typval_T *rettv)
int idx;
char_u *str;
if (in_vim9script()
&& (check_for_string_arg(argvars, 0) == FAIL
|| (argvars[1].v_type != VAR_UNKNOWN
&& check_for_number_arg(argvars, 1) == FAIL)))
return;
str = tv_get_string_chk(&argvars[0]); // NULL on type error
if (str == NULL)
rettv->vval.v_string = NULL;
+9 -1
View File
@@ -3283,7 +3283,7 @@ f_diff_filler(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
f_diff_hlID(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
{
#ifdef FEAT_DIFF
linenr_T lnum = tv_get_lnum(argvars);
linenr_T lnum;
static linenr_T prev_lnum = 0;
static varnumber_T changedtick = 0;
static int fnum = 0;
@@ -3293,6 +3293,14 @@ f_diff_hlID(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
int filler_lines;
int col;
if (in_vim9script()
&& ((argvars[0].v_type != VAR_STRING
&& argvars[0].v_type != VAR_NUMBER
&& check_for_string_arg(argvars, 0) == FAIL)
|| check_for_number_arg(argvars, 1) == FAIL))
return;
lnum = tv_get_lnum(argvars);
if (lnum < 0) // ignore type error in {lnum} arg
lnum = 0;
if (lnum != prev_lnum
+4 -1
View File
@@ -1580,6 +1580,7 @@ install_registry(void)
char display_name[BUFSIZE];
char uninstall_string[BUFSIZE];
char icon_string[BUFSIZE];
char version_string[BUFSIZE];
int i;
int loop_count = is_64bit_os() ? 2 : 1;
DWORD flag;
@@ -1652,13 +1653,15 @@ install_registry(void)
sprintf(icon_string, "%s\\gvim.exe,0", installdir);
sprintf(version_string, VIM_VERSION_SHORT "." VIM_VERSION_PATCHLEVEL_STR);
lRet = register_uninstall(
HKEY_LOCAL_MACHINE,
"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Vim " VIM_VERSION_SHORT,
display_name,
uninstall_string,
icon_string,
VIM_VERSION_SHORT,
version_string,
"Bram Moolenaar et al.");
if (ERROR_SUCCESS != lRet)
return FAIL;
+14 -2
View File
@@ -381,8 +381,8 @@ EXTERN char e_mismatched_endfunction[]
INIT(= N_("E1151: Mismatched endfunction"));
EXTERN char e_mismatched_enddef[]
INIT(= N_("E1152: Mismatched enddef"));
EXTERN char e_invalid_operation_for_bool[]
INIT(= N_("E1153: Invalid operation for bool"));
EXTERN char e_invalid_operation_for_str[]
INIT(= N_("E1153: Invalid operation for %s"));
EXTERN char e_divide_by_zero[]
INIT(= N_("E1154: Divide by zero"));
EXTERN char e_cannot_define_autocommands_for_all_events[]
@@ -496,3 +496,15 @@ EXTERN char e_dict_required_for_argument_nr[]
INIT(= N_("E1206: Dictionary required for argument %d"));
EXTERN char e_expression_without_effect_str[]
INIT(= N_("E1207: Expression without an effect: %s"));
EXTERN char e_complete_used_without_nargs[]
INIT(= N_("E1208: -complete used without -nargs"));
EXTERN char e_invalid_value_for_line_number_str[]
INIT(= N_("E1209: Invalid value for a line number: \"%s\""));
EXTERN char e_number_required_for_argument_nr[]
INIT(= N_("E1210: Number required for argument %d"));
EXTERN char e_list_required_for_argument_nr[]
INIT(= N_("E1211: List required for argument %d"));
EXTERN char e_bool_required_for_argument_nr[]
INIT(= N_("E1211: Bool required for argument %d"));
EXTERN char e_redefining_imported_item_str[]
INIT(= N_("E1212: Redefining imported item %s"));
+25 -3
View File
@@ -1358,7 +1358,8 @@ set_var_lval(
|| (!var_check_ro(di->di_flags, lp->ll_name, FALSE)
&& !tv_check_lock(&di->di_tv, lp->ll_name, FALSE)))
&& tv_op(&tv, rettv, op) == OK)
set_var(lp->ll_name, &tv, FALSE);
set_var_const(lp->ll_name, NULL, &tv, FALSE,
ASSIGN_NO_DECL, 0);
clear_tv(&tv);
}
}
@@ -1784,6 +1785,8 @@ next_for_item(void *fi_void, char_u *arg)
| ASSIGN_NO_MEMBER_TYPE)
: 0);
listitem_T *item;
int skip_assign = in_vim9script() && arg[0] == '_'
&& !eval_isnamec(arg[1]);
if (fi->fi_blob != NULL)
{
@@ -1795,6 +1798,8 @@ next_for_item(void *fi_void, char_u *arg)
tv.v_lock = VAR_FIXED;
tv.vval.v_number = blob_get(fi->fi_blob, fi->fi_bi);
++fi->fi_bi;
if (skip_assign)
return TRUE;
return ex_let_vars(arg, &tv, TRUE, fi->fi_semicolon,
fi->fi_varcount, flag, NULL) == OK;
}
@@ -1812,7 +1817,10 @@ next_for_item(void *fi_void, char_u *arg)
tv.vval.v_string = vim_strnsave(fi->fi_string + fi->fi_byte_idx, len);
fi->fi_byte_idx += len;
++fi->fi_bi;
result = ex_let_vars(arg, &tv, TRUE, fi->fi_semicolon,
if (skip_assign)
result = TRUE;
else
result = ex_let_vars(arg, &tv, TRUE, fi->fi_semicolon,
fi->fi_varcount, flag, NULL) == OK;
vim_free(tv.vval.v_string);
return result;
@@ -1825,7 +1833,10 @@ next_for_item(void *fi_void, char_u *arg)
{
fi->fi_lw.lw_item = item->li_next;
++fi->fi_bi;
result = (ex_let_vars(arg, &item->li_tv, TRUE, fi->fi_semicolon,
if (skip_assign)
result = TRUE;
else
result = (ex_let_vars(arg, &item->li_tv, TRUE, fi->fi_semicolon,
fi->fi_varcount, flag, NULL) == OK);
}
return result;
@@ -2177,6 +2188,11 @@ eval_next_line(evalarg_T *evalarg)
vim_free(evalarg->eval_tofree);
evalarg->eval_tofree = line;
}
// Advanced to the next line, "arg" no longer points into the previous
// line.
VIM_CLEAR(evalarg->eval_tofree_cmdline);
return skipwhite(line);
}
@@ -5376,6 +5392,8 @@ var2fpos(
}
return &pos;
}
if (in_vim9script())
semsg(_(e_invalid_value_for_line_number_str), name);
return NULL;
}
@@ -6189,6 +6207,7 @@ ex_execute(exarg_T *eap)
char_u *p;
garray_T ga;
int len;
long start_lnum = SOURCING_LNUM;
ga_init2(&ga, 1, 80);
@@ -6242,6 +6261,9 @@ ex_execute(exarg_T *eap)
if (ret != FAIL && ga.ga_data != NULL)
{
// use the first line of continuation lines for messages
SOURCING_LNUM = start_lnum;
if (eap->cmdidx == CMD_echomsg || eap->cmdidx == CMD_echoerr)
{
// Mark the already saved text as finishing the line, so that what
+244 -134
View File
@@ -254,6 +254,15 @@ arg_dict_any(type_T *type, argcontext_T *context)
return check_arg_type(&t_dict_any, type, context);
}
/*
* Check "type" is a list of 'any'.
*/
static int
arg_list_any(type_T *type, argcontext_T *context)
{
return check_arg_type(&t_list_any, type, context);
}
/*
* Check "type" is a list of numbers.
*/
@@ -287,9 +296,6 @@ arg_string(type_T *type, argcontext_T *context)
static int
arg_bool(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
|| type->tt_type == VAR_NUMBER || type->tt_type == VAR_BOOL)
return OK;
return check_arg_type(&t_bool, type, context);
}
@@ -322,7 +328,7 @@ arg_string_or_nr(type_T *type, argcontext_T *context)
* Check "type" is a string or a list of strings.
*/
static int
arg_string_or_list(type_T *type, argcontext_T *context)
arg_string_or_list_string(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY || type->tt_type == VAR_STRING)
return OK;
@@ -340,7 +346,20 @@ arg_string_or_list(type_T *type, argcontext_T *context)
}
/*
* Check "type" is a list or a dict.
* Check "type" is a string or a list of 'any'
*/
static int
arg_string_or_list_any(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
|| type->tt_type == VAR_STRING || type->tt_type == VAR_LIST)
return OK;
arg_type_mismatch(&t_string, type, context->arg_idx + 1);
return FAIL;
}
/*
* Check "type" is a list of 'any' or a dict of 'any'.
*/
static int
arg_list_or_dict(type_T *type, argcontext_T *context)
@@ -352,13 +371,23 @@ arg_list_or_dict(type_T *type, argcontext_T *context)
return FAIL;
}
/*
* Check "type" is a job.
*/
static int
arg_job(type_T *type, argcontext_T *context)
{
return check_arg_type(&t_job, type, context);
}
/*
* Check "type" is a channel or a job.
*/
static int
arg_chan_or_job(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_CHANNEL || type->tt_type == VAR_JOB)
if (type->tt_type == VAR_ANY ||
type->tt_type == VAR_CHANNEL || type->tt_type == VAR_JOB)
return OK;
arg_type_mismatch(&t_channel, type, context->arg_idx + 1);
return FAIL;
@@ -412,6 +441,21 @@ arg_item_of_prev(type_T *type, argcontext_T *context)
return check_arg_type(expected, type, context);
}
/*
* Check "type" is a string or a number or a list
*/
static int
arg_str_or_nr_or_list(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
|| type->tt_type == VAR_STRING
|| type->tt_type == VAR_NUMBER
|| type->tt_type == VAR_LIST)
return OK;
arg_type_mismatch(&t_string, type, context->arg_idx + 1);
return FAIL;
}
/*
* Check "type" which is the third argument of extend().
*/
@@ -431,31 +475,51 @@ arg_extend3(type_T *type, argcontext_T *context)
/*
* Lists of functions that check the argument types of a builtin function.
*/
argcheck_T arg1_string[] = {arg_string};
argcheck_T arg1_number[] = {arg_number};
argcheck_T arg1_dict[] = {arg_dict_any};
argcheck_T arg1_list_nr[] = {arg_list_number};
argcheck_T arg1_list_string[] = {arg_list_string};
argcheck_T arg1_float_or_nr[] = {arg_float_or_nr};
argcheck_T arg1_string_or_nr[] = {arg_string_or_nr};
argcheck_T arg1_string_or_list[] = {arg_string_or_list};
argcheck_T arg1_list_or_blob[] = {arg_list_or_blob};
argcheck_T arg1_chan_or_job[] = {arg_chan_or_job};
argcheck_T arg2_float_or_nr[] = {arg_float_or_nr, arg_float_or_nr};
argcheck_T arg2_number[] = {arg_number, arg_number};
argcheck_T arg2_string[] = {arg_string, arg_string};
argcheck_T arg2_list_nr[] = {arg_list_number, arg_list_number};
argcheck_T arg2_dict_string[] = {arg_dict_any, arg_string};
argcheck_T arg2_string_dict[] = {arg_string, arg_dict_any};
argcheck_T arg2_listblob_item[] = {arg_list_or_blob, arg_item_of_prev};
argcheck_T arg2_execute[] = {arg_string_or_list, arg_string};
argcheck_T arg23_extend[] = {arg_list_or_dict, arg_same_as_prev, arg_extend3};
argcheck_T arg23_extendnew[] = {arg_list_or_dict, arg_same_struct_as_prev, arg_extend3};
argcheck_T arg3_string[] = {arg_string, arg_string, arg_string};
argcheck_T arg3_number[] = {arg_number, arg_number, arg_number};
argcheck_T arg3_string_nr_bool[] = {arg_string, arg_number, arg_bool};
argcheck_T arg3_string_string_nr[] = {arg_string, arg_string, arg_number};
argcheck_T arg3_insert[] = {arg_list_or_blob, arg_item_of_prev, arg_number};
static argcheck_T arg1_string[] = {arg_string};
static argcheck_T arg1_number[] = {arg_number};
static argcheck_T arg1_bool[] = {arg_bool};
static argcheck_T arg1_dict_any[] = {arg_dict_any};
static argcheck_T arg1_job[] = {arg_job};
static argcheck_T arg1_list_any[] = {arg_list_any};
static argcheck_T arg1_list_nr[] = {arg_list_number};
static argcheck_T arg1_list_string[] = {arg_list_string};
static argcheck_T arg1_float_or_nr[] = {arg_float_or_nr};
static argcheck_T arg1_string_or_nr[] = {arg_string_or_nr};
static argcheck_T arg1_string_or_list_any[] = {arg_string_or_list_any};
static argcheck_T arg1_string_or_list_string[] = {arg_string_or_list_string};
static argcheck_T arg1_list_or_blob[] = {arg_list_or_blob};
static argcheck_T arg1_list_or_dict[] = {arg_list_or_dict};
static argcheck_T arg1_chan_or_job[] = {arg_chan_or_job};
static argcheck_T arg2_float_or_nr[] = {arg_float_or_nr, arg_float_or_nr};
static argcheck_T arg2_number[] = {arg_number, arg_number};
static argcheck_T arg2_string[] = {arg_string, arg_string};
static argcheck_T arg2_list_nr[] = {arg_list_number, arg_list_number};
static argcheck_T arg2_nr_string[] = {arg_number, arg_string};
static argcheck_T arg2_dict_string[] = {arg_dict_any, arg_string};
static argcheck_T arg2_dict_string_or_nr[] = {arg_dict_any, arg_string_or_nr};
static argcheck_T arg2_string_dict[] = {arg_string, arg_dict_any};
static argcheck_T arg2_string_nr[] = {arg_string, arg_number};
static argcheck_T arg2_string_bool[] = {arg_string, arg_bool};
//static argcheck_T arg2_listblob_item[] = {arg_list_or_blob, arg_item_of_prev};
static argcheck_T arg2_str_or_nr_or_list_dict[] = {arg_str_or_nr_or_list, arg_dict_any};
static argcheck_T arg2_string_or_list_dict[] = {arg_string_or_list_any, arg_dict_any};
static argcheck_T arg2_string_or_nr_string[] = {arg_string_or_nr, arg_string};
static argcheck_T arg2_string_or_nr_nr[] = {arg_string_or_nr, arg_number};
static argcheck_T arg2_chan_or_job_dict[] = {arg_chan_or_job, arg_dict_any};
static argcheck_T arg2_nr_dict_any[] = {arg_number, arg_dict_any};
//static argcheck_T arg2_string_number[] = {arg_string, arg_number};
static argcheck_T arg3_string[] = {arg_string, arg_string, arg_string};
static argcheck_T arg3_number[] = {arg_number, arg_number, arg_number};
static argcheck_T arg3_string_nr_bool[] = {arg_string, arg_number, arg_bool};
static argcheck_T arg3_string_string_nr[] = {arg_string, arg_string, arg_number};
static argcheck_T arg2_execute[] = {arg_string_or_list_string, arg_string};
static argcheck_T arg23_extend[] = {arg_list_or_dict, arg_same_as_prev, arg_extend3};
static argcheck_T arg23_extendnew[] = {arg_list_or_dict, arg_same_struct_as_prev, arg_extend3};
static argcheck_T arg3_insert[] = {arg_list_or_blob, arg_item_of_prev, arg_number};
static argcheck_T arg3_setbufline[] = {arg_string_or_nr, arg_string_or_nr, arg_str_or_nr_or_list};
static argcheck_T arg2_setline[] = {arg_string_or_nr, NULL};
static argcheck_T arg23_win_execute[] = {arg_number, arg_string_or_list_string, arg_string};
static argcheck_T arg4_match_func[] = {arg_string_or_list_any, arg_string, arg_number, arg_number};
/*
* Functions that return the return type of a builtin function.
@@ -727,9 +791,9 @@ static funcentry_T global_functions[] =
ret_first_arg, f_add},
{"and", 2, 2, FEARG_1, arg2_number,
ret_number, f_and},
{"append", 2, 2, FEARG_2, NULL,
{"append", 2, 2, FEARG_2, arg2_setline,
ret_number_bool, f_append},
{"appendbufline", 3, 3, FEARG_3, NULL,
{"appendbufline", 3, 3, FEARG_3, arg3_setbufline,
ret_number_bool, f_appendbufline},
{"argc", 0, 1, 0, arg1_number,
ret_number, f_argc},
@@ -741,7 +805,7 @@ static funcentry_T global_functions[] =
ret_argv, f_argv},
{"asin", 1, 1, FEARG_1, arg1_float_or_nr,
ret_float, FLOAT_FUNC(f_asin)},
{"assert_beeps", 1, 2, FEARG_1, NULL,
{"assert_beeps", 1, 1, FEARG_1, arg1_string,
ret_number_bool, f_assert_beeps},
{"assert_equal", 2, 3, FEARG_2, NULL,
ret_number_bool, f_assert_equal},
@@ -757,13 +821,13 @@ static funcentry_T global_functions[] =
ret_number_bool, f_assert_inrange},
{"assert_match", 2, 3, FEARG_2, arg3_string,
ret_number_bool, f_assert_match},
{"assert_nobeep", 1, 2, FEARG_1, NULL,
{"assert_nobeep", 1, 1, FEARG_1, arg1_string,
ret_number_bool, f_assert_nobeep},
{"assert_notequal", 2, 3, FEARG_2, NULL,
ret_number_bool, f_assert_notequal},
{"assert_notmatch", 2, 3, FEARG_2, arg3_string,
ret_number_bool, f_assert_notmatch},
{"assert_report", 1, 1, FEARG_1, NULL,
{"assert_report", 1, 1, FEARG_1, arg1_string,
ret_number_bool, f_assert_report},
{"assert_true", 1, 2, FEARG_1, NULL,
ret_number_bool, f_assert_true},
@@ -779,7 +843,7 @@ static funcentry_T global_functions[] =
NULL
#endif
},
{"balloon_show", 1, 1, FEARG_1, arg1_string_or_list,
{"balloon_show", 1, 1, FEARG_1, arg1_string_or_list_any,
ret_void,
#ifdef FEAT_BEVAL
f_balloon_show
@@ -825,9 +889,9 @@ static funcentry_T global_functions[] =
ret_number, f_bufwinnr},
{"byte2line", 1, 1, FEARG_1, arg1_number,
ret_number, f_byte2line},
{"byteidx", 2, 2, FEARG_1, NULL,
{"byteidx", 2, 2, FEARG_1, arg2_string_nr,
ret_number, f_byteidx},
{"byteidxcomp", 2, 2, FEARG_1, NULL,
{"byteidxcomp", 2, 2, FEARG_1, arg2_string_nr,
ret_number, f_byteidxcomp},
{"call", 2, 3, FEARG_1, NULL,
ret_any, f_call},
@@ -845,7 +909,7 @@ static funcentry_T global_functions[] =
ret_any, JOB_FUNC(f_ch_evalraw)},
{"ch_getbufnr", 2, 2, FEARG_1, NULL,
ret_number, JOB_FUNC(f_ch_getbufnr)},
{"ch_getjob", 1, 1, FEARG_1, NULL,
{"ch_getjob", 1, 1, FEARG_1, arg1_chan_or_job,
ret_job, JOB_FUNC(f_ch_getjob)},
{"ch_info", 1, 1, FEARG_1, arg1_chan_or_job,
ret_dict_any, JOB_FUNC(f_ch_info)},
@@ -855,27 +919,27 @@ static funcentry_T global_functions[] =
ret_void, JOB_FUNC(f_ch_logfile)},
{"ch_open", 1, 2, FEARG_1, arg2_string_dict,
ret_channel, JOB_FUNC(f_ch_open)},
{"ch_read", 1, 2, FEARG_1, NULL,
{"ch_read", 1, 2, FEARG_1, arg2_chan_or_job_dict,
ret_string, JOB_FUNC(f_ch_read)},
{"ch_readblob", 1, 2, FEARG_1, NULL,
{"ch_readblob", 1, 2, FEARG_1, arg2_chan_or_job_dict,
ret_blob, JOB_FUNC(f_ch_readblob)},
{"ch_readraw", 1, 2, FEARG_1, NULL,
{"ch_readraw", 1, 2, FEARG_1, arg2_chan_or_job_dict,
ret_string, JOB_FUNC(f_ch_readraw)},
{"ch_sendexpr", 2, 3, FEARG_1, NULL,
ret_void, JOB_FUNC(f_ch_sendexpr)},
{"ch_sendraw", 2, 3, FEARG_1, NULL,
ret_void, JOB_FUNC(f_ch_sendraw)},
{"ch_setoptions", 2, 2, FEARG_1, NULL,
{"ch_setoptions", 2, 2, FEARG_1, arg2_chan_or_job_dict,
ret_void, JOB_FUNC(f_ch_setoptions)},
{"ch_status", 1, 2, FEARG_1, NULL,
{"ch_status", 1, 2, FEARG_1, arg2_chan_or_job_dict,
ret_string, JOB_FUNC(f_ch_status)},
{"changenr", 0, 0, 0, NULL,
ret_number, f_changenr},
{"char2nr", 1, 2, FEARG_1, NULL,
{"char2nr", 1, 2, FEARG_1, arg2_string_bool,
ret_number, f_char2nr},
{"charclass", 1, 1, FEARG_1, arg1_string,
ret_number, f_charclass},
{"charcol", 1, 1, FEARG_1, arg1_string_or_list,
{"charcol", 1, 1, FEARG_1, arg1_string_or_list_any,
ret_number, f_charcol},
{"charidx", 2, 3, FEARG_1, arg3_string_nr_bool,
ret_number, f_charidx},
@@ -885,7 +949,7 @@ static funcentry_T global_functions[] =
ret_number, f_cindent},
{"clearmatches", 0, 1, FEARG_1, arg1_number,
ret_void, f_clearmatches},
{"col", 1, 1, FEARG_1, arg1_string_or_list,
{"col", 1, 1, FEARG_1, arg1_string_or_list_any,
ret_number, f_col},
{"complete", 2, 2, FEARG_2, NULL,
ret_void, f_complete},
@@ -927,9 +991,9 @@ static funcentry_T global_functions[] =
ret_number_bool, f_did_filetype},
{"diff_filler", 1, 1, FEARG_1, arg1_string_or_nr,
ret_number, f_diff_filler},
{"diff_hlID", 2, 2, FEARG_1, NULL,
{"diff_hlID", 2, 2, FEARG_1, arg2_string_or_nr_nr,
ret_number, f_diff_hlID},
{"echoraw", 1, 1, FEARG_1, NULL,
{"echoraw", 1, 1, FEARG_1, arg1_string,
ret_void, f_echoraw},
{"empty", 1, 1, FEARG_1, NULL,
ret_number_bool, f_empty},
@@ -1005,7 +1069,7 @@ static funcentry_T global_functions[] =
ret_func_any, f_funcref},
{"function", 1, 3, FEARG_1, NULL,
ret_f_function, f_function},
{"garbagecollect", 0, 1, 0, NULL,
{"garbagecollect", 0, 1, 0, arg1_bool,
ret_void, f_garbagecollect},
{"get", 2, 3, FEARG_1, NULL,
ret_any, f_get},
@@ -1017,15 +1081,15 @@ static funcentry_T global_functions[] =
ret_any, f_getbufvar},
{"getchangelist", 0, 1, FEARG_1, arg1_string_or_nr,
ret_list_any, f_getchangelist},
{"getchar", 0, 1, 0, NULL,
{"getchar", 0, 1, 0, arg1_bool,
ret_any, f_getchar},
{"getcharmod", 0, 0, 0, NULL,
ret_number, f_getcharmod},
{"getcharpos", 1, 1, FEARG_1, NULL,
{"getcharpos", 1, 1, FEARG_1, arg1_string,
ret_list_number, f_getcharpos},
{"getcharsearch", 0, 0, 0, NULL,
ret_dict_any, f_getcharsearch},
{"getcharstr", 0, 1, 0, NULL,
{"getcharstr", 0, 1, 0, arg1_bool,
ret_string, f_getcharstr},
{"getcmdline", 0, 0, 0, NULL,
ret_string, f_getcmdline},
@@ -1061,7 +1125,7 @@ static funcentry_T global_functions[] =
ret_list_any, f_getjumplist},
{"getline", 1, 2, FEARG_1, NULL,
ret_f_getline, f_getline},
{"getloclist", 1, 2, 0, NULL,
{"getloclist", 1, 2, 0, arg2_nr_dict_any,
ret_list_or_dict_1, f_getloclist},
{"getmarklist", 0, 1, FEARG_1, arg1_string_or_nr,
ret_list_dict_any, f_getmarklist},
@@ -1073,7 +1137,7 @@ static funcentry_T global_functions[] =
ret_number, f_getpid},
{"getpos", 1, 1, FEARG_1, arg1_string,
ret_list_number, f_getpos},
{"getqflist", 0, 1, 0, arg1_dict,
{"getqflist", 0, 1, 0, arg1_dict_any,
ret_list_or_dict_0, f_getqflist},
{"getreg", 0, 3, FEARG_1, NULL,
ret_getreg, f_getreg},
@@ -1109,7 +1173,7 @@ static funcentry_T global_functions[] =
ret_any, f_globpath},
{"has", 1, 2, 0, NULL,
ret_number_bool, f_has},
{"has_key", 2, 2, FEARG_1, arg2_dict_string,
{"has_key", 2, 2, FEARG_1, arg2_dict_string_or_nr,
ret_number_bool, f_has_key},
{"haslocaldir", 0, 2, FEARG_1, arg2_number,
ret_number, f_haslocaldir},
@@ -1123,7 +1187,7 @@ static funcentry_T global_functions[] =
ret_number_bool, f_histadd},
{"histdel", 1, 2, FEARG_1, NULL,
ret_number_bool, f_histdel},
{"histget", 1, 2, FEARG_1, NULL,
{"histget", 1, 2, FEARG_1, arg2_string_nr,
ret_string, f_histget},
{"histnr", 1, 1, FEARG_1, arg1_string,
ret_number, f_histnr},
@@ -1161,21 +1225,21 @@ static funcentry_T global_functions[] =
ret_number_bool, f_isdirectory},
{"isinf", 1, 1, FEARG_1, arg1_float_or_nr,
ret_number, MATH_FUNC(f_isinf)},
{"islocked", 1, 1, FEARG_1, NULL,
{"islocked", 1, 1, FEARG_1, arg1_string,
ret_number_bool, f_islocked},
{"isnan", 1, 1, FEARG_1, arg1_float_or_nr,
ret_number_bool, MATH_FUNC(f_isnan)},
{"items", 1, 1, FEARG_1, arg1_dict,
{"items", 1, 1, FEARG_1, arg1_dict_any,
ret_list_items, f_items},
{"job_getchannel", 1, 1, FEARG_1, NULL,
{"job_getchannel", 1, 1, FEARG_1, arg1_job,
ret_channel, JOB_FUNC(f_job_getchannel)},
{"job_info", 0, 1, FEARG_1, NULL,
{"job_info", 0, 1, FEARG_1, arg1_job,
ret_job_info, JOB_FUNC(f_job_info)},
{"job_setoptions", 2, 2, FEARG_1, NULL,
ret_void, JOB_FUNC(f_job_setoptions)},
{"job_start", 1, 2, FEARG_1, NULL,
ret_job, JOB_FUNC(f_job_start)},
{"job_status", 1, 1, FEARG_1, NULL,
{"job_status", 1, 1, FEARG_1, arg1_job,
ret_string, JOB_FUNC(f_job_status)},
{"job_stop", 1, 2, FEARG_1, NULL,
ret_number_bool, JOB_FUNC(f_job_stop)},
@@ -1189,9 +1253,9 @@ static funcentry_T global_functions[] =
ret_any, f_json_decode},
{"json_encode", 1, 1, FEARG_1, NULL,
ret_string, f_json_encode},
{"keys", 1, 1, FEARG_1, arg1_dict,
{"keys", 1, 1, FEARG_1, arg1_dict_any,
ret_list_string, f_keys},
{"last_buffer_nr", 0, 0, 0, arg1_string_or_nr, // obsolete
{"last_buffer_nr", 0, 0, 0, NULL, // obsolete
ret_number, f_last_buffer_nr},
{"len", 1, 1, FEARG_1, NULL,
ret_number, f_len},
@@ -1199,7 +1263,7 @@ static funcentry_T global_functions[] =
ret_string, f_libcall},
{"libcallnr", 3, 3, FEARG_3, NULL,
ret_number, f_libcallnr},
{"line", 1, 2, FEARG_1, NULL,
{"line", 1, 2, FEARG_1, arg2_string_nr,
ret_number, f_line},
{"line2byte", 1, 1, FEARG_1, arg1_string_or_nr,
ret_number, f_line2byte},
@@ -1237,7 +1301,7 @@ static funcentry_T global_functions[] =
ret_first_cont, f_mapnew},
{"mapset", 3, 3, FEARG_1, NULL,
ret_void, f_mapset},
{"match", 2, 4, FEARG_1, NULL,
{"match", 2, 4, FEARG_1, arg4_match_func,
ret_any, f_match},
{"matchadd", 2, 5, FEARG_1, NULL,
ret_number, f_matchadd},
@@ -1247,19 +1311,19 @@ static funcentry_T global_functions[] =
ret_list_string, f_matcharg},
{"matchdelete", 1, 2, FEARG_1, arg2_number,
ret_number_bool, f_matchdelete},
{"matchend", 2, 4, FEARG_1, NULL,
{"matchend", 2, 4, FEARG_1, arg4_match_func,
ret_number, f_matchend},
{"matchfuzzy", 2, 3, FEARG_1, NULL,
ret_list_string, f_matchfuzzy},
{"matchfuzzypos", 2, 3, FEARG_1, NULL,
ret_list_any, f_matchfuzzypos},
{"matchlist", 2, 4, FEARG_1, NULL,
{"matchlist", 2, 4, FEARG_1, arg4_match_func,
ret_list_string, f_matchlist},
{"matchstr", 2, 4, FEARG_1, NULL,
{"matchstr", 2, 4, FEARG_1, arg4_match_func,
ret_string, f_matchstr},
{"matchstrpos", 2, 4, FEARG_1, NULL,
{"matchstrpos", 2, 4, FEARG_1, arg4_match_func,
ret_list_any, f_matchstrpos},
{"max", 1, 1, FEARG_1, NULL,
{"max", 1, 1, FEARG_1, arg1_list_or_dict,
ret_number, f_max},
{"menu_info", 1, 2, FEARG_1, arg2_string,
ret_dict_any,
@@ -1269,13 +1333,13 @@ static funcentry_T global_functions[] =
NULL
#endif
},
{"min", 1, 1, FEARG_1, NULL,
{"min", 1, 1, FEARG_1, arg1_list_or_dict,
ret_number, f_min},
{"mkdir", 1, 3, FEARG_1, arg3_string_string_nr,
ret_number_bool, f_mkdir},
{"mode", 0, 1, FEARG_1, NULL,
{"mode", 0, 1, FEARG_1, arg1_bool,
ret_string, f_mode},
{"mzeval", 1, 1, FEARG_1, NULL,
{"mzeval", 1, 1, FEARG_1, arg1_string,
ret_any,
#ifdef FEAT_MZSCHEME
f_mzeval
@@ -1289,9 +1353,9 @@ static funcentry_T global_functions[] =
ret_string, f_nr2char},
{"or", 2, 2, FEARG_1, arg2_number,
ret_number, f_or},
{"pathshorten", 1, 2, FEARG_1, NULL,
{"pathshorten", 1, 2, FEARG_1, arg2_string_nr,
ret_string, f_pathshorten},
{"perleval", 1, 1, FEARG_1, NULL,
{"perleval", 1, 1, FEARG_1, arg1_string,
ret_any,
#ifdef FEAT_PERL
f_perleval
@@ -1299,47 +1363,47 @@ static funcentry_T global_functions[] =
NULL
#endif
},
{"popup_atcursor", 2, 2, FEARG_1, NULL,
{"popup_atcursor", 2, 2, FEARG_1, arg2_str_or_nr_or_list_dict,
ret_number, PROP_FUNC(f_popup_atcursor)},
{"popup_beval", 2, 2, FEARG_1, NULL,
{"popup_beval", 2, 2, FEARG_1, arg2_str_or_nr_or_list_dict,
ret_number, PROP_FUNC(f_popup_beval)},
{"popup_clear", 0, 1, 0, NULL,
{"popup_clear", 0, 1, 0, arg1_bool,
ret_void, PROP_FUNC(f_popup_clear)},
{"popup_close", 1, 2, FEARG_1, NULL,
ret_void, PROP_FUNC(f_popup_close)},
{"popup_create", 2, 2, FEARG_1, NULL,
{"popup_create", 2, 2, FEARG_1, arg2_str_or_nr_or_list_dict,
ret_number, PROP_FUNC(f_popup_create)},
{"popup_dialog", 2, 2, FEARG_1, NULL,
{"popup_dialog", 2, 2, FEARG_1, arg2_str_or_nr_or_list_dict,
ret_number, PROP_FUNC(f_popup_dialog)},
{"popup_filter_menu", 2, 2, 0, NULL,
{"popup_filter_menu", 2, 2, 0, arg2_nr_string,
ret_bool, PROP_FUNC(f_popup_filter_menu)},
{"popup_filter_yesno", 2, 2, 0, NULL,
{"popup_filter_yesno", 2, 2, 0, arg2_nr_string,
ret_bool, PROP_FUNC(f_popup_filter_yesno)},
{"popup_findinfo", 0, 0, 0, NULL,
ret_number, PROP_FUNC(f_popup_findinfo)},
{"popup_findpreview", 0, 0, 0, NULL,
ret_number, PROP_FUNC(f_popup_findpreview)},
{"popup_getoptions", 1, 1, FEARG_1, NULL,
{"popup_getoptions", 1, 1, FEARG_1, arg1_number,
ret_dict_any, PROP_FUNC(f_popup_getoptions)},
{"popup_getpos", 1, 1, FEARG_1, NULL,
{"popup_getpos", 1, 1, FEARG_1, arg1_number,
ret_dict_any, PROP_FUNC(f_popup_getpos)},
{"popup_hide", 1, 1, FEARG_1, NULL,
{"popup_hide", 1, 1, FEARG_1, arg1_number,
ret_void, PROP_FUNC(f_popup_hide)},
{"popup_list", 0, 0, 0, NULL,
ret_list_number, PROP_FUNC(f_popup_list)},
{"popup_locate", 2, 2, 0, arg2_number,
ret_number, PROP_FUNC(f_popup_locate)},
{"popup_menu", 2, 2, FEARG_1, NULL,
{"popup_menu", 2, 2, FEARG_1, arg2_str_or_nr_or_list_dict,
ret_number, PROP_FUNC(f_popup_menu)},
{"popup_move", 2, 2, FEARG_1, NULL,
{"popup_move", 2, 2, FEARG_1, arg2_nr_dict_any,
ret_void, PROP_FUNC(f_popup_move)},
{"popup_notification", 2, 2, FEARG_1, NULL,
{"popup_notification", 2, 2, FEARG_1, arg2_str_or_nr_or_list_dict,
ret_number, PROP_FUNC(f_popup_notification)},
{"popup_setoptions", 2, 2, FEARG_1, NULL,
{"popup_setoptions", 2, 2, FEARG_1, arg2_nr_dict_any,
ret_void, PROP_FUNC(f_popup_setoptions)},
{"popup_settext", 2, 2, FEARG_1, NULL,
ret_void, PROP_FUNC(f_popup_settext)},
{"popup_show", 1, 1, FEARG_1, NULL,
{"popup_show", 1, 1, FEARG_1, arg1_number,
ret_void, PROP_FUNC(f_popup_show)},
{"pow", 2, 2, FEARG_1, arg2_float_or_nr,
ret_float, FLOAT_FUNC(f_pow)},
@@ -1353,7 +1417,7 @@ static funcentry_T global_functions[] =
ret_void, JOB_FUNC(f_prompt_setcallback)},
{"prompt_setinterrupt", 2, 2, FEARG_1, NULL,
ret_void, JOB_FUNC(f_prompt_setinterrupt)},
{"prompt_setprompt", 2, 2, FEARG_1, NULL,
{"prompt_setprompt", 2, 2, FEARG_1, arg2_string_or_nr_string,
ret_void, JOB_FUNC(f_prompt_setprompt)},
{"prop_add", 3, 3, FEARG_1, NULL,
ret_void, PROP_FUNC(f_prop_add)},
@@ -1361,7 +1425,7 @@ static funcentry_T global_functions[] =
ret_void, PROP_FUNC(f_prop_clear)},
{"prop_find", 1, 2, FEARG_1, arg2_dict_string,
ret_dict_any, PROP_FUNC(f_prop_find)},
{"prop_list", 1, 2, FEARG_1, NULL,
{"prop_list", 1, 2, FEARG_1, arg2_nr_dict_any,
ret_list_dict_any, PROP_FUNC(f_prop_list)},
{"prop_remove", 1, 3, FEARG_1, NULL,
ret_number, PROP_FUNC(f_prop_remove)},
@@ -1373,13 +1437,13 @@ static funcentry_T global_functions[] =
ret_void, PROP_FUNC(f_prop_type_delete)},
{"prop_type_get", 1, 2, FEARG_1, arg2_string_dict,
ret_dict_any, PROP_FUNC(f_prop_type_get)},
{"prop_type_list", 0, 1, FEARG_1, NULL,
{"prop_type_list", 0, 1, FEARG_1, arg1_dict_any,
ret_list_string, PROP_FUNC(f_prop_type_list)},
{"pum_getpos", 0, 0, 0, NULL,
ret_dict_number, f_pum_getpos},
{"pumvisible", 0, 0, 0, NULL,
ret_number_bool, f_pumvisible},
{"py3eval", 1, 1, FEARG_1, NULL,
{"py3eval", 1, 1, FEARG_1, arg1_string,
ret_any,
#ifdef FEAT_PYTHON3
f_py3eval
@@ -1387,7 +1451,7 @@ static funcentry_T global_functions[] =
NULL
#endif
},
{"pyeval", 1, 1, FEARG_1, NULL,
{"pyeval", 1, 1, FEARG_1, arg1_string,
ret_any,
#ifdef FEAT_PYTHON
f_pyeval
@@ -1395,7 +1459,7 @@ static funcentry_T global_functions[] =
NULL
#endif
},
{"pyxeval", 1, 1, FEARG_1, NULL,
{"pyxeval", 1, 1, FEARG_1, arg1_string,
ret_any,
#if defined(FEAT_PYTHON) || defined(FEAT_PYTHON3)
f_pyxeval
@@ -1433,7 +1497,7 @@ static funcentry_T global_functions[] =
ret_string, f_remote_foreground},
{"remote_peek", 1, 2, FEARG_1, arg2_string,
ret_number, f_remote_peek},
{"remote_read", 1, 2, FEARG_1, NULL,
{"remote_read", 1, 2, FEARG_1, arg2_string_nr,
ret_string, f_remote_read},
{"remote_send", 2, 3, FEARG_1, NULL,
ret_string, f_remote_send},
@@ -1451,7 +1515,7 @@ static funcentry_T global_functions[] =
ret_first_arg, f_reverse},
{"round", 1, 1, FEARG_1, arg1_float_or_nr,
ret_float, FLOAT_FUNC(f_round)},
{"rubyeval", 1, 1, FEARG_1, NULL,
{"rubyeval", 1, 1, FEARG_1, arg1_string,
ret_any,
#ifdef FEAT_RUBY
f_rubyeval
@@ -1475,7 +1539,7 @@ static funcentry_T global_functions[] =
ret_string, f_screenstring},
{"search", 1, 5, FEARG_1, NULL,
ret_number, f_search},
{"searchcount", 0, 1, FEARG_1, arg1_dict,
{"searchcount", 0, 1, FEARG_1, arg1_dict_any,
ret_dict_any, f_searchcount},
{"searchdecl", 1, 3, FEARG_1, NULL,
ret_number_bool, f_searchdecl},
@@ -1489,15 +1553,15 @@ static funcentry_T global_functions[] =
ret_number_bool, f_server2client},
{"serverlist", 0, 0, 0, NULL,
ret_string, f_serverlist},
{"setbufline", 3, 3, FEARG_3, NULL,
{"setbufline", 3, 3, FEARG_3, arg3_setbufline,
ret_number_bool, f_setbufline},
{"setbufvar", 3, 3, FEARG_3, NULL,
ret_void, f_setbufvar},
{"setcellwidths", 1, 1, FEARG_1, NULL,
{"setcellwidths", 1, 1, FEARG_1, arg1_list_any,
ret_void, f_setcellwidths},
{"setcharpos", 2, 2, FEARG_2, NULL,
ret_number_bool, f_setcharpos},
{"setcharsearch", 1, 1, FEARG_1, arg1_dict,
{"setcharsearch", 1, 1, FEARG_1, arg1_dict_any,
ret_void, f_setcharsearch},
{"setcmdpos", 1, 1, FEARG_1, arg1_number,
ret_number_bool, f_setcmdpos},
@@ -1507,7 +1571,7 @@ static funcentry_T global_functions[] =
ret_void, f_setenv},
{"setfperm", 2, 2, FEARG_1, arg2_string,
ret_number_bool, f_setfperm},
{"setline", 2, 2, FEARG_2, NULL,
{"setline", 2, 2, FEARG_2, arg2_setline,
ret_number_bool, f_setline},
{"setloclist", 2, 4, FEARG_2, NULL,
ret_number_bool, f_setloclist},
@@ -1539,9 +1603,9 @@ static funcentry_T global_functions[] =
ret_string, f_shellescape},
{"shiftwidth", 0, 1, FEARG_1, arg1_number,
ret_number, f_shiftwidth},
{"sign_define", 1, 2, FEARG_1, arg2_string_dict,
{"sign_define", 1, 2, FEARG_1, arg2_string_or_list_dict,
ret_any, SIGN_FUNC(f_sign_define)},
{"sign_getdefined", 0, 1, FEARG_1, NULL,
{"sign_getdefined", 0, 1, FEARG_1, arg1_string,
ret_list_dict_any, SIGN_FUNC(f_sign_getdefined)},
{"sign_getplaced", 0, 2, FEARG_1, NULL,
ret_list_dict_any, SIGN_FUNC(f_sign_getplaced)},
@@ -1549,13 +1613,13 @@ static funcentry_T global_functions[] =
ret_number, SIGN_FUNC(f_sign_jump)},
{"sign_place", 4, 5, FEARG_1, NULL,
ret_number, SIGN_FUNC(f_sign_place)},
{"sign_placelist", 1, 1, FEARG_1, NULL,
{"sign_placelist", 1, 1, FEARG_1, arg1_list_any,
ret_list_number, SIGN_FUNC(f_sign_placelist)},
{"sign_undefine", 0, 1, FEARG_1, arg1_string_or_list,
{"sign_undefine", 0, 1, FEARG_1, arg1_string_or_list_string,
ret_number_bool, SIGN_FUNC(f_sign_undefine)},
{"sign_unplace", 1, 2, FEARG_1, arg2_string_dict,
ret_number_bool, SIGN_FUNC(f_sign_unplace)},
{"sign_unplacelist", 1, 2, FEARG_1, NULL,
{"sign_unplacelist", 1, 2, FEARG_1, arg1_list_any,
ret_list_number, SIGN_FUNC(f_sign_unplacelist)},
{"simplify", 1, 1, FEARG_1, arg1_string,
ret_string, f_simplify},
@@ -1591,19 +1655,19 @@ static funcentry_T global_functions[] =
ret_string, f_state},
{"str2float", 1, 1, FEARG_1, arg1_string,
ret_float, FLOAT_FUNC(f_str2float)},
{"str2list", 1, 2, FEARG_1, NULL,
{"str2list", 1, 2, FEARG_1, arg2_string_bool,
ret_list_number, f_str2list},
{"str2nr", 1, 3, FEARG_1, arg3_string_nr_bool,
ret_number, f_str2nr},
{"strcharlen", 1, 1, FEARG_1, NULL,
{"strcharlen", 1, 1, FEARG_1, arg1_string_or_nr,
ret_number, f_strcharlen},
{"strcharpart", 2, 4, FEARG_1, NULL,
ret_string, f_strcharpart},
{"strchars", 1, 2, FEARG_1, NULL,
{"strchars", 1, 2, FEARG_1, arg2_string_bool,
ret_number, f_strchars},
{"strdisplaywidth", 1, 2, FEARG_1, NULL,
{"strdisplaywidth", 1, 2, FEARG_1, arg2_string_nr,
ret_number, f_strdisplaywidth},
{"strftime", 1, 2, FEARG_1, NULL,
{"strftime", 1, 2, FEARG_1, arg2_string_nr,
ret_string,
#ifdef HAVE_STRFTIME
f_strftime
@@ -1611,7 +1675,7 @@ static funcentry_T global_functions[] =
NULL
#endif
},
{"strgetchar", 2, 2, FEARG_1, NULL,
{"strgetchar", 2, 2, FEARG_1, arg2_string_nr,
ret_number, f_strgetchar},
{"stridx", 2, 3, FEARG_1, arg3_string_string_nr,
ret_number, f_stridx},
@@ -1649,9 +1713,9 @@ static funcentry_T global_functions[] =
ret_string, f_synIDattr},
{"synIDtrans", 1, 1, FEARG_1, arg1_number,
ret_number, f_synIDtrans},
{"synconcealed", 2, 2, 0, NULL,
{"synconcealed", 2, 2, 0, arg2_string_or_nr_nr,
ret_list_any, f_synconcealed},
{"synstack", 2, 2, 0, NULL,
{"synstack", 2, 2, 0, arg2_string_or_nr_nr,
ret_list_number, f_synstack},
{"system", 1, 2, FEARG_1, NULL,
ret_string, f_system},
@@ -1661,7 +1725,7 @@ static funcentry_T global_functions[] =
ret_list_number, f_tabpagebuflist},
{"tabpagenr", 0, 1, 0, arg1_string,
ret_number, f_tabpagenr},
{"tabpagewinnr", 1, 2, FEARG_1, NULL,
{"tabpagewinnr", 1, 2, FEARG_1, arg2_nr_string,
ret_number, f_tabpagewinnr},
{"tagfiles", 0, 0, 0, NULL,
ret_list_string, f_tagfiles},
@@ -1689,7 +1753,7 @@ static funcentry_T global_functions[] =
NULL
#endif
},
{"term_getattr", 2, 2, FEARG_1, NULL,
{"term_getattr", 2, 2, FEARG_1, arg2_nr_string,
ret_number, TERM_FUNC(f_term_getattr)},
{"term_getcursor", 1, 1, FEARG_1, arg1_string_or_nr,
ret_list_any, TERM_FUNC(f_term_getcursor)},
@@ -1711,7 +1775,7 @@ static funcentry_T global_functions[] =
ret_list_number, TERM_FUNC(f_term_list)},
{"term_scrape", 2, 2, FEARG_1, NULL,
ret_list_dict_any, TERM_FUNC(f_term_scrape)},
{"term_sendkeys", 2, 2, FEARG_1, NULL,
{"term_sendkeys", 2, 2, FEARG_1, arg2_string_or_nr_string,
ret_void, TERM_FUNC(f_term_sendkeys)},
{"term_setansicolors", 2, 2, FEARG_1, NULL,
ret_void,
@@ -1721,17 +1785,17 @@ static funcentry_T global_functions[] =
NULL
#endif
},
{"term_setapi", 2, 2, FEARG_1, NULL,
{"term_setapi", 2, 2, FEARG_1, arg2_string_or_nr_string,
ret_void, TERM_FUNC(f_term_setapi)},
{"term_setkill", 2, 2, FEARG_1, NULL,
{"term_setkill", 2, 2, FEARG_1, arg2_string_or_nr_string,
ret_void, TERM_FUNC(f_term_setkill)},
{"term_setrestore", 2, 2, FEARG_1, NULL,
{"term_setrestore", 2, 2, FEARG_1, arg2_string_or_nr_string,
ret_void, TERM_FUNC(f_term_setrestore)},
{"term_setsize", 3, 3, FEARG_1, NULL,
ret_void, TERM_FUNC(f_term_setsize)},
{"term_start", 1, 2, FEARG_1, NULL,
ret_number, TERM_FUNC(f_term_start)},
{"term_wait", 1, 2, FEARG_1, NULL,
{"term_wait", 1, 2, FEARG_1, arg2_string_or_nr_nr,
ret_void, TERM_FUNC(f_term_wait)},
{"terminalprops", 0, 0, 0, NULL,
ret_dict_string, f_terminalprops},
@@ -1771,7 +1835,7 @@ static funcentry_T global_functions[] =
ret_string, f_test_null_string},
{"test_option_not_set", 1, 1, FEARG_1, arg1_string,
ret_void, f_test_option_not_set},
{"test_override", 2, 2, FEARG_2, NULL,
{"test_override", 2, 2, FEARG_2, arg2_string_nr,
ret_void, f_test_override},
{"test_refcount", 1, 1, FEARG_1, NULL,
ret_number, f_test_refcount},
@@ -1823,15 +1887,15 @@ static funcentry_T global_functions[] =
ret_dict_any, f_undotree},
{"uniq", 1, 3, FEARG_1, NULL,
ret_list_any, f_uniq},
{"values", 1, 1, FEARG_1, arg1_dict,
{"values", 1, 1, FEARG_1, arg1_dict_any,
ret_list_any, f_values},
{"virtcol", 1, 1, FEARG_1, arg1_string_or_list,
{"virtcol", 1, 1, FEARG_1, arg1_string_or_list_any,
ret_number, f_virtcol},
{"visualmode", 0, 1, 0, NULL,
{"visualmode", 0, 1, 0, arg1_bool,
ret_string, f_visualmode},
{"wildmenumode", 0, 0, 0, NULL,
ret_number, f_wildmenumode},
{"win_execute", 2, 3, FEARG_2, NULL,
{"win_execute", 2, 3, FEARG_2, arg23_win_execute,
ret_string, f_win_execute},
{"win_findbuf", 1, 1, FEARG_1, arg1_number,
ret_list_number, f_win_findbuf},
@@ -1865,7 +1929,7 @@ static funcentry_T global_functions[] =
ret_number, f_winnr},
{"winrestcmd", 0, 0, 0, NULL,
ret_string, f_winrestcmd},
{"winrestview", 1, 1, FEARG_1, arg1_dict,
{"winrestview", 1, 1, FEARG_1, arg1_dict_any,
ret_void, f_winrestview},
{"winsaveview", 0, 0, 0, NULL,
ret_dict_number, f_winsaveview},
@@ -2413,8 +2477,12 @@ f_changenr(typval_T *argvars UNUSED, typval_T *rettv)
static void
f_char2nr(typval_T *argvars, typval_T *rettv)
{
if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
if (in_vim9script()
&& (check_for_string_arg(argvars, 0) == FAIL
|| (argvars[1].v_type != VAR_UNKNOWN
&& check_for_bool_arg(argvars, 1) == FAIL)))
return;
if (has_mbyte)
{
int utf8 = 0;
@@ -2728,8 +2796,12 @@ f_did_filetype(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
static void
f_echoraw(typval_T *argvars, typval_T *rettv UNUSED)
{
char_u *str = tv_get_string_chk(&argvars[0]);
char_u *str;
if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
return;
str = tv_get_string_chk(&argvars[0]);
if (str != NULL && *str != NUL)
{
out_str(str);
@@ -5956,12 +6028,19 @@ f_islocked(typval_T *argvars, typval_T *rettv)
dictitem_T *di;
rettv->vval.v_number = -1;
if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
return;
end = get_lval(tv_get_string(&argvars[0]), NULL, &lv, FALSE, FALSE,
GLV_NO_AUTOLOAD | GLV_READ_ONLY, FNE_CHECK_START);
if (end != NULL && lv.ll_name != NULL)
{
if (*end != NUL)
semsg(_(e_trailing_arg), end);
{
semsg(_(lv.ll_name == lv.ll_name_end
? e_invarg2 : e_trailing_arg), end);
}
else
{
if (lv.ll_tv == NULL)
@@ -6119,6 +6198,12 @@ f_line(typval_T *argvars, typval_T *rettv)
win_T *save_curwin;
tabpage_T *save_curtab;
if (in_vim9script()
&& (check_for_string_arg(argvars, 0) == FAIL
|| (argvars[1].v_type != VAR_UNKNOWN
&& check_for_number_arg(argvars, 1) == FAIL)))
return;
if (argvars[1].v_type != VAR_UNKNOWN)
{
// use window specified in the second argument
@@ -6262,6 +6347,17 @@ find_some_match(typval_T *argvars, typval_T *rettv, matchtype_T type)
rettv->vval.v_string = NULL;
}
if (in_vim9script()
&& ((argvars[0].v_type != VAR_STRING
&& argvars[0].v_type != VAR_LIST
&& check_for_string_arg(argvars, 0) == FAIL)
|| (check_for_string_arg(argvars, 1) == FAIL)
|| (argvars[2].v_type != VAR_UNKNOWN
&& (check_for_number_arg(argvars, 2) == FAIL
|| (argvars[3].v_type != VAR_UNKNOWN
&& check_for_number_arg(argvars, 3) == FAIL)))))
goto theend;
if (argvars[0].v_type == VAR_LIST)
{
if ((l = argvars[0].vval.v_list) == NULL)
@@ -8919,6 +9015,13 @@ f_synconcealed(typval_T *argvars UNUSED, typval_T *rettv)
rettv_list_set(rettv, NULL);
if (in_vim9script()
&& ((argvars[0].v_type != VAR_STRING
&& argvars[0].v_type != VAR_NUMBER
&& check_for_string_arg(argvars, 0) == FAIL)
|| check_for_number_arg(argvars, 1) == FAIL))
return;
#if defined(FEAT_SYN_HL) && defined(FEAT_CONCEAL)
lnum = tv_get_lnum(argvars); // -1 on type error
col = (colnr_T)tv_get_number(&argvars[1]) - 1; // -1 on type error
@@ -8975,6 +9078,13 @@ f_synstack(typval_T *argvars UNUSED, typval_T *rettv)
rettv_list_set(rettv, NULL);
if (in_vim9script()
&& ((argvars[0].v_type != VAR_STRING
&& argvars[0].v_type != VAR_NUMBER
&& check_for_string_arg(argvars, 0) == FAIL)
|| check_for_number_arg(argvars, 1) == FAIL))
return;
#ifdef FEAT_SYN_HL
lnum = tv_get_lnum(argvars); // -1 on type error
col = (colnr_T)tv_get_number(&argvars[1]) - 1; // -1 on type error
+180 -144
View File
@@ -2662,7 +2662,8 @@ eval_variable(
}
else if (rettv != NULL)
{
if (ht != NULL && ht == get_script_local_ht())
if (ht != NULL && ht == get_script_local_ht()
&& tv != &SCRIPT_SV(current_sctx.sc_sid)->sv_var.di_tv)
{
svar_T *sv = find_typval_in_script(tv);
@@ -3202,6 +3203,7 @@ set_var_const(
typval_T *tv = tv_arg;
typval_T bool_tv;
dictitem_T *di;
typval_T *dest_tv = NULL;
char_u *varname;
hashtab_T *ht;
int is_script_local;
@@ -3242,182 +3244,215 @@ set_var_const(
di = find_var_in_ht(ht, 0, varname, TRUE);
// Search in parent scope which is possible to reference from lambda
if (di == NULL)
di = find_var_in_scoped_ht(name, TRUE);
if ((tv->v_type == VAR_FUNC || tv->v_type == VAR_PARTIAL)
&& var_wrong_func_name(name, di == NULL))
goto failed;
if (need_convert_to_bool(type, tv))
if (di == NULL && var_in_vim9script)
{
// Destination is a bool and the value is not, but it can be converted.
CLEAR_FIELD(bool_tv);
bool_tv.v_type = VAR_BOOL;
bool_tv.vval.v_number = tv2bool(tv) ? VVAL_TRUE : VVAL_FALSE;
tv = &bool_tv;
}
imported_T *import = find_imported(varname, 0, NULL);
if (di != NULL)
{
// Item already exists. Allowed to replace when reloading.
if ((di->di_flags & DI_FLAGS_RELOAD) == 0)
if (import != NULL)
{
if ((flags & (ASSIGN_CONST | ASSIGN_FINAL))
&& (flags & ASSIGN_FOR_LOOP) == 0)
scriptitem_T *si = SCRIPT_ITEM(import->imp_sid);
svar_T *sv;
// imported variable from another script
if ((flags & ASSIGN_NO_DECL) == 0)
{
emsg(_(e_cannot_mod));
semsg(_(e_redefining_imported_item_str), name);
goto failed;
}
sv = ((svar_T *)si->sn_var_vals.ga_data)
+ import->imp_var_vals_idx;
// TODO: check the type
// TODO: check for const and locked
dest_tv = sv->sv_tv;
clear_tv(dest_tv);
}
}
if (is_script_local && vim9script
if (dest_tv == NULL)
{
// Search in parent scope which is possible to reference from lambda
if (di == NULL)
di = find_var_in_scoped_ht(name, TRUE);
if ((tv->v_type == VAR_FUNC || tv->v_type == VAR_PARTIAL)
&& var_wrong_func_name(name, di == NULL))
goto failed;
if (need_convert_to_bool(type, tv))
{
// Destination is a bool and the value is not, but it can be
// converted.
CLEAR_FIELD(bool_tv);
bool_tv.v_type = VAR_BOOL;
bool_tv.vval.v_number = tv2bool(tv) ? VVAL_TRUE : VVAL_FALSE;
tv = &bool_tv;
}
if (di != NULL)
{
// Item already exists. Allowed to replace when reloading.
if ((di->di_flags & DI_FLAGS_RELOAD) == 0)
{
if ((flags & (ASSIGN_CONST | ASSIGN_FINAL))
&& (flags & ASSIGN_FOR_LOOP) == 0)
{
emsg(_(e_cannot_mod));
goto failed;
}
if (is_script_local && vim9script
&& (flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) == 0)
{
semsg(_(e_redefining_script_item_str), name);
goto failed;
}
if (var_in_vim9script)
{
where_T where;
// check the type and adjust to bool if needed
where.wt_index = var_idx;
where.wt_variable = TRUE;
if (check_script_var_type(&di->di_tv, tv, name, where)
== FAIL)
goto failed;
}
if (var_check_permission(di, name) == FAIL)
goto failed;
}
else
{
// can only redefine once
di->di_flags &= ~DI_FLAGS_RELOAD;
// A Vim9 script-local variable is also present in sn_all_vars
// and sn_var_vals. It may set "type" from "tv".
if (var_in_vim9script)
update_vim9_script_var(FALSE, di, flags, tv, &type,
(flags & ASSIGN_NO_MEMBER_TYPE) == 0);
}
// existing variable, need to clear the value
// Handle setting internal di: variables separately where needed to
// prevent changing the type.
if (ht == &vimvarht)
{
if (di->di_tv.v_type == VAR_STRING)
{
VIM_CLEAR(di->di_tv.vval.v_string);
if (copy || tv->v_type != VAR_STRING)
{
char_u *val = tv_get_string(tv);
// Careful: when assigning to v:errmsg and
// tv_get_string() causes an error message the variable
// will already be set.
if (di->di_tv.vval.v_string == NULL)
di->di_tv.vval.v_string = vim_strsave(val);
}
else
{
// Take over the string to avoid an extra alloc/free.
di->di_tv.vval.v_string = tv->vval.v_string;
tv->vval.v_string = NULL;
}
goto failed;
}
else if (di->di_tv.v_type == VAR_NUMBER)
{
di->di_tv.vval.v_number = tv_get_number(tv);
if (STRCMP(varname, "searchforward") == 0)
set_search_direction(di->di_tv.vval.v_number
? '/' : '?');
#ifdef FEAT_SEARCH_EXTRA
else if (STRCMP(varname, "hlsearch") == 0)
{
no_hlsearch = !di->di_tv.vval.v_number;
redraw_all_later(SOME_VALID);
}
#endif
goto failed;
}
else if (di->di_tv.v_type != tv->v_type)
{
semsg(_("E963: setting %s to value with wrong type"), name);
goto failed;
}
}
clear_tv(&di->di_tv);
}
else
{
// Item not found, check if a function already exists.
if (is_script_local && (flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) == 0
&& lookup_scriptitem(name, STRLEN(name), FALSE, NULL) == OK)
{
semsg(_(e_redefining_script_item_str), name);
goto failed;
}
if (var_in_vim9script)
// add a new variable
if (var_in_vim9script && (flags & ASSIGN_NO_DECL))
{
where_T where;
// check the type and adjust to bool if needed
where.wt_index = var_idx;
where.wt_variable = TRUE;
if (check_script_var_type(&di->di_tv, tv, name, where) == FAIL)
goto failed;
}
if (var_check_permission(di, name) == FAIL)
goto failed;
}
else
{
// can only redefine once
di->di_flags &= ~DI_FLAGS_RELOAD;
// A Vim9 script-local variable is also present in sn_all_vars and
// sn_var_vals. It may set "type" from "tv".
if (var_in_vim9script)
update_vim9_script_var(FALSE, di, flags, tv, &type,
(flags & ASSIGN_NO_MEMBER_TYPE) == 0);
}
// existing variable, need to clear the value
// Handle setting internal di: variables separately where needed to
// prevent changing the type.
if (ht == &vimvarht)
{
if (di->di_tv.v_type == VAR_STRING)
{
VIM_CLEAR(di->di_tv.vval.v_string);
if (copy || tv->v_type != VAR_STRING)
{
char_u *val = tv_get_string(tv);
// Careful: when assigning to v:errmsg and tv_get_string()
// causes an error message the variable will already be set.
if (di->di_tv.vval.v_string == NULL)
di->di_tv.vval.v_string = vim_strsave(val);
}
else
{
// Take over the string to avoid an extra alloc/free.
di->di_tv.vval.v_string = tv->vval.v_string;
tv->vval.v_string = NULL;
}
semsg(_(e_unknown_variable_str), name);
goto failed;
}
else if (di->di_tv.v_type == VAR_NUMBER)
// Can't add "v:" or "a:" variable.
if (ht == &vimvarht || ht == get_funccal_args_ht())
{
di->di_tv.vval.v_number = tv_get_number(tv);
if (STRCMP(varname, "searchforward") == 0)
set_search_direction(di->di_tv.vval.v_number ? '/' : '?');
#ifdef FEAT_SEARCH_EXTRA
else if (STRCMP(varname, "hlsearch") == 0)
{
no_hlsearch = !di->di_tv.vval.v_number;
redraw_all_later(SOME_VALID);
}
#endif
semsg(_(e_illvar), name);
goto failed;
}
else if (di->di_tv.v_type != tv->v_type)
{
semsg(_("E963: setting %s to value with wrong type"), name);
goto failed;
}
}
clear_tv(&di->di_tv);
}
else
{
// Item not found, check if a function already exists.
if (is_script_local && (flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) == 0
&& lookup_scriptitem(name, STRLEN(name), FALSE, NULL) == OK)
{
semsg(_(e_redefining_script_item_str), name);
goto failed;
}
// add a new variable
if (var_in_vim9script && (flags & ASSIGN_NO_DECL))
{
semsg(_(e_unknown_variable_str), name);
goto failed;
}
// Can't add "v:" or "a:" variable.
if (ht == &vimvarht || ht == get_funccal_args_ht())
{
semsg(_(e_illvar), name);
goto failed;
}
// Make sure the variable name is valid. In Vim9 script an autoload
// variable must be prefixed with "g:".
if (!valid_varname(varname, !vim9script
// Make sure the variable name is valid. In Vim9 script an autoload
// variable must be prefixed with "g:".
if (!valid_varname(varname, !vim9script
|| STRNCMP(name, "g:", 2) == 0))
goto failed;
goto failed;
di = alloc(sizeof(dictitem_T) + STRLEN(varname));
if (di == NULL)
goto failed;
STRCPY(di->di_key, varname);
if (hash_add(ht, DI2HIKEY(di)) == FAIL)
{
vim_free(di);
goto failed;
}
di->di_flags = DI_FLAGS_ALLOC;
if (flags & (ASSIGN_CONST | ASSIGN_FINAL))
di->di_flags |= DI_FLAGS_LOCK;
di = alloc(sizeof(dictitem_T) + STRLEN(varname));
if (di == NULL)
goto failed;
STRCPY(di->di_key, varname);
if (hash_add(ht, DI2HIKEY(di)) == FAIL)
{
vim_free(di);
goto failed;
}
di->di_flags = DI_FLAGS_ALLOC;
if (flags & (ASSIGN_CONST | ASSIGN_FINAL))
di->di_flags |= DI_FLAGS_LOCK;
// A Vim9 script-local variable is also added to sn_all_vars and
// sn_var_vals. It may set "type" from "tv".
if (var_in_vim9script)
update_vim9_script_var(TRUE, di, flags, tv, &type,
// A Vim9 script-local variable is also added to sn_all_vars and
// sn_var_vals. It may set "type" from "tv".
if (var_in_vim9script)
update_vim9_script_var(TRUE, di, flags, tv, &type,
(flags & ASSIGN_NO_MEMBER_TYPE) == 0);
}
dest_tv = &di->di_tv;
}
if (copy || tv->v_type == VAR_NUMBER || tv->v_type == VAR_FLOAT)
copy_tv(tv, &di->di_tv);
copy_tv(tv, dest_tv);
else
{
di->di_tv = *tv;
di->di_tv.v_lock = 0;
*dest_tv = *tv;
dest_tv->v_lock = 0;
init_tv(tv);
}
if (vim9script && type != NULL)
{
if (type->tt_type == VAR_DICT && di->di_tv.vval.v_dict != NULL)
di->di_tv.vval.v_dict->dv_type = alloc_type(type);
else if (type->tt_type == VAR_LIST && di->di_tv.vval.v_list != NULL)
di->di_tv.vval.v_list->lv_type = alloc_type(type);
if (type->tt_type == VAR_DICT && dest_tv->vval.v_dict != NULL)
dest_tv->vval.v_dict->dv_type = alloc_type(type);
else if (type->tt_type == VAR_LIST && dest_tv->vval.v_list != NULL)
dest_tv->vval.v_list->lv_type = alloc_type(type);
}
// ":const var = value" locks the value
@@ -3426,8 +3461,9 @@ set_var_const(
// Like :lockvar! name: lock the value and what it contains, but only
// if the reference count is up to one. That locks only literal
// values.
item_lock(&di->di_tv, DICT_MAXNEST, TRUE, TRUE);
item_lock(dest_tv, DICT_MAXNEST, TRUE, TRUE);
return;
failed:
if (!copy)
clear_tv(tv_arg);
+6
View File
@@ -653,6 +653,12 @@ f_tabpagewinnr(typval_T *argvars UNUSED, typval_T *rettv)
int nr = 1;
tabpage_T *tp;
if (in_vim9script()
&& (check_for_number_arg(argvars, 0) == FAIL
|| (argvars[1].v_type != VAR_UNKNOWN
&& check_for_string_arg(argvars, 1) == FAIL)))
return;
tp = find_tabpage((int)tv_get_number(&argvars[0]));
if (tp == NULL)
nr = 0;
+6
View File
@@ -1447,6 +1447,12 @@ f_pathshorten(typval_T *argvars, typval_T *rettv)
char_u *p;
int trim_len = 1;
if (in_vim9script()
&& (check_for_string_arg(argvars, 0) == FAIL
|| (argvars[1].v_type != VAR_UNKNOWN
&& check_for_number_arg(argvars, 1) == FAIL)))
return;
if (argvars[1].v_type != VAR_UNKNOWN)
{
trim_len = (int)tv_get_number(&argvars[1]);
+2
View File
@@ -1703,6 +1703,8 @@ EXTERN char e_cannot_mod[] INIT(= N_("E995: Cannot modify existing variable"));
EXTERN char e_readonlyvar[] INIT(= N_("E46: Cannot change read-only variable \"%s\""));
EXTERN char e_readonlysbx[] INIT(= N_("E794: Cannot set variable in the sandbox: \"%s\""));
EXTERN char e_stringreq[] INIT(= N_("E928: String required"));
EXTERN char e_numberreq[] INIT(= N_("E889: Number required"));
EXTERN char e_boolreq[] INIT(= N_("E839: Number required"));
EXTERN char e_emptykey[] INIT(= N_("E713: Cannot use empty key for Dictionary"));
EXTERN char e_dictreq[] INIT(= N_("E715: Dictionary required"));
EXTERN char e_listidx[] INIT(= N_("E684: list index out of range: %ld"));
+23
View File
@@ -854,6 +854,7 @@ briopt_check(win_T *wp)
int bri_shift = 0;
long bri_min = 20;
int bri_sbr = FALSE;
int bri_list = 0;
p = wp->w_p_briopt;
while (*p != NUL)
@@ -874,6 +875,11 @@ briopt_check(win_T *wp)
p += 3;
bri_sbr = TRUE;
}
else if (STRNCMP(p, "list:", 5) == 0)
{
p += 5;
bri_list = getdigits(&p);
}
if (*p != ',' && *p != NUL)
return FAIL;
if (*p == ',')
@@ -883,6 +889,7 @@ briopt_check(win_T *wp)
wp->w_briopt_shift = bri_shift;
wp->w_briopt_min = bri_min;
wp->w_briopt_sbr = bri_sbr;
wp->w_briopt_list = bri_list;
return OK;
}
@@ -941,9 +948,25 @@ get_breakindent_win(
// Add offset for number column, if 'n' is in 'cpoptions'
bri += win_col_off2(wp);
// add additional indent for numbered lists
if (wp->w_briopt_list > 0)
{
regmatch_T regmatch;
regmatch.regprog = vim_regcomp(curbuf->b_p_flp,
RE_MAGIC + RE_STRING + RE_AUTO + RE_STRICT);
if (regmatch.regprog != NULL)
{
if (vim_regexec(&regmatch, line, 0))
bri += wp->w_briopt_list;
vim_regfree(regmatch.regprog);
}
}
// never indent past left window margin
if (bri < 0)
bri = 0;
// always leave at least bri_min characters on the left,
// if text width is sufficient
else if (bri > eff_wwidth - wp->w_briopt_min)
+7
View File
@@ -1737,6 +1737,13 @@ f_prompt_setprompt(typval_T *argvars, typval_T *rettv UNUSED)
buf_T *buf;
char_u *text;
if (in_vim9script()
&& ((argvars[0].v_type != VAR_STRING
&& argvars[0].v_type != VAR_NUMBER
&& check_for_string_arg(argvars, 0) == FAIL)
|| check_for_string_arg(argvars, 1) == FAIL))
return;
if (check_secure())
return;
buf = tv_get_buf(&argvars[0], FALSE);
+26 -6
View File
@@ -1566,12 +1566,32 @@ list_remove(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg)
vimlist_remove(l, item, item2);
if (rettv_list_alloc(rettv) == OK)
{
l = rettv->vval.v_list;
l->lv_first = item;
l->lv_u.mat.lv_last = item2;
item->li_prev = NULL;
item2->li_next = NULL;
l->lv_len = cnt;
list_T *rl = rettv->vval.v_list;
if (l->lv_with_items > 0)
{
// need to copy the list items and move the value
while (item != NULL)
{
li = listitem_alloc();
if (li == NULL)
return;
li->li_tv = item->li_tv;
init_tv(&item->li_tv);
list_append(rl, li);
if (item == item2)
break;
item = item->li_next;
}
}
else
{
rl->lv_first = item;
rl->lv_u.mat.lv_last = item2;
item->li_prev = NULL;
item2->li_next = NULL;
rl->lv_len = cnt;
}
}
}
}
+20 -1
View File
@@ -3618,6 +3618,12 @@ verbose_open(void)
*/
void
give_warning(char_u *message, int hl)
{
give_warning_with_source(message, hl, FALSE);
}
void
give_warning_with_source(char_u *message, int hl, int with_source)
{
// Don't do this for ":silent".
if (msg_silent != 0)
@@ -3634,8 +3640,21 @@ give_warning(char_u *message, int hl)
keep_msg_attr = HL_ATTR(HLF_W);
else
keep_msg_attr = 0;
if (msg_attr((char *)message, keep_msg_attr) && msg_scrolled == 0)
if (with_source)
{
// Do what msg() does, but with a column offset if the warning should
// be after the mode message.
msg_start();
msg_source(HL_ATTR(HLF_W));
msg_puts(" ");
msg_puts_attr((char *)message, HL_ATTR(HLF_W) | MSG_HIST);
msg_clr_eos();
(void)msg_end();
}
else if (msg_attr((char *)message, keep_msg_attr) && msg_scrolled == 0)
set_keep_msg(message, keep_msg_attr);
msg_didout = FALSE; // overwrite this message
msg_nowait = TRUE; // don't wait for this message
msg_col = 0;
+18 -3
View File
@@ -2607,8 +2607,8 @@ path_is_url(char_u *p)
}
/*
* Check if "fname" starts with "name://". Return URL_SLASH if it does.
* Return URL_BACKSLASH for "name:\\".
* Check if "fname" starts with "name://" or "name:\\".
* Return URL_SLASH for "name://", URL_BACKSLASH for "name:\\".
* Return zero otherwise.
*/
int
@@ -2616,7 +2616,22 @@ path_with_url(char_u *fname)
{
char_u *p;
for (p = fname; isalpha(*p); ++p)
// We accept alphabetic characters and a dash in scheme part.
// RFC 3986 allows for more, but it increases the risk of matching
// non-URL text.
// first character must be alpha
if (!isalpha(*fname))
return 0;
// check body: alpha or dash
for (p = fname; (isalpha(*p) || (*p == '-')); ++p)
;
// check last char is not a dash
if (p[-1] == '-')
return 0;
// "://" or ":\\" must follow
return path_is_url(p);
}
+40 -10
View File
@@ -2359,13 +2359,21 @@ filter_handle_drag(win_T *wp, int c, typval_T *rettv)
void
f_popup_filter_menu(typval_T *argvars, typval_T *rettv)
{
int id = tv_get_number(&argvars[0]);
win_T *wp = win_id2wp(id);
char_u *key = tv_get_string(&argvars[1]);
int id;
win_T *wp;
char_u *key;
typval_T res;
int c;
linenr_T old_lnum;
if (in_vim9script()
&& (check_for_number_arg(argvars, 0) == FAIL
|| check_for_string_arg(argvars, 1) == FAIL))
return;
id = tv_get_number(&argvars[0]);
wp = win_id2wp(id);
key = tv_get_string(&argvars[1]);
// If the popup has been closed do not consume the key.
if (wp == NULL)
return;
@@ -2416,12 +2424,20 @@ f_popup_filter_menu(typval_T *argvars, typval_T *rettv)
void
f_popup_filter_yesno(typval_T *argvars, typval_T *rettv)
{
int id = tv_get_number(&argvars[0]);
win_T *wp = win_id2wp(id);
char_u *key = tv_get_string(&argvars[1]);
int id;
win_T *wp;
char_u *key;
typval_T res;
int c;
if (in_vim9script()
&& (check_for_number_arg(argvars, 0) == FAIL
|| check_for_string_arg(argvars, 1) == FAIL))
return;
id = tv_get_number(&argvars[0]);
wp = win_id2wp(id);
key = tv_get_string(&argvars[1]);
// If the popup has been closed don't consume the key.
if (wp == NULL)
return;
@@ -2727,9 +2743,16 @@ close_all_popups(int force)
f_popup_move(typval_T *argvars, typval_T *rettv UNUSED)
{
dict_T *dict;
int id = (int)tv_get_number(argvars);
win_T *wp = find_popup_win(id);
int id;
win_T *wp;
if (in_vim9script()
&& (check_for_number_arg(argvars, 0) == FAIL
|| check_for_dict_arg(argvars, 1) == FAIL))
return;
id = (int)tv_get_number(argvars);
wp = find_popup_win(id);
if (wp == NULL)
return; // invalid {id}
@@ -2754,10 +2777,17 @@ f_popup_move(typval_T *argvars, typval_T *rettv UNUSED)
f_popup_setoptions(typval_T *argvars, typval_T *rettv UNUSED)
{
dict_T *dict;
int id = (int)tv_get_number(argvars);
win_T *wp = find_popup_win(id);
int id;
win_T *wp;
linenr_T old_firstline;
if (in_vim9script()
&& (check_for_number_arg(argvars, 0) == FAIL
|| check_for_dict_arg(argvars, 1) == FAIL))
return;
id = (int)tv_get_number(argvars);
wp = find_popup_win(id);
if (wp == NULL)
return; // invalid {id}
+1
View File
@@ -69,6 +69,7 @@ void verbose_leave_scroll(void);
void verbose_stop(void);
int verbose_open(void);
void give_warning(char_u *message, int hl);
void give_warning_with_source(char_u *message, int hl, int with_source);
void give_warning2(char_u *message, char_u *a1, int hl);
void msg_advance(int col);
int do_dialog(int type, char_u *title, char_u *message, char_u *buttons, int dfltbutton, char_u *textfield, int ex_cmd);
+3
View File
@@ -11,6 +11,9 @@ varnumber_T tv_get_bool_chk(typval_T *varp, int *denote);
float_T tv_get_float(typval_T *varp);
int check_for_string_arg(typval_T *args, int idx);
int check_for_nonempty_string_arg(typval_T *args, int idx);
int check_for_number_arg(typval_T *args, int idx);
int check_for_bool_arg(typval_T *args, int idx);
int check_for_list_arg(typval_T *args, int idx);
int check_for_dict_arg(typval_T *args, int idx);
char_u *tv_get_string(typval_T *varp);
char_u *tv_get_string_strict(typval_T *varp);
+1
View File
@@ -3461,6 +3461,7 @@ qf_jump_newwin(qf_info_T *qi,
}
qfl->qf_index = qf_index;
qfl->qf_ptr = qf_ptr;
if (qf_win_pos_update(qi, old_qf_index))
// No need to print the error message if it's visible in the error
// window
+4
View File
@@ -2274,7 +2274,11 @@ f_sign_getdefined(typval_T *argvars, typval_T *rettv)
return;
if (argvars[0].v_type != VAR_UNKNOWN)
{
if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
return;
name = tv_get_string(&argvars[0]);
}
sign_getlist(name, rettv->vval.v_list);
}
+35 -2
View File
@@ -795,9 +795,15 @@ byteidx(typval_T *argvars, typval_T *rettv, int comp UNUSED)
char_u *str;
varnumber_T idx;
rettv->vval.v_number = -1;
if (in_vim9script()
&& (check_for_string_arg(argvars, 0) == FAIL
|| check_for_number_arg(argvars, 1) == FAIL))
return;
str = tv_get_string_chk(&argvars[0]);
idx = tv_get_number_chk(&argvars[1], NULL);
rettv->vval.v_number = -1;
if (str == NULL || idx < 0)
return;
@@ -896,6 +902,12 @@ f_str2list(typval_T *argvars, typval_T *rettv)
if (rettv_list_alloc(rettv) == FAIL)
return;
if (in_vim9script()
&& (check_for_string_arg(argvars, 0) == FAIL
|| (argvars[1].v_type != VAR_UNKNOWN
&& check_for_bool_arg(argvars, 1) == FAIL)))
return;
if (argvars[1].v_type != VAR_UNKNOWN)
utf8 = (int)tv_get_bool_chk(&argvars[1], NULL);
@@ -981,6 +993,12 @@ f_strgetchar(typval_T *argvars, typval_T *rettv)
int byteidx = 0;
rettv->vval.v_number = -1;
if (in_vim9script()
&& (check_for_string_arg(argvars, 0) == FAIL
|| check_for_number_arg(argvars, 1) == FAIL))
return;
str = tv_get_string_chk(&argvars[0]);
if (str == NULL)
return;
@@ -1096,6 +1114,12 @@ f_strchars(typval_T *argvars, typval_T *rettv)
{
varnumber_T skipcc = FALSE;
if (in_vim9script()
&& (check_for_string_arg(argvars, 0) == FAIL
|| (argvars[1].v_type != VAR_UNKNOWN
&& check_for_bool_arg(argvars, 1) == FAIL)))
return;
if (argvars[1].v_type != VAR_UNKNOWN)
skipcc = tv_get_bool(&argvars[1]);
if (skipcc < 0 || skipcc > 1)
@@ -1110,9 +1134,18 @@ f_strchars(typval_T *argvars, typval_T *rettv)
void
f_strdisplaywidth(typval_T *argvars, typval_T *rettv)
{
char_u *s = tv_get_string(&argvars[0]);
char_u *s;
int col = 0;
rettv->vval.v_number = -1;
if (in_vim9script()
&& (check_for_string_arg(argvars, 0) == FAIL
|| (argvars[1].v_type != VAR_UNKNOWN
&& check_for_number_arg(argvars, 1) == FAIL)))
return;
s = tv_get_string(&argvars[0]);
if (argvars[1].v_type != VAR_UNKNOWN)
col = (int)tv_get_number(&argvars[1]);
+1
View File
@@ -3683,6 +3683,7 @@ struct window_S
int w_briopt_min; // minimum width for breakindent
int w_briopt_shift; // additional shift for breakindent
int w_briopt_sbr; // sbr in 'briopt'
int w_briopt_list; // additional indent for lists
#endif
// transform a pointer to a "onebuf" option into a "allbuf" option
+16 -16
View File
@@ -3312,7 +3312,6 @@ jumpto_tag(
int forceit, // :ta with !
int keep_help) // keep help flag (FALSE for cscope)
{
int save_secure;
optmagic_T save_magic_overruled;
int save_p_ws, save_p_scs, save_p_ic;
linenr_T save_lnum;
@@ -3500,11 +3499,6 @@ jumpto_tag(
curwin->w_set_curswant = TRUE;
postponed_split = 0;
save_secure = secure;
secure = 1;
#ifdef HAVE_SANDBOX
++sandbox;
#endif
save_magic_overruled = magic_overruled;
magic_overruled = OPTION_MAGIC_OFF; // always execute with 'nomagic'
#ifdef FEAT_SEARCH_EXTRA
@@ -3621,22 +3615,28 @@ jumpto_tag(
}
else
{
int save_secure = secure;
// Setup the sandbox for executing the command from the tags file.
secure = 1;
#ifdef HAVE_SANDBOX
++sandbox;
#endif
curwin->w_cursor.lnum = 1; // start command in line 1
do_cmdline_cmd(pbuf);
retval = OK;
// When the command has done something that is not allowed make
// sure the error message can be seen.
if (secure == 2)
wait_return(TRUE);
secure = save_secure;
#ifdef HAVE_SANDBOX
--sandbox;
#endif
}
/*
* When the command has done something that is not allowed make sure
* the error message can be seen.
*/
if (secure == 2)
wait_return(TRUE);
secure = save_secure;
magic_overruled = save_magic_overruled;
#ifdef HAVE_SANDBOX
--sandbox;
#endif
#ifdef FEAT_SEARCH_EXTRA
// restore no_hlsearch when keeping the old search pattern
if (search_options)
+51 -5
View File
@@ -5694,6 +5694,11 @@ f_term_getattr(typval_T *argvars, typval_T *rettv)
{"reverse", HL_INVERSE},
};
if (in_vim9script()
&& (check_for_number_arg(argvars, 0) == FAIL
|| check_for_string_arg(argvars, 1) == FAIL))
return;
attr = tv_get_number(&argvars[0]);
name = tv_get_string_chk(&argvars[1]);
if (name == NULL)
@@ -6093,10 +6098,18 @@ f_term_scrape(typval_T *argvars, typval_T *rettv)
void
f_term_sendkeys(typval_T *argvars, typval_T *rettv UNUSED)
{
buf_T *buf = term_get_buf(argvars, "term_sendkeys()");
buf_T *buf;
char_u *msg;
term_T *term;
if (in_vim9script()
&& ((argvars[0].v_type != VAR_STRING
&& argvars[0].v_type != VAR_NUMBER
&& check_for_string_arg(argvars, 0) == FAIL)
|| check_for_string_arg(argvars, 1) == FAIL))
return;
buf = term_get_buf(argvars, "term_sendkeys()");
if (buf == NULL)
return;
@@ -6193,10 +6206,18 @@ f_term_setansicolors(typval_T *argvars, typval_T *rettv UNUSED)
void
f_term_setapi(typval_T *argvars, typval_T *rettv UNUSED)
{
buf_T *buf = term_get_buf(argvars, "term_setapi()");
buf_T *buf;
term_T *term;
char_u *api;
if (in_vim9script()
&& ((argvars[0].v_type != VAR_STRING
&& argvars[0].v_type != VAR_NUMBER
&& check_for_string_arg(argvars, 0) == FAIL)
|| check_for_string_arg(argvars, 1) == FAIL))
return;
buf = term_get_buf(argvars, "term_setapi()");
if (buf == NULL)
return;
term = buf->b_term;
@@ -6215,10 +6236,18 @@ f_term_setapi(typval_T *argvars, typval_T *rettv UNUSED)
f_term_setrestore(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
{
#if defined(FEAT_SESSION)
buf_T *buf = term_get_buf(argvars, "term_setrestore()");
buf_T *buf;
term_T *term;
char_u *cmd;
if (in_vim9script()
&& ((argvars[0].v_type != VAR_STRING
&& argvars[0].v_type != VAR_NUMBER
&& check_for_string_arg(argvars, 0) == FAIL)
|| check_for_string_arg(argvars, 1) == FAIL))
return;
buf = term_get_buf(argvars, "term_setrestore()");
if (buf == NULL)
return;
term = buf->b_term;
@@ -6237,10 +6266,18 @@ f_term_setrestore(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
void
f_term_setkill(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
{
buf_T *buf = term_get_buf(argvars, "term_setkill()");
buf_T *buf;
term_T *term;
char_u *how;
if (in_vim9script()
&& ((argvars[0].v_type != VAR_STRING
&& argvars[0].v_type != VAR_NUMBER
&& check_for_string_arg(argvars, 0) == FAIL)
|| check_for_string_arg(argvars, 1) == FAIL))
return;
buf = term_get_buf(argvars, "term_setkill()");
if (buf == NULL)
return;
term = buf->b_term;
@@ -6286,8 +6323,17 @@ f_term_start(typval_T *argvars, typval_T *rettv)
void
f_term_wait(typval_T *argvars, typval_T *rettv UNUSED)
{
buf_T *buf = term_get_buf(argvars, "term_wait()");
buf_T *buf;
if (in_vim9script()
&& ((argvars[0].v_type != VAR_STRING
&& argvars[0].v_type != VAR_NUMBER
&& check_for_string_arg(argvars, 0) == FAIL) ||
(argvars[1].v_type != VAR_UNKNOWN
&& check_for_number_arg(argvars, 1) == FAIL)))
return;
buf = term_get_buf(argvars, "term_wait()");
if (buf == NULL)
return;
if (buf->b_term->tl_job == NULL)
+70
View File
@@ -15,6 +15,10 @@ func s:screen_lines(lnum, width) abort
return ScreenLines([a:lnum, a:lnum + 2], a:width)
endfunc
func s:screen_lines2(lnums, lnume, width) abort
return ScreenLines([a:lnums, a:lnume], a:width)
endfunc
func s:compare_lines(expect, actual)
call assert_equal(join(a:expect, "\n"), join(a:actual, "\n"))
endfunc
@@ -708,4 +712,70 @@ func Test_breakindent20_cpo_n_nextpage()
call s:close_windows('set breakindent& briopt& cpo& number&')
endfunc
func Test_breakindent20_list()
call s:test_windows('setl breakindent breakindentopt= linebreak')
" default:
call setline(1, [' 1. Congress shall make no law',
\ ' 2.) Congress shall make no law',
\ ' 3.] Congress shall make no law'])
norm! 1gg
redraw!
let lines = s:screen_lines2(1, 6, 20)
let expect = [
\ " 1. Congress ",
\ "shall make no law ",
\ " 2.) Congress ",
\ "shall make no law ",
\ " 3.] Congress ",
\ "shall make no law ",
\ ]
call s:compare_lines(expect, lines)
" set mininum indent
setl briopt=min:5
redraw!
let lines = s:screen_lines2(1, 6, 20)
let expect = [
\ " 1. Congress ",
\ " shall make no law ",
\ " 2.) Congress ",
\ " shall make no law ",
\ " 3.] Congress ",
\ " shall make no law ",
\ ]
call s:compare_lines(expect, lines)
" set additional handing indent
setl briopt+=list:4
redraw!
let expect = [
\ " 1. Congress ",
\ " shall make no ",
\ " law ",
\ " 2.) Congress ",
\ " shall make no ",
\ " law ",
\ " 3.] Congress ",
\ " shall make no ",
\ " law ",
\ ]
let lines = s:screen_lines2(1, 9, 20)
call s:compare_lines(expect, lines)
" reset linebreak option
" Note: it indents by one additional
" space, because of the leading space.
setl linebreak&vim list listchars=eol:$,space:_
redraw!
let expect = [
\ "__1.__Congress_shall",
\ " _make_no_law$ ",
\ "__2.)_Congress_shall",
\ " _make_no_law$ ",
\ "__3.]_Congress_shall",
\ " _make_no_law$ ",
\ ]
let lines = s:screen_lines2(1, 6, 20)
call s:compare_lines(expect, lines)
call s:close_windows('set breakindent& briopt& linebreak& list& listchars&')
endfunc
" vim: shiftwidth=2 sts=2 expandtab
+29
View File
@@ -381,6 +381,35 @@ func Test_balt()
call assert_equal('OtherBuffer', bufname())
endfunc
" Test for buffer match URL(scheme) check
" scheme is alpha and inner hyphen only.
func Test_buffer_scheme()
CheckMSWindows
set noshellslash
%bwipe!
let bufnames = [
\ #{id: 'b0', name: 'test://xyz/foo/b0' , match: 1},
\ #{id: 'b1', name: 'test+abc://xyz/foo/b1', match: 0},
\ #{id: 'b2', name: 'test_abc://xyz/foo/b2', match: 0},
\ #{id: 'b3', name: 'test-abc://xyz/foo/b3', match: 1},
\ #{id: 'b4', name: '-test://xyz/foo/b4' , match: 0},
\ #{id: 'b5', name: 'test-://xyz/foo/b5' , match: 0},
\]
for buf in bufnames
new `=buf.name`
if buf.match
call assert_equal(buf.name, getbufinfo(buf.id)[0].name)
else
" slashes will have become backslashes
call assert_notequal(buf.name, getbufinfo(buf.id)[0].name)
endif
bwipe
endfor
set shellslash&
endfunc
" Test for the 'maxmem' and 'maxmemtot' options
func Test_buffer_maxmem()
" use 1KB per buffer and 2KB for all the buffers
+2 -2
View File
@@ -162,8 +162,8 @@ func Test_uncrypt_xchacha20_2()
call assert_equal(range(1, 4000)->map( {_, v -> string(v)}), getline(1,'$'))
set key=
w! ++ff=unix
" enryption removed
call assert_match('"Xcrypt_sodium.txt" 4000L, 18893B written', execute(':message'))
" enryption removed (on MS-Windows the .* matches [unix])
call assert_match('"Xcrypt_sodium.txt".*4000L, 18893B written', execute(':message'))
bw!
call delete('Xcrypt_sodium.txt')
set cryptmethod&vim
+5
View File
@@ -95,6 +95,11 @@ func Test_test_void()
call assert_fails('let x = copy([test_void()])', 'E1031:')
endfunc
func Test_islocked()
call assert_fails('call islocked(99)', 'E475:')
call assert_fails('call islocked("s: x")', 'E488:')
endfunc
func Test_len()
call assert_equal(1, len(0))
call assert_equal(2, len(12))
+1 -1
View File
@@ -2614,7 +2614,7 @@ func Test_normal40_ctrl_bsl()
set noim
call assert_equal('are some words', getline(1))
call assert_false(&insertmode)
call assert_beeps("normal! \<C-\>\<C-A>", 'xt')
call assert_beeps("normal! \<C-\>\<C-A>")
if has('cmdwin')
" Using CTRL-\ CTRL-N in cmd window should close the window
+44
View File
@@ -941,6 +941,28 @@ func Test_opt_local_to_global()
set autoread&
endfunc
func Test_set_in_sandbox()
" Some boolean options cannot be set in sandbox, some can.
call assert_fails('sandbox set modelineexpr', 'E48:')
sandbox set number
call assert_true(&number)
set number&
" Some boolean options cannot be set in sandbox, some can.
if has('python') || has('python3')
call assert_fails('sandbox set pyxversion=3', 'E48:')
endif
sandbox set tabstop=4
call assert_equal(4, &tabstop)
set tabstop&
" Some string options cannot be set in sandbox, some can.
call assert_fails('sandbox set backupdir=/tmp', 'E48:')
sandbox set filetype=perl
call assert_equal('perl', &filetype)
set filetype&
endfunc
" Test for incrementing, decrementing and multiplying a number option value
func Test_opt_num_op()
set shiftwidth=4
@@ -1157,4 +1179,26 @@ func Test_opt_errorbells()
set noerrorbells
endfunc
func Test_opt_scrolljump()
help
resize 10
" Test with positive 'scrolljump'.
set scrolljump=2
norm! Lj
call assert_equal({'lnum':11, 'leftcol':0, 'col':0, 'topfill':0,
\ 'topline':3, 'coladd':0, 'skipcol':0, 'curswant':0},
\ winsaveview())
" Test with negative 'scrolljump' (percentage of window height).
set scrolljump=-40
norm! ggLj
call assert_equal({'lnum':11, 'leftcol':0, 'col':0, 'topfill':0,
\ 'topline':5, 'coladd':0, 'skipcol':0, 'curswant':0},
\ winsaveview())
set scrolljump&
bw
endfunc
" vim: shiftwidth=2 sts=2 expandtab
+33
View File
@@ -5554,4 +5554,37 @@ func Test_vimgrep_fuzzy_match()
call delete('Xfile2')
endfunc
func Test_locationlist_open_in_newtab()
call s:create_test_file('Xqftestfile1')
call s:create_test_file('Xqftestfile2')
call s:create_test_file('Xqftestfile3')
%bwipe!
lgetexpr ['Xqftestfile1:5:Line5',
\ 'Xqftestfile2:10:Line10',
\ 'Xqftestfile3:16:Line16']
silent! llast
call assert_equal(1, tabpagenr('$'))
call assert_equal('Xqftestfile3', bufname())
set switchbuf=newtab
silent! lfirst
call assert_equal(2, tabpagenr('$'))
call assert_equal('Xqftestfile1', bufname())
silent! lnext
call assert_equal(3, tabpagenr('$'))
call assert_equal('Xqftestfile2', bufname())
call delete('Xqftestfile1')
call delete('Xqftestfile2')
call delete('Xqftestfile3')
set switchbuf&vim
%bwipe!
endfunc
" vim: shiftwidth=2 sts=2 expandtab
+2 -2
View File
@@ -24,8 +24,8 @@ func Test_reltime()
call assert_true(reltimefloat(differs) < 0.1)
call assert_true(reltimefloat(differs) > 0.0)
call assert_equal(0, reltime({}))
call assert_equal(0, reltime({}, {}))
call assert_equal([], reltime({}))
call assert_equal([], reltime({}, {}))
endfunc
" vim: shiftwidth=2 sts=2 expandtab
+19
View File
@@ -26,4 +26,23 @@ function Test_set_add()
let &wig = wig_save
endfunction
" :set, :setlocal, :setglobal without arguments show values of options.
func Test_set_no_arg()
set textwidth=79
let a = execute('set')
call assert_match("^\n--- Options ---\n.*textwidth=79\\>", a)
set textwidth&
setlocal textwidth=78
let a = execute('setlocal')
call assert_match("^\n--- Local option values ---\n.*textwidth=78\\>", a)
setlocal textwidth&
setglobal textwidth=77
let a = execute('setglobal')
call assert_match("^\n--- Global option values ---\n.*textwidth=77\\>", a)
setglobal textwidth&
endfunc
" vim: shiftwidth=2 sts=2 expandtab
+35 -19
View File
@@ -1,5 +1,7 @@
" Tests for user defined commands
source vim9.vim
" Test for <mods> in user defined commands
function Test_cmdmods()
let g:mods = ''
@@ -275,6 +277,24 @@ func Test_CmdErrors()
call assert_fails('com! -count=x DoCmd :', 'E178:')
call assert_fails('com! -range=x DoCmd :', 'E178:')
com! -complete=file DoCmd :
call assert_match('E1208:', v:warningmsg)
let v:warningmsg = ''
com! -nargs=0 -complete=file DoCmd :
call assert_match('E1208:', v:warningmsg)
let lines =<< trim END
vim9script
com! -complete=file DoCmd :
END
call CheckScriptFailure(lines, 'E1208', 2)
let lines =<< trim END
vim9script
com! -nargs=0 -complete=file DoCmd :
END
call CheckScriptFailure(lines, 'E1208', 2)
com! -nargs=0 DoCmd :
call assert_fails('DoCmd x', 'E488:')
@@ -338,34 +358,30 @@ func Test_CmdCompletion()
call feedkeys(":com DoC\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"com DoC', @:)
com! -complete=behave DoCmd :
com! -nargs=1 -complete=behave DoCmd :
call feedkeys(":DoCmd \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"DoCmd mswin xterm', @:)
" This does not work. Why?
"call feedkeys(":DoCmd x\<C-A>\<C-B>\"\<CR>", 'tx')
"call assert_equal('"DoCmd xterm', @:)
com! -complete=custom,CustomComplete DoCmd :
com! -nargs=* -complete=custom,CustomComplete DoCmd :
call feedkeys(":DoCmd \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"DoCmd January February Mars', @:)
com! -complete=customlist,CustomCompleteList DoCmd :
com! -nargs=? -complete=customlist,CustomCompleteList DoCmd :
call feedkeys(":DoCmd \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"DoCmd Monday Tuesday Wednesday', @:)
com! -complete=custom,CustomCompleteList DoCmd :
com! -nargs=+ -complete=custom,CustomCompleteList DoCmd :
call assert_fails("call feedkeys(':DoCmd \<C-D>', 'tx')", 'E730:')
com! -complete=customlist,CustomComp DoCmd :
com! -nargs=+ -complete=customlist,CustomComp DoCmd :
call assert_fails("call feedkeys(':DoCmd \<C-D>', 'tx')", 'E117:')
" custom completion without a function
com! -complete=custom, DoCmd
com! -nargs=? -complete=custom, DoCmd
call assert_beeps("call feedkeys(':DoCmd \t', 'tx')")
" custom completion failure with the wrong function
com! -complete=custom,min DoCmd
com! -nargs=? -complete=custom,min DoCmd
call assert_fails("call feedkeys(':DoCmd \t', 'tx')", 'E118:')
delcom DoCmd
@@ -500,21 +516,21 @@ func Test_command_list()
\ execute('command DoCmd'))
" Test with various -complete= argument values (non-exhaustive list)
command! -complete=arglist DoCmd :
command! -nargs=1 -complete=arglist DoCmd :
call assert_equal("\n Name Args Address Complete Definition"
\ .. "\n DoCmd 0 arglist :",
\ .. "\n DoCmd 1 arglist :",
\ execute('command DoCmd'))
command! -complete=augroup DoCmd :
command! -nargs=* -complete=augroup DoCmd :
call assert_equal("\n Name Args Address Complete Definition"
\ .. "\n DoCmd 0 augroup :",
\ .. "\n DoCmd * augroup :",
\ execute('command DoCmd'))
command! -complete=custom,CustomComplete DoCmd :
command! -nargs=? -complete=custom,CustomComplete DoCmd :
call assert_equal("\n Name Args Address Complete Definition"
\ .. "\n DoCmd 0 custom :",
\ .. "\n DoCmd ? custom :",
\ execute('command DoCmd'))
command! -complete=customlist,CustomComplete DoCmd :
command! -nargs=+ -complete=customlist,CustomComplete DoCmd :
call assert_equal("\n Name Args Address Complete Definition"
\ .. "\n DoCmd 0 customlist :",
\ .. "\n DoCmd + customlist :",
\ execute('command DoCmd'))
" Test with various -narg= argument values.
+17
View File
@@ -1632,6 +1632,13 @@ def Test_script_local_in_legacy()
let s:legvar = 'one'
END
CheckScriptFailure(lines, 'E476:', 1)
edit! Xfile
lines =<< trim END
var edit: bool
legacy edit
END
CheckDefAndScriptSuccess(lines)
enddef
def Test_var_type_check()
@@ -1667,6 +1674,16 @@ def Test_var_type_check()
s:d = {}
END
CheckScriptSuccess(lines)
lines =<< trim END
vim9script
var d = {a: 1, b: [2]}
def Func(b: bool)
var l: list<number> = b ? d.b : [3]
enddef
defcompile
END
CheckScriptSuccess(lines)
enddef
let g:dict_number = #{one: 1, two: 2}
File diff suppressed because it is too large Load Diff
+40 -2
View File
@@ -401,6 +401,13 @@ def Test_expr2_fails()
# comment
END
CheckScriptFailure(lines, 'E1004: White space required before and after ''||'' at "||true"', 3)
lines =<< trim END
var x = false
|| false
|| a.b
END
CheckDefFailure(lines, 'E1001:', 3)
enddef
" test &&
@@ -653,13 +660,36 @@ def Test_expr4_equal()
CheckDefExecAndScriptFailure(["var x: any = true", 'echo x == ""'], 'E1072: Cannot compare bool with string', 2)
CheckDefExecAndScriptFailure2(["var x: any = 99", 'echo x == true'], 'E1138', 'E1072:', 2)
CheckDefExecAndScriptFailure2(["var x: any = 'a'", 'echo x == 99'], 'E1030:', 'E1072:', 2)
enddef
def Test_expr4_wrong_type()
for op in ['>', '>=', '<', '<=', '=~', '!~']
CheckDefExecAndScriptFailure([
"var a: any = 'a'",
'var b: any = true',
'echo a ' .. op .. ' b'], 'E1072:', 3)
endfor
for op in ['>', '>=', '<', '<=']
CheckDefExecAndScriptFailure2([
"var n: any = 2",
'echo n ' .. op .. ' "3"'], 'E1030:', 'E1072:', 2)
endfor
for op in ['=~', '!~']
CheckDefExecAndScriptFailure([
"var n: any = 2",
'echo n ' .. op .. ' "3"'], 'E1072:', 2)
endfor
CheckDefAndScriptFailure([
'echo v:none == true'], 'E1072:', 1)
CheckDefAndScriptFailure([
'echo false >= true'], 'E1072:', 1)
CheckDefExecAndScriptFailure([
"var n: any = v:none",
'echo n == true'], 'E1072:', 2)
CheckDefExecAndScriptFailure([
"var n: any = v:none",
'echo n < true'], 'E1072:', 2)
enddef
" test != comperator
@@ -2075,7 +2105,8 @@ def Test_expr7_lambda_block()
var Func = (nr: number): int => {
return nr
END
CheckDefAndScriptFailure(lines, 'E1171', 1) # line nr is function start
CheckDefFailure(lines, 'E1171', 0) # line nr is function start
CheckScriptFailure(['vim9script'] + lines, 'E1171', 2)
lines =<< trim END
var Func = (nr: number): int => {
@@ -2478,6 +2509,13 @@ def Test_expr7_dict_vim9script()
else
CheckDefAndScriptFailure(lines, 'E117:', 0)
endif
lines =<< trim END
vim9script
var x = 99
assert_equal({x: 99}, s:)
END
CheckScriptSuccess(lines)
enddef
def Test_expr7_call_2bool()
@@ -2975,7 +3013,7 @@ def Test_expr7_method_call()
enddef
RetVoid()->byteidx(3)
END
CheckDefExecAndScriptFailure(lines, 'E1031:')
CheckDefExecFailure(lines, 'E1013:')
enddef
+26
View File
@@ -2255,6 +2255,32 @@ def Test_nested_inline_lambda()
assert_equal('--there', F('unused')('there')('--'))
END
CheckScriptSuccess(lines)
lines =<< trim END
vim9script
echo range(4)->mapnew((_, v) => {
return range(v) ->mapnew((_, s) => {
return string(s)
})
})
END
CheckScriptSuccess(lines)
lines =<< trim END
vim9script
def s:func()
range(10)
->mapnew((_, _) => ({
key: range(10)->mapnew((_, _) => {
return ' '
}),
}))
enddef
defcomp
END
CheckScriptSuccess(lines)
enddef
def Shadowed(): list<number>
+157 -61
View File
@@ -1062,6 +1062,12 @@ let s:export_script_lines =<< trim END
export def Exported(): string
return 'Exported'
enddef
export def ExportedValue(): number
return exported
enddef
export def ExportedInc()
exported += 5
enddef
export final theList = [1]
END
@@ -1073,10 +1079,21 @@ enddef
def Test_vim9_import_export()
var import_script_lines =<< trim END
vim9script
import {exported, Exported} from './Xexport.vim'
g:imported = exported
import {exported, Exported, ExportedValue} from './Xexport.vim'
g:exported1 = exported
exported += 3
g:imported_added = exported
g:exported2 = exported
g:exported3 = ExportedValue()
import ExportedInc from './Xexport.vim'
ExportedInc()
g:exported_i1 = exported
g:exported_i2 = ExportedValue()
exported = 11
g:exported_s1 = exported
g:exported_s2 = ExportedValue()
g:imported_func = Exported()
def GetExported(): string
@@ -1085,11 +1102,13 @@ def Test_vim9_import_export()
enddef
g:funcref_result = GetExported()
import {exp_name} from './Xexport.vim'
var dir = './'
var ext = ".vim"
import {exp_name} from dir .. 'Xexport' .. ext
g:imported_name = exp_name
exp_name ..= ' Doe'
g:imported_name_appended = exp_name
g:imported_later = exported
g:exported_later = exported
import theList from './Xexport.vim'
theList->add(2)
@@ -1103,9 +1122,17 @@ def Test_vim9_import_export()
assert_equal('bobbie', g:result)
assert_equal('bob', g:localname)
assert_equal(9876, g:imported)
assert_equal(9879, g:imported_added)
assert_equal(9879, g:imported_later)
assert_equal(9876, g:exported1)
assert_equal(9879, g:exported2)
assert_equal(9879, g:exported3)
assert_equal(9884, g:exported_i1)
assert_equal(9884, g:exported_i2)
assert_equal(11, g:exported_s1)
assert_equal(11, g:exported_s2)
assert_equal(11, g:exported_later)
assert_equal('Exported', g:imported_func)
assert_equal('Exported', g:funcref_result)
assert_equal('John', g:imported_name)
@@ -1113,9 +1140,12 @@ def Test_vim9_import_export()
assert_false(exists('g:name'))
Undo_export_script_lines()
unlet g:imported
unlet g:imported_added
unlet g:imported_later
unlet g:exported1
unlet g:exported2
unlet g:exported3
unlet g:exported_i1
unlet g:exported_i2
unlet g:exported_later
unlet g:imported_func
unlet g:imported_name g:imported_name_appended
delete('Ximport.vim')
@@ -1129,60 +1159,43 @@ def Test_vim9_import_export()
}
from
'./Xexport.vim'
g:imported = exported
exported += 5
g:imported_added = exported
g:exported = exported
exported += 7
g:exported_added = exported
g:imported_func = Exported()
END
writefile(import_line_break_script_lines, 'Ximport_lbr.vim')
source Ximport_lbr.vim
assert_equal(9876, g:imported)
assert_equal(9881, g:imported_added)
assert_equal(11, g:exported)
assert_equal(18, g:exported_added)
assert_equal('Exported', g:imported_func)
# exported script not sourced again
assert_false(exists('g:result'))
unlet g:imported
unlet g:imported_added
unlet g:exported
unlet g:exported_added
unlet g:imported_func
delete('Ximport_lbr.vim')
# import inside :def function
var import_in_def_lines =<< trim END
vim9script
def ImportInDef()
import exported from './Xexport.vim'
g:imported = exported
exported += 7
g:imported_added = exported
enddef
ImportInDef()
END
writefile(import_in_def_lines, 'Ximport2.vim')
source Ximport2.vim
# TODO: this should be 9879
assert_equal(9876, g:imported)
assert_equal(9883, g:imported_added)
unlet g:imported
unlet g:imported_added
delete('Ximport2.vim')
var import_star_as_lines =<< trim END
vim9script
import * as Export from './Xexport.vim'
def UseExport()
g:imported_def = Export.exported
g:exported_def = Export.exported
enddef
g:imported_script = Export.exported
g:exported_script = Export.exported
assert_equal(1, exists('Export.exported'))
assert_equal(0, exists('Export.notexported'))
UseExport()
END
writefile(import_star_as_lines, 'Ximport.vim')
source Ximport.vim
assert_equal(9883, g:imported_def)
assert_equal(9883, g:imported_script)
assert_equal(18, g:exported_def)
assert_equal(18, g:exported_script)
unlet g:exported_def
unlet g:exported_script
var import_star_as_lines_no_dot =<< trim END
vim9script
@@ -1251,13 +1264,14 @@ def Test_vim9_import_export()
from
'./Xexport.vim'
def UseExport()
g:imported = Export.exported
g:exported = Export.exported
enddef
UseExport()
END
writefile(import_star_as_lbr_lines, 'Ximport.vim')
source Ximport.vim
assert_equal(9883, g:imported)
assert_equal(18, g:exported)
unlet g:exported
var import_star_lines =<< trim END
vim9script
@@ -1345,7 +1359,7 @@ def Test_vim9_import_export()
import name from Xexport.vim
END
writefile(import_invalid_string_lines, 'Ximport.vim')
assert_fails('source Ximport.vim', 'E1071:', '', 2, 'Ximport.vim')
assert_fails('source Ximport.vim', 'E121:', '', 2, 'Ximport.vim')
var import_wrong_name_lines =<< trim END
vim9script
@@ -1659,22 +1673,6 @@ def Test_vim9script_reload_import()
source Xreload.vim
source Xreload.vim
var testlines =<< trim END
vim9script
def TheFunc()
import GetValtwo from './Xreload.vim'
assert_equal(222, GetValtwo())
enddef
TheFunc()
END
writefile(testlines, 'Ximport.vim')
source Ximport.vim
# Test that when not using "morelines" GetValtwo() and valtwo are still
# defined, because import doesn't reload a script.
writefile(lines, 'Xreload.vim')
source Ximport.vim
# cannot declare a var twice
lines =<< trim END
vim9script
@@ -2557,6 +2555,12 @@ def Test_for_loop()
dd.counter = 12
endfor
assert_equal([{a: 'Cat', counter: 12}], foo)
reslist = []
for _ in range(3)
reslist->add('x')
endfor
assert_equal(['x', 'x', 'x'], reslist)
END
CheckDefAndScriptSuccess(lines)
enddef
@@ -3699,6 +3703,46 @@ def Test_script_var_in_autocmd()
CheckScriptSuccess(lines)
enddef
def Test_error_in_autoload_script()
var save_rtp = &rtp
var dir = getcwd() .. '/Xruntime'
&rtp = dir
mkdir(dir .. '/autoload', 'p')
var lines =<< trim END
vim9script noclear
def script#autoloaded()
enddef
def Broken()
var x: any = ''
eval x != 0
enddef
Broken()
END
writefile(lines, dir .. '/autoload/script.vim')
lines =<< trim END
vim9script
def CallAutoloaded()
script#autoloaded()
enddef
function Legacy()
try
call s:CallAutoloaded()
catch
call assert_match('E1030: Using a String as a Number', v:exception)
endtry
endfunction
Legacy()
END
CheckScriptSuccess(lines)
&rtp = save_rtp
delete(dir, 'rf')
enddef
def Test_cmdline_win()
# if the Vim syntax highlighting uses Vim9 constructs they can be used from
# the command line window.
@@ -4167,6 +4211,58 @@ def Test_option_modifier()
set hlsearch&
enddef
" This must be called last, it may cause following :def functions to fail
def Test_xxx_echoerr_line_number()
var lines =<< trim END
echoerr 'some'
.. ' error'
.. ' continued'
END
CheckDefExecAndScriptFailure(lines, 'some error continued', 1)
enddef
def ProfiledWithLambda()
var n = 3
echo [[1, 2], [3, 4]]->filter((_, l) => l[0] == n)
enddef
def ProfiledNested()
var x = 0
def Nested(): any
return x
enddef
Nested()
enddef
def ProfiledNestedProfiled()
var x = 0
def Nested(): any
return x
enddef
Nested()
enddef
" Execute this near the end, profiling doesn't stop until Vim exists.
" This only tests that it works, not the profiling output.
def Test_xx_profile_with_lambda()
CheckFeature profile
profile start Xprofile.log
profile func ProfiledWithLambda
ProfiledWithLambda()
profile func ProfiledNested
ProfiledNested()
# Also profile the nested function. Use a different function, although the
# contents is the same, to make sure it was not already compiled.
profile func *
ProfiledNestedProfiled()
profdel func *
profile pause
enddef
" Keep this last, it messes up highlighting.
def Test_substitute_cmd()
new
+15 -3
View File
@@ -340,10 +340,14 @@ assert_append_cmd_or_arg(garray_T *gap, typval_T *argvars, char_u *cmd)
static int
assert_beeps(typval_T *argvars, int no_beep)
{
char_u *cmd = tv_get_string_chk(&argvars[0]);
char_u *cmd;
garray_T ga;
int ret = 0;
if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
return 0;
cmd = tv_get_string_chk(&argvars[0]);
called_vim_beep = FALSE;
suppress_errthrow = TRUE;
emsg_silent = FALSE;
@@ -367,7 +371,7 @@ assert_beeps(typval_T *argvars, int no_beep)
}
/*
* "assert_beeps(cmd [, error])" function
* "assert_beeps(cmd)" function
*/
void
f_assert_beeps(typval_T *argvars, typval_T *rettv)
@@ -376,7 +380,7 @@ f_assert_beeps(typval_T *argvars, typval_T *rettv)
}
/*
* "assert_nobeep(cmd [, error])" function
* "assert_nobeep(cmd)" function
*/
void
f_assert_nobeep(typval_T *argvars, typval_T *rettv)
@@ -824,6 +828,9 @@ f_assert_report(typval_T *argvars, typval_T *rettv)
{
garray_T ga;
if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
return;
prepare_assert_error(&ga);
ga_concat(&ga, tv_get_string(&argvars[0]));
assert_error(&ga);
@@ -944,6 +951,11 @@ f_test_override(typval_T *argvars, typval_T *rettv UNUSED)
int val;
static int save_starting = -1;
if (in_vim9script()
&& (check_for_string_arg(argvars, 0) == FAIL
|| check_for_number_arg(argvars, 1) == FAIL))
return;
if (argvars[0].v_type != VAR_STRING
|| (argvars[1].v_type) != VAR_NUMBER)
emsg(_(e_invarg));
+8 -1
View File
@@ -769,9 +769,16 @@ f_prop_find(typval_T *argvars, typval_T *rettv)
void
f_prop_list(typval_T *argvars, typval_T *rettv)
{
linenr_T lnum = tv_get_number(&argvars[0]);
linenr_T lnum;
buf_T *buf = curbuf;
if (in_vim9script()
&& (check_for_number_arg(argvars, 0) == FAIL
|| (argvars[1].v_type != VAR_UNKNOWN &&
check_for_dict_arg(argvars, 1) == FAIL)))
return;
lnum = tv_get_number(&argvars[0]);
if (argvars[1].v_type != VAR_UNKNOWN)
{
if (get_bufnr_from_arg(&argvars[1], &buf) == FAIL)
+28 -11
View File
@@ -169,6 +169,10 @@ f_reltime(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
# ifdef FEAT_RELTIME
proftime_T res;
proftime_T start;
long n1, n2;
if (rettv_list_alloc(rettv) != OK)
return;
if (argvars[0].v_type == VAR_UNKNOWN)
{
@@ -178,7 +182,11 @@ f_reltime(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
else if (argvars[1].v_type == VAR_UNKNOWN)
{
if (list2proftime(&argvars[0], &res) == FAIL)
{
if (in_vim9script())
emsg(_(e_invarg));
return;
}
profile_end(&res);
}
else
@@ -186,24 +194,23 @@ f_reltime(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
// Two arguments: compute the difference.
if (list2proftime(&argvars[0], &start) == FAIL
|| list2proftime(&argvars[1], &res) == FAIL)
{
if (in_vim9script())
emsg(_(e_invarg));
return;
}
profile_sub(&res, &start);
}
if (rettv_list_alloc(rettv) == OK)
{
long n1, n2;
# ifdef MSWIN
n1 = res.HighPart;
n2 = res.LowPart;
n1 = res.HighPart;
n2 = res.LowPart;
# else
n1 = res.tv_sec;
n2 = res.tv_usec;
n1 = res.tv_sec;
n2 = res.tv_usec;
# endif
list_append_number(rettv->vval.v_list, (varnumber_T)n1);
list_append_number(rettv->vval.v_list, (varnumber_T)n2);
}
list_append_number(rettv->vval.v_list, (varnumber_T)n1);
list_append_number(rettv->vval.v_list, (varnumber_T)n2);
# endif
}
@@ -223,6 +230,8 @@ f_reltimefloat(typval_T *argvars UNUSED, typval_T *rettv)
# ifdef FEAT_RELTIME
if (list2proftime(&argvars[0], &tm) == OK)
rettv->vval.v_float = profile_float(&tm);
else if (in_vim9script())
emsg(_(e_invarg));
# endif
}
# endif
@@ -242,6 +251,8 @@ f_reltimestr(typval_T *argvars UNUSED, typval_T *rettv)
# ifdef FEAT_RELTIME
if (list2proftime(&argvars[0], &tm) == OK)
rettv->vval.v_string = vim_strsave((char_u *)profile_msg(&tm));
else if (in_vim9script())
emsg(_(e_invarg));
# endif
}
@@ -257,6 +268,12 @@ f_strftime(typval_T *argvars, typval_T *rettv)
time_t seconds;
char_u *p;
if (in_vim9script()
&& (check_for_string_arg(argvars, 0) == FAIL
|| (argvars[1].v_type != VAR_UNKNOWN
&& check_for_number_arg(argvars, 1) == FAIL)))
return;
rettv->v_type = VAR_STRING;
p = tv_get_string(&argvars[0]);
+70 -4
View File
@@ -352,7 +352,7 @@ tv_get_float(typval_T *varp)
#endif
/*
* Give an error and return FAIL unless "tv" is a string.
* Give an error and return FAIL unless "args[idx]" is a string.
*/
int
check_for_string_arg(typval_T *args, int idx)
@@ -385,7 +385,61 @@ check_for_nonempty_string_arg(typval_T *args, int idx)
}
/*
* Give an error and return FAIL unless "tv" is a dict.
* Give an error and return FAIL unless "args[idx]" is a number.
*/
int
check_for_number_arg(typval_T *args, int idx)
{
if (args[idx].v_type != VAR_NUMBER)
{
if (idx >= 0)
semsg(_(e_number_required_for_argument_nr), idx + 1);
else
emsg(_(e_numberreq));
return FAIL;
}
return OK;
}
/*
* Give an error and return FAIL unless "args[idx]" is a bool.
*/
int
check_for_bool_arg(typval_T *args, int idx)
{
if (args[idx].v_type != VAR_BOOL
&& !(args[idx].v_type == VAR_NUMBER
&& (args[idx].vval.v_number == 0
|| args[idx].vval.v_number == 1)))
{
if (idx >= 0)
semsg(_(e_bool_required_for_argument_nr), idx + 1);
else
emsg(_(e_boolreq));
return FAIL;
}
return OK;
}
/*
* Give an error and return FAIL unless "args[idx]" is a list.
*/
int
check_for_list_arg(typval_T *args, int idx)
{
if (args[idx].v_type != VAR_LIST)
{
if (idx >= 0)
semsg(_(e_list_required_for_argument_nr), idx + 1);
else
emsg(_(e_listreq));
return FAIL;
}
return OK;
}
/*
* Give an error and return FAIL unless "args[idx]" is a dict.
*/
int
check_for_dict_arg(typval_T *args, int idx)
@@ -883,7 +937,9 @@ typval_compare(
}
}
else if (in_vim9script() && (typ1->v_type == VAR_BOOL
|| typ2->v_type == VAR_BOOL))
|| typ2->v_type == VAR_BOOL
|| (typ1->v_type == VAR_SPECIAL
&& typ2->v_type == VAR_SPECIAL)))
{
if (typ1->v_type != typ2->v_type)
{
@@ -901,13 +957,23 @@ typval_compare(
case EXPR_ISNOT:
case EXPR_NEQUAL: n1 = (n1 != n2); break;
default:
emsg(_(e_invalid_operation_for_bool));
semsg(_(e_invalid_operation_for_str),
vartype_name(typ1->v_type));
clear_tv(typ1);
return FAIL;
}
}
else
{
if (in_vim9script()
&& ((typ1->v_type != VAR_STRING && typ1->v_type != VAR_SPECIAL)
|| (typ2->v_type != VAR_STRING && typ2->v_type != VAR_SPECIAL)))
{
semsg(_(e_cannot_compare_str_with_str),
vartype_name(typ1->v_type), vartype_name(typ2->v_type));
clear_tv(typ1);
return FAIL;
}
s1 = tv_get_string_buf(typ1, buf1);
s2 = tv_get_string_buf(typ2, buf2);
if (type != EXPR_MATCH && type != EXPR_NOMATCH)
+9 -7
View File
@@ -1019,20 +1019,22 @@ ex_command(exarg_T *eap)
// we are listing commands
p = skipwhite(end);
if (!has_attr && ends_excmd2(eap->arg, p))
{
uc_list(name, end - name);
}
else if (!ASCII_ISUPPER(*name))
{
emsg(_("E183: User defined commands must start with an uppercase letter"));
return;
}
else if ((name_len == 1 && *name == 'X')
|| (name_len <= 4
&& STRNCMP(name, "Next", name_len > 4 ? 4 : name_len) == 0))
{
emsg(_("E841: Reserved name, cannot be used for user defined command"));
return;
else if (compl > 0 && (argt & EX_EXTRA) == 0)
{
// Some plugins rely on silently ignoring the mistake, only make this
// an error in Vim9 script.
if (in_vim9script())
emsg(_(e_complete_used_without_nargs));
else
give_warning_with_source(
(char_u *)_(e_complete_used_without_nargs), TRUE, TRUE);
}
else
uc_add_command(name, end - name, p, argt, def, flags, compl, compl_arg,
+33 -5
View File
@@ -634,6 +634,7 @@ get_function_body(
|| eap->cmdidx == CMD_block;
#define MAX_FUNC_NESTING 50
char nesting_def[MAX_FUNC_NESTING];
char nesting_inline[MAX_FUNC_NESTING];
int nesting = 0;
getline_opt_T getline_options;
int indent = 2;
@@ -658,7 +659,8 @@ get_function_body(
((char_u **)(newlines->ga_data))[newlines->ga_len++] = NULL;
}
nesting_def[nesting] = vim9_function;
nesting_def[0] = vim9_function;
nesting_inline[0] = eap->cmdidx == CMD_block;
getline_options = vim9_function
? GETLINE_CONCAT_CONTBAR : GETLINE_CONCAT_CONT;
for (;;)
@@ -705,10 +707,10 @@ get_function_body(
SOURCING_LNUM = sourcing_lnum_top;
if (skip_until != NULL)
semsg(_(e_missing_heredoc_end_marker_str), skip_until);
else if (nesting_inline[nesting])
emsg(_(e_missing_end_block));
else if (eap->cmdidx == CMD_def)
emsg(_(e_missing_enddef));
else if (eap->cmdidx == CMD_block)
emsg(_(e_missing_end_block));
else
emsg(_("E126: Missing :endfunction"));
goto theend;
@@ -765,7 +767,8 @@ get_function_body(
}
else
{
int c;
int c;
char_u *end;
// skip ':' and blanks
for (p = theline; VIM_ISWHITE(*p) || *p == ':'; ++p)
@@ -773,7 +776,7 @@ get_function_body(
// Check for "endfunction", "enddef" or "}".
// When a ":" follows it must be a dict key; "enddef: value,"
if ((nesting == 0 && eap->cmdidx == CMD_block)
if (nesting_inline[nesting]
? *p == '}'
: (checkforcmd(&p, nesting_def[nesting]
? "enddef" : "endfunction", 4)
@@ -857,6 +860,31 @@ get_function_body(
{
++nesting;
nesting_def[nesting] = (c == 'd');
nesting_inline[nesting] = FALSE;
indent += 2;
}
}
}
// Check for nested inline function.
end = p + STRLEN(p) - 1;
while (end > p && VIM_ISWHITE(*end))
--end;
if (end > p && *end == '{')
{
--end;
while (end > p && VIM_ISWHITE(*end))
--end;
if (end > p + 2 && end[-1] == '=' && end[0] == '>')
{
// found trailing "=> {", start of an inline function
if (nesting == MAX_FUNC_NESTING - 1)
emsg(_(e_function_nesting_too_deep));
else
{
++nesting;
nesting_def[nesting] = TRUE;
nesting_inline[nesting] = TRUE;
indent += 2;
}
}
+84
View File
@@ -770,6 +770,90 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
3182,
/**/
3181,
/**/
3180,
/**/
3179,
/**/
3178,
/**/
3177,
/**/
3176,
/**/
3175,
/**/
3174,
/**/
3173,
/**/
3172,
/**/
3171,
/**/
3170,
/**/
3169,
/**/
3168,
/**/
3167,
/**/
3166,
/**/
3165,
/**/
3164,
/**/
3163,
/**/
3162,
/**/
3161,
/**/
3160,
/**/
3159,
/**/
3158,
/**/
3157,
/**/
3156,
/**/
3155,
/**/
3154,
/**/
3153,
/**/
3152,
/**/
3151,
/**/
3150,
/**/
3149,
/**/
3148,
/**/
3147,
/**/
3146,
/**/
3145,
/**/
3144,
/**/
3143,
/**/
3142,
/**/
3141,
/**/
3140,
/**/
+44 -16
View File
@@ -1051,7 +1051,8 @@ need_type(
// If the actual type can be the expected type add a runtime check.
// If it's a constant a runtime check makes no sense.
if (!actual_is_const && use_typecheck(actual, expected))
if ((!actual_is_const || actual == &t_any)
&& use_typecheck(actual, expected))
{
generate_TYPECHECK(cctx, expected, offset, arg_idx);
return OK;
@@ -1781,6 +1782,7 @@ generate_BCALL(cctx_T *cctx, int func_idx, int argcount, int method_call)
garray_T *stack = &cctx->ctx_type_stack;
int argoff;
type_T **argtypes = NULL;
type_T *shuffled_argtypes[MAX_FUNC_ARGS];
type_T *maptype = NULL;
RETURN_OK_IF_SKIP(cctx);
@@ -1800,6 +1802,16 @@ generate_BCALL(cctx_T *cctx, int func_idx, int argcount, int method_call)
{
// Check the types of the arguments.
argtypes = ((type_T **)stack->ga_data) + stack->ga_len - argcount;
if (method_call && argoff > 1)
{
int i;
for (i = 0; i < argcount; ++i)
shuffled_argtypes[i] = (i < argoff - 1)
? argtypes[i + 1]
: (i == argoff - 1) ? argtypes[0] : argtypes[i];
argtypes = shuffled_argtypes;
}
if (internal_func_check_arg_types(argtypes, func_idx, argcount,
cctx) == FAIL)
return FAIL;
@@ -3624,6 +3636,13 @@ compile_lambda(char_u **arg, cctx_T *cctx)
ufunc->uf_ret_type = &t_unknown;
compile_def_function(ufunc, FALSE, cctx->ctx_compile_type, cctx);
#ifdef FEAT_PROFILE
// When the outer function is compiled for profiling, the lambda may be
// called without profiling. Compile it here in the right context.
if (cctx->ctx_compile_type == CT_PROFILE)
compile_def_function(ufunc, FALSE, CT_NONE, cctx);
#endif
// evalarg.eval_tofree_cmdline may have a copy of the last line and "*arg"
// points into it. Point to the original line to avoid a dangling pointer.
if (evalarg.eval_tofree_cmdline != NULL)
@@ -4316,7 +4335,6 @@ compile_subscript(
semsg(_(e_missing_paren), *arg);
return FAIL;
}
// TODO: base value may not be the first argument
if (compile_call(arg, p - *arg, cctx, ppconst, 1) == FAIL)
return FAIL;
}
@@ -5077,6 +5095,7 @@ compile_and_or(
while (p[0] == opchar && p[1] == opchar)
{
long start_lnum = SOURCING_LNUM;
long save_sourcing_lnum;
int start_ctx_lnum = cctx->ctx_lnum;
int save_lnum;
@@ -5098,6 +5117,7 @@ compile_and_or(
generate_ppconst(cctx, ppconst);
// Every part must evaluate to a bool.
save_sourcing_lnum = SOURCING_LNUM;
SOURCING_LNUM = start_lnum;
save_lnum = cctx->ctx_lnum;
cctx->ctx_lnum = start_ctx_lnum;
@@ -5120,6 +5140,7 @@ compile_and_or(
? JUMP_IF_COND_TRUE : JUMP_IF_COND_FALSE, 0);
// eval the next expression
SOURCING_LNUM = save_sourcing_lnum;
if (may_get_next_line_error(p + 2, arg, cctx) == FAIL)
{
ga_clear(&end_ga);
@@ -5552,6 +5573,7 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx)
char_u *lambda_name;
ufunc_T *ufunc;
int r = FAIL;
compiletype_T compile_type;
if (eap->forceit)
{
@@ -5618,14 +5640,27 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx)
}
}
if (func_needs_compiling(ufunc, COMPILE_TYPE(ufunc))
&& compile_def_function(ufunc, TRUE, COMPILE_TYPE(ufunc), cctx)
== FAIL)
compile_type = COMPILE_TYPE(ufunc);
#ifdef FEAT_PROFILE
// If the outer function is profiled, also compile the nested function for
// profiling.
if (cctx->ctx_compile_type == CT_PROFILE)
compile_type = CT_PROFILE;
#endif
if (func_needs_compiling(ufunc, compile_type)
&& compile_def_function(ufunc, TRUE, compile_type, cctx) == FAIL)
{
func_ptr_unref(ufunc);
goto theend;
}
#ifdef FEAT_PROFILE
// When the outer function is compiled for profiling, the nested function
// may be called without profiling. Compile it here in the right context.
if (compile_type == CT_PROFILE && func_needs_compiling(ufunc, CT_NONE))
compile_def_function(ufunc, FALSE, CT_NONE, cctx);
#endif
if (is_global)
{
char_u *func_name = vim_strnsave(name_start + 2,
@@ -7257,15 +7292,6 @@ compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx)
return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd;
}
/*
* Compile an :import command.
*/
static char_u *
compile_import(char_u *arg, cctx_T *cctx)
{
return handle_import(arg, &cctx->ctx_imports, 0, NULL, cctx);
}
/*
* generate a jump to the ":endif"/":endfor"/":endwhile"/":finally"/":endtry".
*/
@@ -9474,7 +9500,8 @@ compile_def_function(
}
}
}
p = find_ex_command(&ea, NULL, starts_with_colon
p = find_ex_command(&ea, NULL,
starts_with_colon || (local_cmdmod.cmod_flags & CMOD_LEGACY)
? NULL : item_exists, &cctx);
if (p == NULL)
@@ -9601,7 +9628,8 @@ compile_def_function(
break;
case CMD_import:
line = compile_import(p, &cctx);
emsg(_(e_import_can_only_be_used_in_script));
line = NULL;
break;
case CMD_if:
+11 -13
View File
@@ -197,6 +197,7 @@ call_dfunc(
int idx;
estack_T *entry;
funclocal_T *floc = NULL;
int res = OK;
if (dfunc->df_deleted)
{
@@ -219,14 +220,6 @@ call_dfunc(
(((dfunc_T *)def_functions.ga_data)
+ ectx->ec_dfunc_idx)->df_ufunc);
}
// Profiling might be enabled/disabled along the way. This should not
// fail, since the function was compiled before and toggling profiling
// doesn't change any errors.
if (func_needs_compiling(ufunc, COMPILE_TYPE(ufunc))
&& compile_def_function(ufunc, FALSE, COMPILE_TYPE(ufunc), NULL)
== FAIL)
return FAIL;
}
#endif
@@ -235,10 +228,14 @@ call_dfunc(
// When debugging and using "cont" switches to the not-debugged
// instructions, may need to still compile them.
if ((func_needs_compiling(ufunc, COMPILE_TYPE(ufunc))
&& compile_def_function(ufunc, FALSE, COMPILE_TYPE(ufunc), NULL)
== FAIL)
|| INSTRUCTIONS(dfunc) == NULL)
if (func_needs_compiling(ufunc, COMPILE_TYPE(ufunc)))
{
res = compile_def_function(ufunc, FALSE, COMPILE_TYPE(ufunc), NULL);
// compile_def_function() may cause def_functions.ga_data to change
dfunc = ((dfunc_T *)def_functions.ga_data) + cdf_idx;
}
if (res == FAIL || INSTRUCTIONS(dfunc) == NULL)
{
if (did_emsg_cumul + did_emsg == did_emsg_before)
semsg(_(e_function_is_not_compiled_str),
@@ -4740,7 +4737,8 @@ failed_early:
// Not sure if this is necessary.
suppress_errthrow = save_suppress_errthrow;
if (ret != OK && did_emsg_cumul + did_emsg == did_emsg_before)
if (ret != OK && did_emsg_cumul + did_emsg == did_emsg_before
&& !need_rethrow)
semsg(_(e_unknown_error_while_executing_str),
printable_func_name(ufunc));
funcdepth_restore(orig_funcdepth);
+9 -13
View File
@@ -412,6 +412,7 @@ handle_import(
garray_T names;
garray_T as_names;
tv.v_type = VAR_UNKNOWN;
ga_init2(&names, sizeof(char_u *), 10);
ga_init2(&as_names, sizeof(char_u *), 10);
if (*arg == '{')
@@ -496,14 +497,14 @@ handle_import(
goto erret;
}
// The name of the file can be an expression, which must evaluate to a
// string.
arg = skipwhite_and_linebreak(arg + 4, evalarg);
tv.v_type = VAR_UNKNOWN;
// TODO: should we accept any expression?
if (*arg == '\'')
ret = eval_lit_string(&arg, &tv, TRUE);
else if (*arg == '"')
ret = eval_string(&arg, &tv, TRUE);
if (ret == FAIL || tv.vval.v_string == NULL || *tv.vval.v_string == NUL)
ret = eval0(arg, &tv, NULL, evalarg);
if (ret == FAIL)
goto erret;
if (tv.v_type != VAR_STRING
|| tv.vval.v_string == NULL || *tv.vval.v_string == NUL)
{
emsg(_(e_invalid_string_after_from));
goto erret;
@@ -524,10 +525,7 @@ handle_import(
len = STRLEN(si->sn_name) - STRLEN(tail) + STRLEN(tv.vval.v_string) + 2;
from_name = alloc((int)len);
if (from_name == NULL)
{
clear_tv(&tv);
goto erret;
}
vim_strncpy(from_name, si->sn_name, tail - si->sn_name);
add_pathsep(from_name);
STRCAT(from_name, tv.vval.v_string);
@@ -550,7 +548,6 @@ handle_import(
from_name = alloc((int)len);
if (from_name == NULL)
{
clear_tv(&tv);
goto erret;
}
vim_snprintf((char *)from_name, len, "import/%s", tv.vval.v_string);
@@ -561,10 +558,8 @@ handle_import(
if (res == FAIL || sid <= 0)
{
semsg(_(e_could_not_import_str), tv.vval.v_string);
clear_tv(&tv);
goto erret;
}
clear_tv(&tv);
if (*arg_start == '*')
{
@@ -669,6 +664,7 @@ handle_import(
}
}
erret:
clear_tv(&tv);
ga_clear_strings(&names);
ga_clear_strings(&as_names);
return cmd_end;