aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2022-11-07 10:26:54 +0800
committerzeertzjq <zeertzjq@outlook.com>2022-11-07 14:25:32 +0800
commit42e44d6d334bda8b97afe9e34a819ab293e5e10a (patch)
tree4087d6827987d2d6360af4f2df093ff4f4dfb806 /src
parentf91d200c056940e92277e59ffd6507c4db1973d8 (diff)
downloadrneovim-42e44d6d334bda8b97afe9e34a819ab293e5e10a.tar.gz
rneovim-42e44d6d334bda8b97afe9e34a819ab293e5e10a.tar.bz2
rneovim-42e44d6d334bda8b97afe9e34a819ab293e5e10a.zip
vim-patch:8.2.3751: cannot assign a lambda to an option that takes a function
Problem: Cannot assign a lambda to an option that takes a function. Solution: Automatically convert the lambda to a string. (Yegappan Lakshmanan, closes vim/vim#9286) https://github.com/vim/vim/commit/6409553b6e3b4de4e1d72b8ee5445595214581ff Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
Diffstat (limited to 'src')
-rw-r--r--src/nvim/api/options.c2
-rw-r--r--src/nvim/context.c2
-rw-r--r--src/nvim/eval.c14
-rw-r--r--src/nvim/eval/vars.c23
-rw-r--r--src/nvim/generators/gen_options.lua5
-rw-r--r--src/nvim/option.c25
-rw-r--r--src/nvim/option_defs.h5
-rw-r--r--src/nvim/options.lua9
-rw-r--r--src/nvim/spell.c2
-rw-r--r--src/nvim/testdir/test_ins_complete.vim192
-rw-r--r--src/nvim/testdir/test_tagfunc.vim56
11 files changed, 287 insertions, 48 deletions
diff --git a/src/nvim/api/options.c b/src/nvim/api/options.c
index ec1f19cf6a..92f20fff48 100644
--- a/src/nvim/api/options.c
+++ b/src/nvim/api/options.c
@@ -487,7 +487,7 @@ static getoption_T access_option_value(char *key, long *numval, char **stringval
bool get, Error *err)
{
if (get) {
- return get_option_value(key, numval, stringval, opt_flags);
+ return get_option_value(key, numval, stringval, NULL, opt_flags);
} else {
char *errmsg;
if ((errmsg = set_option_value(key, *numval, *stringval, opt_flags))) {
diff --git a/src/nvim/context.c b/src/nvim/context.c
index 34692cdf64..c765b95733 100644
--- a/src/nvim/context.c
+++ b/src/nvim/context.c
@@ -131,7 +131,7 @@ bool ctx_restore(Context *ctx, const int flags)
}
char *op_shada;
- get_option_value("shada", NULL, &op_shada, OPT_GLOBAL);
+ get_option_value("shada", NULL, &op_shada, NULL, OPT_GLOBAL);
set_option_value("shada", 0L, "!,'100,%", OPT_GLOBAL);
if (flags & kCtxRegs) {
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 0848326d90..a4fadcd7bc 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -3689,10 +3689,10 @@ static int eval_index(char **arg, typval_T *rettv, int evaluate, int verbose)
int get_option_tv(const char **const arg, typval_T *const rettv, const bool evaluate)
FUNC_ATTR_NONNULL_ARG(1)
{
- int opt_flags;
+ int scope;
// Isolate the option name and find its value.
- char *option_end = (char *)find_option_end(arg, &opt_flags);
+ char *option_end = (char *)find_option_end(arg, &scope);
if (option_end == NULL) {
if (rettv != NULL) {
semsg(_("E112: Option name missing: %s"), *arg);
@@ -3712,7 +3712,7 @@ int get_option_tv(const char **const arg, typval_T *const rettv, const bool eval
char c = *option_end;
*option_end = NUL;
getoption_T opt_type = get_option_value(*arg, &numval,
- rettv == NULL ? NULL : &stringval, opt_flags);
+ rettv == NULL ? NULL : &stringval, NULL, scope);
if (opt_type == gov_unknown) {
if (rettv != NULL) {
@@ -7794,19 +7794,19 @@ void ex_execute(exarg_T *eap)
///
/// @return NULL when no option name found. Otherwise pointer to the char
/// after the option name.
-const char *find_option_end(const char **const arg, int *const opt_flags)
+const char *find_option_end(const char **const arg, int *const scope)
{
const char *p = *arg;
p++;
if (*p == 'g' && p[1] == ':') {
- *opt_flags = OPT_GLOBAL;
+ *scope = OPT_GLOBAL;
p += 2;
} else if (*p == 'l' && p[1] == ':') {
- *opt_flags = OPT_LOCAL;
+ *scope = OPT_LOCAL;
p += 2;
} else {
- *opt_flags = 0;
+ *scope = 0;
}
if (!ASCII_ISALPHA(*p)) {
diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c
index 139e7ed66b..6c4d33df89 100644
--- a/src/nvim/eval/vars.c
+++ b/src/nvim/eval/vars.c
@@ -560,8 +560,6 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo
{
char *arg_end = NULL;
int len;
- int opt_flags;
- char *tofree = NULL;
// ":let $VAR = expr": Set environment variable.
if (*arg == '$') {
@@ -582,12 +580,12 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo
&& vim_strchr(endchars, *skipwhite(arg)) == NULL) {
emsg(_(e_letunexp));
} else if (!check_secure()) {
+ char *tofree = NULL;
const char c1 = name[len];
name[len] = NUL;
const char *p = tv_get_string_chk(tv);
if (p != NULL && op != NULL && *op == '.') {
char *s = vim_getenv(name);
-
if (s != NULL) {
tofree = concat_str(s, p);
p = (const char *)tofree;
@@ -611,7 +609,8 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo
return NULL;
}
// Find the end of the name.
- char *const p = (char *)find_option_end((const char **)&arg, &opt_flags);
+ int scope;
+ char *const p = (char *)find_option_end((const char **)&arg, &scope);
if (p == NULL
|| (endchars != NULL
&& vim_strchr(endchars, *skipwhite(p)) == NULL)) {
@@ -623,11 +622,13 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo
char *stringval = NULL;
const char *s = NULL;
bool failed = false;
+ uint32_t opt_p_flags;
+ char *tofree = NULL;
const char c1 = *p;
*p = NUL;
- opt_type = get_option_value(arg, &numval, &stringval, opt_flags);
+ opt_type = get_option_value(arg, &numval, &stringval, &opt_p_flags, scope);
if (opt_type == gov_bool
|| opt_type == gov_number
|| opt_type == gov_hidden_bool
@@ -636,8 +637,13 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo
n = (long)tv_get_number(tv);
}
- // Avoid setting a string option to the text "v:false" or similar.
- if (tv->v_type != VAR_BOOL && tv->v_type != VAR_SPECIAL) {
+ if ((opt_p_flags & P_FUNC) && tv_is_func(*tv)) {
+ // If the option can be set to a function reference or a lambda
+ // and the passed value is a function reference, then convert it to
+ // the name (string) of the function reference.
+ s = tofree = encode_tv2string(tv, NULL);
+ } else if (tv->v_type != VAR_BOOL && tv->v_type != VAR_SPECIAL) {
+ // Avoid setting a string option to the text "v:false" or similar.
s = tv_get_string_chk(tv);
}
@@ -674,7 +680,7 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo
if (!failed) {
if (opt_type != gov_string || s != NULL) {
- char *err = set_option_value(arg, n, s, opt_flags);
+ char *err = set_option_value(arg, n, s, scope);
arg_end = p;
if (err != NULL) {
emsg(_(err));
@@ -685,6 +691,7 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo
}
*p = c1;
xfree(stringval);
+ xfree(tofree);
}
// ":let @r = expr": Set register contents.
} else if (*arg == '@') {
diff --git a/src/nvim/generators/gen_options.lua b/src/nvim/generators/gen_options.lua
index 4e4dd83367..af21d44eaf 100644
--- a/src/nvim/generators/gen_options.lua
+++ b/src/nvim/generators/gen_options.lua
@@ -29,14 +29,14 @@ local type_flags={
}
local redraw_flags={
+ ui_option='P_UI_OPTION',
+ tabline='P_RTABL',
statuslines='P_RSTAT',
- tabline = 'P_RTABL',
current_window='P_RWIN',
current_window_only='P_RWINONLY',
current_buffer='P_RBUF',
all_windows='P_RALL',
curswant='P_CURSWANT',
- ui_option='P_UI_OPTION',
}
local list_flags={
@@ -78,6 +78,7 @@ local get_flags = function(o)
{'deny_in_modelines', 'P_NO_ML'},
{'deny_duplicates', 'P_NODUP'},
{'modelineexpr', 'P_MLE'},
+ {'func'}
}) do
local key_name = flag_desc[1]
local def_name = flag_desc[2] or ('P_' .. key_name:upper())
diff --git a/src/nvim/option.c b/src/nvim/option.c
index da3fad0d61..c0a1f14463 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -2842,6 +2842,7 @@ int findoption(const char *const arg)
/// Gets the value for an option.
///
/// @param stringval NULL when only checking existence
+/// @param flagsp set to the option flags (P_xxxx) (if not NULL)
///
/// @returns:
/// Number option: gov_number, *numval gets value.
@@ -2851,7 +2852,8 @@ int findoption(const char *const arg)
/// Hidden Toggle option: gov_hidden_bool.
/// Hidden String option: gov_hidden_string.
/// Unknown option: gov_unknown.
-getoption_T get_option_value(const char *name, long *numval, char **stringval, int opt_flags)
+getoption_T get_option_value(const char *name, long *numval, char **stringval, uint32_t *flagsp,
+ int scope)
{
if (get_tty_option(name, stringval)) {
return gov_string;
@@ -2862,7 +2864,12 @@ getoption_T get_option_value(const char *name, long *numval, char **stringval, i
return gov_unknown;
}
- char_u *varp = (char_u *)get_varp_scope(&(options[opt_idx]), opt_flags);
+ char_u *varp = (char_u *)get_varp_scope(&(options[opt_idx]), scope);
+
+ if (flagsp != NULL) {
+ // Return the P_xxxx option flags.
+ *flagsp = options[opt_idx].flags;
+ }
if (options[opt_idx].flags & P_STRING) {
if (varp == NULL) { // hidden option
@@ -3092,7 +3099,7 @@ char *set_option_value(const char *const name, const long number, const char *co
numval = -1;
} else {
char *s = NULL;
- (void)get_option_value(name, &numval, &s, OPT_GLOBAL);
+ (void)get_option_value(name, &numval, &s, NULL, OPT_GLOBAL);
}
}
if (flags & P_NUM) {
@@ -3701,15 +3708,17 @@ void unset_global_local_option(char *name, void *from)
}
/// Get pointer to option variable, depending on local or global scope.
-char *get_varp_scope(vimoption_T *p, int opt_flags)
+///
+/// @param scope can be OPT_LOCAL, OPT_GLOBAL or a combination.
+char *get_varp_scope(vimoption_T *p, int scope)
{
- if ((opt_flags & OPT_GLOBAL) && p->indir != PV_NONE) {
+ if ((scope & OPT_GLOBAL) && p->indir != PV_NONE) {
if (p->var == VAR_WIN) {
return GLOBAL_WO(get_varp(p));
}
return (char *)p->var;
}
- if ((opt_flags & OPT_LOCAL) && ((int)p->indir & PV_BOTH)) {
+ if ((scope & OPT_LOCAL) && ((int)p->indir & PV_BOTH)) {
switch ((int)p->indir) {
case PV_FP:
return (char *)&(curbuf->b_p_fp);
@@ -4863,9 +4872,9 @@ void ExpandOldSetting(int *num_file, char ***file)
/// NameBuff[]. Must not be called with a hidden option!
///
/// @param opt_flags OPT_GLOBAL and/or OPT_LOCAL
-static void option_value2string(vimoption_T *opp, int opt_flags)
+static void option_value2string(vimoption_T *opp, int scope)
{
- char_u *varp = (char_u *)get_varp_scope(opp, opt_flags);
+ char_u *varp = (char_u *)get_varp_scope(opp, scope);
if (opp->flags & P_NUM) {
long wc = 0;
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index 7c33773e41..d505e75be4 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -24,6 +24,7 @@
#define P_NO_MKRC 0x200U ///< don't include in :mkvimrc output
// when option changed, what to display:
+#define P_UI_OPTION 0x400U ///< send option to remote UI
#define P_RTABL 0x800U ///< redraw tabline
#define P_RSTAT 0x1000U ///< redraw status lines
#define P_RWIN 0x2000U ///< redraw current window and recompute text
@@ -50,9 +51,9 @@
#define P_NDNAME 0x8000000U ///< only normal dir name chars allowed
#define P_RWINONLY 0x10000000U ///< only redraw current window
#define P_MLE 0x20000000U ///< under control of 'modelineexpr'
+#define P_FUNC 0x40000000U ///< accept a function reference or a lambda
-#define P_NO_DEF_EXP 0x40000000U ///< Do not expand default value.
-#define P_UI_OPTION 0x80000000U ///< send option to remote ui
+#define P_NO_DEF_EXP 0x80000000U ///< Do not expand default value.
/// Flags for option-setting functions
///
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index 3a59becb33..e938760e67 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -10,6 +10,7 @@
-- secure=nil, gettext=nil, noglob=nil, normal_fname_chars=nil,
-- pri_mkrc=nil, deny_in_modelines=nil, normal_dname_chars=nil,
-- modelineexpr=nil,
+-- func=nil,
-- expand=nil, nodefault=nil, no_mkrc=nil,
-- alloced=nil,
-- save_pv_indir=nil,
@@ -455,6 +456,7 @@ return {
type='string', scope={'buffer'},
secure=true,
alloced=true,
+ func=true,
varname='p_cfu',
defaults={if_true=""}
},
@@ -1638,6 +1640,7 @@ return {
type='string', scope={'buffer'},
secure=true,
alloced=true,
+ func=true,
varname='p_ofu',
defaults={if_true=""}
},
@@ -1653,6 +1656,7 @@ return {
short_desc=N_("function to be called for |g@| operator"),
type='string', scope={'global'},
secure=true,
+ func=true,
varname='p_opfunc',
defaults={if_true=""}
},
@@ -1835,6 +1839,8 @@ return {
full_name='quickfixtextfunc', abbreviation='qftf',
short_desc=N_("customize the quickfix window"),
type='string', scope={'global'},
+ secure=true,
+ func=true,
varname='p_qftf',
defaults={if_true=""}
},
@@ -2408,6 +2414,8 @@ return {
full_name='tagfunc', abbreviation='tfu',
short_desc=N_("function used to perform tag searches"),
type='string', scope={'buffer'},
+ secure=true,
+ func=true,
varname='p_tfu',
defaults={if_true=""}
},
@@ -2538,6 +2546,7 @@ return {
type='string', scope={'global', 'buffer'},
secure=true,
alloced=true,
+ func=true,
varname='p_tsrfu',
defaults={if_true=""}
},
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index e76ac49b5d..1b78aa4d72 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -3145,7 +3145,7 @@ void ex_spelldump(exarg_T *eap)
}
char *spl;
long dummy;
- (void)get_option_value("spl", &dummy, &spl, OPT_LOCAL);
+ (void)get_option_value("spl", &dummy, &spl, NULL, OPT_LOCAL);
// Create a new empty buffer in a new window.
do_cmdline_cmd("new");
diff --git a/src/nvim/testdir/test_ins_complete.vim b/src/nvim/testdir/test_ins_complete.vim
index 0478ad1516..8b5f9a189f 100644
--- a/src/nvim/testdir/test_ins_complete.vim
+++ b/src/nvim/testdir/test_ins_complete.vim
@@ -1302,13 +1302,22 @@ func Test_completefunc_callback()
" Using a funcref variable to set 'completefunc'
let Fn = function('MycompleteFunc1')
+ let &completefunc = Fn
+ new | only
+ call setline(1, 'two')
+ let g:MycompleteFunc1_args = []
+ call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
+ call assert_equal([[1, ''], [0, 'two']], g:MycompleteFunc1_args)
+ bw!
+
+ " Using string(funcref_variable) to set 'completefunc'
+ let Fn = function('MycompleteFunc1')
let &completefunc = string(Fn)
new | only
call setline(1, 'two')
let g:MycompleteFunc1_args = []
call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
call assert_equal([[1, ''], [0, 'two']], g:MycompleteFunc1_args)
- call assert_fails('let &completefunc = Fn', 'E729:')
bw!
" Test for using a funcref()
@@ -1326,13 +1335,22 @@ func Test_completefunc_callback()
" Using a funcref variable to set 'completefunc'
let Fn = funcref('MycompleteFunc2')
+ let &completefunc = Fn
+ new | only
+ call setline(1, 'four')
+ let g:MycompleteFunc2_args = []
+ call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
+ call assert_equal([[1, ''], [0, 'four']], g:MycompleteFunc2_args)
+ bw!
+
+ " Using a string(funcref_variable) to set 'completefunc'
+ let Fn = funcref('MycompleteFunc2')
let &completefunc = string(Fn)
new | only
call setline(1, 'four')
let g:MycompleteFunc2_args = []
call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
call assert_equal([[1, ''], [0, 'four']], g:MycompleteFunc2_args)
- call assert_fails('let &completefunc = Fn', 'E729:')
bw!
" Test for using a lambda function
@@ -1349,6 +1367,15 @@ func Test_completefunc_callback()
bw!
" Set 'completefunc' to a lambda expression
+ let &completefunc = {a, b -> MycompleteFunc3(a, b)}
+ new | only
+ call setline(1, 'six')
+ let g:MycompleteFunc3_args = []
+ call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
+ call assert_equal([[1, ''], [0, 'six']], g:MycompleteFunc3_args)
+ bw!
+
+ " Set 'completefunc' to string(lambda_expression)
let &completefunc = '{a, b -> MycompleteFunc3(a, b)}'
new | only
call setline(1, 'six')
@@ -1359,18 +1386,27 @@ func Test_completefunc_callback()
" Set 'completefunc' to a variable with a lambda expression
let Lambda = {a, b -> MycompleteFunc3(a, b)}
+ let &completefunc = Lambda
+ new | only
+ call setline(1, 'seven')
+ let g:MycompleteFunc3_args = []
+ call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
+ call assert_equal([[1, ''], [0, 'seven']], g:MycompleteFunc3_args)
+ bw!
+
+ " Set 'completefunc' to a string(variable with a lambda expression)
+ let Lambda = {a, b -> MycompleteFunc3(a, b)}
let &completefunc = string(Lambda)
new | only
call setline(1, 'seven')
let g:MycompleteFunc3_args = []
call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
call assert_equal([[1, ''], [0, 'seven']], g:MycompleteFunc3_args)
- call assert_fails('let &completefunc = Lambda', 'E729:')
bw!
" Test for using a lambda function with incorrect return value
let Lambda = {s -> strlen(s)}
- let &completefunc = string(Lambda)
+ let &completefunc = Lambda
new | only
call setline(1, 'eight')
call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
@@ -1382,7 +1418,7 @@ func Test_completefunc_callback()
call assert_fails("set completefunc=function('abc')", "E700:")
call assert_fails("set completefunc=funcref('abc')", "E700:")
- let &completefunc = "{a -> 'abc'}"
+ let &completefunc = {a -> 'abc'}
call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
" Vim9 tests
@@ -1407,6 +1443,15 @@ func Test_completefunc_callback()
add(g:LambdaComplete1_args, [findstart, base])
return findstart ? 0 : []
enddef
+ &completefunc = (a, b) => LambdaComplete1(a, b)
+ new | only
+ setline(1, 'two')
+ g:LambdaComplete1_args = []
+ feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
+ assert_equal([[1, ''], [0, 'two']], g:LambdaComplete1_args)
+ bw!
+
+ # Test for using a string(lambda)
&completefunc = '(a, b) => LambdaComplete1(a, b)'
new | only
setline(1, 'two')
@@ -1420,6 +1465,15 @@ func Test_completefunc_callback()
add(g:LambdaComplete2_args, [findstart, base])
return findstart ? 0 : []
}
+ &completefunc = Fn
+ new | only
+ setline(1, 'three')
+ g:LambdaComplete2_args = []
+ feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
+ assert_equal([[1, ''], [0, 'three']], g:LambdaComplete2_args)
+ bw!
+
+ # Test for using a string(variable with a lambda expression)
&completefunc = string(Fn)
new | only
setline(1, 'three')
@@ -1462,13 +1516,22 @@ func Test_omnifunc_callback()
" Using a funcref variable to set 'omnifunc'
let Fn = function('MyomniFunc1')
+ let &omnifunc = Fn
+ new | only
+ call setline(1, 'two')
+ let g:MyomniFunc1_args = []
+ call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
+ call assert_equal([[1, ''], [0, 'two']], g:MyomniFunc1_args)
+ bw!
+
+ " Using a string(funcref_variable) to set 'omnifunc'
+ let Fn = function('MyomniFunc1')
let &omnifunc = string(Fn)
new | only
call setline(1, 'two')
let g:MyomniFunc1_args = []
call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
call assert_equal([[1, ''], [0, 'two']], g:MyomniFunc1_args)
- call assert_fails('let &omnifunc = Fn', 'E729:')
bw!
" Test for using a funcref()
@@ -1486,13 +1549,22 @@ func Test_omnifunc_callback()
" Using a funcref variable to set 'omnifunc'
let Fn = funcref('MyomniFunc2')
+ let &omnifunc = Fn
+ new | only
+ call setline(1, 'four')
+ let g:MyomniFunc2_args = []
+ call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
+ call assert_equal([[1, ''], [0, 'four']], g:MyomniFunc2_args)
+ bw!
+
+ " Using a string(funcref_variable) to set 'omnifunc'
+ let Fn = funcref('MyomniFunc2')
let &omnifunc = string(Fn)
new | only
call setline(1, 'four')
let g:MyomniFunc2_args = []
call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
call assert_equal([[1, ''], [0, 'four']], g:MyomniFunc2_args)
- call assert_fails('let &omnifunc = Fn', 'E729:')
bw!
" Test for using a lambda function
@@ -1509,6 +1581,15 @@ func Test_omnifunc_callback()
bw!
" Set 'omnifunc' to a lambda expression
+ let &omnifunc = {a, b -> MyomniFunc3(a, b)}
+ new | only
+ call setline(1, 'six')
+ let g:MyomniFunc3_args = []
+ call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
+ call assert_equal([[1, ''], [0, 'six']], g:MyomniFunc3_args)
+ bw!
+
+ " Set 'omnifunc' to a string(lambda_expression)
let &omnifunc = '{a, b -> MyomniFunc3(a, b)}'
new | only
call setline(1, 'six')
@@ -1519,18 +1600,27 @@ func Test_omnifunc_callback()
" Set 'omnifunc' to a variable with a lambda expression
let Lambda = {a, b -> MyomniFunc3(a, b)}
+ let &omnifunc = Lambda
+ new | only
+ call setline(1, 'seven')
+ let g:MyomniFunc3_args = []
+ call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
+ call assert_equal([[1, ''], [0, 'seven']], g:MyomniFunc3_args)
+ bw!
+
+ " Set 'omnifunc' to a string(variable with a lambda expression)
+ let Lambda = {a, b -> MyomniFunc3(a, b)}
let &omnifunc = string(Lambda)
new | only
call setline(1, 'seven')
let g:MyomniFunc3_args = []
call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
call assert_equal([[1, ''], [0, 'seven']], g:MyomniFunc3_args)
- call assert_fails('let &omnifunc = Lambda', 'E729:')
bw!
" Test for using a lambda function with incorrect return value
let Lambda = {s -> strlen(s)}
- let &omnifunc = string(Lambda)
+ let &omnifunc = Lambda
new | only
call setline(1, 'eight')
call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
@@ -1542,7 +1632,7 @@ func Test_omnifunc_callback()
call assert_fails("set omnifunc=function('abc')", "E700:")
call assert_fails("set omnifunc=funcref('abc')", "E700:")
- let &omnifunc = "{a -> 'abc'}"
+ let &omnifunc = {a -> 'abc'}
call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
" Vim9 tests
@@ -1567,6 +1657,15 @@ func Test_omnifunc_callback()
add(g:MyomniFunc2_args, [findstart, base])
return findstart ? 0 : []
enddef
+ &omnifunc = (a, b) => MyomniFunc2(a, b)
+ new | only
+ setline(1, 'two')
+ g:MyomniFunc2_args = []
+ feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
+ assert_equal([[1, ''], [0, 'two']], g:MyomniFunc2_args)
+ bw!
+
+ # Test for using a string(lambda)
&omnifunc = '(a, b) => MyomniFunc2(a, b)'
new | only
setline(1, 'two')
@@ -1577,6 +1676,15 @@ func Test_omnifunc_callback()
# Test for using a variable with a lambda expression
var Fn: func = (a, b) => MyomniFunc2(a, b)
+ &omnifunc = Fn
+ new | only
+ setline(1, 'three')
+ g:MyomniFunc2_args = []
+ feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
+ assert_equal([[1, ''], [0, 'three']], g:MyomniFunc2_args)
+ bw!
+
+ # Test for using a string(variable with a lambda expression)
&omnifunc = string(Fn)
new | only
setline(1, 'three')
@@ -1619,13 +1727,22 @@ func Test_thesaurusfunc_callback()
" Using a funcref variable to set 'thesaurusfunc'
let Fn = function('MytsrFunc1')
+ let &thesaurusfunc = Fn
+ new | only
+ call setline(1, 'two')
+ let g:MytsrFunc1_args = []
+ call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
+ call assert_equal([[1, ''], [0, 'two']], g:MytsrFunc1_args)
+ bw!
+
+ " Using a string(funcref_variable) to set 'thesaurusfunc'
+ let Fn = function('MytsrFunc1')
let &thesaurusfunc = string(Fn)
new | only
call setline(1, 'two')
let g:MytsrFunc1_args = []
call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
call assert_equal([[1, ''], [0, 'two']], g:MytsrFunc1_args)
- call assert_fails('let &thesaurusfunc = Fn', 'E729:')
bw!
" Test for using a funcref()
@@ -1643,13 +1760,22 @@ func Test_thesaurusfunc_callback()
" Using a funcref variable to set 'thesaurusfunc'
let Fn = funcref('MytsrFunc2')
+ let &thesaurusfunc = Fn
+ new | only
+ call setline(1, 'four')
+ let g:MytsrFunc2_args = []
+ call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
+ call assert_equal([[1, ''], [0, 'four']], g:MytsrFunc2_args)
+ bw!
+
+ " Using a string(funcref_variable) to set 'thesaurusfunc'
+ let Fn = funcref('MytsrFunc2')
let &thesaurusfunc = string(Fn)
new | only
call setline(1, 'four')
let g:MytsrFunc2_args = []
call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
call assert_equal([[1, ''], [0, 'four']], g:MytsrFunc2_args)
- call assert_fails('let &thesaurusfunc = Fn', 'E729:')
bw!
" Test for using a lambda function
@@ -1666,6 +1792,15 @@ func Test_thesaurusfunc_callback()
bw!
" Set 'thesaurusfunc' to a lambda expression
+ let &thesaurusfunc = {a, b -> MytsrFunc3(a, b)}
+ new | only
+ call setline(1, 'six')
+ let g:MytsrFunc3_args = []
+ call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
+ call assert_equal([[1, ''], [0, 'six']], g:MytsrFunc3_args)
+ bw!
+
+ " Set 'thesaurusfunc' to a string(lambda expression)
let &thesaurusfunc = '{a, b -> MytsrFunc3(a, b)}'
new | only
call setline(1, 'six')
@@ -1676,18 +1811,27 @@ func Test_thesaurusfunc_callback()
" Set 'thesaurusfunc' to a variable with a lambda expression
let Lambda = {a, b -> MytsrFunc3(a, b)}
+ let &thesaurusfunc = Lambda
+ new | only
+ call setline(1, 'seven')
+ let g:MytsrFunc3_args = []
+ call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
+ call assert_equal([[1, ''], [0, 'seven']], g:MytsrFunc3_args)
+ bw!
+
+ " Set 'thesaurusfunc' to a string(variable with a lambda expression)
+ let Lambda = {a, b -> MytsrFunc3(a, b)}
let &thesaurusfunc = string(Lambda)
new | only
call setline(1, 'seven')
let g:MytsrFunc3_args = []
call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
call assert_equal([[1, ''], [0, 'seven']], g:MytsrFunc3_args)
- call assert_fails('let &thesaurusfunc = Lambda', 'E729:')
bw!
" Test for using a lambda function with incorrect return value
let Lambda = {s -> strlen(s)}
- let &thesaurusfunc = string(Lambda)
+ let &thesaurusfunc = Lambda
new | only
call setline(1, 'eight')
call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
@@ -1699,7 +1843,7 @@ func Test_thesaurusfunc_callback()
call assert_fails("set thesaurusfunc=function('abc')", "E700:")
call assert_fails("set thesaurusfunc=funcref('abc')", "E700:")
- let &thesaurusfunc = "{a -> 'abc'}"
+ let &thesaurusfunc = {a -> 'abc'}
call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
" Vim9 tests
@@ -1724,6 +1868,15 @@ func Test_thesaurusfunc_callback()
add(g:MytsrFunc2_args, [findstart, base])
return findstart ? 0 : []
enddef
+ &thesaurusfunc = (a, b) => MytsrFunc2(a, b)
+ new | only
+ setline(1, 'two')
+ g:MytsrFunc2_args = []
+ feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
+ assert_equal([[1, ''], [0, 'two']], g:MytsrFunc2_args)
+ bw!
+
+ # Test for using a string(lambda)
&thesaurusfunc = '(a, b) => MytsrFunc2(a, b)'
new | only
setline(1, 'two')
@@ -1734,6 +1887,15 @@ func Test_thesaurusfunc_callback()
# Test for using a variable with a lambda expression
var Fn: func = (a, b) => MytsrFunc2(a, b)
+ &thesaurusfunc = Fn
+ new | only
+ setline(1, 'three')
+ g:MytsrFunc2_args = []
+ feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
+ assert_equal([[1, ''], [0, 'three']], g:MytsrFunc2_args)
+ bw!
+
+ # Test for using a string(variable with a lambda expression)
&thesaurusfunc = string(Fn)
new | only
setline(1, 'three')
diff --git a/src/nvim/testdir/test_tagfunc.vim b/src/nvim/testdir/test_tagfunc.vim
index 8690e30e77..06d074c261 100644
--- a/src/nvim/testdir/test_tagfunc.vim
+++ b/src/nvim/testdir/test_tagfunc.vim
@@ -138,12 +138,19 @@ func Test_tagfunc_callback()
" Using a funcref variable to set 'tagfunc'
let Fn = function('MytagFunc1')
+ let &tagfunc = Fn
+ new | only
+ let g:MytagFunc1_args = []
+ call assert_fails('tag a12', 'E433:')
+ call assert_equal(['a12', '', {}], g:MytagFunc1_args)
+
+ " Using a string(funcref_variable) to set 'tagfunc'
+ let Fn = function('MytagFunc1')
let &tagfunc = string(Fn)
new | only
let g:MytagFunc1_args = []
call assert_fails('tag a12', 'E433:')
call assert_equal(['a12', '', {}], g:MytagFunc1_args)
- call assert_fails('let &tagfunc = Fn', 'E729:')
" Test for using a funcref()
func MytagFunc2(pat, flags, info)
@@ -158,12 +165,19 @@ func Test_tagfunc_callback()
" Using a funcref variable to set 'tagfunc'
let Fn = funcref('MytagFunc2')
+ let &tagfunc = Fn
+ new | only
+ let g:MytagFunc2_args = []
+ call assert_fails('tag a14', 'E433:')
+ call assert_equal(['a14', '', {}], g:MytagFunc2_args)
+
+ " Using a string(funcref_variable) to set 'tagfunc'
+ let Fn = funcref('MytagFunc2')
let &tagfunc = string(Fn)
new | only
let g:MytagFunc2_args = []
call assert_fails('tag a14', 'E433:')
call assert_equal(['a14', '', {}], g:MytagFunc2_args)
- call assert_fails('let &tagfunc = Fn', 'E729:')
" Test for using a script local function
set tagfunc=<SID>ScriptLocalTagFunc
@@ -174,6 +188,14 @@ func Test_tagfunc_callback()
" Test for using a script local funcref variable
let Fn = function("s:ScriptLocalTagFunc")
+ let &tagfunc= Fn
+ new | only
+ let g:ScriptLocalFuncArgs = []
+ call assert_fails('tag a16', 'E433:')
+ call assert_equal(['a16', '', {}], g:ScriptLocalFuncArgs)
+
+ " Test for using a string(script local funcref variable)
+ let Fn = function("s:ScriptLocalTagFunc")
let &tagfunc= string(Fn)
new | only
let g:ScriptLocalFuncArgs = []
@@ -192,6 +214,13 @@ func Test_tagfunc_callback()
call assert_equal(['a17', '', {}], g:MytagFunc3_args)
" Set 'tagfunc' to a lambda expression
+ let &tagfunc = {a, b, c -> MytagFunc3(a, b, c)}
+ new | only
+ let g:MytagFunc3_args = []
+ call assert_fails('tag a18', 'E433:')
+ call assert_equal(['a18', '', {}], g:MytagFunc3_args)
+
+ " Set 'tagfunc' to a string(lambda expression)
let &tagfunc = '{a, b, c -> MytagFunc3(a, b, c)}'
new | only
let g:MytagFunc3_args = []
@@ -200,12 +229,19 @@ func Test_tagfunc_callback()
" Set 'tagfunc' to a variable with a lambda expression
let Lambda = {a, b, c -> MytagFunc3(a, b, c)}
+ let &tagfunc = Lambda
+ new | only
+ let g:MytagFunc3_args = []
+ call assert_fails("tag a19", "E433:")
+ call assert_equal(['a19', '', {}], g:MytagFunc3_args)
+
+ " Set 'tagfunc' to a string(variable with a lambda expression)
+ let Lambda = {a, b, c -> MytagFunc3(a, b, c)}
let &tagfunc = string(Lambda)
new | only
let g:MytagFunc3_args = []
call assert_fails("tag a19", "E433:")
call assert_equal(['a19', '', {}], g:MytagFunc3_args)
- call assert_fails('let &tagfunc = Lambda', 'E729:')
" Test for using a lambda function with incorrect return value
let Lambda = {s -> strlen(s)}
@@ -242,6 +278,13 @@ func Test_tagfunc_callback()
g:MytagFunc2_args = [pat, flags, info]
return null
enddef
+ &tagfunc = (a, b, c) => MytagFunc2(a, b, c)
+ new | only
+ g:MytagFunc2_args = []
+ assert_fails('tag a20', 'E433:')
+ assert_equal(['a20', '', {}], g:MytagFunc2_args)
+
+ # Test for using a string(lambda)
&tagfunc = '(a, b, c) => MytagFunc2(a, b, c)'
new | only
g:MytagFunc2_args = []
@@ -250,6 +293,13 @@ func Test_tagfunc_callback()
# Test for using a variable with a lambda expression
var Fn: func = (a, b, c) => MytagFunc2(a, b, c)
+ &tagfunc = Fn
+ new | only
+ g:MytagFunc2_args = []
+ assert_fails('tag a30', 'E433:')
+ assert_equal(['a30', '', {}], g:MytagFunc2_args)
+
+ # Test for using a variable with a lambda expression
&tagfunc = string(Fn)
new | only
g:MytagFunc2_args = []