summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYegappan Lakshmanan <yegappan@yahoo.com>2024-11-02 18:40:10 +0100
committerChristian Brabandt <cb@256bit.org>2024-11-02 18:43:42 +0100
commita13f3a4f5de9c150f70298850e34747838904995 (patch)
treea6ed380325af51e922e3a57d48b902fbd625716b
parent0b8176dff2dada4be1c8d3ca5e1dd1a7a536b4ca (diff)
patch 9.1.0831: 'findexpr' can't be used as lambad or Funcrefv9.1.0831
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>
-rw-r--r--runtime/doc/eval.txt9
-rw-r--r--runtime/doc/options.txt55
-rw-r--r--runtime/doc/quickref.txt4
-rw-r--r--runtime/doc/tags6
-rw-r--r--runtime/doc/version9.txt2
-rw-r--r--src/buffer.c3
-rw-r--r--src/cmdexpand.c12
-rw-r--r--src/errors.h4
-rw-r--r--src/evalbuffer.c2
-rw-r--r--src/evalvars.c4
-rw-r--r--src/ex_docmd.c149
-rw-r--r--src/gc.c3
-rw-r--r--src/option.c40
-rw-r--r--src/option.h4
-rw-r--r--src/optiondefs.h9
-rw-r--r--src/optionstr.c9
-rw-r--r--src/proto/ex_docmd.pro5
-rw-r--r--src/proto/option.pro2
-rw-r--r--src/structs.h5
-rw-r--r--src/testdir/test_findfile.vim497
-rw-r--r--src/testdir/test_modeline.vim2
-rw-r--r--src/testdir/test_options.vim2
-rw-r--r--src/testdir/test_vim9_import.vim48
-rw-r--r--src/version.c2
-rw-r--r--src/vim.h5
25 files changed, 628 insertions, 255 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 027cf08c5b..6b26475042 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1,4 +1,4 @@
-*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
@@ -2027,10 +2027,6 @@ v:cmdbang Set like v:cmdarg for a file read/write command. When a "!"
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
@@ -2228,8 +2224,7 @@ v:fcs_choice What should happen after a |FileChangedShell| event was
*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:
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index e221fe3e29..7a554dbb28 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -1,4 +1,4 @@
-*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
@@ -439,10 +439,11 @@ Note: In the future more global options can be made |global-local|. Using
":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')
@@ -3552,36 +3553,36 @@ A jump table for the options with a short description can be found at |Q_op|.
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.
@@ -3589,18 +3590,18 @@ A jump table for the options with a short description can be found at |Q_op|.
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)
diff --git a/runtime/doc/quickref.txt b/runtime/doc/quickref.txt
index 0f7453a9e5..a43d28f1e3 100644
--- a/runtime/doc/quickref.txt
+++ b/runtime/doc/quickref.txt
@@ -1,4 +1,4 @@
-*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
@@ -707,7 +707,7 @@ Short explanation of each option: *option-list*
'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
diff --git a/runtime/doc/tags b/runtime/doc/tags
index 1ae1ff61e9..79d9dafb94 100644
--- a/runtime/doc/tags
+++ b/runtime/doc/tags
@@ -267,9 +267,9 @@ $quote eval.txt /*$quote*
'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'*
@@ -278,7 +278,7 @@ $quote eval.txt /*$quote*
'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'*
@@ -6510,7 +6510,6 @@ close_cb channel.txt /*close_cb*
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*
@@ -10942,7 +10941,6 @@ v:charconvert_from eval.txt /*v:charconvert_from*
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*
diff --git a/runtime/doc/version9.txt b/runtime/doc/version9.txt
index 66f98e10e6..5f9250348b 100644
--- a/runtime/doc/version9.txt
+++ b/runtime/doc/version9.txt
@@ -41652,7 +41652,7 @@ Options: ~
'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
diff --git a/src/buffer.c b/src/buffer.c
index f1e133095e..3b05f25d7f 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -2412,7 +2412,6 @@ free_buf_options(
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 @@ free_buf_options(
#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 3862d69eda..7e5311481b 100644
--- a/src/cmdexpand.c
+++ b/src/cmdexpand.c
@@ -50,7 +50,7 @@ cmdline_fuzzy_completion_supported(expand_T *xp)
&& 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 @@ addstar(
// 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 @@ set_context_by_cmdname(
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 @@ expand_files_and_dirs(
}
}
- 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 @@ ExpandFromContext(
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 6c172e09c0..1e59597d96 100644
--- a/src/errors.h
+++ b/src/errors.h
@@ -3652,5 +3652,5 @@ EXTERN char e_wrong_character_width_for_field_str[]
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 6ec734d370..cefd6428f6 100644
--- a/src/evalbuffer.c
+++ b/src/evalbuffer.c
@@ -45,6 +45,8 @@ set_ref_in_buffers(int copyID)
#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 9f03ada09a..038d7ed5a1 100644
--- a/src/evalvars.c
+++ b/src/evalvars.c
@@ -160,8 +160,7 @@ static struct vimvar
{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 @@ evalvars_init(void)
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 d60e34473c..380bd236fd 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -6924,58 +6924,71 @@ ex_wrongmodifier(exarg_T *eap)
}
#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;
@@ -6983,7 +6996,7 @@ expand_findexpr(char_u *pat, char_u ***files, int *numMatches)
*numMatches = 0;
*files = NULL;
- l = eval_findexpr(pat, TRUE);
+ l = call_findfunc(pat, VVAL_TRUE);
if (l == NULL)
return FAIL;
@@ -7015,11 +7028,11 @@ expand_findexpr(char_u *pat, char_u ***files, int *numMatches)
}
/*
- * 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 @@ findexpr_find_file(char_u *findarg, int findarg_len, int count)
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 @@ findexpr_find_file(char_u *findarg, int findarg_len, int count)
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 @@ ex_splitview(exarg_T *eap)
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 @@ ex_find(exarg_T *eap)
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 987ca27e76..54c7444804 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -183,6 +183,9 @@ garbage_collect(int testing)
// '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 f408fb9dfb..dcb5752e18 100644
--- a/src/option.c
+++ b/src/option.c
@@ -1014,6 +1014,9 @@ free_all_options(void)
}
free_operatorfunc_option();
free_tagfunc_option();
+# if defined(FEAT_EVAL)
+ free_findfunc_option();
+# endif
}
#endif
@@ -6372,8 +6375,8 @@ unset_global_local_option(char_u *name, void *from)
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 @@ get_varp_scope(struct vimoption *p, int scope)
{
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 @@ get_varp(struct vimoption *p)
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_equalprg(void)
}
/*
- * 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 @@ buf_copy_options(buf_T *buf, int flags)
#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 @@ option_set_callback_func(char_u *optval UNUSED, callback_T *optcb UNUSED)
#ifdef FEAT_EVAL
typval_T *tv;
callback_T cb;
+ int funcname = FALSE;
if (optval == NULL || *optval == NUL)
{
@@ -8762,8 +8765,11 @@ option_set_callback_func(char_u *optval UNUSED, callback_T *optcb UNUSED)
// 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 @@ option_set_callback_func(char_u *optval UNUSED, callback_T *optcb UNUSED)
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 641514d219..d5f72a1ccd 100644
--- a/src/option.h
+++ b/src/option.h
@@ -597,7 +597,7 @@ EXTERN int p_fic; // 'fileignorecase'
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 @@ enum
, 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 96c30e283d..97fc4d4a69 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 @@ static struct vimoption options[] =
{(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 d82b8e116d..0554c0eb24 100644
--- a/src/optionstr.c
+++ b/src/optionstr.c
@@ -313,6 +313,7 @@ check_buf_options(buf_T *buf)
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_buf_options(buf_T *buf)
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 @@ expand_set_nrformats(optexpand_T *args, int *numMatches, char_u ***matches)
#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 d3f1a4ea76..7b837c989e 100644
--- a/src/proto/ex_docmd.pro
+++ b/src/proto/ex_docmd.pro
@@ -46,7 +46,10 @@ void tabpage_close_other(tabpage_T *tp, int forceit);
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 fce9199188..83f32aad61 100644
--- a/src/proto/option.pro
+++ b/src/proto/option.pro
@@ -120,7 +120,7 @@ char_u *get_option_var(int opt_idx);
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 33367f099a..47999a9538 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -3248,6 +3248,8 @@ struct file_buffer
#ifd