-*eval.txt* For Vim version 9.1. Last change: 2024 Oct 28
+*eval.txt* For Vim version 9.1. Last change: 2024 Nov 02
VIM REFERENCE MANUAL by Bram Moolenaar
can only be used in autocommands. For user commands |<bang>|
can be used.
- *v:cmdcomplete* *cmdcomplete-variable*
-v:cmdcomplete When evaluating 'findexpr': if 'findexpr' is used for cmdline
- completion the value is |v:true|, otherwise it is |v:false|.
-
*v:collate* *collate-variable*
v:collate The current locale setting for collation order of the runtime
environment. This allows Vim scripts to be aware of the
*v:fname* *fname-variable*
v:fname When evaluating 'includeexpr': the file name that was
- detected. When evaluating 'findexpr': the argument passed to
- the |:find| command. Empty otherwise.
+ detected. Empty otherwise.
*v:fname_in* *fname_in-variable*
v:fname_in The name of the input file. Valid while evaluating:
-*options.txt* For Vim version 9.1. Last change: 2024 Oct 28
+*options.txt* For Vim version 9.1. Last change: 2024 Nov 02
VIM REFERENCE MANUAL by Bram Moolenaar
":setlocal" on a global option might work differently then.
*option-value-function*
-Some options ('completefunc', 'imactivatefunc', 'imstatusfunc', 'omnifunc',
-'operatorfunc', 'quickfixtextfunc', 'tagfunc' and 'thesaurusfunc') are set to
-a function name or a function reference or a lambda function. When using a
-lambda it will be converted to the name, e.g. "<lambda>123". Examples:
+Some options ('completefunc', 'findfunc', 'imactivatefunc', 'imstatusfunc',
+'omnifunc', 'operatorfunc', 'quickfixtextfunc', 'tagfunc' and 'thesaurusfunc')
+are set to a function name or a function reference or a lambda function. When
+using a lambda it will be converted to the name, e.g. "<lambda>123".
+Examples:
>
set opfunc=MyOpFunc
set opfunc=function('MyOpFunc')
eob EndOfBuffer |hl-EndOfBuffer|
lastline NonText |hl-NonText|
- *'findexpr'* *'fexpr'* *E1514*
-'findexpr' 'fexpr' string (default "")
+ *'findfunc'* *'ffu'* *E1514*
+'findfunc' 'ffu' string (default empty)
global or local to buffer |global-local|
{not available when compiled without the |+eval|
feature}
- Expression that is evaluated to obtain the filename(s) for the |:find|
+ Function that is called to obtain the filename(s) for the |:find|
command. When this option is empty, the internal |file-searching|
mechanism is used.
- While evaluating the expression, the |v:fname| variable is set to the
- argument of the |:find| command.
+ The value can be the name of a function, a |lambda| or a |Funcref|.
+ See |option-value-function| for more information.
- The expression is evaluated only once per |:find| command invocation.
- The expression can process all the directories specified in 'path'.
+ The function is called with two arguments. The first argument is a
+ |String| and is the |:find| command argument. The second argument is
+ a |Boolean| and is set to |v:true| when the function is called to get
+ a List of command-line completion matches for the |:find| command.
+ The function should return a List of strings.
- The expression may be evaluated for command-line completion as well,
- in which case the |v:cmdcomplete| variable will be set to |v:true|,
- otherwise it will be set to |v:false|.
+ The function is called only once per |:find| command invocation.
+ The function can process all the directories specified in 'path'.
- If a match is found, the expression should return a |List| containing
- one or more file names. If a match is not found, the expression
+ If a match is found, the function should return a |List| containing
+ one or more file names. If a match is not found, the function
should return an empty List.
- If any errors are encountered during the expression evaluation, an
+ If any errors are encountered during the function invocation, an
empty List is used as the return value.
- Using a function call without arguments is faster |expr-option-function|
-
It is not allowed to change text or jump to another window while
- evaluating 'findexpr' |textlock|.
+ executing the 'findfunc' |textlock|.
This option cannot be set from a |modeline| or in the |sandbox|, for
security reasons.
Examples:
>
" Use glob()
- func FindExprGlob()
- let pat = v:cmdcomplete ? $'{v:fname}*' : v:fname
+ func FindFuncGlob(cmdarg, cmdcomplete)
+ let pat = a:cmdcomplete ? $'{a:cmdarg}*' : a:cmdarg
return glob(pat, v:false, v:true)
endfunc
- set findexpr=FindExprGlob()
+ set findfunc=FindFuncGlob
" Use the 'git ls-files' output
- func FindGitFiles()
+ func FindGitFiles(cmdarg, cmdcomplete)
let fnames = systemlist('git ls-files')
- return fnames->filter('v:val =~? v:fname')
+ return fnames->filter('v:val =~? a:cmdarg')
endfunc
- set findexpr=FindGitFiles()
+ set findfunc=FindGitFiles
<
*'fixendofline'* *'fixeol'* *'nofixendofline'* *'nofixeol'*
'fixendofline' 'fixeol' boolean (default on)
-*quickref.txt* For Vim version 9.1. Last change: 2024 Oct 22
+*quickref.txt* For Vim version 9.1. Last change: 2024 Nov 02
VIM REFERENCE MANUAL by Bram Moolenaar
'fileignorecase' 'fic' ignore case when using file names
'filetype' 'ft' type of file, used for autocommands
'fillchars' 'fcs' characters to use for displaying special items
-'findexpr' 'fexpr' expression to evaluate for |:find|
+'findfunc' 'ffu' function to be called for the |:find| command
'fixendofline' 'fixeol' make sure last line in file has <EOL>
'fkmap' 'fk' obsolete option for Farsi
'foldclose' 'fcl' close a fold when the cursor leaves it
'fenc' options.txt /*'fenc'*
'fencs' options.txt /*'fencs'*
'fex' options.txt /*'fex'*
-'fexpr' options.txt /*'fexpr'*
'ff' options.txt /*'ff'*
'ffs' options.txt /*'ffs'*
+'ffu' options.txt /*'ffu'*
'fic' options.txt /*'fic'*
'fileencoding' options.txt /*'fileencoding'*
'fileencodings' options.txt /*'fileencodings'*
'fileignorecase' options.txt /*'fileignorecase'*
'filetype' options.txt /*'filetype'*
'fillchars' options.txt /*'fillchars'*
-'findexpr' options.txt /*'findexpr'*
+'findfunc' options.txt /*'findfunc'*
'fixendofline' options.txt /*'fixendofline'*
'fixeol' options.txt /*'fixeol'*
'fk' options.txt /*'fk'*
closure eval.txt /*closure*
cmdarg-variable eval.txt /*cmdarg-variable*
cmdbang-variable eval.txt /*cmdbang-variable*
-cmdcomplete-variable eval.txt /*cmdcomplete-variable*
cmdline-arguments vi_diff.txt /*cmdline-arguments*
cmdline-changed version5.txt /*cmdline-changed*
cmdline-completion cmdline.txt /*cmdline-completion*
v:charconvert_to eval.txt /*v:charconvert_to*
v:cmdarg eval.txt /*v:cmdarg*
v:cmdbang eval.txt /*v:cmdbang*
-v:cmdcomplete eval.txt /*v:cmdcomplete*
v:collate eval.txt /*v:collate*
v:colornames eval.txt /*v:colornames*
v:completed_item eval.txt /*v:completed_item*
'completeitemalign' Order of |complete-items| in Insert mode completion
popup
-'findexpr' Vim expression to obtain the results for a |:find|
+'findfunc' Vim function to obtain the results for a |:find|
command
'winfixbuf' Keep buffer focused in a window
'tabclose' Which tab page to focus after closing a tab page
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
#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);
&& 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
// 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
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:
}
}
- 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
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);
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"));
#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;
}
{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
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));
}
#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.
- */
+
+// 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 *
-eval_findexpr(char_u *pat, int cmdcomplete)
+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;
+
+ // 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;
+
+ // 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;
- findexpr = get_findexpr();
+ ctx = get_option_sctx("findfunc");
+ if (ctx != NULL)
+ current_sctx = *ctx;
- 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];
+ cb = get_findfunc_callback();
+ retval = call_callback(cb, -1, &rettv, 2, args);
- arg = skipwhite(findexpr);
+ current_sctx = saved_sctx;
- ++textlock;
+ --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
+ list_T *retlist = NULL;
+
+ if (retval == OK)
{
- if (tv.v_type == VAR_LIST)
- retlist = list_copy(tv.vval.v_list, TRUE, TRUE, get_copyID());
+ if (rettv.v_type == VAR_LIST)
+ retlist = list_copy(rettv.vval.v_list, FALSE, FALSE, get_copyID());
else
- emsg(_(e_invalid_return_type_from_findexpr));
- clear_tv(&tv);
- }
- --textlock;
- clear_evalarg(&EVALARG_EVALUATE, NULL);
+ emsg(_(e_invalid_return_type_from_findfunc));
- set_vim_var_string(VV_FNAME, NULL, 0);
- set_vim_var_nr(VV_CMDCOMPLETE, VVAL_FALSE);
- current_sctx = saved_sctx;
+ 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;
*numMatches = 0;
*files = NULL;
- l = eval_findexpr(pat, TRUE);
+ l = call_findfunc(pat, VVAL_TRUE);
if (l == NULL)
return FAIL;
}
/*
- * 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;
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)
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
/*
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
}
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
}
// '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
}
free_operatorfunc_option();
free_tagfunc_option();
+# if defined(FEAT_EVAL)
+ free_findfunc_option();
+# endif
}
#endif
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
{
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);
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
}
/*
- * 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
#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;
#ifdef FEAT_EVAL
typval_T *tv;
callback_T cb;
+ int funcname = FALSE;
if (optval == NULL || *optval == NUL)
{
// 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;
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);
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
, BV_EP
, BV_ET
, BV_FENC
- , BV_FEXPR
, BV_FP
#ifdef FEAT_EVAL
, BV_BEXPR
, BV_FEX
+ , BV_FFU
#endif
, BV_FF
, BV_FLP
#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)
#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)
{(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,
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
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);
#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)
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);
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);
#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'
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
" Test findfile() and finddir()
source check.vim
+import './vim9.vim' as v9
let s:files = [ 'Xfinddir1/foo',
\ 'Xfinddir1/bar',
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')
-
- " Expression returning a string
- set findexpr='abc'
- call assert_fails('find Xfindexpr1.c', "E1514: 'findexpr' did not return a List type")
-
- set findexpr&
- delfunc! FindExpr1
- delfunc! FindExpr2
- delfunc! FindExpr3
- delfunc! FindExpr4
+ set findfunc=FindFuncModifyBuf
+ call assert_fails('find Xfindfunc1.c', 'E565: Not allowed to change text or change window')
+ delfunc FindFuncModifyBuf
+
+ " 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 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
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:')
" 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
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 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
- set findexpr=find.FindExpr()
+ &findfunc = find2.FindFunc
END
v9.CheckScriptSuccess(lines)
find Xfile1
assert_equal('Xfile1.c', @%)
- set findexpr=
+ set findfunc=
bwipe!
enddef
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 831,
/**/
830,
/**/
#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)
#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