forked from aniani/vim
patch 8.2.3725: cannot use a lambda for 'completefunc' and 'omnifunc'
Problem: Cannot use a lambda for 'completefunc' and 'omnifunc'. Solution: Implement lambda support. (Yegappan Lakshmanan, closes #9257)
This commit is contained in:
committed by
Bram Moolenaar
parent
021ef351c2
commit
8658c759f0
@@ -373,8 +373,8 @@ Note: In the future more global options can be made global-local. Using
|
|||||||
|
|
||||||
*option-value-function*
|
*option-value-function*
|
||||||
Some options ('completefunc', 'imactivatefunc', 'imstatusfunc', 'omnifunc',
|
Some options ('completefunc', 'imactivatefunc', 'imstatusfunc', 'omnifunc',
|
||||||
'operatorfunc', 'quickfixtextfunc' and 'tagfunc') are set to a function name
|
'operatorfunc', 'quickfixtextfunc', 'tagfunc' and 'thesaurusfunc') are set to
|
||||||
or a function reference or a lambda function. Examples:
|
a function name or a function reference or a lambda function. Examples:
|
||||||
>
|
>
|
||||||
set opfunc=MyOpFunc
|
set opfunc=MyOpFunc
|
||||||
set opfunc=function('MyOpFunc')
|
set opfunc=function('MyOpFunc')
|
||||||
@@ -1939,7 +1939,9 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
This option specifies a function to be used for Insert mode completion
|
This option specifies a function to be used for Insert mode completion
|
||||||
with CTRL-X CTRL-U. |i_CTRL-X_CTRL-U|
|
with CTRL-X CTRL-U. |i_CTRL-X_CTRL-U|
|
||||||
See |complete-functions| for an explanation of how the function is
|
See |complete-functions| for an explanation of how the function is
|
||||||
invoked and what it should return.
|
invoked and what it should return. The value can be the name of a
|
||||||
|
function, a |lambda| or a |Funcref|. See |option-value-function| for
|
||||||
|
more information.
|
||||||
This option cannot be set from a |modeline| or in the |sandbox|, for
|
This option cannot be set from a |modeline| or in the |sandbox|, for
|
||||||
security reasons.
|
security reasons.
|
||||||
|
|
||||||
@@ -5616,7 +5618,9 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
This option specifies a function to be used for Insert mode omni
|
This option specifies a function to be used for Insert mode omni
|
||||||
completion with CTRL-X CTRL-O. |i_CTRL-X_CTRL-O|
|
completion with CTRL-X CTRL-O. |i_CTRL-X_CTRL-O|
|
||||||
See |complete-functions| for an explanation of how the function is
|
See |complete-functions| for an explanation of how the function is
|
||||||
invoked and what it should return.
|
invoked and what it should return. The value can be the name of a
|
||||||
|
function, a |lambda| or a |Funcref|. See |option-value-function| for
|
||||||
|
more information.
|
||||||
This option is usually set by a filetype plugin:
|
This option is usually set by a filetype plugin:
|
||||||
|:filetype-plugin-on|
|
|:filetype-plugin-on|
|
||||||
This option cannot be set from a |modeline| or in the |sandbox|, for
|
This option cannot be set from a |modeline| or in the |sandbox|, for
|
||||||
@@ -8075,6 +8079,8 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
feature}
|
feature}
|
||||||
This option specifies a function to be used for thesaurus completion
|
This option specifies a function to be used for thesaurus completion
|
||||||
with CTRL-X CTRL-T. |i_CTRL-X_CTRL-T| See |compl-thesaurusfunc|.
|
with CTRL-X CTRL-T. |i_CTRL-X_CTRL-T| See |compl-thesaurusfunc|.
|
||||||
|
The value can be the name of a function, a |lambda| or a |Funcref|.
|
||||||
|
See |option-value-function| for more information.
|
||||||
|
|
||||||
This option cannot be set from a |modeline| or in the |sandbox|, for
|
This option cannot be set from a |modeline| or in the |sandbox|, for
|
||||||
security reasons.
|
security reasons.
|
||||||
|
@@ -2326,8 +2326,11 @@ free_buf_options(
|
|||||||
clear_string_option(&buf->b_p_cpt);
|
clear_string_option(&buf->b_p_cpt);
|
||||||
#ifdef FEAT_COMPL_FUNC
|
#ifdef FEAT_COMPL_FUNC
|
||||||
clear_string_option(&buf->b_p_cfu);
|
clear_string_option(&buf->b_p_cfu);
|
||||||
|
free_callback(&buf->b_cfu_cb);
|
||||||
clear_string_option(&buf->b_p_ofu);
|
clear_string_option(&buf->b_p_ofu);
|
||||||
|
free_callback(&buf->b_ofu_cb);
|
||||||
clear_string_option(&buf->b_p_tsrfu);
|
clear_string_option(&buf->b_p_tsrfu);
|
||||||
|
free_callback(&buf->b_tsrfu_cb);
|
||||||
#endif
|
#endif
|
||||||
#ifdef FEAT_QUICKFIX
|
#ifdef FEAT_QUICKFIX
|
||||||
clear_string_option(&buf->b_p_gp);
|
clear_string_option(&buf->b_p_gp);
|
||||||
|
137
src/insexpand.c
137
src/insexpand.c
@@ -2237,6 +2237,113 @@ ins_compl_next_buf(buf_T *buf, int flag)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FEAT_COMPL_FUNC
|
#ifdef FEAT_COMPL_FUNC
|
||||||
|
|
||||||
|
# ifdef FEAT_EVAL
|
||||||
|
static callback_T cfu_cb; // 'completefunc' callback function
|
||||||
|
static callback_T ofu_cb; // 'omnifunc' callback function
|
||||||
|
static callback_T tsrfu_cb; // 'thesaurusfunc' callback function
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy a global callback function to a buffer local callback.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
copy_global_to_buflocal_cb(callback_T *globcb, callback_T *bufcb)
|
||||||
|
{
|
||||||
|
free_callback(bufcb);
|
||||||
|
if (globcb->cb_name != NULL && *globcb->cb_name != NUL)
|
||||||
|
copy_callback(bufcb, globcb);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse the 'completefunc' option value and set the callback function.
|
||||||
|
* Invoked when the 'completefunc' option is set. The option value can be a
|
||||||
|
* name of a function (string), or function(<name>) or funcref(<name>) or a
|
||||||
|
* lambda expression.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
set_completefunc_option(void)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
retval = option_set_callback_func(curbuf->b_p_cfu, &cfu_cb);
|
||||||
|
if (retval == OK)
|
||||||
|
set_buflocal_cfu_callback(curbuf);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy the global 'completefunc' callback function to the buffer-local
|
||||||
|
* 'completefunc' callback for 'buf'.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
set_buflocal_cfu_callback(buf_T *buf UNUSED)
|
||||||
|
{
|
||||||
|
# ifdef FEAT_EVAL
|
||||||
|
copy_global_to_buflocal_cb(&cfu_cb, &buf->b_cfu_cb);
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse the 'omnifunc' option value and set the callback function.
|
||||||
|
* Invoked when the 'omnifunc' option is set. The option value can be a
|
||||||
|
* name of a function (string), or function(<name>) or funcref(<name>) or a
|
||||||
|
* lambda expression.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
set_omnifunc_option(void)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
retval = option_set_callback_func(curbuf->b_p_ofu, &ofu_cb);
|
||||||
|
if (retval == OK)
|
||||||
|
set_buflocal_ofu_callback(curbuf);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy the global 'omnifunc' callback function to the buffer-local 'omnifunc'
|
||||||
|
* callback for 'buf'.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
set_buflocal_ofu_callback(buf_T *buf UNUSED)
|
||||||
|
{
|
||||||
|
# ifdef FEAT_EVAL
|
||||||
|
copy_global_to_buflocal_cb(&ofu_cb, &buf->b_ofu_cb);
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse the 'thesaurusfunc' option value and set the callback function.
|
||||||
|
* Invoked when the 'thesaurusfunc' option is set. The option value can be a
|
||||||
|
* name of a function (string), or function(<name>) or funcref(<name>) or a
|
||||||
|
* lambda expression.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
set_thesaurusfunc_option(void)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
if (*curbuf->b_p_tsrfu != NUL)
|
||||||
|
{
|
||||||
|
// buffer-local option set
|
||||||
|
free_callback(&curbuf->b_tsrfu_cb);
|
||||||
|
retval = option_set_callback_func(curbuf->b_p_tsrfu,
|
||||||
|
&curbuf->b_tsrfu_cb);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// global option set
|
||||||
|
free_callback(&tsrfu_cb);
|
||||||
|
retval = option_set_callback_func(p_tsrfu, &tsrfu_cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the user-defined completion function name for completion 'type'
|
* Get the user-defined completion function name for completion 'type'
|
||||||
*/
|
*/
|
||||||
@@ -2256,6 +2363,20 @@ get_complete_funcname(int type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the callback to use for insert mode completion.
|
||||||
|
*/
|
||||||
|
callback_T *
|
||||||
|
get_insert_callback(int type)
|
||||||
|
{
|
||||||
|
if (type == CTRL_X_FUNCTION)
|
||||||
|
return &curbuf->b_cfu_cb;
|
||||||
|
if (type == CTRL_X_OMNI)
|
||||||
|
return &curbuf->b_ofu_cb;
|
||||||
|
// CTRL_X_THESAURUS
|
||||||
|
return (*curbuf->b_p_tsrfu != NUL) ? &curbuf->b_tsrfu_cb : &tsrfu_cb;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Execute user defined complete function 'completefunc', 'omnifunc' or
|
* Execute user defined complete function 'completefunc', 'omnifunc' or
|
||||||
* 'thesaurusfunc', and get matches in "matches".
|
* 'thesaurusfunc', and get matches in "matches".
|
||||||
@@ -2269,8 +2390,10 @@ expand_by_function(int type, char_u *base)
|
|||||||
typval_T args[3];
|
typval_T args[3];
|
||||||
char_u *funcname;
|
char_u *funcname;
|
||||||
pos_T pos;
|
pos_T pos;
|
||||||
|
callback_T *cb;
|
||||||
typval_T rettv;
|
typval_T rettv;
|
||||||
int save_State = State;
|
int save_State = State;
|
||||||
|
int retval;
|
||||||
|
|
||||||
funcname = get_complete_funcname(type);
|
funcname = get_complete_funcname(type);
|
||||||
if (*funcname == NUL)
|
if (*funcname == NUL)
|
||||||
@@ -2289,8 +2412,11 @@ expand_by_function(int type, char_u *base)
|
|||||||
// Insert mode in another buffer.
|
// Insert mode in another buffer.
|
||||||
++textwinlock;
|
++textwinlock;
|
||||||
|
|
||||||
|
cb = get_insert_callback(type);
|
||||||
|
retval = call_callback(cb, 0, &rettv, 2, args);
|
||||||
|
|
||||||
// Call a function, which returns a list or dict.
|
// Call a function, which returns a list or dict.
|
||||||
if (call_vim_function(funcname, 2, args, &rettv) == OK)
|
if (retval == OK)
|
||||||
{
|
{
|
||||||
switch (rettv.v_type)
|
switch (rettv.v_type)
|
||||||
{
|
{
|
||||||
@@ -3971,6 +4097,7 @@ ins_complete(int c, int enable_pum)
|
|||||||
char_u *funcname;
|
char_u *funcname;
|
||||||
pos_T pos;
|
pos_T pos;
|
||||||
int save_State = State;
|
int save_State = State;
|
||||||
|
callback_T *cb;
|
||||||
|
|
||||||
// Call 'completefunc' or 'omnifunc' and get pattern length as a
|
// Call 'completefunc' or 'omnifunc' and get pattern length as a
|
||||||
// string
|
// string
|
||||||
@@ -3991,7 +4118,8 @@ ins_complete(int c, int enable_pum)
|
|||||||
args[2].v_type = VAR_UNKNOWN;
|
args[2].v_type = VAR_UNKNOWN;
|
||||||
pos = curwin->w_cursor;
|
pos = curwin->w_cursor;
|
||||||
++textwinlock;
|
++textwinlock;
|
||||||
col = call_func_retnr(funcname, 2, args);
|
cb = get_insert_callback(ctrl_x_mode);
|
||||||
|
col = call_callback_retnr(cb, 2, args);
|
||||||
--textwinlock;
|
--textwinlock;
|
||||||
|
|
||||||
State = save_State;
|
State = save_State;
|
||||||
@@ -4339,6 +4467,11 @@ quote_meta(char_u *dest, char_u *src, int len)
|
|||||||
free_insexpand_stuff(void)
|
free_insexpand_stuff(void)
|
||||||
{
|
{
|
||||||
VIM_CLEAR(compl_orig_text);
|
VIM_CLEAR(compl_orig_text);
|
||||||
|
# ifdef FEAT_EVAL
|
||||||
|
free_callback(&cfu_cb);
|
||||||
|
free_callback(&ofu_cb);
|
||||||
|
free_callback(&tsrfu_cb);
|
||||||
|
# endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -5927,13 +5927,15 @@ buf_copy_options(buf_T *buf, int flags)
|
|||||||
#ifdef FEAT_COMPL_FUNC
|
#ifdef FEAT_COMPL_FUNC
|
||||||
buf->b_p_cfu = vim_strsave(p_cfu);
|
buf->b_p_cfu = vim_strsave(p_cfu);
|
||||||
COPY_OPT_SCTX(buf, BV_CFU);
|
COPY_OPT_SCTX(buf, BV_CFU);
|
||||||
|
set_buflocal_cfu_callback(buf);
|
||||||
buf->b_p_ofu = vim_strsave(p_ofu);
|
buf->b_p_ofu = vim_strsave(p_ofu);
|
||||||
COPY_OPT_SCTX(buf, BV_OFU);
|
COPY_OPT_SCTX(buf, BV_OFU);
|
||||||
|
set_buflocal_ofu_callback(buf);
|
||||||
#endif
|
#endif
|
||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
buf->b_p_tfu = vim_strsave(p_tfu);
|
buf->b_p_tfu = vim_strsave(p_tfu);
|
||||||
COPY_OPT_SCTX(buf, BV_TFU);
|
COPY_OPT_SCTX(buf, BV_TFU);
|
||||||
buf_set_tfu_callback(buf);
|
set_buflocal_tfu_callback(buf);
|
||||||
#endif
|
#endif
|
||||||
buf->b_p_sts = p_sts;
|
buf->b_p_sts = p_sts;
|
||||||
COPY_OPT_SCTX(buf, BV_STS);
|
COPY_OPT_SCTX(buf, BV_STS);
|
||||||
|
@@ -2307,6 +2307,29 @@ ambw_end:
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef FEAT_COMPL_FUNC
|
||||||
|
// 'completefunc'
|
||||||
|
else if (gvarp == &p_cfu)
|
||||||
|
{
|
||||||
|
if (set_completefunc_option() == FAIL)
|
||||||
|
errmsg = e_invarg;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 'omnifunc'
|
||||||
|
else if (gvarp == &p_ofu)
|
||||||
|
{
|
||||||
|
if (set_omnifunc_option() == FAIL)
|
||||||
|
errmsg = e_invarg;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 'thesaurusfunc'
|
||||||
|
else if (gvarp == &p_tsrfu)
|
||||||
|
{
|
||||||
|
if (set_thesaurusfunc_option() == FAIL)
|
||||||
|
errmsg = e_invarg;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// 'operatorfunc'
|
// 'operatorfunc'
|
||||||
else if (varp == &p_opfunc)
|
else if (varp == &p_opfunc)
|
||||||
{
|
{
|
||||||
|
@@ -39,6 +39,12 @@ int ins_compl_bs(void);
|
|||||||
void ins_compl_addleader(int c);
|
void ins_compl_addleader(int c);
|
||||||
void ins_compl_addfrommatch(void);
|
void ins_compl_addfrommatch(void);
|
||||||
int ins_compl_prep(int c);
|
int ins_compl_prep(int c);
|
||||||
|
int set_completefunc_option(void);
|
||||||
|
void set_buflocal_cfu_callback(buf_T *buf);
|
||||||
|
int set_omnifunc_option(void);
|
||||||
|
void set_buflocal_ofu_callback(buf_T *buf);
|
||||||
|
int set_thesaurusfunc_option(void);
|
||||||
|
callback_T *get_insert_callback(int type);
|
||||||
void f_complete(typval_T *argvars, typval_T *rettv);
|
void f_complete(typval_T *argvars, typval_T *rettv);
|
||||||
void f_complete_add(typval_T *argvars, typval_T *rettv);
|
void f_complete_add(typval_T *argvars, typval_T *rettv);
|
||||||
void f_complete_check(typval_T *argvars, typval_T *rettv);
|
void f_complete_check(typval_T *argvars, typval_T *rettv);
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
/* tag.c */
|
/* tag.c */
|
||||||
int set_tagfunc_option(void);
|
int set_tagfunc_option(void);
|
||||||
void free_tagfunc_option(void);
|
void free_tagfunc_option(void);
|
||||||
void buf_set_tfu_callback(buf_T *buf);
|
void set_buflocal_tfu_callback(buf_T *buf);
|
||||||
int do_tag(char_u *tag, int type, int count, int forceit, int verbose);
|
int do_tag(char_u *tag, int type, int count, int forceit, int verbose);
|
||||||
void tag_freematch(void);
|
void tag_freematch(void);
|
||||||
void do_tags(exarg_T *eap);
|
void do_tags(exarg_T *eap);
|
||||||
|
@@ -28,6 +28,7 @@ int builtin_function(char_u *name, int len);
|
|||||||
int func_call(char_u *name, typval_T *args, partial_T *partial, dict_T *selfdict, typval_T *rettv);
|
int func_call(char_u *name, typval_T *args, partial_T *partial, dict_T *selfdict, typval_T *rettv);
|
||||||
int get_callback_depth(void);
|
int get_callback_depth(void);
|
||||||
int call_callback(callback_T *callback, int len, typval_T *rettv, int argcount, typval_T *argvars);
|
int call_callback(callback_T *callback, int len, typval_T *rettv, int argcount, typval_T *argvars);
|
||||||
|
varnumber_T call_callback_retnr(callback_T *callback, int argcount, typval_T *argvars);
|
||||||
void user_func_error(int error, char_u *name);
|
void user_func_error(int error, char_u *name);
|
||||||
int call_func(char_u *funcname, int len, typval_T *rettv, int argcount_in, typval_T *argvars_in, funcexe_T *funcexe);
|
int call_func(char_u *funcname, int len, typval_T *rettv, int argcount_in, typval_T *argvars_in, funcexe_T *funcexe);
|
||||||
char_u *printable_func_name(ufunc_T *fp);
|
char_u *printable_func_name(ufunc_T *fp);
|
||||||
|
@@ -2876,7 +2876,9 @@ struct file_buffer
|
|||||||
#endif
|
#endif
|
||||||
#ifdef FEAT_COMPL_FUNC
|
#ifdef FEAT_COMPL_FUNC
|
||||||
char_u *b_p_cfu; // 'completefunc'
|
char_u *b_p_cfu; // 'completefunc'
|
||||||
|
callback_T b_cfu_cb; // 'completefunc' callback
|
||||||
char_u *b_p_ofu; // 'omnifunc'
|
char_u *b_p_ofu; // 'omnifunc'
|
||||||
|
callback_T b_ofu_cb; // 'omnifunc' callback
|
||||||
#endif
|
#endif
|
||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
char_u *b_p_tfu; // 'tagfunc' option value
|
char_u *b_p_tfu; // 'tagfunc' option value
|
||||||
@@ -2982,6 +2984,7 @@ struct file_buffer
|
|||||||
char_u *b_p_tsr; // 'thesaurus' local value
|
char_u *b_p_tsr; // 'thesaurus' local value
|
||||||
#ifdef FEAT_COMPL_FUNC
|
#ifdef FEAT_COMPL_FUNC
|
||||||
char_u *b_p_tsrfu; // 'thesaurusfunc' local value
|
char_u *b_p_tsrfu; // 'thesaurusfunc' local value
|
||||||
|
callback_T b_tsrfu_cb; // 'thesaurusfunc' callback
|
||||||
#endif
|
#endif
|
||||||
long b_p_ul; // 'undolevels' local value
|
long b_p_ul; // 'undolevels' local value
|
||||||
#ifdef FEAT_PERSISTENT_UNDO
|
#ifdef FEAT_PERSISTENT_UNDO
|
||||||
|
@@ -115,7 +115,7 @@ static callback_T tfu_cb; // 'tagfunc' callback function
|
|||||||
* a function (string), or function(<name>) or funcref(<name>) or a lambda.
|
* a function (string), or function(<name>) or funcref(<name>) or a lambda.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
set_tagfunc_option()
|
set_tagfunc_option(void)
|
||||||
{
|
{
|
||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
free_callback(&tfu_cb);
|
free_callback(&tfu_cb);
|
||||||
@@ -148,7 +148,7 @@ free_tagfunc_option(void)
|
|||||||
* callback for 'buf'.
|
* callback for 'buf'.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
buf_set_tfu_callback(buf_T *buf UNUSED)
|
set_buflocal_tfu_callback(buf_T *buf UNUSED)
|
||||||
{
|
{
|
||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
free_callback(&buf->b_tfu_cb);
|
free_callback(&buf->b_tfu_cb);
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
source screendump.vim
|
source screendump.vim
|
||||||
source check.vim
|
source check.vim
|
||||||
|
source vim9.vim
|
||||||
|
|
||||||
" Test for insert expansion
|
" Test for insert expansion
|
||||||
func Test_ins_complete()
|
func Test_ins_complete()
|
||||||
@@ -867,4 +868,503 @@ func Test_z1_complete_no_history()
|
|||||||
close!
|
close!
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
" Test for different ways of setting the 'completefunc' option
|
||||||
|
func Test_completefunc_callback()
|
||||||
|
" Test for using a function()
|
||||||
|
func MycompleteFunc1(findstart, base)
|
||||||
|
call add(g:MycompleteFunc1_args, [a:findstart, a:base])
|
||||||
|
return a:findstart ? 0 : []
|
||||||
|
endfunc
|
||||||
|
set completefunc=function('MycompleteFunc1')
|
||||||
|
new | only
|
||||||
|
call setline(1, 'one')
|
||||||
|
let g:MycompleteFunc1_args = []
|
||||||
|
call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
|
||||||
|
call assert_equal([[1, ''], [0, 'one']], g:MycompleteFunc1_args)
|
||||||
|
bw!
|
||||||
|
|
||||||
|
" Using a 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()
|
||||||
|
func MycompleteFunc2(findstart, base)
|
||||||
|
call add(g:MycompleteFunc2_args, [a:findstart, a:base])
|
||||||
|
return a:findstart ? 0 : []
|
||||||
|
endfunc
|
||||||
|
set completefunc=funcref('MycompleteFunc2')
|
||||||
|
new | only
|
||||||
|
call setline(1, 'three')
|
||||||
|
let g:MycompleteFunc2_args = []
|
||||||
|
call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
|
||||||
|
call assert_equal([[1, ''], [0, 'three']], g:MycompleteFunc2_args)
|
||||||
|
bw!
|
||||||
|
|
||||||
|
" Using a 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
|
||||||
|
func MycompleteFunc3(findstart, base)
|
||||||
|
call add(g:MycompleteFunc3_args, [a:findstart, a:base])
|
||||||
|
return a:findstart ? 0 : []
|
||||||
|
endfunc
|
||||||
|
set completefunc={a,\ b,\ ->\ MycompleteFunc3(a,\ b,)}
|
||||||
|
new | only
|
||||||
|
call setline(1, 'five')
|
||||||
|
let g:MycompleteFunc3_args = []
|
||||||
|
call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
|
||||||
|
call assert_equal([[1, ''], [0, 'five']], g:MycompleteFunc3_args)
|
||||||
|
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 a 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)
|
||||||
|
new | only
|
||||||
|
call setline(1, 'eight')
|
||||||
|
call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
|
||||||
|
bw!
|
||||||
|
|
||||||
|
" Test for clearing the 'completefunc' option
|
||||||
|
set completefunc=''
|
||||||
|
set completefunc&
|
||||||
|
|
||||||
|
call assert_fails("set completefunc=function('abc')", "E700:")
|
||||||
|
call assert_fails("set completefunc=funcref('abc')", "E700:")
|
||||||
|
let &completefunc = "{a -> 'abc'}"
|
||||||
|
call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
|
||||||
|
|
||||||
|
" Vim9 tests
|
||||||
|
let lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
|
||||||
|
# Test for using function()
|
||||||
|
def MycompleteFunc1(findstart: number, base: string): any
|
||||||
|
add(g:MycompleteFunc1_args, [findstart, base])
|
||||||
|
return findstart ? 0 : []
|
||||||
|
enddef
|
||||||
|
set completefunc=function('MycompleteFunc1')
|
||||||
|
new | only
|
||||||
|
setline(1, 'one')
|
||||||
|
g:MycompleteFunc1_args = []
|
||||||
|
feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
|
||||||
|
assert_equal([[1, ''], [0, 'one']], g:MycompleteFunc1_args)
|
||||||
|
bw!
|
||||||
|
|
||||||
|
# Test for using a lambda
|
||||||
|
def MycompleteFunc2(findstart: number, base: string): any
|
||||||
|
add(g:MycompleteFunc2_args, [findstart, base])
|
||||||
|
return findstart ? 0 : []
|
||||||
|
enddef
|
||||||
|
&completefunc = '(a, b) => MycompleteFunc2(a, b)'
|
||||||
|
new | only
|
||||||
|
setline(1, 'two')
|
||||||
|
g:MycompleteFunc2_args = []
|
||||||
|
feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
|
||||||
|
assert_equal([[1, ''], [0, 'two']], g:MycompleteFunc2_args)
|
||||||
|
bw!
|
||||||
|
|
||||||
|
# Test for using a variable with a lambda expression
|
||||||
|
var Fn: func = (a, b) => MycompleteFunc2(a, b)
|
||||||
|
&completefunc = string(Fn)
|
||||||
|
new | only
|
||||||
|
setline(1, 'three')
|
||||||
|
g:MycompleteFunc2_args = []
|
||||||
|
feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
|
||||||
|
assert_equal([[1, ''], [0, 'three']], g:MycompleteFunc2_args)
|
||||||
|
bw!
|
||||||
|
END
|
||||||
|
call CheckScriptSuccess(lines)
|
||||||
|
|
||||||
|
" Using Vim9 lambda expression in legacy context should fail
|
||||||
|
set completefunc=(a,\ b)\ =>\ g:MycompleteFunc2(a,\ b)
|
||||||
|
new | only
|
||||||
|
let g:MycompleteFunc2_args = []
|
||||||
|
call assert_fails('call feedkeys("A\<C-X>\<C-U>\<Esc>", "x")', 'E117:')
|
||||||
|
call assert_equal([], g:MycompleteFunc2_args)
|
||||||
|
|
||||||
|
" cleanup
|
||||||
|
delfunc MycompleteFunc1
|
||||||
|
delfunc MycompleteFunc2
|
||||||
|
delfunc MycompleteFunc3
|
||||||
|
set completefunc&
|
||||||
|
%bw!
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" Test for different ways of setting the 'omnifunc' option
|
||||||
|
func Test_omnifunc_callback()
|
||||||
|
" Test for using a function()
|
||||||
|
func MyomniFunc1(findstart, base)
|
||||||
|
call add(g:MyomniFunc1_args, [a:findstart, a:base])
|
||||||
|
return a:findstart ? 0 : []
|
||||||
|
endfunc
|
||||||
|
set omnifunc=function('MyomniFunc1')
|
||||||
|
new | only
|
||||||
|
call setline(1, 'one')
|
||||||
|
let g:MyomniFunc1_args = []
|
||||||
|
call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
|
||||||
|
call assert_equal([[1, ''], [0, 'one']], g:MyomniFunc1_args)
|
||||||
|
bw!
|
||||||
|
|
||||||
|
" Using a 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()
|
||||||
|
func MyomniFunc2(findstart, base)
|
||||||
|
call add(g:MyomniFunc2_args, [a:findstart, a:base])
|
||||||
|
return a:findstart ? 0 : []
|
||||||
|
endfunc
|
||||||
|
set omnifunc=funcref('MyomniFunc2')
|
||||||
|
new | only
|
||||||
|
call setline(1, 'three')
|
||||||
|
let g:MyomniFunc2_args = []
|
||||||
|
call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
|
||||||
|
call assert_equal([[1, ''], [0, 'three']], g:MyomniFunc2_args)
|
||||||
|
bw!
|
||||||
|
|
||||||
|
" Using a 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
|
||||||
|
func MyomniFunc3(findstart, base)
|
||||||
|
call add(g:MyomniFunc3_args, [a:findstart, a:base])
|
||||||
|
return a:findstart ? 0 : []
|
||||||
|
endfunc
|
||||||
|
set omnifunc={a,\ b,\ ->\ MyomniFunc3(a,\ b,)}
|
||||||
|
new | only
|
||||||
|
call setline(1, 'five')
|
||||||
|
let g:MyomniFunc3_args = []
|
||||||
|
call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
|
||||||
|
call assert_equal([[1, ''], [0, 'five']], g:MyomniFunc3_args)
|
||||||
|
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 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)
|
||||||
|
new | only
|
||||||
|
call setline(1, 'eight')
|
||||||
|
call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
|
||||||
|
bw!
|
||||||
|
|
||||||
|
" Test for clearing the 'omnifunc' option
|
||||||
|
set omnifunc=''
|
||||||
|
set omnifunc&
|
||||||
|
|
||||||
|
call assert_fails("set omnifunc=function('abc')", "E700:")
|
||||||
|
call assert_fails("set omnifunc=funcref('abc')", "E700:")
|
||||||
|
let &omnifunc = "{a -> 'abc'}"
|
||||||
|
call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
|
||||||
|
|
||||||
|
" Vim9 tests
|
||||||
|
let lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
|
||||||
|
# Test for using function()
|
||||||
|
def MyomniFunc1(findstart: number, base: string): any
|
||||||
|
add(g:MyomniFunc1_args, [findstart, base])
|
||||||
|
return findstart ? 0 : []
|
||||||
|
enddef
|
||||||
|
set omnifunc=function('MyomniFunc1')
|
||||||
|
new | only
|
||||||
|
setline(1, 'one')
|
||||||
|
g:MyomniFunc1_args = []
|
||||||
|
feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
|
||||||
|
assert_equal([[1, ''], [0, 'one']], g:MyomniFunc1_args)
|
||||||
|
bw!
|
||||||
|
|
||||||
|
# Test for using a lambda
|
||||||
|
def MyomniFunc2(findstart: number, base: string): any
|
||||||
|
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 variable with a lambda expression
|
||||||
|
var Fn: func = (a, b) => MyomniFunc2(a, b)
|
||||||
|
&omnifunc = string(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!
|
||||||
|
END
|
||||||
|
call CheckScriptSuccess(lines)
|
||||||
|
|
||||||
|
" Using Vim9 lambda expression in legacy context should fail
|
||||||
|
set omnifunc=(a,\ b)\ =>\ g:MyomniFunc2(a,\ b)
|
||||||
|
new | only
|
||||||
|
let g:MyomniFunc2_args = []
|
||||||
|
call assert_fails('call feedkeys("A\<C-X>\<C-O>\<Esc>", "x")', 'E117:')
|
||||||
|
call assert_equal([], g:MyomniFunc2_args)
|
||||||
|
|
||||||
|
" cleanup
|
||||||
|
delfunc MyomniFunc1
|
||||||
|
delfunc MyomniFunc2
|
||||||
|
delfunc MyomniFunc3
|
||||||
|
set omnifunc&
|
||||||
|
%bw!
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" Test for different ways of setting the 'thesaurusfunc' option
|
||||||
|
func Test_thesaurusfunc_callback()
|
||||||
|
" Test for using a function()
|
||||||
|
func MytsrFunc1(findstart, base)
|
||||||
|
call add(g:MytsrFunc1_args, [a:findstart, a:base])
|
||||||
|
return a:findstart ? 0 : []
|
||||||
|
endfunc
|
||||||
|
set thesaurusfunc=function('MytsrFunc1')
|
||||||
|
new | only
|
||||||
|
call setline(1, 'one')
|
||||||
|
let g:MytsrFunc1_args = []
|
||||||
|
call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
|
||||||
|
call assert_equal([[1, ''], [0, 'one']], g:MytsrFunc1_args)
|
||||||
|
bw!
|
||||||
|
|
||||||
|
" Using a 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()
|
||||||
|
func MytsrFunc2(findstart, base)
|
||||||
|
call add(g:MytsrFunc2_args, [a:findstart, a:base])
|
||||||
|
return a:findstart ? 0 : []
|
||||||
|
endfunc
|
||||||
|
set thesaurusfunc=funcref('MytsrFunc2')
|
||||||
|
new | only
|
||||||
|
call setline(1, 'three')
|
||||||
|
let g:MytsrFunc2_args = []
|
||||||
|
call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
|
||||||
|
call assert_equal([[1, ''], [0, 'three']], g:MytsrFunc2_args)
|
||||||
|
bw!
|
||||||
|
|
||||||
|
" Using a 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
|
||||||
|
func MytsrFunc3(findstart, base)
|
||||||
|
call add(g:MytsrFunc3_args, [a:findstart, a:base])
|
||||||
|
return a:findstart ? 0 : []
|
||||||
|
endfunc
|
||||||
|
set thesaurusfunc={a,\ b,\ ->\ MytsrFunc3(a,\ b,)}
|
||||||
|
new | only
|
||||||
|
call setline(1, 'five')
|
||||||
|
let g:MytsrFunc3_args = []
|
||||||
|
call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
|
||||||
|
call assert_equal([[1, ''], [0, 'five']], g:MytsrFunc3_args)
|
||||||
|
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 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)
|
||||||
|
new | only
|
||||||
|
call setline(1, 'eight')
|
||||||
|
call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
|
||||||
|
bw!
|
||||||
|
|
||||||
|
" Test for clearing the 'thesaurusfunc' option
|
||||||
|
set thesaurusfunc=''
|
||||||
|
set thesaurusfunc&
|
||||||
|
|
||||||
|
call assert_fails("set thesaurusfunc=function('abc')", "E700:")
|
||||||
|
call assert_fails("set thesaurusfunc=funcref('abc')", "E700:")
|
||||||
|
let &thesaurusfunc = "{a -> 'abc'}"
|
||||||
|
call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
|
||||||
|
|
||||||
|
" Vim9 tests
|
||||||
|
let lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
|
||||||
|
# Test for using function()
|
||||||
|
def MytsrFunc1(findstart: number, base: string): any
|
||||||
|
add(g:MytsrFunc1_args, [findstart, base])
|
||||||
|
return findstart ? 0 : []
|
||||||
|
enddef
|
||||||
|
set thesaurusfunc=function('MytsrFunc1')
|
||||||
|
new | only
|
||||||
|
setline(1, 'one')
|
||||||
|
g:MytsrFunc1_args = []
|
||||||
|
feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
|
||||||
|
assert_equal([[1, ''], [0, 'one']], g:MytsrFunc1_args)
|
||||||
|
bw!
|
||||||
|
|
||||||
|
# Test for using a lambda
|
||||||
|
def MytsrFunc2(findstart: number, base: string): any
|
||||||
|
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 variable with a lambda expression
|
||||||
|
var Fn: func = (a, b) => MytsrFunc2(a, b)
|
||||||
|
&thesaurusfunc = string(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!
|
||||||
|
END
|
||||||
|
call CheckScriptSuccess(lines)
|
||||||
|
|
||||||
|
" Using Vim9 lambda expression in legacy context should fail
|
||||||
|
set thesaurusfunc=(a,\ b)\ =>\ g:MytsrFunc2(a,\ b)
|
||||||
|
new | only
|
||||||
|
let g:MytsrFunc2_args = []
|
||||||
|
call assert_fails('call feedkeys("A\<C-X>\<C-T>\<Esc>", "x")', 'E117:')
|
||||||
|
call assert_equal([], g:MytsrFunc2_args)
|
||||||
|
bw!
|
||||||
|
|
||||||
|
" Use a buffer-local value and a global value
|
||||||
|
func MytsrFunc4(findstart, base)
|
||||||
|
call add(g:MytsrFunc4_args, [a:findstart, a:base])
|
||||||
|
return a:findstart ? 0 : ['sunday']
|
||||||
|
endfunc
|
||||||
|
set thesaurusfunc&
|
||||||
|
setlocal thesaurusfunc=function('MytsrFunc4')
|
||||||
|
call setline(1, 'sun')
|
||||||
|
let g:MytsrFunc4_args = []
|
||||||
|
call feedkeys("A\<C-X>\<C-T>\<Esc>", "x")
|
||||||
|
call assert_equal('sunday', getline(1))
|
||||||
|
call assert_equal([[1, ''], [0, 'sun']], g:MytsrFunc4_args)
|
||||||
|
new
|
||||||
|
call setline(1, 'sun')
|
||||||
|
let g:MytsrFunc4_args = []
|
||||||
|
call feedkeys("A\<C-X>\<C-T>\<Esc>", "x")
|
||||||
|
call assert_equal('sun', getline(1))
|
||||||
|
call assert_equal([], g:MytsrFunc4_args)
|
||||||
|
set thesaurusfunc=function('MytsrFunc1')
|
||||||
|
wincmd w
|
||||||
|
call setline(1, 'sun')
|
||||||
|
let g:MytsrFunc4_args = []
|
||||||
|
call feedkeys("A\<C-X>\<C-T>\<Esc>", "x")
|
||||||
|
call assert_equal('sunday', getline(1))
|
||||||
|
call assert_equal([[1, ''], [0, 'sun']], g:MytsrFunc4_args)
|
||||||
|
|
||||||
|
" cleanup
|
||||||
|
set thesaurusfunc&
|
||||||
|
delfunc MytsrFunc1
|
||||||
|
delfunc MytsrFunc2
|
||||||
|
delfunc MytsrFunc3
|
||||||
|
delfunc MytsrFunc4
|
||||||
|
%bw!
|
||||||
|
endfunc
|
||||||
|
|
||||||
" vim: shiftwidth=2 sts=2 expandtab
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
@@ -119,6 +119,12 @@ func Test_tagfunc_settagstack()
|
|||||||
delfunc Mytagfunc2
|
delfunc Mytagfunc2
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
" Script local tagfunc callback function
|
||||||
|
func s:ScriptLocalTagFunc(pat, flags, info)
|
||||||
|
let g:ScriptLocalFuncArgs = [a:pat, a:flags, a:info]
|
||||||
|
return v:null
|
||||||
|
endfunc
|
||||||
|
|
||||||
" Test for different ways of setting the 'tagfunc' option
|
" Test for different ways of setting the 'tagfunc' option
|
||||||
func Test_tagfunc_callback()
|
func Test_tagfunc_callback()
|
||||||
" Test for using a function()
|
" Test for using a function()
|
||||||
@@ -161,6 +167,21 @@ func Test_tagfunc_callback()
|
|||||||
call assert_equal(['a14', '', {}], g:MytagFunc2_args)
|
call assert_equal(['a14', '', {}], g:MytagFunc2_args)
|
||||||
call assert_fails('let &tagfunc = Fn', 'E729:')
|
call assert_fails('let &tagfunc = Fn', 'E729:')
|
||||||
|
|
||||||
|
" Test for using a script local function
|
||||||
|
set tagfunc=<SID>ScriptLocalTagFunc
|
||||||
|
new | only
|
||||||
|
let g:ScriptLocalFuncArgs = []
|
||||||
|
call assert_fails('tag a15', 'E433:')
|
||||||
|
call assert_equal(['a15', '', {}], g:ScriptLocalFuncArgs)
|
||||||
|
|
||||||
|
" Test for using a script local funcref variable
|
||||||
|
let Fn = function("s:ScriptLocalTagFunc")
|
||||||
|
let &tagfunc= string(Fn)
|
||||||
|
new | only
|
||||||
|
let g:ScriptLocalFuncArgs = []
|
||||||
|
call assert_fails('tag a16', 'E433:')
|
||||||
|
call assert_equal(['a16', '', {}], g:ScriptLocalFuncArgs)
|
||||||
|
|
||||||
" Test for using a lambda function
|
" Test for using a lambda function
|
||||||
func MytagFunc3(pat, flags, info)
|
func MytagFunc3(pat, flags, info)
|
||||||
let g:MytagFunc3_args = [a:pat, a:flags, a:info]
|
let g:MytagFunc3_args = [a:pat, a:flags, a:info]
|
||||||
@@ -169,30 +190,30 @@ func Test_tagfunc_callback()
|
|||||||
set tagfunc={a,\ b,\ c\ ->\ MytagFunc3(a,\ b,\ c)}
|
set tagfunc={a,\ b,\ c\ ->\ MytagFunc3(a,\ b,\ c)}
|
||||||
new | only
|
new | only
|
||||||
let g:MytagFunc3_args = []
|
let g:MytagFunc3_args = []
|
||||||
call assert_fails('tag a15', 'E433:')
|
call assert_fails('tag a17', 'E433:')
|
||||||
call assert_equal(['a15', '', {}], g:MytagFunc3_args)
|
call assert_equal(['a17', '', {}], g:MytagFunc3_args)
|
||||||
|
|
||||||
" Set 'tagfunc' to a lambda expression
|
" Set 'tagfunc' to a lambda expression
|
||||||
let &tagfunc = '{a, b, c -> MytagFunc3(a, b, c)}'
|
let &tagfunc = '{a, b, c -> MytagFunc3(a, b, c)}'
|
||||||
new | only
|
new | only
|
||||||
let g:MytagFunc3_args = []
|
let g:MytagFunc3_args = []
|
||||||
call assert_fails('tag a16', 'E433:')
|
call assert_fails('tag a18', 'E433:')
|
||||||
call assert_equal(['a16', '', {}], g:MytagFunc3_args)
|
call assert_equal(['a18', '', {}], g:MytagFunc3_args)
|
||||||
|
|
||||||
" Set 'tagfunc' to a variable with a lambda expression
|
" Set 'tagfunc' to a variable with a lambda expression
|
||||||
let Lambda = {a, b, c -> MytagFunc3(a, b, c)}
|
let Lambda = {a, b, c -> MytagFunc3(a, b, c)}
|
||||||
let &tagfunc = string(Lambda)
|
let &tagfunc = string(Lambda)
|
||||||
new | only
|
new | only
|
||||||
let g:MytagFunc3_args = []
|
let g:MytagFunc3_args = []
|
||||||
call assert_fails("tag a17", "E433:")
|
call assert_fails("tag a19", "E433:")
|
||||||
call assert_equal(['a17', '', {}], g:MytagFunc3_args)
|
call assert_equal(['a19', '', {}], g:MytagFunc3_args)
|
||||||
call assert_fails('let &tagfunc = Lambda', 'E729:')
|
call assert_fails('let &tagfunc = Lambda', 'E729:')
|
||||||
|
|
||||||
" Test for using a lambda function with incorrect return value
|
" Test for using a lambda function with incorrect return value
|
||||||
let Lambda = {s -> strlen(s)}
|
let Lambda = {s -> strlen(s)}
|
||||||
let &tagfunc = string(Lambda)
|
let &tagfunc = string(Lambda)
|
||||||
new | only
|
new | only
|
||||||
call assert_fails("tag a17", "E987:")
|
call assert_fails("tag a20", "E987:")
|
||||||
|
|
||||||
" Test for clearing the 'tagfunc' option
|
" Test for clearing the 'tagfunc' option
|
||||||
set tagfunc=''
|
set tagfunc=''
|
||||||
|
@@ -3168,6 +3168,29 @@ call_callback(
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* call the 'callback' function and return the result as a number.
|
||||||
|
* Returns -1 when calling the function fails. Uses argv[0] to argv[argc - 1]
|
||||||
|
* for the function arguments. argv[argc] should have type VAR_UNKNOWN.
|
||||||
|
*/
|
||||||
|
varnumber_T
|
||||||
|
call_callback_retnr(
|
||||||
|
callback_T *callback,
|
||||||
|
int argcount, // number of "argvars"
|
||||||
|
typval_T *argvars) // vars for arguments, must have "argcount"
|
||||||
|
// PLUS ONE elements!
|
||||||
|
{
|
||||||
|
typval_T rettv;
|
||||||
|
varnumber_T retval;
|
||||||
|
|
||||||
|
if (call_callback(callback, 0, &rettv, argcount, argvars) == FAIL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
retval = tv_get_number_chk(&rettv, NULL);
|
||||||
|
clear_tv(&rettv);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Give an error message for the result of a function.
|
* Give an error message for the result of a function.
|
||||||
* Nothing if "error" is FCERR_NONE.
|
* Nothing if "error" is FCERR_NONE.
|
||||||
|
@@ -753,6 +753,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
3725,
|
||||||
/**/
|
/**/
|
||||||
3724,
|
3724,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user