patch 9.1.0831: 'findexpr' can't be used as lambad or Funcref
Problem: 'findexpr' can't be used for lambads
(Justin Keyes)
Solution: Replace the findexpr option with the findfunc option
(Yegappan Lakshmanan)
related: #15905
closes: #15976
Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/src/buffer.c b/src/buffer.c
index f1e1330..3b05f25 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -2412,7 +2412,6 @@
clear_string_option(&buf->b_p_fp);
#if defined(FEAT_EVAL)
clear_string_option(&buf->b_p_fex);
- clear_string_option(&buf->b_p_fexpr);
#endif
#ifdef FEAT_CRYPT
# ifdef FEAT_SODIUM
@@ -2485,6 +2484,8 @@
#ifdef FEAT_EVAL
clear_string_option(&buf->b_p_tfu);
free_callback(&buf->b_tfu_cb);
+ clear_string_option(&buf->b_p_ffu);
+ free_callback(&buf->b_ffu_cb);
#endif
clear_string_option(&buf->b_p_dict);
clear_string_option(&buf->b_p_tsr);
diff --git a/src/cmdexpand.c b/src/cmdexpand.c
index 3862d69..7e53114 100644
--- a/src/cmdexpand.c
+++ b/src/cmdexpand.c
@@ -50,7 +50,7 @@
&& xp->xp_context != EXPAND_FILES
&& xp->xp_context != EXPAND_FILES_IN_PATH
&& xp->xp_context != EXPAND_FILETYPE
- && xp->xp_context != EXPAND_FINDEXPR
+ && xp->xp_context != EXPAND_FINDFUNC
&& xp->xp_context != EXPAND_HELP
&& xp->xp_context != EXPAND_KEYMAP
&& xp->xp_context != EXPAND_OLD_SETTING
@@ -1419,7 +1419,7 @@
// For help tags the translation is done in find_help_tags().
// For a tag pattern starting with "/" no translation is needed.
- if (context == EXPAND_FINDEXPR
+ if (context == EXPAND_FINDFUNC
|| context == EXPAND_HELP
|| context == EXPAND_COLORS
|| context == EXPAND_COMPILER
@@ -2140,7 +2140,7 @@
case CMD_sfind:
case CMD_tabfind:
if (xp->xp_context == EXPAND_FILES)
- xp->xp_context = *get_findexpr() != NUL ? EXPAND_FINDEXPR
+ xp->xp_context = *get_findfunc() != NUL ? EXPAND_FINDFUNC
: EXPAND_FILES_IN_PATH;
break;
case CMD_cd:
@@ -2853,10 +2853,10 @@
}
}
- if (xp->xp_context == EXPAND_FINDEXPR)
+ if (xp->xp_context == EXPAND_FINDFUNC)
{
#ifdef FEAT_EVAL
- ret = expand_findexpr(pat, matches, numMatches);
+ ret = expand_findfunc(pat, matches, numMatches);
#endif
}
else
@@ -3122,7 +3122,7 @@
if (xp->xp_context == EXPAND_FILES
|| xp->xp_context == EXPAND_DIRECTORIES
|| xp->xp_context == EXPAND_FILES_IN_PATH
- || xp->xp_context == EXPAND_FINDEXPR
+ || xp->xp_context == EXPAND_FINDFUNC
|| xp->xp_context == EXPAND_DIRS_IN_CDPATH)
return expand_files_and_dirs(xp, pat, matches, numMatches, flags,
options);
diff --git a/src/errors.h b/src/errors.h
index 6c172e0..1e59597 100644
--- a/src/errors.h
+++ b/src/errors.h
@@ -3652,5 +3652,5 @@
INIT(= N_("E1512: Wrong character width for field \"%s\""));
EXTERN char e_winfixbuf_cannot_go_to_buffer[]
INIT(= N_("E1513: Cannot switch buffer. 'winfixbuf' is enabled"));
-EXTERN char e_invalid_return_type_from_findexpr[]
- INIT(= N_("E1514: 'findexpr' did not return a List type"));
+EXTERN char e_invalid_return_type_from_findfunc[]
+ INIT(= N_("E1514: 'findfunc' did not return a List type"));
diff --git a/src/evalbuffer.c b/src/evalbuffer.c
index 6ec734d..cefd642 100644
--- a/src/evalbuffer.c
+++ b/src/evalbuffer.c
@@ -45,6 +45,8 @@
#endif
if (!abort)
abort = abort || set_ref_in_callback(&bp->b_tfu_cb, copyID);
+ if (!abort)
+ abort = abort || set_ref_in_callback(&bp->b_ffu_cb, copyID);
if (abort)
break;
}
diff --git a/src/evalvars.c b/src/evalvars.c
index 9f03ada..038d7ed 100644
--- a/src/evalvars.c
+++ b/src/evalvars.c
@@ -160,8 +160,7 @@
{VV_NAME("python3_version", VAR_NUMBER), NULL, VV_RO},
{VV_NAME("t_typealias", VAR_NUMBER), NULL, VV_RO},
{VV_NAME("t_enum", VAR_NUMBER), NULL, VV_RO},
- {VV_NAME("t_enumvalue", VAR_NUMBER), NULL, VV_RO},
- {VV_NAME("cmdcomplete", VAR_BOOL), NULL, VV_RO},
+ {VV_NAME("t_enumvalue", VAR_NUMBER), NULL, VV_RO}
};
// shorthand
@@ -235,7 +234,6 @@
set_vim_var_nr(VV_SEARCHFORWARD, 1L);
set_vim_var_nr(VV_HLSEARCH, 1L);
set_vim_var_nr(VV_EXITING, VVAL_NULL);
- set_vim_var_nr(VV_CMDCOMPLETE, VVAL_FALSE);
set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc_lock(VAR_FIXED));
set_vim_var_list(VV_ERRORS, list_alloc());
set_vim_var_dict(VV_EVENT, dict_alloc_lock(VAR_FIXED));
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index d60e344..380bd23 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -6924,58 +6924,71 @@
}
#if defined(FEAT_EVAL) || defined(PROTO)
-/*
- * Evaluate the 'findexpr' expression and return the result. When evaluating
- * the expression, v:fname is set to the ":find" command argument.
- */
- static list_T *
-eval_findexpr(char_u *pat, int cmdcomplete)
+
+// callback function for 'findfunc'
+static callback_T ffu_cb;
+
+ static callback_T *
+get_findfunc_callback(void)
{
+ return *curbuf->b_p_ffu != NUL ? &curbuf->b_ffu_cb : &ffu_cb;
+}
+
+ static list_T *
+call_findfunc(char_u *pat, int cmdcomplete)
+{
+ typval_T args[3];
+ callback_T *cb;
+ typval_T rettv;
+ int retval;
sctx_T saved_sctx = current_sctx;
- char_u *findexpr;
- char_u *arg;
- typval_T tv;
- list_T *retlist = NULL;
+ sctx_T *ctx;
- findexpr = get_findexpr();
+ // Call 'findfunc' to obtain the list of file names.
+ args[0].v_type = VAR_STRING;
+ args[0].vval.v_string = pat;
+ args[1].v_type = VAR_BOOL;
+ args[1].vval.v_number = cmdcomplete;
+ args[2].v_type = VAR_UNKNOWN;
- set_vim_var_string(VV_FNAME, pat, -1);
- set_vim_var_nr(VV_CMDCOMPLETE, cmdcomplete ? VVAL_TRUE : VVAL_FALSE);
- current_sctx = curbuf->b_p_script_ctx[BV_FEXPR];
-
- arg = skipwhite(findexpr);
-
+ // Lock the text to prevent weird things from happening. Also disallow
+ // switching to another window, it should not be needed and may end up in
+ // Insert mode in another buffer.
++textlock;
- // Evaluate the expression. If the expression is "FuncName()" call the
- // function directly.
- if (eval0_simple_funccal(arg, &tv, NULL, &EVALARG_EVALUATE) == FAIL)
- retlist = NULL;
- else
- {
- if (tv.v_type == VAR_LIST)
- retlist = list_copy(tv.vval.v_list, TRUE, TRUE, get_copyID());
- else
- emsg(_(e_invalid_return_type_from_findexpr));
- clear_tv(&tv);
- }
- --textlock;
- clear_evalarg(&EVALARG_EVALUATE, NULL);
+ ctx = get_option_sctx("findfunc");
+ if (ctx != NULL)
+ current_sctx = *ctx;
- set_vim_var_string(VV_FNAME, NULL, 0);
- set_vim_var_nr(VV_CMDCOMPLETE, VVAL_FALSE);
+ cb = get_findfunc_callback();
+ retval = call_callback(cb, -1, &rettv, 2, args);
+
current_sctx = saved_sctx;
+ --textlock;
+
+ list_T *retlist = NULL;
+
+ if (retval == OK)
+ {
+ if (rettv.v_type == VAR_LIST)
+ retlist = list_copy(rettv.vval.v_list, FALSE, FALSE, get_copyID());
+ else
+ emsg(_(e_invalid_return_type_from_findfunc));
+
+ clear_tv(&rettv);
+ }
+
return retlist;
}
/*
- * Find file names matching "pat" using 'findexpr' and return it in "files".
+ * Find file names matching "pat" using 'findfunc' and return it in "files".
* Used for expanding the :find, :sfind and :tabfind command argument.
* Returns OK on success and FAIL otherwise.
*/
int
-expand_findexpr(char_u *pat, char_u ***files, int *numMatches)
+expand_findfunc(char_u *pat, char_u ***files, int *numMatches)
{
list_T *l;
int len;
@@ -6983,7 +6996,7 @@
*numMatches = 0;
*files = NULL;
- l = eval_findexpr(pat, TRUE);
+ l = call_findfunc(pat, VVAL_TRUE);
if (l == NULL)
return FAIL;
@@ -7015,11 +7028,11 @@
}
/*
- * Use 'findexpr' to find file 'findarg'. The 'count' argument is used to find
+ * Use 'findfunc' to find file 'findarg'. The 'count' argument is used to find
* the n'th matching file.
*/
static char_u *
-findexpr_find_file(char_u *findarg, int findarg_len, int count)
+findfunc_find_file(char_u *findarg, int findarg_len, int count)
{
list_T *fname_list;
char_u *ret_fname = NULL;
@@ -7029,7 +7042,7 @@
cc = findarg[findarg_len];
findarg[findarg_len] = NUL;
- fname_list = eval_findexpr(findarg, FALSE);
+ fname_list = call_findfunc(findarg, VVAL_FALSE);
fname_count = list_len(fname_list);
if (fname_count == 0)
@@ -7053,6 +7066,62 @@
return ret_fname;
}
+
+/*
+ * Process the 'findfunc' option value.
+ * Returns NULL on success and an error message on failure.
+ */
+ char *
+did_set_findfunc(optset_T *args UNUSED)
+{
+ int retval;
+
+ if (*curbuf->b_p_ffu != NUL)
+ {
+ // buffer-local option set
+ retval = option_set_callback_func(curbuf->b_p_ffu, &curbuf->b_ffu_cb);
+ }
+ else
+ {
+ // global option set
+ retval = option_set_callback_func(p_ffu, &ffu_cb);
+ }
+
+ if (retval == FAIL)
+ return e_invalid_argument;
+
+ // If the option value starts with <SID> or s:, then replace that with
+ // the script identifier.
+ char_u **varp = (char_u **)args->os_varp;
+ char_u *name = get_scriptlocal_funcname(*varp);
+ if (name != NULL)
+ {
+ free_string_option(*varp);
+ *varp = name;
+ }
+
+ return NULL;
+}
+
+# if defined(EXITFREE) || defined(PROTO)
+ void
+free_findfunc_option(void)
+{
+ free_callback(&ffu_cb);
+}
+# endif
+
+/*
+ * Mark the global 'findfunc' callback with "copyID" so that it is not
+ * garbage collected.
+ */
+ int
+set_ref_in_findfunc(int copyID UNUSED)
+{
+ int abort = FALSE;
+ abort = set_ref_in_callback(&ffu_cb, copyID);
+ return abort;
+}
#endif
/*
@@ -7105,10 +7174,10 @@
char_u *file_to_find = NULL;
char *search_ctx = NULL;
- if (*get_findexpr() != NUL)
+ if (*get_findfunc() != NUL)
{
#ifdef FEAT_EVAL
- fname = findexpr_find_file(eap->arg, (int)STRLEN(eap->arg),
+ fname = findfunc_find_file(eap->arg, (int)STRLEN(eap->arg),
eap->addr_count > 0 ? eap->line2 : 1);
#endif
}
@@ -7389,10 +7458,10 @@
char_u *file_to_find = NULL;
char *search_ctx = NULL;
- if (*get_findexpr() != NUL)
+ if (*get_findfunc() != NUL)
{
#ifdef FEAT_EVAL
- fname = findexpr_find_file(eap->arg, (int)STRLEN(eap->arg),
+ fname = findfunc_find_file(eap->arg, (int)STRLEN(eap->arg),
eap->addr_count > 0 ? eap->line2 : 1);
#endif
}
diff --git a/src/gc.c b/src/gc.c
index 987ca27..54c7444 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -183,6 +183,9 @@
// 'imactivatefunc' and 'imstatusfunc' callbacks
abort = abort || set_ref_in_im_funcs(copyID);
+ // 'findfunc' callback
+ abort = abort || set_ref_in_findfunc(copyID);
+
#ifdef FEAT_LUA
abort = abort || set_ref_in_lua(copyID);
#endif
diff --git a/src/option.c b/src/option.c
index f408fb9..dcb5752 100644
--- a/src/option.c
+++ b/src/option.c
@@ -1014,6 +1014,9 @@
}
free_operatorfunc_option();
free_tagfunc_option();
+# if defined(FEAT_EVAL)
+ free_findfunc_option();
+# endif
}
#endif
@@ -6372,8 +6375,8 @@
clear_string_option(&buf->b_p_fp);
break;
# ifdef FEAT_EVAL
- case PV_FEXPR:
- clear_string_option(&buf->b_p_fexpr);
+ case PV_FFU:
+ clear_string_option(&buf->b_p_ffu);
break;
# endif
# ifdef FEAT_QUICKFIX
@@ -6455,7 +6458,7 @@
{
case PV_FP: return (char_u *)&(curbuf->b_p_fp);
#ifdef FEAT_EVAL
- case PV_FEXPR: return (char_u *)&(curbuf->b_p_fexpr);
+ case PV_FFU: return (char_u *)&(curbuf->b_p_ffu);
#endif
#ifdef FEAT_QUICKFIX
case PV_EFM: return (char_u *)&(curbuf->b_p_efm);
@@ -6568,8 +6571,8 @@
case PV_FP: return *curbuf->b_p_fp != NUL
? (char_u *)&(curbuf->b_p_fp) : p->var;
#ifdef FEAT_EVAL
- case PV_FEXPR: return *curbuf->b_p_fexpr != NUL
- ? (char_u *)&curbuf->b_p_fexpr : p->var;
+ case PV_FFU: return *curbuf->b_p_ffu != NUL
+ ? (char_u *)&(curbuf->b_p_ffu) : p->var;
#endif
#ifdef FEAT_QUICKFIX
case PV_EFM: return *curbuf->b_p_efm != NUL
@@ -6818,15 +6821,15 @@
}
/*
- * Get the value of 'findexpr', either the buffer-local one or the global one.
+ * Get the value of 'findfunc', either the buffer-local one or the global one.
*/
char_u *
-get_findexpr(void)
+get_findfunc(void)
{
#ifdef FEAT_EVAL
- if (*curbuf->b_p_fexpr == NUL)
- return p_fexpr;
- return curbuf->b_p_fexpr;
+ if (*curbuf->b_p_ffu == NUL)
+ return p_ffu;
+ return curbuf->b_p_ffu;
#else
return (char_u *)"";
#endif
@@ -7361,8 +7364,7 @@
#endif
buf->b_p_ep = empty_option;
#if defined(FEAT_EVAL)
- buf->b_p_fexpr = vim_strsave(p_fexpr);
- COPY_OPT_SCTX(buf, BV_FEXPR);
+ buf->b_p_ffu = empty_option;
#endif
buf->b_p_kp = empty_option;
buf->b_p_path = empty_option;
@@ -8749,6 +8751,7 @@
#ifdef FEAT_EVAL
typval_T *tv;
callback_T cb;
+ int funcname = FALSE;
if (optval == NULL || *optval == NUL)
{
@@ -8762,8 +8765,11 @@
// Lambda expression or a funcref
tv = eval_expr(optval, NULL);
else
+ {
// treat everything else as a function name string
tv = alloc_string_tv(vim_strsave(optval));
+ funcname = TRUE;
+ }
if (tv == NULL)
return FAIL;
@@ -8780,6 +8786,16 @@
vim_free(cb.cb_name);
free_tv(tv);
+ if (in_vim9script() && funcname && (vim_strchr(optval, '.') != NULL))
+ {
+ // When a Vim9 imported function name is used, it is expanded by the
+ // call to get_callback() above to <SNR>_funcname. Revert the name to
+ // back to "import.funcname".
+ if (optcb->cb_free_name)
+ vim_free(optcb->cb_name);
+ optcb->cb_name = vim_strsave(optval);
+ optcb->cb_free_name = TRUE;
+ }
// when using Vim9 style "import.funcname" it needs to be expanded to
// "import#funcname".
expand_autload_callback(optcb);
diff --git a/src/option.h b/src/option.h
index 641514d..d5f72a1 100644
--- a/src/option.h
+++ b/src/option.h
@@ -597,7 +597,7 @@
EXTERN char_u *p_ft; // 'filetype'
EXTERN char_u *p_fcs; // 'fillchar'
#ifdef FEAT_EVAL
-EXTERN char_u *p_fexpr; // 'findexpr'
+EXTERN char_u *p_ffu; // 'findfunc'
#endif
EXTERN int p_fixeol; // 'fixendofline'
#ifdef FEAT_FOLDING
@@ -1171,11 +1171,11 @@
, BV_EP
, BV_ET
, BV_FENC
- , BV_FEXPR
, BV_FP
#ifdef FEAT_EVAL
, BV_BEXPR
, BV_FEX
+ , BV_FFU
#endif
, BV_FF
, BV_FLP
diff --git a/src/optiondefs.h b/src/optiondefs.h
index 96c30e2..97fc4d4 100644
--- a/src/optiondefs.h
+++ b/src/optiondefs.h
@@ -54,6 +54,7 @@
#define PV_CPT OPT_BUF(BV_CPT)
#define PV_DICT OPT_BOTH(OPT_BUF(BV_DICT))
#define PV_TSR OPT_BOTH(OPT_BUF(BV_TSR))
+#define PV_FFU OPT_BOTH(OPT_BUF(BV_FFU))
#define PV_CSL OPT_BUF(BV_CSL)
#ifdef FEAT_COMPL_FUNC
# define PV_CFU OPT_BUF(BV_CFU)
@@ -74,7 +75,6 @@
#define PV_FP OPT_BOTH(OPT_BUF(BV_FP))
#ifdef FEAT_EVAL
# define PV_FEX OPT_BUF(BV_FEX)
-# define PV_FEXPR OPT_BOTH(OPT_BUF(BV_FEXPR))
#endif
#define PV_FF OPT_BUF(BV_FF)
#define PV_FLP OPT_BUF(BV_FLP)
@@ -959,9 +959,10 @@
{(char_u *)"vert:|,fold:-,eob:~,lastline:@",
(char_u *)0L}
SCTX_INIT},
- {"findexpr", "fexpr", P_STRING|P_ALLOCED|P_VI_DEF|P_VIM|P_SECURE,
-#if defined(FEAT_EVAL)
- (char_u *)&p_fexpr, PV_FEXPR, did_set_optexpr, NULL,
+ {"findfunc", "ffu", P_STRING|P_ALLOCED|P_VI_DEF|P_SECURE|P_FUNC,
+#ifdef FEAT_EVAL
+ (char_u *)&p_ffu, PV_FFU,
+ did_set_findfunc, NULL,
{(char_u *)"", (char_u *)0L}
#else
(char_u *)NULL, PV_NONE, NULL, NULL,
diff --git a/src/optionstr.c b/src/optionstr.c
index d82b8e1..0554c0e 100644
--- a/src/optionstr.c
+++ b/src/optionstr.c
@@ -313,6 +313,7 @@
check_string_option(&buf->b_p_tsrfu);
#endif
#ifdef FEAT_EVAL
+ check_string_option(&buf->b_p_ffu);
check_string_option(&buf->b_p_tfu);
#endif
#ifdef FEAT_KEYMAP
@@ -324,9 +325,6 @@
check_string_option(&buf->b_p_efm);
#endif
check_string_option(&buf->b_p_ep);
-#ifdef FEAT_EVAL
- check_string_option(&buf->b_p_fexpr);
-#endif
check_string_option(&buf->b_p_path);
check_string_option(&buf->b_p_tags);
check_string_option(&buf->b_p_tc);
@@ -3135,9 +3133,8 @@
#if defined(FEAT_EVAL) || defined(PROTO)
/*
* One of the '*expr' options is changed: 'balloonexpr', 'diffexpr',
- * 'findexpr', 'foldexpr', 'foldtext', 'formatexpr', 'includeexpr',
- * 'indentexpr', 'patchexpr', 'printexpr' and 'charconvert'.
- *
+ * 'foldexpr', 'foldtext', 'formatexpr', 'includeexpr', 'indentexpr',
+ * 'patchexpr', 'printexpr' and 'charconvert'.
*/
char *
did_set_optexpr(optset_T *args)
diff --git a/src/proto/ex_docmd.pro b/src/proto/ex_docmd.pro
index d3f1a4e..7b837c9 100644
--- a/src/proto/ex_docmd.pro
+++ b/src/proto/ex_docmd.pro
@@ -46,7 +46,10 @@
void ex_stop(exarg_T *eap);
void handle_drop(int filec, char_u **filev, int split, void (*callback)(void *), void *cookie);
void handle_any_postponed_drop(void);
-int expand_findexpr(char_u *pat, char_u ***files, int *numMatches);
+int expand_findfunc(char_u *pat, char_u ***files, int *numMatches);
+char *did_set_findfunc(optset_T *args);
+void free_findfunc_option(void);
+int set_ref_in_findfunc(int copyID);
void ex_splitview(exarg_T *eap);
void tabpage_new(void);
void do_exedit(exarg_T *eap, win_T *old_curwin);
diff --git a/src/proto/option.pro b/src/proto/option.pro
index fce9199..83f32aa 100644
--- a/src/proto/option.pro
+++ b/src/proto/option.pro
@@ -120,7 +120,7 @@
char_u *get_option_fullname(int opt_idx);
opt_did_set_cb_T get_option_did_set_cb(int opt_idx);
char_u *get_equalprg(void);
-char_u *get_findexpr(void);
+char_u *get_findfunc(void);
void win_copy_options(win_T *wp_from, win_T *wp_to);
void after_copy_winopt(win_T *wp);
void copy_winopt(winopt_T *from, winopt_T *to);
diff --git a/src/structs.h b/src/structs.h
index 33367f0..47999a9 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -3248,6 +3248,8 @@
#ifdef FEAT_EVAL
char_u *b_p_tfu; // 'tagfunc' option value
callback_T b_tfu_cb; // 'tagfunc' callback
+ char_u *b_p_ffu; // 'findfunc' option value
+ callback_T b_ffu_cb; // 'findfunc' callback
#endif
int b_p_eof; // 'endoffile'
int b_p_eol; // 'endofline'
@@ -3334,9 +3336,6 @@
char_u *b_p_efm; // 'errorformat' local value
#endif
char_u *b_p_ep; // 'equalprg' local value
-#ifdef FEAT_EVAL
- char_u *b_p_fexpr; // 'findexpr' local value
-#endif
char_u *b_p_path; // 'path' local value
int b_p_ar; // 'autoread' local value
char_u *b_p_tags; // 'tags' local value
diff --git a/src/testdir/test_findfile.vim b/src/testdir/test_findfile.vim
index 25cd9da..4db5850 100644
--- a/src/testdir/test_findfile.vim
+++ b/src/testdir/test_findfile.vim
@@ -1,6 +1,7 @@
" Test findfile() and finddir()
source check.vim
+import './vim9.vim' as v9
let s:files = [ 'Xfinddir1/foo',
\ 'Xfinddir1/bar',
@@ -283,223 +284,491 @@
let &path = save_path
endfunc
-" Test for 'findexpr'
-func Test_findexpr()
+" Test for 'findfunc'
+func Test_findfunc()
CheckUnix
- call assert_equal('', &findexpr)
- call writefile(['aFile'], 'Xfindexpr1.c', 'D')
- call writefile(['bFile'], 'Xfindexpr2.c', 'D')
- call writefile(['cFile'], 'Xfindexpr3.c', 'D')
+ call assert_equal('', &findfunc)
+ call writefile(['aFile'], 'Xfindfunc1.c', 'D')
+ call writefile(['bFile'], 'Xfindfunc2.c', 'D')
+ call writefile(['cFile'], 'Xfindfunc3.c', 'D')
" basic tests
- func FindExpr1()
- let fnames = ['Xfindexpr1.c', 'Xfindexpr2.c', 'Xfindexpr3.c']
- return fnames->copy()->filter('v:val =~? v:fname')
+ func FindFuncBasic(pat, cmdcomplete)
+ let fnames = ['Xfindfunc1.c', 'Xfindfunc2.c', 'Xfindfunc3.c']
+ return fnames->copy()->filter('v:val =~? a:pat')
endfunc
- set findexpr=FindExpr1()
- find Xfindexpr3
- call assert_match('Xfindexpr3.c', @%)
+ set findfunc=FindFuncBasic
+ find Xfindfunc3
+ call assert_match('Xfindfunc3.c', @%)
bw!
2find Xfind
- call assert_match('Xfindexpr2.c', @%)
+ call assert_match('Xfindfunc2.c', @%)
bw!
call assert_fails('4find Xfind', 'E347: No more file "Xfind" found in path')
call assert_fails('find foobar', 'E345: Can''t find file "foobar" in path')
- sfind Xfindexpr2.c
- call assert_match('Xfindexpr2.c', @%)
+ sfind Xfindfunc2.c
+ call assert_match('Xfindfunc2.c', @%)
call assert_equal(2, winnr('$'))
%bw!
call assert_fails('sfind foobar', 'E345: Can''t find file "foobar" in path')
- tabfind Xfindexpr3.c
- call assert_match('Xfindexpr3.c', @%)
+ tabfind Xfindfunc3.c
+ call assert_match('Xfindfunc3.c', @%)
call assert_equal(2, tabpagenr())
%bw!
call assert_fails('tabfind foobar', 'E345: Can''t find file "foobar" in path')
+ " Test garbage collection
+ call test_garbagecollect_now()
+ find Xfindfunc2
+ call assert_match('Xfindfunc2.c', @%)
+ bw!
+ delfunc FindFuncBasic
+ call test_garbagecollect_now()
+ call assert_fails('find Xfindfunc2', 'E117: Unknown function: FindFuncBasic')
+
" Buffer-local option
- set findexpr=['abc']
+ func GlobalFindFunc(pat, cmdcomplete)
+ return ['global']
+ endfunc
+ func LocalFindFunc(pat, cmdcomplete)
+ return ['local']
+ endfunc
+ set findfunc=GlobalFindFunc
new
- setlocal findexpr=['def']
+ setlocal findfunc=LocalFindFunc
find xxxx
- call assert_equal('def', @%)
+ call assert_equal('local', @%)
wincmd w
find xxxx
- call assert_equal('abc', @%)
+ call assert_equal('global', @%)
aboveleft new
- call assert_equal("['abc']", &findexpr)
+ call assert_equal("GlobalFindFunc", &findfunc)
wincmd k
aboveleft new
- call assert_equal("['abc']", &findexpr)
+ call assert_equal("GlobalFindFunc", &findfunc)
%bw!
+ delfunc GlobalFindFunc
+ delfunc LocalFindFunc
- " Empty list
- set findexpr=[]
- call assert_fails('find xxxx', 'E345: Can''t find file "xxxx" in path')
+ " Assign an expression
+ set findfunc=[]
+ call assert_fails('find xxxx', 'E117: Unknown function: []')
" Error cases
- " Syntax error in the expression
- set findexpr=FindExpr1{}
- call assert_fails('find Xfindexpr1.c', 'E15: Invalid expression')
+ " Function that doesn't any argument
+ func FindFuncNoArg()
+ endfunc
+ set findfunc=FindFuncNoArg
+ call assert_fails('find Xfindfunc1.c', 'E118: Too many arguments for function: FindFuncNoArg')
+ delfunc FindFuncNoArg
- " Find expression throws an error
- func FindExpr2()
+ " Syntax error in the function
+ func FindFuncSyntaxError(pat, cmdcomplete)
+ return l
+ endfunc
+ set findfunc=FindFuncSyntaxError
+ call assert_fails('find Xfindfunc1.c', 'E121: Undefined variable: l')
+ delfunc FindFuncSyntaxError
+
+ " Find function throws an error
+ func FindFuncWithThrow(pat, cmdcomplete)
throw 'find error'
endfunc
- set findexpr=FindExpr2()
- call assert_fails('find Xfindexpr1.c', 'find error')
+ set findfunc=FindFuncWithThrow
+ call assert_fails('find Xfindfunc1.c', 'find error')
+ delfunc FindFuncWithThrow
- " Try using a null List as the expression
- set findexpr=test_null_list()
- call assert_fails('find Xfindexpr1.c', 'E345: Can''t find file "Xfindexpr1.c" in path')
+ " Try using a null function
+ call assert_fails('let &findfunc = test_null_function()', 'E129: Function name required')
- " Try to create a new window from the find expression
- func FindExpr3()
+ " Try to create a new window from the find function
+ func FindFuncNewWindow(pat, cmdexpand)
new
return ["foo"]
endfunc
- set findexpr=FindExpr3()
- call assert_fails('find Xfindexpr1.c', 'E565: Not allowed to change text or change window')
+ set findfunc=FindFuncNewWindow
+ call assert_fails('find Xfindfunc1.c', 'E565: Not allowed to change text or change window')
+ delfunc FindFuncNewWindow
- " Try to modify the current buffer from the find expression
- func FindExpr4()
+ " Try to modify the current buffer from the find function
+ func FindFuncModifyBuf(pat, cmdexpand)
call setline(1, ['abc'])
return ["foo"]
endfunc
- set findexpr=FindExpr4()
- call assert_fails('find Xfindexpr1.c', 'E565: Not allowed to change text or change window')
+ set findfunc=FindFuncModifyBuf
+ call assert_fails('find Xfindfunc1.c', 'E565: Not allowed to change text or change window')
+ delfunc FindFuncModifyBuf
- " Expression returning a string
- set findexpr='abc'
- call assert_fails('find Xfindexpr1.c', "E1514: 'findexpr' did not return a List type")
+ " Return the wrong type from the function
+ func FindFuncWrongRet(pat, cmdexpand)
+ return 'foo'
+ endfunc
+ set findfunc=FindFuncWrongRet
+ call assert_fails('find Xfindfunc1.c', "E1514: 'findfunc' did not return a List type")
+ delfunc FindFuncWrongRet
- set findexpr&
- delfunc! FindExpr1
- delfunc! FindExpr2
- delfunc! FindExpr3
- delfunc! FindExpr4
+ set findfunc&
endfunc
-" Test for using a script-local function for 'findexpr'
-func Test_findexpr_scriptlocal_func()
- func! s:FindExprScript()
- let g:FindExprArg = v:fname
+" Test for using a script-local function for 'findfunc'
+func Test_findfunc_scriptlocal_func()
+ func! s:FindFuncScript(pat, cmdexpand)
+ let g:FindFuncArg = a:pat
return ['xxx']
endfunc
- set findexpr=s:FindExprScript()
- call assert_equal(expand('<SID>') .. 'FindExprScript()', &findexpr)
- call assert_equal(expand('<SID>') .. 'FindExprScript()', &g:findexpr)
+ set findfunc=s:FindFuncScript
+ call assert_equal(expand('<SID>') .. 'FindFuncScript', &findfunc)
+ call assert_equal(expand('<SID>') .. 'FindFuncScript', &g:findfunc)
new | only
- let g:FindExprArg = ''
+ let g:FindFuncArg = ''
find abc
- call assert_equal('abc', g:FindExprArg)
+ call assert_equal('abc', g:FindFuncArg)
bw!
- set findexpr=<SID>FindExprScript()
- call assert_equal(expand('<SID>') .. 'FindExprScript()', &findexpr)
- call assert_equal(expand('<SID>') .. 'FindExprScript()', &g:findexpr)
+ set findfunc=<SID>FindFuncScript
+ call assert_equal(expand('<SID>') .. 'FindFuncScript', &findfunc)
+ call assert_equal(expand('<SID>') .. 'FindFuncScript', &g:findfunc)
new | only
- let g:FindExprArg = ''
+ let g:FindFuncArg = ''
find abc
- call assert_equal('abc', g:FindExprArg)
+ call assert_equal('abc', g:FindFuncArg)
bw!
- let &findexpr = 's:FindExprScript()'
- call assert_equal(expand('<SID>') .. 'FindExprScript()', &g:findexpr)
+ let &findfunc = 's:FindFuncScript'
+ call assert_equal(expand('<SID>') .. 'FindFuncScript', &g:findfunc)
new | only
- let g:FindExprArg = ''
+ let g:FindFuncArg = ''
find abc
- call assert_equal('abc', g:FindExprArg)
+ call assert_equal('abc', g:FindFuncArg)
bw!
- let &findexpr = '<SID>FindExprScript()'
- call assert_equal(expand('<SID>') .. 'FindExprScript()', &g:findexpr)
+ let &findfunc = '<SID>FindFuncScript'
+ call assert_equal(expand('<SID>') .. 'FindFuncScript', &g:findfunc)
new | only
- let g:FindExprArg = ''
+ let g:FindFuncArg = ''
find abc
- call assert_equal('abc', g:FindExprArg)
+ call assert_equal('abc', g:FindFuncArg)
bw!
- set findexpr=
- setglobal findexpr=s:FindExprScript()
- setlocal findexpr=
- call assert_equal(expand('<SID>') .. 'FindExprScript()', &findexpr)
- call assert_equal(expand('<SID>') .. 'FindExprScript()', &g:findexpr)
- call assert_equal('', &l:findexpr)
+ set findfunc=
+ setglobal findfunc=s:FindFuncScript
+ setlocal findfunc=
+ call assert_equal(expand('<SID>') .. 'FindFuncScript', &findfunc)
+ call assert_equal(expand('<SID>') .. 'FindFuncScript', &g:findfunc)
+ call assert_equal('', &l:findfunc)
new | only
- let g:FindExprArg = ''
+ let g:FindFuncArg = ''
find abc
- call assert_equal('abc', g:FindExprArg)
+ call assert_equal('abc', g:FindFuncArg)
bw!
new | only
- set findexpr=
- setglobal findexpr=
- setlocal findexpr=s:FindExprScript()
- call assert_equal(expand('<SID>') .. 'FindExprScript()', &findexpr)
- call assert_equal(expand('<SID>') .. 'FindExprScript()', &l:findexpr)
- call assert_equal('', &g:findexpr)
- let g:FindExprArg = ''
+ set findfunc=
+ setglobal findfunc=
+ setlocal findfunc=s:FindFuncScript
+ call assert_equal(expand('<SID>') .. 'FindFuncScript', &findfunc)
+ call assert_equal(expand('<SID>') .. 'FindFuncScript', &l:findfunc)
+ call assert_equal('', &g:findfunc)
+ let g:FindFuncArg = ''
find abc
- call assert_equal('abc', g:FindExprArg)
+ call assert_equal('abc', g:FindFuncArg)
bw!
- set findexpr=
- delfunc s:FindExprScript
+ set findfunc=
+ delfunc s:FindFuncScript
endfunc
-" Test for expanding the argument to the :find command using 'findexpr'
-func Test_findexpr_expand_arg()
- let s:fnames = ['Xfindexpr1.c', 'Xfindexpr2.c', 'Xfindexpr3.c']
+" Test for expanding the argument to the :find command using 'findfunc'
+func Test_findfunc_expand_arg()
+ let s:fnames = ['Xfindfunc1.c', 'Xfindfunc2.c', 'Xfindfunc3.c']
- " 'findexpr' that accepts a regular expression
- func FindExprRegexp()
- return s:fnames->copy()->filter('v:val =~? v:fname')
+ " 'findfunc' that accepts a regular expression
+ func FindFuncRegexp(pat, cmdcomplete)
+ return s:fnames->copy()->filter('v:val =~? a:pat')
endfunc
- " 'findexpr' that accepts a glob
- func FindExprGlob()
- let pat = glob2regpat(v:cmdcomplete ? $'*{v:fname}*' : v:fname)
+ " 'findfunc' that accepts a glob
+ func FindFuncGlob(pat_arg, cmdcomplete)
+ let pat = glob2regpat(a:cmdcomplete ? $'*{a:pat_arg}*' : a:pat_arg)
return s:fnames->copy()->filter('v:val =~? pat')
endfunc
for regexp in [v:true, v:false]
- let &findexpr = regexp ? 'FindExprRegexp()' : 'FindExprGlob()'
+ let &findfunc = regexp ? 'FindFuncRegexp' : 'FindFuncGlob'
call feedkeys(":find \<Tab>\<C-B>\"\<CR>", "xt")
- call assert_equal('"find Xfindexpr1.c', @:)
+ call assert_equal('"find Xfindfunc1.c', @:)
call feedkeys(":find Xfind\<Tab>\<Tab>\<C-B>\"\<CR>", "xt")
- call assert_equal('"find Xfindexpr2.c', @:)
+ call assert_equal('"find Xfindfunc2.c', @:)
call assert_equal(s:fnames, getcompletion('find ', 'cmdline'))
call assert_equal(s:fnames, getcompletion('find Xfind', 'cmdline'))
let pat = regexp ? 'X.*1\.c' : 'X*1.c'
call feedkeys($":find {pat}\<Tab>\<C-B>\"\<CR>", "xt")
- call assert_equal('"find Xfindexpr1.c', @:)
- call assert_equal(['Xfindexpr1.c'], getcompletion($'find {pat}', 'cmdline'))
+ call assert_equal('"find Xfindfunc1.c', @:)
+ call assert_equal(['Xfindfunc1.c'], getcompletion($'find {pat}', 'cmdline'))
call feedkeys(":find 3\<Tab>\<C-B>\"\<CR>", "xt")
- call assert_equal('"find Xfindexpr3.c', @:)
- call assert_equal(['Xfindexpr3.c'], getcompletion($'find 3', 'cmdline'))
+ call assert_equal('"find Xfindfunc3.c', @:)
+ call assert_equal(['Xfindfunc3.c'], getcompletion($'find 3', 'cmdline'))
call feedkeys(":find Xfind\<C-A>\<C-B>\"\<CR>", "xt")
- call assert_equal('"find Xfindexpr1.c Xfindexpr2.c Xfindexpr3.c', @:)
+ call assert_equal('"find Xfindfunc1.c Xfindfunc2.c Xfindfunc3.c', @:)
call feedkeys(":find abc\<Tab>\<C-B>\"\<CR>", "xt")
call assert_equal('"find abc', @:)
call assert_equal([], getcompletion('find abc', 'cmdline'))
endfor
- set findexpr&
- delfunc! FindExprRegexp
- delfunc! FindExprGlob
+ set findfunc&
+ delfunc! FindFuncRegexp
+ delfunc! FindFuncGlob
unlet s:fnames
endfunc
+" Test for different ways of setting the 'findfunc' option
+func Test_findfunc_callback()
+ new
+ func FindFunc1(pat, cmdexpand)
+ let g:FindFunc1Args = [a:pat, a:cmdexpand]
+ return ['findfunc1']
+ endfunc
+
+ let lines =<< trim END
+ #" Test for using a function name
+ LET &findfunc = 'g:FindFunc1'
+ LET g:FindFunc1Args = []
+ find abc1
+ call assert_equal(['abc1', v:false], g:FindFunc1Args)
+
+ #" Test for using a function()
+ set findfunc=function('g:FindFunc1')
+ LET g:FindFunc1Args = []
+ find abc2
+ call assert_equal(['abc2', v:false], g:FindFunc1Args)
+
+ #" Using a funcref variable to set 'findfunc'
+ VAR Fn = function('g:FindFunc1')
+ LET &findfunc = Fn
+ LET g:FindFunc1Args = []
+ find abc3
+ call assert_equal(['abc3', v:false], g:FindFunc1Args)
+
+ #" Using a string(funcref_variable) to set 'findfunc'
+ LET Fn = function('g:FindFunc1')
+ LET &findfunc = string(Fn)
+ LET g:FindFunc1Args = []
+ find abc4
+ call assert_equal(['abc4', v:false], g:FindFunc1Args)
+
+ #" Test for using a funcref()
+ set findfunc=funcref('g:FindFunc1')
+ LET g:FindFunc1Args = []
+ find abc5
+ call assert_equal(['abc5', v:false], g:FindFunc1Args)
+
+ #" Using a funcref variable to set 'findfunc'
+ LET Fn = funcref('g:FindFunc1')
+ LET &findfunc = Fn
+ LET g:FindFunc1Args = []
+ find abc6
+ call assert_equal(['abc6', v:false], g:FindFunc1Args)
+
+ #" Using a string(funcref_variable) to set 'findfunc'
+ LET Fn = funcref('g:FindFunc1')
+ LET &findfunc = string(Fn)
+ LET g:FindFunc1Args = []
+ find abc7
+ call assert_equal(['abc7', v:false], g:FindFunc1Args)
+
+ #" Test for using a lambda function using set
+ VAR optval = "LSTART pat, cmdexpand LMIDDLE FindFunc1(pat, cmdexpand) LEND"
+ LET optval = substitute(optval, ' ', '\\ ', 'g')
+ exe "set findfunc=" .. optval
+ LET g:FindFunc1Args = []
+ find abc8
+ call assert_equal(['abc8', v:false], g:FindFunc1Args)
+
+ #" Test for using a lambda function using LET
+ LET &findfunc = LSTART pat, _ LMIDDLE FindFunc1(pat, v:false) LEND
+ LET g:FindFunc1Args = []
+ find abc9
+ call assert_equal(['abc9', v:false], g:FindFunc1Args)
+
+ #" Set 'findfunc' to a string(lambda expression)
+ LET &findfunc = 'LSTART pat, _ LMIDDLE FindFunc1(pat, v:false) LEND'
+ LET g:FindFunc1Args = []
+ find abc10
+ call assert_equal(['abc10', v:false], g:FindFunc1Args)
+
+ #" Set 'findfunc' to a variable with a lambda expression
+ VAR Lambda = LSTART pat, _ LMIDDLE FindFunc1(pat, v:false) LEND
+ LET &findfunc = Lambda
+ LET g:FindFunc1Args = []
+ find abc11
+ call assert_equal(['abc11', v:false], g:FindFunc1Args)
+
+ #" Set 'findfunc' to a string(variable with a lambda expression)
+ LET Lambda = LSTART pat, _ LMIDDLE FindFunc1(pat, v:false) LEND
+ LET &findfunc = string(Lambda)
+ LET g:FindFunc1Args = []
+ find abc12
+ call assert_equal(['abc12', v:false], g:FindFunc1Args)
+
+ #" Try to use 'findfunc' after the function is deleted
+ func g:TmpFindFunc(pat, cmdexpand)
+ let g:TmpFindFunc1Args = [a:pat, a:cmdexpand]
+ endfunc
+ LET &findfunc = function('g:TmpFindFunc')
+ delfunc g:TmpFindFunc
+ call test_garbagecollect_now()
+ LET g:TmpFindFunc1Args = []
+ call assert_fails('find abc13', 'E117:')
+ call assert_equal([], g:TmpFindFunc1Args)
+
+ #" Try to use a function with three arguments for 'findfunc'
+ func g:TmpFindFunc2(x, y, z)
+ let g:TmpFindFunc2Args = [a:x, a:y, a:z]
+ endfunc
+ set findfunc=TmpFindFunc2
+ LET g:TmpFindFunc2Args = []
+ call assert_fails('find abc14', 'E119:')
+ call assert_equal([], g:TmpFindFunc2Args)
+ delfunc TmpFindFunc2
+
+ #" Try to use a function with zero arguments for 'findfunc'
+ func g:TmpFindFunc3()
+ let g:TmpFindFunc3Called = v:true
+ endfunc
+ set findfunc=TmpFindFunc3
+ LET g:TmpFindFunc3Called = v:false
+ call assert_fails('find abc15', 'E118:')
+ call assert_equal(v:false, g:TmpFindFunc3Called)
+ delfunc TmpFindFunc3
+
+ #" Try to use a lambda function with three arguments for 'findfunc'
+ LET &findfunc = LSTART a, b, c LMIDDLE FindFunc1(a, v:false) LEND
+ LET g:FindFunc1Args = []
+ call assert_fails('find abc16', 'E119:')
+ call assert_equal([], g:FindFunc1Args)
+
+ #" Test for clearing the 'findfunc' option
+ set findfunc=''
+ set findfunc&
+ call assert_fails("set findfunc=function('abc')", "E700:")
+ call assert_fails("set findfunc=funcref('abc')", "E700:")
+
+ #" set 'findfunc' to a non-existing function
+ LET &findfunc = function('g:FindFunc1')
+ call assert_fails("set findfunc=function('NonExistingFunc')", 'E700:')
+ call assert_fails("LET &findfunc = function('NonExistingFunc')", 'E700:')
+ LET g:FindFunc1Args = []
+ find abc17
+ call assert_equal(['abc17', v:false], g:FindFunc1Args)
+ END
+ call v9.CheckTransLegacySuccess(lines)
+
+ " Test for using a script-local function name
+ func s:FindFunc2(pat, cmdexpand)
+ let g:FindFunc2Args = [a:pat, a:cmdexpand]
+ return ['findfunc2']
+ endfunc
+ set findfunc=s:FindFunc2
+ let g:FindFunc2Args = []
+ find abc18
+ call assert_equal(['abc18', v:false], g:FindFunc2Args)
+
+ let &findfunc = 's:FindFunc2'
+ let g:FindFunc2Args = []
+ find abc19
+ call assert_equal(['abc19', v:false], g:FindFunc2Args)
+ delfunc s:FindFunc2
+
+ " Using Vim9 lambda expression in legacy context should fail
+ set findfunc=(pat,\ cmdexpand)\ =>\ FindFunc1(pat,\ v:false)
+ let g:FindFunc1Args = []
+ call assert_fails('find abc20', 'E117:')
+ call assert_equal([], g:FindFunc1Args)
+
+ " set 'findfunc' to a partial with dict.
+ func SetFindFunc()
+ let operator = {'execute': function('FindFuncExecute')}
+ let &findfunc = operator.execute
+ endfunc
+ func FindFuncExecute(pat, cmdexpand) dict
+ return ['findfuncexecute']
+ endfunc
+ call SetFindFunc()
+ call test_garbagecollect_now()
+ set findfunc=
+ delfunc SetFindFunc
+ delfunc FindFuncExecute
+
+ func FindFunc2(pat, cmdexpand)
+ let g:FindFunc2Args = [a:pat, a:cmdexpand]
+ return ['findfunc2']
+ endfunc
+
+ " Vim9 tests
+ let lines =<< trim END
+ vim9script
+
+ def g:Vim9findFunc(pat: string, cmdexpand: bool): list<string>
+ g:FindFunc1Args = [pat, cmdexpand]
+ return ['vim9findfunc']
+ enddef
+
+ # Test for using a def function with findfunc
+ set findfunc=function('g:Vim9findFunc')
+ g:FindFunc1Args = []
+ find abc21
+ assert_equal(['abc21', false], g:FindFunc1Args)
+
+ # Test for using a global function name
+ &findfunc = g:FindFunc2
+ g:FindFunc2Args = []
+ find abc22
+ assert_equal(['abc22', false], g:FindFunc2Args)
+ bw!
+
+ # Test for using a script-local function name
+ def LocalFindFunc(pat: string, cmdexpand: bool): list<string>
+ g:LocalFindFuncArgs = [pat, cmdexpand]
+ return ['localfindfunc']
+ enddef
+ &findfunc = LocalFindFunc
+ g:LocalFindFuncArgs = []
+ find abc23
+ assert_equal(['abc23', false], g:LocalFindFuncArgs)
+ bw!
+ END
+ call v9.CheckScriptSuccess(lines)
+
+ " setting 'findfunc' to a script local function outside of a script context
+ " should fail
+ let cleanup =<< trim END
+ call writefile([execute('messages')], 'Xtest.out')
+ qall
+ END
+ call writefile(cleanup, 'Xverify.vim', 'D')
+ call RunVim([], [], "-c \"set findfunc=s:abc\" -S Xverify.vim")
+ call assert_match('E81: Using <SID> not in a', readfile('Xtest.out')[0])
+ call delete('Xtest.out')
+
+ " cleanup
+ set findfunc&
+ delfunc FindFunc1
+ delfunc FindFunc2
+ unlet g:FindFunc1Args g:FindFunc2Args
+ %bw!
+endfunc
+
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_modeline.vim b/src/testdir/test_modeline.vim
index bb5bc6b..0697fbb 100644
--- a/src/testdir/test_modeline.vim
+++ b/src/testdir/test_modeline.vim
@@ -208,7 +208,7 @@
call s:modeline_fails('equalprg', 'equalprg=Something()', 'E520:')
call s:modeline_fails('errorfile', 'errorfile=Something()', 'E520:')
call s:modeline_fails('exrc', 'exrc=Something()', 'E520:')
- call s:modeline_fails('findexpr', 'findexpr=Something()', 'E520:')
+ call s:modeline_fails('findfunc', 'findfunc=Something', 'E520:')
call s:modeline_fails('formatprg', 'formatprg=Something()', 'E520:')
call s:modeline_fails('fsync', 'fsync=Something()', 'E520:')
call s:modeline_fails('grepprg', 'grepprg=Something()', 'E520:')
diff --git a/src/testdir/test_options.vim b/src/testdir/test_options.vim
index 35b7d48..bd9da73 100644
--- a/src/testdir/test_options.vim
+++ b/src/testdir/test_options.vim
@@ -1570,7 +1570,7 @@
" Test for changing options in a sandbox
func Test_opt_sandbox()
- for opt in ['backupdir', 'cdpath', 'exrc', 'findexpr']
+ for opt in ['backupdir', 'cdpath', 'exrc', 'findfunc']
call assert_fails('sandbox set ' .. opt .. '?', 'E48:')
call assert_fails('sandbox let &' .. opt .. ' = 1', 'E48:')
endfor
diff --git a/src/testdir/test_vim9_import.vim b/src/testdir/test_vim9_import.vim
index ad0248c..4a3e239 100644
--- a/src/testdir/test_vim9_import.vim
+++ b/src/testdir/test_vim9_import.vim
@@ -1560,27 +1560,47 @@
set printexpr=
enddef
-" Test for using an imported function as 'findexpr'
-func Test_import_in_findexpr()
- call Run_Test_import_in_findexpr()
+" Test for using an imported function as 'findfunc'
+func Test_import_in_findfunc()
+ call Run_Test_import_in_findfunc()
endfunc
-def Run_Test_import_in_findexpr()
+def Run_Test_import_in_findfunc()
var lines =<< trim END
- vim9script
+ vim9script
- export def FindExpr(): list<string>
- var fnames = ['Xfile1.c', 'Xfile2.c', 'Xfile3.c']
- return fnames->copy()->filter('v:val =~? v:fname')
- enddef
+ export def FindFunc(pat: string, cmdexpand: bool): list<string>
+ var fnames = ['Xfile1.c', 'Xfile2.c', 'Xfile3.c']
+ return fnames->filter((_, v) => v =~? pat)
+ enddef
END
- writefile(lines, 'Xfindexpr', 'D')
+ writefile(lines, 'Xfindfunc', 'D')
+ # Test using the "set" command
lines =<< trim END
- vim9script
- import './Xfindexpr' as find
+ vim9script
+ import './Xfindfunc' as find1
- set findexpr=find.FindExpr()
+ set findfunc=find1.FindFunc
+ END
+ v9.CheckScriptSuccess(lines)
+
+ enew!
+ find Xfile2
+ assert_equal('Xfile2.c', @%)
+ bwipe!
+
+ botright vert new
+ find Xfile1
+ assert_equal('Xfile1.c', @%)
+ bw!
+
+ # Test using the option variable
+ lines =<< trim END
+ vim9script
+ import './Xfindfunc' as find2
+
+ &findfunc = find2.FindFunc
END
v9.CheckScriptSuccess(lines)
@@ -1593,7 +1613,7 @@
find Xfile1
assert_equal('Xfile1.c', @%)
- set findexpr=
+ set findfunc=
bwipe!
enddef
diff --git a/src/version.c b/src/version.c
index 74660c6..3e8bfbd 100644
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 831,
+/**/
830,
/**/
829,
diff --git a/src/vim.h b/src/vim.h
index f4acaf9..2878541 100644
--- a/src/vim.h
+++ b/src/vim.h
@@ -845,7 +845,7 @@
#define EXPAND_KEYMAP 58
#define EXPAND_DIRS_IN_CDPATH 59
#define EXPAND_SHELLCMDLINE 60
-#define EXPAND_FINDEXPR 61
+#define EXPAND_FINDFUNC 61
// Values for exmode_active (0 is no exmode)
@@ -2189,8 +2189,7 @@
#define VV_TYPE_TYPEALIAS 107
#define VV_TYPE_ENUM 108
#define VV_TYPE_ENUMVALUE 109
-#define VV_CMDCOMPLETE 110
-#define VV_LEN 111 // number of v: vars
+#define VV_LEN 110 // number of v: vars
// used for v_number in VAR_BOOL and VAR_SPECIAL
#define VVAL_FALSE 0L // VAR_BOOL