diff options
author | Yegappan Lakshmanan <yegappan@yahoo.com> | 2021-12-03 11:09:29 +0000 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2021-12-03 11:09:29 +0000 |
commit | 8658c759f05b317707d56e3b65a5ef63930c7498 (patch) | |
tree | 124fcda187b5515dfaeba4c86aa7a5e0f0888686 /src/insexpand.c | |
parent | 021ef351c2127cf8aa5668a881435a0a12774644 (diff) |
patch 8.2.3725: cannot use a lambda for 'completefunc' and 'omnifunc'v8.2.3725
Problem: Cannot use a lambda for 'completefunc' and 'omnifunc'.
Solution: Implement lambda support. (Yegappan Lakshmanan, closes #9257)
Diffstat (limited to 'src/insexpand.c')
-rw-r--r-- | src/insexpand.c | 137 |
1 files changed, 135 insertions, 2 deletions
diff --git a/src/insexpand.c b/src/insexpand.c index 630548bec1..92f0731eb5 100644 --- a/src/insexpand.c +++ b/src/insexpand.c @@ -2237,6 +2237,113 @@ ins_compl_next_buf(buf_T *buf, int flag) } #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' */ @@ -2257,6 +2364,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 * 'thesaurusfunc', and get matches in "matches". * "type" is either CTRL_X_OMNI or CTRL_X_FUNCTION or CTRL_X_THESAURUS. @@ -2269,8 +2390,10 @@ expand_by_function(int type, char_u *base) typval_T args[3]; char_u *funcname; pos_T pos; + callback_T *cb; typval_T rettv; int save_State = State; + int retval; funcname = get_complete_funcname(type); if (*funcname == NUL) @@ -2289,8 +2412,11 @@ expand_by_function(int type, char_u *base) // Insert mode in another buffer. ++textwinlock; + cb = get_insert_callback(type); + retval = call_callback(cb, 0, &rettv, 2, args); + // 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) { @@ -3971,6 +4097,7 @@ ins_complete(int c, int enable_pum) char_u *funcname; pos_T pos; int save_State = State; + callback_T *cb; // Call 'completefunc' or 'omnifunc' and get pattern length as a // string @@ -3991,7 +4118,8 @@ ins_complete(int c, int enable_pum) args[2].v_type = VAR_UNKNOWN; pos = curwin->w_cursor; ++textwinlock; - col = call_func_retnr(funcname, 2, args); + cb = get_insert_callback(ctrl_x_mode); + col = call_callback_retnr(cb, 2, args); --textwinlock; State = save_State; @@ -4339,6 +4467,11 @@ quote_meta(char_u *dest, char_u *src, int len) free_insexpand_stuff(void) { VIM_CLEAR(compl_orig_text); +# ifdef FEAT_EVAL + free_callback(&cfu_cb); + free_callback(&ofu_cb); + free_callback(&tsrfu_cb); +# endif } #endif |