summaryrefslogtreecommitdiffstats
path: root/src/insexpand.c
diff options
context:
space:
mode:
authorYegappan Lakshmanan <yegappan@yahoo.com>2021-12-03 11:09:29 +0000
committerBram Moolenaar <Bram@vim.org>2021-12-03 11:09:29 +0000
commit8658c759f05b317707d56e3b65a5ef63930c7498 (patch)
tree124fcda187b5515dfaeba4c86aa7a5e0f0888686 /src/insexpand.c
parent021ef351c2127cf8aa5668a881435a0a12774644 (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.c137
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