mirror of
https://github.com/vim/vim
synced 2025-07-16 01:01:58 +00:00
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>
This commit is contained in:
committed by
Christian Brabandt
parent
0b8176dff2
commit
a13f3a4f5d
155
src/ex_docmd.c
155
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.
|
||||
*/
|
||||
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();
|
||||
|
||||
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);
|
||||
// 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;
|
||||
|
||||
// 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;
|
||||
|
||||
cb = get_findfunc_callback();
|
||||
retval = call_callback(cb, -1, &rettv, 2, args);
|
||||
|
||||
set_vim_var_string(VV_FNAME, NULL, 0);
|
||||
set_vim_var_nr(VV_CMDCOMPLETE, VVAL_FALSE);
|
||||
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 @@ 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
|
||||
}
|
||||
|
Reference in New Issue
Block a user