summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYegappan Lakshmanan <yegappan@yahoo.com>2021-12-06 11:03:55 +0000
committerBram Moolenaar <Bram@vim.org>2021-12-06 11:03:55 +0000
commit6409553b6e3b4de4e1d72b8ee5445595214581ff (patch)
tree1b24d5f956763a1bc7a5b47fc9875598d0d438d6
parent40bcec1bac34d34a3d4d7c5f6b2cc1f163acbd00 (diff)
patch 8.2.3751: cannot assign a lambda to an option that takes a functionv8.2.3751
Problem: Cannot assign a lambda to an option that takes a function. Solution: Automatically convert the lambda to a string. (Yegappan Lakshmanan, closes #9286)
-rw-r--r--runtime/doc/options.txt7
-rw-r--r--src/eval.c8
-rw-r--r--src/evalvars.c25
-rw-r--r--src/if_mzsch.c20
-rw-r--r--src/if_ruby.c4
-rw-r--r--src/if_tcl.c2
-rw-r--r--src/option.c30
-rw-r--r--src/option.h1
-rw-r--r--src/optiondefs.h16
-rw-r--r--src/proto/eval.pro2
-rw-r--r--src/proto/option.pro4
-rw-r--r--src/spell.c2
-rw-r--r--src/testdir/test_iminsert.vim44
-rw-r--r--src/testdir/test_ins_complete.vim192
-rw-r--r--src/testdir/test_tagfunc.vim56
-rw-r--r--src/typval.c6
-rw-r--r--src/version.c2
-rw-r--r--src/vim9compile.c8
18 files changed, 344 insertions, 85 deletions
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index ee03570ba8..c49b608247 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -376,7 +376,8 @@ Note: In the future more global options can be made global-local. Using
*option-value-function*
Some options ('completefunc', 'imactivatefunc', 'imstatusfunc', 'omnifunc',
'operatorfunc', 'quickfixtextfunc', 'tagfunc' and 'thesaurusfunc') are set to
-a function name or a function reference or a lambda function. Examples:
+a function name or a function reference or a lambda function. When using a
+lambda it will be converted to the name, e.g. "<lambda>123". Examples:
>
set opfunc=MyOpFunc
set opfunc=function('MyOpFunc')
@@ -386,10 +387,10 @@ a function name or a function reference or a lambda function. Examples:
let Fn = function('MyTagFunc')
let &tagfunc = string(Fn)
" set using a lambda expression
- let &tagfunc = "{t -> MyTagFunc(t)}"
+ let &tagfunc = {t -> MyTagFunc(t)}
" set using a variable with lambda expression
let L = {a, b, c -> MyTagFunc(a, b , c)}
- let &tagfunc = string(L)
+ let &tagfunc = L
<
Setting the filetype
diff --git a/src/eval.c b/src/eval.c
index bebe2f0ad5..bc4db2906c 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -6281,23 +6281,23 @@ ex_execute(exarg_T *eap)
* after the option name.
*/
char_u *
-find_option_end(char_u **arg, int *opt_flags)
+find_option_end(char_u **arg, int *scope)
{
char_u *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))
return NULL;
diff --git a/src/evalvars.c b/src/evalvars.c
index 4342100312..f5465cfb74 100644
--- a/src/evalvars.c
+++ b/src/evalvars.c
@@ -1367,7 +1367,7 @@ ex_let_option(
char_u *op)
{
char_u *p;
- int opt_flags;
+ int scope;
char_u *arg_end = NULL;
if ((flags & (ASSIGN_CONST | ASSIGN_FINAL))
@@ -1378,7 +1378,7 @@ ex_let_option(
}
// Find the end of the name.
- p = find_option_end(&arg, &opt_flags);
+ p = find_option_end(&arg, &scope);
if (p == NULL || (endchars != NULL
&& vim_strchr(endchars, *skipwhite(p)) == NULL))
emsg(_(e_unexpected_characters_in_let));
@@ -1391,11 +1391,14 @@ ex_let_option(
char_u *stringval = NULL;
char_u *s = NULL;
int failed = FALSE;
+ int opt_p_flags;
+ char_u *tofree = NULL;
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
@@ -1410,9 +1413,20 @@ ex_let_option(
n = (long)tv_get_number(tv);
}
+ if (opt_p_flags & P_FUNC && (tv->v_type == VAR_PARTIAL
+ || tv->v_type == VAR_FUNC))
+ {
+ char_u numbuf[NUMBUFLEN];
+
+ // 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 = tv2string(tv, &tofree, numbuf, 0);
+ }
// Avoid setting a string option to the text "v:false" or similar.
// In Vim9 script also don't convert a number to string.
- if (tv->v_type != VAR_BOOL && tv->v_type != VAR_SPECIAL
+ else if (tv->v_type != VAR_BOOL && tv->v_type != VAR_SPECIAL
&& (!in_vim9script() || tv->v_type != VAR_NUMBER))
s = tv_get_string_chk(tv);
@@ -1458,7 +1472,7 @@ ex_let_option(
{
if (opt_type != gov_string || s != NULL)
{
- set_option_value(arg, n, s, opt_flags);
+ set_option_value(arg, n, s, scope);
arg_end = p;
}
else
@@ -1466,6 +1480,7 @@ ex_let_option(
}
*p = c1;
vim_free(stringval);
+ vim_free(tofree);
}
return arg_end;
}
diff --git a/src/if_mzsch.c b/src/if_mzsch.c
index 57b593a19e..41b6d0006f 100644
--- a/src/if_mzsch.c
+++ b/src/if_mzsch.c
@@ -1715,7 +1715,7 @@ get_option(void *data, int argc, Scheme_Object **argv)
getoption_T rc;
Scheme_Object *rval = NULL;
Scheme_Object *name = NULL;
- int opt_flags = 0;
+ int scope = 0;
buf_T *save_curb = curbuf;
win_T *save_curw = curwin;
@@ -1736,11 +1736,11 @@ get_option(void *data, int argc, Scheme_Object **argv)
}
if (argv[1] == M_global)
- opt_flags = OPT_GLOBAL;
+ scope = OPT_GLOBAL;
else if (SCHEME_VIMBUFFERP(argv[1]))
{
curbuf = get_valid_buffer(argv[1]);
- opt_flags = OPT_LOCAL;
+ scope = OPT_LOCAL;
}
else if (SCHEME_VIMWINDOWP(argv[1]))
{
@@ -1748,14 +1748,14 @@ get_option(void *data, int argc, Scheme_Object **argv)
curwin = win;
curbuf = win->w_buffer;
- opt_flags = OPT_LOCAL;
+ scope = OPT_LOCAL;
}
else
scheme_wrong_type(prim->name, "vim-buffer/window", 1, argc, argv);
}
rc = get_option_value(BYTE_STRING_VALUE(name), &value, (char_u **)&strval,
- opt_flags);
+ NULL, scope);
curbuf = save_curb;
curwin = save_curw;
@@ -1793,7 +1793,7 @@ get_option(void *data, int argc, Scheme_Object **argv)
set_option(void *data, int argc, Scheme_Object **argv)
{
char_u *command = NULL;
- int opt_flags = 0;
+ int scope = 0;
buf_T *save_curb = curbuf;
win_T *save_curw = curwin;
Vim_Prim *prim = (Vim_Prim *)data;
@@ -1814,18 +1814,18 @@ set_option(void *data, int argc, Scheme_Object **argv)
}
if (argv[1] == M_global)
- opt_flags = OPT_GLOBAL;
+ scope = OPT_GLOBAL;
else if (SCHEME_VIMBUFFERP(argv[1]))
{
curbuf = get_valid_buffer(argv[1]);
- opt_flags = OPT_LOCAL;
+ scope = OPT_LOCAL;
}
else if (SCHEME_VIMWINDOWP(argv[1]))
{
win_T *win = get_valid_window(argv[1]);
curwin = win;
curbuf = win->w_buffer;
- opt_flags = OPT_LOCAL;
+ scope = OPT_LOCAL;
}
else
scheme_wrong_type(prim->name, "vim-buffer/window", 1, argc, argv);
@@ -1834,7 +1834,7 @@ set_option(void *data, int argc, Scheme_Object **argv)
// do_set can modify cmd, make copy
command = vim_strsave(BYTE_STRING_VALUE(cmd));
MZ_GC_UNREG();
- do_set(command, opt_flags);
+ do_set(command, scope);
vim_free(command);
update_screen(NOT_VALID);
curbuf = save_curb;
diff --git a/src/if_ruby.c b/src/if_ruby.c
index 5098468e6a..0d7eaf2e89 100644
--- a/src/if_ruby.c
+++ b/src/if_ruby.c
@@ -875,7 +875,7 @@ vim_str2rb_enc_str(const char *s)
char_u *sval;
rb_encoding *enc;
- if (get_option_value((char_u *)"enc", &lval, &sval, 0) == gov_string)
+ if (get_option_value((char_u *)"enc", &lval, &sval, NULL, 0) == gov_string)
{
enc = rb_enc_find((char *)sval);
vim_free(sval);
@@ -895,7 +895,7 @@ eval_enc_string_protect(const char *str, int *state)
rb_encoding *enc;
VALUE v;
- if (get_option_value((char_u *)"enc", &lval, &sval, 0) == gov_string)
+ if (get_option_value((char_u *)"enc", &lval, &sval, NULL, 0) == gov_string)
{
enc = rb_enc_find((char *)sval);
vim_free(sval);
diff --git a/src/if_tcl.c b/src/if_tcl.c
index 4838e31976..75fa858e8e 100644
--- a/src/if_tcl.c
+++ b/src/if_tcl.c
@@ -1308,7 +1308,7 @@ tclsetoption(
option = (char_u *)Tcl_GetStringFromObj(objv[objn], NULL);
++objn;
- gov = get_option_value(option, &lval, &sval, 0);
+ gov = get_option_value(option, &lval, &sval, NULL, 0);
err = TCL_OK;
switch (gov)
{
diff --git a/src/option.c b/src/option.c
index c6230c4027..8d950b1770 100644
--- a/src/option.c
+++ b/src/option.c
@@ -56,10 +56,10 @@ static int put_setstring(FILE *fd, char *cmd, char *name, char_u **valuep, long_
static int put_setnum(FILE *fd, char *cmd, char *name, long *valuep);
static int put_setbool(FILE *fd, char *cmd, char *name, int value);
static int istermoption(struct vimoption *p);
-static char_u *get_varp_scope(struct vimoption *p, int opt_flags);
+static char_u *get_varp_scope(struct vimoption *p, int scope);
static char_u *get_varp(struct vimoption *);
static void check_win_options(win_T *win);
-static void option_value2string(struct vimoption *, int opt_flags);
+static void option_value2string(struct vimoption *, int scope);
static void check_winopt(winopt_T *wop);
static int wc_use_keyname(char_u *varp, long *wcp);
static void paste_option_changed(void);
@@ -3937,13 +3937,16 @@ findoption(char_u *arg)
* Hidden Toggle option: gov_hidden_bool.
* Hidden String option: gov_hidden_string.
* Unknown option: gov_unknown.
+ *
+ * "flagsp" (if not NULL) is set to the option flags (P_xxxx).
*/
getoption_T
get_option_value(
char_u *name,
long *numval,
char_u **stringval, // NULL when only checking existence
- int opt_flags)
+ int *flagsp,
+ int scope)
{
int opt_idx;
char_u *varp;
@@ -3981,7 +3984,11 @@ get_option_value(
return gov_unknown;
}
- varp = get_varp_scope(&(options[opt_idx]), opt_flags);
+ varp = 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)
{
@@ -5179,17 +5186,18 @@ unset_global_local_option(char_u *name, void *from)
/*
* Get pointer to option variable, depending on local or global scope.
+ * "scope" can be OPT_LOCAL, OPT_GLOBAL or a combination.
*/
static char_u *
-get_varp_scope(struct vimoption *p, int opt_flags)
+get_varp_scope(struct vimoption *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 (char_u *)GLOBAL_WO(get_varp(p));
return 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)
{
@@ -5248,9 +5256,9 @@ get_varp_scope(struct vimoption *p, int opt_flags)
* scope.
*/
char_u *
-get_option_varp_scope(int opt_idx, int opt_flags)
+get_option_varp_scope(int opt_idx, int scope)
{
- return get_varp_scope(&(options[opt_idx]), opt_flags);
+ return get_varp_scope(&(options[opt_idx]), scope);
}
/*
@@ -6618,11 +6626,11 @@ ExpandOldSetting(int *num_file, char_u ***file)
static void
option_value2string(
struct vimoption *opp,
- int opt_flags) // OPT_GLOBAL and/or OPT_LOCAL
+ int scope) // OPT_GLOBAL and/or OPT_LOCAL
{
char_u *varp;
- varp = get_varp_scope(opp, opt_flags);
+ varp = get_varp_scope(opp, scope);
if (opp->flags & P_NUM)
{
diff --git a/src/option.h b/src/option.h
index 080d90d5c0..fc8124543e 100644
--- a/src/option.h
+++ b/src/option.h
@@ -59,6 +59,7 @@
#define P_NDNAME 0x8000000L // only normal dir name chars allowed
#define P_RWINONLY 0x10000000L // only redraw current window
#define P_MLE 0x20000000L // under control of 'modelineexpr'
+#define P_FUNC 0x40000000L // accept a function reference or a lambda
// Returned by get_option_value().
typedef enum {
diff --git a/src/optiondefs.h b/src/optiondefs.h
index 5a9a674537..6a96a9f2fc 100644
--- a/src/optiondefs.h
+++ b/src/optiondefs.h
@@ -684,7 +684,7 @@ static struct vimoption options[] =
#endif
{(char_u *)0L, (char_u *)0L}
SCTX_INIT},
- {"completefunc", "cfu", P_STRING|P_ALLOCED|P_VI_DEF|P_SECURE,
+ {"completefunc", "cfu", P_STRING|P_ALLOCED|P_VI_DEF|P_SECURE|P_FUNC,
#ifdef FEAT_COMPL_FUNC
(char_u *)&p_cfu, PV_CFU,
{(char_u *)"", (char_u *)0L}
@@ -1321,7 +1321,7 @@ static struct vimoption options[] =
{"ignorecase", "ic", P_BOOL|P_VI_DEF,
(char_u *)&p_ic, PV_NONE,
{(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
- {"imactivatefunc","imaf",P_STRING|P_VI_DEF|P_SECURE,
+ {"imactivatefunc","imaf",P_STRING|P_VI_DEF|P_SECURE|P_FUNC,
#if defined(FEAT_EVAL)
(char_u *)&p_imaf, PV_NONE,
{(char_u *)"", (char_u *)NULL}
@@ -1356,7 +1356,7 @@ static struct vimoption options[] =
(char_u *)&p_imsearch, PV_IMS,
{(char_u *)B_IMODE_USE_INSERT, (char_u *)0L}
SCTX_INIT},
- {"imstatusfunc","imsf",P_STRING|P_VI_DEF|P_SECURE,
+ {"imstatusfunc","imsf",P_STRING|P_VI_DEF|P_SECURE|P_FUNC,
#if defined(FEAT_EVAL)
(char_u *)&p_imsf, PV_NONE,
{(char_u *)"", (char_u *)NULL}
@@ -1822,7 +1822,7 @@ static struct vimoption options[] =
(char_u *)NULL, PV_NONE,
#endif
{(char_u *)8L, (char_u *)4L} SCTX_INIT},
- {"omnifunc", "ofu", P_STRING|P_ALLOCED|P_VI_DEF|P_SECURE,
+ {"omnifunc", "ofu", P_STRING|P_ALLOCED|P_VI_DEF|P_SECURE|P_FUNC,
#ifdef FEAT_COMPL_FUNC
(char_u *)&p_ofu, PV_OFU,
{(char_u *)"", (char_u *)0L}
@@ -1842,7 +1842,7 @@ static struct vimoption options[] =
#endif
{(char_u *)FALSE, (char_u *)FALSE}
SCTX_INIT},
- {"operatorfunc", "opfunc", P_STRING|P_VI_DEF|P_SECURE,
+ {"operatorfunc", "opfunc", P_STRING|P_VI_DEF|P_SECURE|P_FUNC,
(char_u *)&p_opfunc, PV_NONE,
{(char_u *)"", (char_u *)0L} SCTX_INIT},
{"optimize", "opt", P_BOOL|P_VI_DEF,
@@ -2055,7 +2055,7 @@ static struct vimoption options[] =
#endif
{(char_u *)DEFAULT_PYTHON_VER, (char_u *)0L}
SCTX_INIT},
- {"quickfixtextfunc", "qftf", P_STRING|P_ALLOCED|P_VI_DEF|P_VIM|P_SECURE,
+ {"quickfixtextfunc", "qftf", P_STRING|P_ALLOCED|P_VI_DEF|P_VIM|P_SECURE|P_FUNC,
#if defined(FEAT_QUICKFIX) && defined(FEAT_EVAL)
(char_u *)&p_qftf, PV_NONE,
{(char_u *)"", (char_u *)0L}
@@ -2507,7 +2507,7 @@ static struct vimoption options[] =
{"tagcase", "tc", P_STRING|P_VIM,
(char_u *)&p_tc, PV_TC,
{(char_u *)"followic", (char_u *)"followic"} SCTX_INIT},
- {"tagfunc", "tfu", P_STRING|P_ALLOCED|P_VI_DEF|P_SECURE,
+ {"tagfunc", "tfu", P_STRING|P_ALLOCED|P_VI_DEF|P_SECURE|P_FUNC,
#ifdef FEAT_EVAL
(char_u *)&p_tfu, PV_TFU,
{(char_u *)"", (char_u *)0L}
@@ -2624,7 +2624,7 @@ static struct vimoption options[] =
{"thesaurus", "tsr", P_STRING|P_EXPAND|P_VI_DEF|P_ONECOMMA|P_NODUP|P_NDNAME,
(char_u *)&p_tsr, PV_TSR,
{(char_u *)"", (char_u *)0L} SCTX_INIT},
- {"thesaurusfunc", "tsrfu", P_STRING|P_ALLOCED|P_VI_DEF|P_SECURE,
+ {"thesaurusfunc", "tsrfu", P_STRING|P_ALLOCED|P_VI_DEF|P_SECURE|P_FUNC,
#ifdef FEAT_COMPL_FUNC
(char_u *)&p_tsrfu, PV_TSRFU,
{(char_u *)"", (char_u *)0L}
diff --git a/src/proto/eval.pro b/src/proto/eval.pro
index 96a2c6d1e6..45b559de52 100644
--- a/src/proto/eval.pro
+++ b/src/proto/eval.pro
@@ -73,7 +73,7 @@ void ex_echo(exarg_T *eap);
void ex_echohl(exarg_T *eap);
int get_echo_attr(void);
void ex_execute(exarg_T *eap);
-char_u *find_option_end(char_u **arg, int *opt_flags);
+char_u *find_option_end(char_u **arg, int *scope);
void last_set_msg(sctx_T script_ctx);
char_u *do_string_sub(char_u *str, char_u *pat, char_u *sub, typval_T *expr, char_u *flags);
/* vim: set ft=c : */
diff --git a/src/proto/option.pro b/src/proto/option.pro
index ea6baa7e4f..2390f58776 100644
--- a/src/proto/option.pro
+++ b/src/proto/option.pro
@@ -25,7 +25,7 @@ void set_option_sctx_idx(int opt_idx, int opt_flags, sctx_T script_ctx);
void set_term_option_sctx_idx(char *name, int opt_idx);
void check_redraw(long_u flags);
int findoption(char_u *arg);
-getoption_T get_option_value(char_u *name, long *numval, char_u **stringval, int opt_flags);
+getoption_T get_option_value(char_u *name, long *numval, char_u **stringval, int *flagsp, int scope);
int get_option_value_strict(char_u *name, long *numval, char_u **stringval, int opt_type, void *from);
char_u *option_iter_next(void **option, int opt_type);
long_u get_option_flags(int opt_idx);
@@ -48,7 +48,7 @@ void free_one_termoption(char_u *var);
void set_term_defaults(void);
int istermoption_idx(int opt_idx);
void unset_global_local_option(char_u *name, void *from);
-char_u *get_option_varp_scope(int opt_idx, int opt_flags);
+char_u *get_option_varp_scope(int opt_idx, int scope);
char_u *get_option_var(int opt_idx);
char_u *get_option_fullname(int opt_idx);
char_u *get_equalprg(void);
diff --git a/src/spell.c b/src/spell.c
index f472f99326..9b2d3e89f6 100644
--- a/src/spell.c
+++ b/src/spell.c
@@ -3830,7 +3830,7 @@ ex_spelldump(exarg_T *eap)
if (no_spell_checking(curwin))
return;
- (void)get_option_value((char_u*)"spl", &dummy, &spl, OPT_LOCAL);
+ (void)get_option_value((char_u*)"spl", &dummy, &spl, NULL, OPT_LOCAL);
// Create a new empty buffer in a new window.
do_cmdline_cmd((char_u *)"new");
diff --git a/src/testdir/test_iminsert.vim b/src/testdir/test_iminsert.vim
index 14063f9d89..c3c4725a1e 100644
--- a/src/testdir/test_iminsert.vim
+++ b/src/testdir/test_iminsert.vim
@@ -130,12 +130,15 @@ func Test_imactivatefunc_imstatusfunc_callback()
" Using a funcref variable to set 'completefunc'
let Fn1 = function('IMactivatefunc1')
- let &imactivatefunc = string(Fn1)
+ let &imactivatefunc = Fn1
let Fn2 = function('IMstatusfunc1')
+ let &imstatusfunc = Fn2
+ normal! i
+
+ " Using a string(funcref variable) to set 'completefunc'
+ let &imactivatefunc = string(Fn1)
let &imstatusfunc = string(Fn2)
normal! i
- call assert_fails('let &imactivatefunc = Fn1', 'E729:')
- call assert_fails('let &imstatusfunc = Fn2', 'E729:')
" Test for using a funcref()
set imactivatefunc=funcref('IMactivatefunc1')
@@ -144,12 +147,15 @@ func Test_imactivatefunc_imstatusfunc_callback()
" Using a funcref variable to set 'imactivatefunc'
let Fn1 = funcref('IMactivatefunc1')
- let &imactivatefunc = string(Fn1)
+ let &imactivatefunc = Fn1
let Fn2 = funcref('IMstatusfunc1')
+ let &imstatusfunc = Fn2
+ normal! i
+
+ " Using a string(funcref variable) to set 'imactivatefunc'
+ let &imactivatefunc = string(Fn1)
let &imstatusfunc = string(Fn2)
normal! i
- call assert_fails('let &imactivatefunc = Fn1', 'E729:')
- call assert_fails('let &imstatusfunc = Fn2', 'E729:')
" Test for using a lambda function
set imactivatefunc={a\ ->\ IMactivatefunc1(a)}
@@ -157,6 +163,11 @@ func Test_imactivatefunc_imstatusfunc_callback()
normal! i
" Set 'imactivatefunc' and 'imstatusfunc' to a lambda expression
+ let &imactivatefunc = {a -> IMactivatefunc1(a)}
+ let &imstatusfunc = { -> IMstatusfunc1()}
+ normal! i
+
+ " Set 'imactivatefunc' and 'imstatusfunc' to a string(lambda expression)
let &imactivatefunc = '{a -> IMactivatefunc1(a)}'
let &imstatusfunc = '{ -> IMstatusfunc1()}'
normal! i
@@ -164,11 +175,15 @@ func Test_imactivatefunc_imstatusfunc_callback()
" Set 'imactivatefunc' 'imstatusfunc' to a variable with a lambda expression
let Lambda1 = {a -> IMactivatefunc1(a)}
let Lambda2 = { -> IMstatusfunc1()}
+ let &imactivatefunc = Lambda1
+ let &imstatusfunc = Lambda2
+ normal! i
+
+ " Set 'imactivatefunc' 'imstatusfunc' to a string(variable with a lambda
+ " expression)
let &imactivatefunc = string(Lambda1)
let &imstatusfunc = string(Lambda2)
normal! i
- call assert_fails('let &imactivatefunc = Lambda1', 'E729:')
- call assert_fails('let &imstatusfunc = Lambda2', 'E729:')
" Test for clearing the 'completefunc' option
set imactivatefunc='' imstatusfunc=''
@@ -179,8 +194,8 @@ func Test_imactivatefunc_imstatusfunc_callback()
call assert_fails("set imactivatefunc=funcref('abc')", "E700:")
call assert_fails("set imstatusfunc=funcref('abc')", "E700:")
- call assert_equal(7, g:IMactivatefunc_called)
- call assert_equal(14, g:IMstatusfunc_called)
+ call assert_equal(11, g:IMactivatefunc_called)
+ call assert_equal(22, g:IMstatusfunc_called)
" Vim9 tests
let lines =<< trim END
@@ -216,12 +231,17 @@ func Test_imactivatefunc_imstatusfunc_callback()
g:IMstatusfunc_called += 1
return 1
}
+ &imactivatefunc = Fn1
+ &imstatusfunc = Fn2
+ normal! i
+
+ # Test for using a string(variable with a lambda expression)
&imactivatefunc = string(Fn1)
&imstatusfunc = string(Fn2)
normal! i
- assert_equal(3, g:IMactivatefunc_called)
- assert_equal(6, g:IMstatusfunc_called)
+ assert_equal(4, g:IMactivatefunc_called)
+ assert_equal(8, g:IMstatusfunc_called)
set iminsert=0
set imactivatefunc=
diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim
index d39acf4270..d508ba087f 100644
--- a/src/testdir/test_ins_complete.vim
+++ b/src/testdir/test_ins_complete.vim
@@ -885,13 +885,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()
@@ -909,13 +918,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
@@ -932,6 +950,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')
@@ -942,18 +969,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')
@@ -965,7 +1001,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
@@ -990,6 +1026,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')
@@ -1003,6 +1048,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')
@@ -1045,13 +1099,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()
@@ -1069,13 +1132,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
@@ -1092,6 +1164,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')
@@ -1102,18 +1183,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')
@@ -1125,7 +1215,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
@@ -1150,6 +1240,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')
@@ -1160,6 +1259,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')
@@ -1202,13 +1310,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()
@@ -1226,13 +1343,22 @@ func Test_thesaurusfunc_callback()
" Using a funcref variable to set 'thesaurusfunc'