mirror of
https://github.com/vim/vim.git
synced 2025-08-26 20:03:41 -04:00
patch 9.1.0810: cannot easily adjust the |:find| command
Problem: cannot easily adjust the |:find| command Solution: Add support for the 'findexpr' option (Yegappan Lakshmanan) closes: #15901 closes: #15905 Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
parent
626b6ab486
commit
aeb1c97db5
@ -1,4 +1,4 @@
|
|||||||
*eval.txt* For Vim version 9.1. Last change: 2024 Jul 28
|
*eval.txt* For Vim version 9.1. Last change: 2024 Oct 22
|
||||||
|
|
||||||
|
|
||||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||||
@ -2223,7 +2223,8 @@ v:fcs_choice What should happen after a |FileChangedShell| event was
|
|||||||
|
|
||||||
*v:fname* *fname-variable*
|
*v:fname* *fname-variable*
|
||||||
v:fname When evaluating 'includeexpr': the file name that was
|
v:fname When evaluating 'includeexpr': the file name that was
|
||||||
detected. Empty otherwise.
|
detected. When evaluating 'findexpr': the argument passed to
|
||||||
|
the |:find| command. Empty otherwise.
|
||||||
|
|
||||||
*v:fname_in* *fname_in-variable*
|
*v:fname_in* *fname_in-variable*
|
||||||
v:fname_in The name of the input file. Valid while evaluating:
|
v:fname_in The name of the input file. Valid while evaluating:
|
||||||
|
@ -3552,6 +3552,51 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
eob EndOfBuffer |hl-EndOfBuffer|
|
eob EndOfBuffer |hl-EndOfBuffer|
|
||||||
lastline NonText |hl-NonText|
|
lastline NonText |hl-NonText|
|
||||||
|
|
||||||
|
*'findexpr'* *'fexpr'*
|
||||||
|
'findexpr' 'fexpr' string (default "")
|
||||||
|
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|
|
||||||
|
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 expression is evaluated only once per |:find| command invocation.
|
||||||
|
The expression 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
|
||||||
|
should return an empty List.
|
||||||
|
|
||||||
|
If any errors are encountered during the expression evaluation, 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|.
|
||||||
|
|
||||||
|
This option cannot be set from a |modeline| or in the |sandbox|, for
|
||||||
|
security reasons.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
>
|
||||||
|
" Use glob()
|
||||||
|
func FindExprGlob()
|
||||||
|
return glob(v:fname, v:false, v:true)
|
||||||
|
endfunc
|
||||||
|
set findexpr=FindExprGlob()
|
||||||
|
|
||||||
|
" Use the 'git ls-files' output
|
||||||
|
func FindGitFiles()
|
||||||
|
let fnames = systemlist('git ls-files')
|
||||||
|
return fnames->filter('v:val =~? v:fname')
|
||||||
|
endfunc
|
||||||
|
set findexpr=FindGitFiles()
|
||||||
|
<
|
||||||
*'fixendofline'* *'fixeol'* *'nofixendofline'* *'nofixeol'*
|
*'fixendofline'* *'fixeol'* *'nofixendofline'* *'nofixeol'*
|
||||||
'fixendofline' 'fixeol' boolean (default on)
|
'fixendofline' 'fixeol' boolean (default on)
|
||||||
local to buffer
|
local to buffer
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
*quickref.txt* For Vim version 9.1. Last change: 2024 Mar 03
|
*quickref.txt* For Vim version 9.1. Last change: 2024 Oct 22
|
||||||
|
|
||||||
|
|
||||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||||
@ -707,6 +707,7 @@ Short explanation of each option: *option-list*
|
|||||||
'fileignorecase' 'fic' ignore case when using file names
|
'fileignorecase' 'fic' ignore case when using file names
|
||||||
'filetype' 'ft' type of file, used for autocommands
|
'filetype' 'ft' type of file, used for autocommands
|
||||||
'fillchars' 'fcs' characters to use for displaying special items
|
'fillchars' 'fcs' characters to use for displaying special items
|
||||||
|
'findexpr' 'fexpr' expression to evaluate for |:find|
|
||||||
'fixendofline' 'fixeol' make sure last line in file has <EOL>
|
'fixendofline' 'fixeol' make sure last line in file has <EOL>
|
||||||
'fkmap' 'fk' obsolete option for Farsi
|
'fkmap' 'fk' obsolete option for Farsi
|
||||||
'foldclose' 'fcl' close a fold when the cursor leaves it
|
'foldclose' 'fcl' close a fold when the cursor leaves it
|
||||||
|
@ -267,6 +267,7 @@ $quote eval.txt /*$quote*
|
|||||||
'fenc' options.txt /*'fenc'*
|
'fenc' options.txt /*'fenc'*
|
||||||
'fencs' options.txt /*'fencs'*
|
'fencs' options.txt /*'fencs'*
|
||||||
'fex' options.txt /*'fex'*
|
'fex' options.txt /*'fex'*
|
||||||
|
'fexpr' options.txt /*'fexpr'*
|
||||||
'ff' options.txt /*'ff'*
|
'ff' options.txt /*'ff'*
|
||||||
'ffs' options.txt /*'ffs'*
|
'ffs' options.txt /*'ffs'*
|
||||||
'fic' options.txt /*'fic'*
|
'fic' options.txt /*'fic'*
|
||||||
@ -277,6 +278,7 @@ $quote eval.txt /*$quote*
|
|||||||
'fileignorecase' options.txt /*'fileignorecase'*
|
'fileignorecase' options.txt /*'fileignorecase'*
|
||||||
'filetype' options.txt /*'filetype'*
|
'filetype' options.txt /*'filetype'*
|
||||||
'fillchars' options.txt /*'fillchars'*
|
'fillchars' options.txt /*'fillchars'*
|
||||||
|
'findexpr' options.txt /*'findexpr'*
|
||||||
'fixendofline' options.txt /*'fixendofline'*
|
'fixendofline' options.txt /*'fixendofline'*
|
||||||
'fixeol' options.txt /*'fixeol'*
|
'fixeol' options.txt /*'fixeol'*
|
||||||
'fk' options.txt /*'fk'*
|
'fk' options.txt /*'fk'*
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
*version9.txt* For Vim version 9.1. Last change: 2024 Oct 14
|
*version9.txt* For Vim version 9.1. Last change: 2024 Oct 22
|
||||||
|
|
||||||
|
|
||||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||||
@ -41649,6 +41649,8 @@ Options: ~
|
|||||||
|
|
||||||
'completeitemalign' Order of |complete-items| in Insert mode completion
|
'completeitemalign' Order of |complete-items| in Insert mode completion
|
||||||
popup
|
popup
|
||||||
|
'findexpr' Vim expression to obtain the results for a |:find|
|
||||||
|
command
|
||||||
'winfixbuf' Keep buffer focused in a window
|
'winfixbuf' Keep buffer focused in a window
|
||||||
'tabclose' Which tab page to focus after closing a tab page
|
'tabclose' Which tab page to focus after closing a tab page
|
||||||
't_xo' Terminal uses XON/XOFF handshaking (e.g. vt420)
|
't_xo' Terminal uses XON/XOFF handshaking (e.g. vt420)
|
||||||
|
@ -2412,6 +2412,7 @@ free_buf_options(
|
|||||||
clear_string_option(&buf->b_p_fp);
|
clear_string_option(&buf->b_p_fp);
|
||||||
#if defined(FEAT_EVAL)
|
#if defined(FEAT_EVAL)
|
||||||
clear_string_option(&buf->b_p_fex);
|
clear_string_option(&buf->b_p_fex);
|
||||||
|
clear_string_option(&buf->b_p_fexpr);
|
||||||
#endif
|
#endif
|
||||||
#ifdef FEAT_CRYPT
|
#ifdef FEAT_CRYPT
|
||||||
# ifdef FEAT_SODIUM
|
# ifdef FEAT_SODIUM
|
||||||
|
158
src/ex_docmd.c
158
src/ex_docmd.c
@ -6923,6 +6923,103 @@ ex_wrongmodifier(exarg_T *eap)
|
|||||||
eap->errmsg = ex_errmsg(e_invalid_command_str, eap->cmd);
|
eap->errmsg = ex_errmsg(e_invalid_command_str, eap->cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef FEAT_EVAL
|
||||||
|
/*
|
||||||
|
* 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 *ptr, int len)
|
||||||
|
{
|
||||||
|
sctx_T saved_sctx = current_sctx;
|
||||||
|
int use_sandbox = FALSE;
|
||||||
|
char_u *findexpr;
|
||||||
|
char_u *arg;
|
||||||
|
typval_T tv;
|
||||||
|
list_T *retlist = NULL;
|
||||||
|
|
||||||
|
if (*curbuf->b_p_fexpr == NUL)
|
||||||
|
{
|
||||||
|
use_sandbox = was_set_insecurely((char_u *)"findexpr", OPT_GLOBAL);
|
||||||
|
findexpr = p_fexpr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
use_sandbox = was_set_insecurely((char_u *)"findexpr", OPT_LOCAL);
|
||||||
|
findexpr = curbuf->b_p_fexpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_vim_var_string(VV_FNAME, ptr, len);
|
||||||
|
current_sctx = curbuf->b_p_script_ctx[BV_FEXPR];
|
||||||
|
|
||||||
|
arg = skipwhite(findexpr);
|
||||||
|
|
||||||
|
if (use_sandbox)
|
||||||
|
++sandbox;
|
||||||
|
++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());
|
||||||
|
clear_tv(&tv);
|
||||||
|
}
|
||||||
|
if (use_sandbox)
|
||||||
|
--sandbox;
|
||||||
|
--textlock;
|
||||||
|
clear_evalarg(&EVALARG_EVALUATE, NULL);
|
||||||
|
|
||||||
|
set_vim_var_string(VV_FNAME, NULL, 0);
|
||||||
|
current_sctx = saved_sctx;
|
||||||
|
|
||||||
|
return retlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use 'findexpr' 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)
|
||||||
|
{
|
||||||
|
list_T *fname_list;
|
||||||
|
char_u *ret_fname = NULL;
|
||||||
|
char_u cc;
|
||||||
|
int fname_count;
|
||||||
|
|
||||||
|
cc = findarg[findarg_len];
|
||||||
|
findarg[findarg_len] = NUL;
|
||||||
|
|
||||||
|
fname_list = eval_findexpr(findarg, findarg_len);
|
||||||
|
fname_count = list_len(fname_list);
|
||||||
|
|
||||||
|
if (fname_count == 0)
|
||||||
|
semsg(_(e_cant_find_file_str_in_path), findarg);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (count > fname_count)
|
||||||
|
semsg(_(e_no_more_file_str_found_in_path), findarg);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
listitem_T *li = list_find(fname_list, count - 1);
|
||||||
|
if (li != NULL && li->li_tv.v_type == VAR_STRING)
|
||||||
|
ret_fname = vim_strsave(li->li_tv.vval.v_string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fname_list != NULL)
|
||||||
|
list_free(fname_list);
|
||||||
|
|
||||||
|
findarg[findarg_len] = cc;
|
||||||
|
|
||||||
|
return ret_fname;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* :sview [+command] file split window with new file, read-only
|
* :sview [+command] file split window with new file, read-only
|
||||||
* :split [[+command] file] split window with current or new file
|
* :split [[+command] file] split window with current or new file
|
||||||
@ -6972,11 +7069,22 @@ ex_splitview(exarg_T *eap)
|
|||||||
{
|
{
|
||||||
char_u *file_to_find = NULL;
|
char_u *file_to_find = NULL;
|
||||||
char *search_ctx = NULL;
|
char *search_ctx = NULL;
|
||||||
fname = find_file_in_path(eap->arg, (int)STRLEN(eap->arg),
|
|
||||||
FNAME_MESS, TRUE, curbuf->b_ffname,
|
if (*get_findexpr() != NUL)
|
||||||
&file_to_find, &search_ctx);
|
{
|
||||||
vim_free(file_to_find);
|
#ifdef FEAT_EVAL
|
||||||
vim_findfile_cleanup(search_ctx);
|
fname = findexpr_find_file(eap->arg, (int)STRLEN(eap->arg),
|
||||||
|
eap->addr_count > 0 ? eap->line2 : 1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fname = find_file_in_path(eap->arg, (int)STRLEN(eap->arg),
|
||||||
|
FNAME_MESS, TRUE, curbuf->b_ffname,
|
||||||
|
&file_to_find, &search_ctx);
|
||||||
|
vim_free(file_to_find);
|
||||||
|
vim_findfile_cleanup(search_ctx);
|
||||||
|
}
|
||||||
if (fname == NULL)
|
if (fname == NULL)
|
||||||
goto theend;
|
goto theend;
|
||||||
eap->arg = fname;
|
eap->arg = fname;
|
||||||
@ -7241,27 +7349,37 @@ ex_find(exarg_T *eap)
|
|||||||
if (!check_can_set_curbuf_forceit(eap->forceit))
|
if (!check_can_set_curbuf_forceit(eap->forceit))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
char_u *fname;
|
char_u *fname = NULL;
|
||||||
int count;
|
int count;
|
||||||
char_u *file_to_find = NULL;
|
char_u *file_to_find = NULL;
|
||||||
char *search_ctx = NULL;
|
char *search_ctx = NULL;
|
||||||
|
|
||||||
fname = find_file_in_path(eap->arg, (int)STRLEN(eap->arg), FNAME_MESS,
|
if (*get_findexpr() != NUL)
|
||||||
TRUE, curbuf->b_ffname, &file_to_find, &search_ctx);
|
|
||||||
if (eap->addr_count > 0)
|
|
||||||
{
|
{
|
||||||
// Repeat finding the file "count" times. This matters when it appears
|
#ifdef FEAT_EVAL
|
||||||
// several times in the path.
|
fname = findexpr_find_file(eap->arg, (int)STRLEN(eap->arg),
|
||||||
count = eap->line2;
|
eap->addr_count > 0 ? eap->line2 : 1);
|
||||||
while (fname != NULL && --count > 0)
|
#endif
|
||||||
{
|
}
|
||||||
vim_free(fname);
|
else
|
||||||
fname = find_file_in_path(NULL, 0, FNAME_MESS,
|
{
|
||||||
FALSE, curbuf->b_ffname, &file_to_find, &search_ctx);
|
fname = find_file_in_path(eap->arg, (int)STRLEN(eap->arg), FNAME_MESS,
|
||||||
}
|
TRUE, curbuf->b_ffname, &file_to_find, &search_ctx);
|
||||||
|
if (eap->addr_count > 0)
|
||||||
|
{
|
||||||
|
// Repeat finding the file "count" times. This matters when it appears
|
||||||
|
// several times in the path.
|
||||||
|
count = eap->line2;
|
||||||
|
while (fname != NULL && --count > 0)
|
||||||
|
{
|
||||||
|
vim_free(fname);
|
||||||
|
fname = find_file_in_path(NULL, 0, FNAME_MESS,
|
||||||
|
FALSE, curbuf->b_ffname, &file_to_find, &search_ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VIM_CLEAR(file_to_find);
|
||||||
|
vim_findfile_cleanup(search_ctx);
|
||||||
}
|
}
|
||||||
VIM_CLEAR(file_to_find);
|
|
||||||
vim_findfile_cleanup(search_ctx);
|
|
||||||
|
|
||||||
if (fname == NULL)
|
if (fname == NULL)
|
||||||
return;
|
return;
|
||||||
|
31
src/option.c
31
src/option.c
@ -6313,6 +6313,11 @@ unset_global_local_option(char_u *name, void *from)
|
|||||||
case PV_FP:
|
case PV_FP:
|
||||||
clear_string_option(&buf->b_p_fp);
|
clear_string_option(&buf->b_p_fp);
|
||||||
break;
|
break;
|
||||||
|
# ifdef FEAT_EVAL
|
||||||
|
case PV_FEXPR:
|
||||||
|
clear_string_option(&buf->b_p_fexpr);
|
||||||
|
break;
|
||||||
|
# endif
|
||||||
# ifdef FEAT_QUICKFIX
|
# ifdef FEAT_QUICKFIX
|
||||||
case PV_EFM:
|
case PV_EFM:
|
||||||
clear_string_option(&buf->b_p_efm);
|
clear_string_option(&buf->b_p_efm);
|
||||||
@ -6391,6 +6396,9 @@ get_varp_scope(struct vimoption *p, int scope)
|
|||||||
switch ((int)p->indir)
|
switch ((int)p->indir)
|
||||||
{
|
{
|
||||||
case PV_FP: return (char_u *)&(curbuf->b_p_fp);
|
case PV_FP: return (char_u *)&(curbuf->b_p_fp);
|
||||||
|
#ifdef FEAT_EVAL
|
||||||
|
case PV_FEXPR: return (char_u *)&(curbuf->b_p_fexpr);
|
||||||
|
#endif
|
||||||
#ifdef FEAT_QUICKFIX
|
#ifdef FEAT_QUICKFIX
|
||||||
case PV_EFM: return (char_u *)&(curbuf->b_p_efm);
|
case PV_EFM: return (char_u *)&(curbuf->b_p_efm);
|
||||||
case PV_GP: return (char_u *)&(curbuf->b_p_gp);
|
case PV_GP: return (char_u *)&(curbuf->b_p_gp);
|
||||||
@ -6501,6 +6509,10 @@ get_varp(struct vimoption *p)
|
|||||||
#endif
|
#endif
|
||||||
case PV_FP: return *curbuf->b_p_fp != NUL
|
case PV_FP: return *curbuf->b_p_fp != NUL
|
||||||
? (char_u *)&(curbuf->b_p_fp) : p->var;
|
? (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;
|
||||||
|
#endif
|
||||||
#ifdef FEAT_QUICKFIX
|
#ifdef FEAT_QUICKFIX
|
||||||
case PV_EFM: return *curbuf->b_p_efm != NUL
|
case PV_EFM: return *curbuf->b_p_efm != NUL
|
||||||
? (char_u *)&(curbuf->b_p_efm) : p->var;
|
? (char_u *)&(curbuf->b_p_efm) : p->var;
|
||||||
@ -6747,6 +6759,21 @@ get_equalprg(void)
|
|||||||
return curbuf->b_p_ep;
|
return curbuf->b_p_ep;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the value of 'findexpr', either the buffer-local one or the global one.
|
||||||
|
*/
|
||||||
|
char_u *
|
||||||
|
get_findexpr(void)
|
||||||
|
{
|
||||||
|
#ifdef FEAT_EVAL
|
||||||
|
if (*curbuf->b_p_fexpr == NUL)
|
||||||
|
return p_fexpr;
|
||||||
|
return curbuf->b_p_fexpr;
|
||||||
|
#else
|
||||||
|
return (char_u *)"";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copy options from one window to another.
|
* Copy options from one window to another.
|
||||||
* Used when splitting a window.
|
* Used when splitting a window.
|
||||||
@ -7275,6 +7302,10 @@ buf_copy_options(buf_T *buf, int flags)
|
|||||||
buf->b_p_efm = empty_option;
|
buf->b_p_efm = empty_option;
|
||||||
#endif
|
#endif
|
||||||
buf->b_p_ep = empty_option;
|
buf->b_p_ep = empty_option;
|
||||||
|
#if defined(FEAT_EVAL)
|
||||||
|
buf->b_p_fexpr = vim_strsave(p_fexpr);
|
||||||
|
COPY_OPT_SCTX(buf, BV_FEXPR);
|
||||||
|
#endif
|
||||||
buf->b_p_kp = empty_option;
|
buf->b_p_kp = empty_option;
|
||||||
buf->b_p_path = empty_option;
|
buf->b_p_path = empty_option;
|
||||||
buf->b_p_tags = empty_option;
|
buf->b_p_tags = empty_option;
|
||||||
|
@ -596,6 +596,9 @@ EXTERN char_u *p_ffs; // 'fileformats'
|
|||||||
EXTERN int p_fic; // 'fileignorecase'
|
EXTERN int p_fic; // 'fileignorecase'
|
||||||
EXTERN char_u *p_ft; // 'filetype'
|
EXTERN char_u *p_ft; // 'filetype'
|
||||||
EXTERN char_u *p_fcs; // 'fillchar'
|
EXTERN char_u *p_fcs; // 'fillchar'
|
||||||
|
#ifdef FEAT_EVAL
|
||||||
|
EXTERN char_u *p_fexpr; // 'findexpr'
|
||||||
|
#endif
|
||||||
EXTERN int p_fixeol; // 'fixendofline'
|
EXTERN int p_fixeol; // 'fixendofline'
|
||||||
#ifdef FEAT_FOLDING
|
#ifdef FEAT_FOLDING
|
||||||
EXTERN char_u *p_fcl; // 'foldclose'
|
EXTERN char_u *p_fcl; // 'foldclose'
|
||||||
@ -1168,6 +1171,7 @@ enum
|
|||||||
, BV_EP
|
, BV_EP
|
||||||
, BV_ET
|
, BV_ET
|
||||||
, BV_FENC
|
, BV_FENC
|
||||||
|
, BV_FEXPR
|
||||||
, BV_FP
|
, BV_FP
|
||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
, BV_BEXPR
|
, BV_BEXPR
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
#define PV_FP OPT_BOTH(OPT_BUF(BV_FP))
|
#define PV_FP OPT_BOTH(OPT_BUF(BV_FP))
|
||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
# define PV_FEX OPT_BUF(BV_FEX)
|
# define PV_FEX OPT_BUF(BV_FEX)
|
||||||
|
# define PV_FEXPR OPT_BOTH(OPT_BUF(BV_FEXPR))
|
||||||
#endif
|
#endif
|
||||||
#define PV_FF OPT_BUF(BV_FF)
|
#define PV_FF OPT_BUF(BV_FF)
|
||||||
#define PV_FLP OPT_BUF(BV_FLP)
|
#define PV_FLP OPT_BUF(BV_FLP)
|
||||||
@ -958,6 +959,15 @@ static struct vimoption options[] =
|
|||||||
{(char_u *)"vert:|,fold:-,eob:~,lastline:@",
|
{(char_u *)"vert:|,fold:-,eob:~,lastline:@",
|
||||||
(char_u *)0L}
|
(char_u *)0L}
|
||||||
SCTX_INIT},
|
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,
|
||||||
|
{(char_u *)"", (char_u *)0L}
|
||||||
|
#else
|
||||||
|
(char_u *)NULL, PV_NONE, NULL, NULL,
|
||||||
|
{(char_u *)0L, (char_u *)0L}
|
||||||
|
#endif
|
||||||
|
SCTX_INIT},
|
||||||
{"fixendofline", "fixeol", P_BOOL|P_VI_DEF|P_RSTAT,
|
{"fixendofline", "fixeol", P_BOOL|P_VI_DEF|P_RSTAT,
|
||||||
(char_u *)&p_fixeol, PV_FIXEOL,
|
(char_u *)&p_fixeol, PV_FIXEOL,
|
||||||
did_set_eof_eol_fixeol_bomb, NULL,
|
did_set_eof_eol_fixeol_bomb, NULL,
|
||||||
|
@ -324,6 +324,9 @@ check_buf_options(buf_T *buf)
|
|||||||
check_string_option(&buf->b_p_efm);
|
check_string_option(&buf->b_p_efm);
|
||||||
#endif
|
#endif
|
||||||
check_string_option(&buf->b_p_ep);
|
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_path);
|
||||||
check_string_option(&buf->b_p_tags);
|
check_string_option(&buf->b_p_tags);
|
||||||
check_string_option(&buf->b_p_tc);
|
check_string_option(&buf->b_p_tc);
|
||||||
@ -3132,8 +3135,8 @@ expand_set_nrformats(optexpand_T *args, int *numMatches, char_u ***matches)
|
|||||||
#if defined(FEAT_EVAL) || defined(PROTO)
|
#if defined(FEAT_EVAL) || defined(PROTO)
|
||||||
/*
|
/*
|
||||||
* One of the '*expr' options is changed: 'balloonexpr', 'diffexpr',
|
* One of the '*expr' options is changed: 'balloonexpr', 'diffexpr',
|
||||||
* 'foldexpr', 'foldtext', 'formatexpr', 'includeexpr', 'indentexpr',
|
* 'findexpr', 'foldexpr', 'foldtext', 'formatexpr', 'includeexpr',
|
||||||
* 'patchexpr', 'printexpr' and 'charconvert'.
|
* 'indentexpr', 'patchexpr', 'printexpr' and 'charconvert'.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
char *
|
char *
|
||||||
|
@ -120,6 +120,7 @@ char_u *get_option_var(int opt_idx);
|
|||||||
char_u *get_option_fullname(int opt_idx);
|
char_u *get_option_fullname(int opt_idx);
|
||||||
opt_did_set_cb_T get_option_did_set_cb(int opt_idx);
|
opt_did_set_cb_T get_option_did_set_cb(int opt_idx);
|
||||||
char_u *get_equalprg(void);
|
char_u *get_equalprg(void);
|
||||||
|
char_u *get_findexpr(void);
|
||||||
void win_copy_options(win_T *wp_from, win_T *wp_to);
|
void win_copy_options(win_T *wp_from, win_T *wp_to);
|
||||||
void after_copy_winopt(win_T *wp);
|
void after_copy_winopt(win_T *wp);
|
||||||
void copy_winopt(winopt_T *from, winopt_T *to);
|
void copy_winopt(winopt_T *from, winopt_T *to);
|
||||||
|
@ -3327,6 +3327,9 @@ struct file_buffer
|
|||||||
char_u *b_p_efm; // 'errorformat' local value
|
char_u *b_p_efm; // 'errorformat' local value
|
||||||
#endif
|
#endif
|
||||||
char_u *b_p_ep; // 'equalprg' local value
|
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
|
char_u *b_p_path; // 'path' local value
|
||||||
int b_p_ar; // 'autoread' local value
|
int b_p_ar; // 'autoread' local value
|
||||||
char_u *b_p_tags; // 'tags' local value
|
char_u *b_p_tags; // 'tags' local value
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
" Test findfile() and finddir()
|
" Test findfile() and finddir()
|
||||||
|
|
||||||
|
source check.vim
|
||||||
|
|
||||||
let s:files = [ 'Xfinddir1/foo',
|
let s:files = [ 'Xfinddir1/foo',
|
||||||
\ 'Xfinddir1/bar',
|
\ 'Xfinddir1/bar',
|
||||||
\ 'Xfinddir1/Xdir2/foo',
|
\ 'Xfinddir1/Xdir2/foo',
|
||||||
@ -281,4 +283,170 @@ func Test_find_non_existing_path()
|
|||||||
let &path = save_path
|
let &path = save_path
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
" Test for 'findexpr'
|
||||||
|
func Test_findexpr()
|
||||||
|
CheckUnix
|
||||||
|
call assert_equal('', &findexpr)
|
||||||
|
call writefile(['aFile'], 'Xfindexpr1.c', 'D')
|
||||||
|
call writefile(['bFile'], 'Xfindexpr2.c', 'D')
|
||||||
|
call writefile(['cFile'], 'Xfindexpr3.c', 'D')
|
||||||
|
|
||||||
|
" basic tests
|
||||||
|
func FindExpr1()
|
||||||
|
let fnames = ['Xfindexpr1.c', 'Xfindexpr2.c', 'Xfindexpr3.c']
|
||||||
|
"return fnames->copy()->filter('v:val =~? v:fname')->join("\n")
|
||||||
|
return fnames->copy()->filter('v:val =~? v:fname')
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
set findexpr=FindExpr1()
|
||||||
|
find Xfindexpr3
|
||||||
|
call assert_match('Xfindexpr3.c', @%)
|
||||||
|
bw!
|
||||||
|
2find Xfind
|
||||||
|
call assert_match('Xfindexpr2.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', @%)
|
||||||
|
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', @%)
|
||||||
|
call assert_equal(2, tabpagenr())
|
||||||
|
%bw!
|
||||||
|
call assert_fails('tabfind foobar', 'E345: Can''t find file "foobar" in path')
|
||||||
|
|
||||||
|
" Buffer-local option
|
||||||
|
set findexpr=['abc']
|
||||||
|
new
|
||||||
|
setlocal findexpr=['def']
|
||||||
|
find xxxx
|
||||||
|
call assert_equal('def', @%)
|
||||||
|
wincmd w
|
||||||
|
find xxxx
|
||||||
|
call assert_equal('abc', @%)
|
||||||
|
aboveleft new
|
||||||
|
call assert_equal("['abc']", &findexpr)
|
||||||
|
wincmd k
|
||||||
|
aboveleft new
|
||||||
|
call assert_equal("['abc']", &findexpr)
|
||||||
|
%bw!
|
||||||
|
|
||||||
|
" Empty list
|
||||||
|
set findexpr=[]
|
||||||
|
call assert_fails('find xxxx', 'E345: Can''t find file "xxxx" in path')
|
||||||
|
|
||||||
|
" Error cases
|
||||||
|
|
||||||
|
" Syntax error in the expression
|
||||||
|
set findexpr=FindExpr1{}
|
||||||
|
call assert_fails('find Xfindexpr1.c', 'E15: Invalid expression')
|
||||||
|
|
||||||
|
" Find expression throws an error
|
||||||
|
func FindExpr2()
|
||||||
|
throw 'find error'
|
||||||
|
endfunc
|
||||||
|
set findexpr=FindExpr2()
|
||||||
|
call assert_fails('find Xfindexpr1.c', 'find error')
|
||||||
|
|
||||||
|
" Try using a null string as the expression
|
||||||
|
set findexpr=test_null_string()
|
||||||
|
call assert_fails('find Xfindexpr1.c', 'E345: Can''t find file "Xfindexpr1.c" in path')
|
||||||
|
|
||||||
|
" Try to create a new window from the find expression
|
||||||
|
func FindExpr3()
|
||||||
|
new
|
||||||
|
return ["foo"]
|
||||||
|
endfunc
|
||||||
|
set findexpr=FindExpr3()
|
||||||
|
call assert_fails('find Xfindexpr1.c', 'E565: Not allowed to change text or change window')
|
||||||
|
|
||||||
|
" Try to modify the current buffer from the find expression
|
||||||
|
func FindExpr4()
|
||||||
|
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 findexpr&
|
||||||
|
delfunc! FindExpr1
|
||||||
|
delfunc! FindExpr2
|
||||||
|
delfunc! FindExpr3
|
||||||
|
delfunc! FindExpr4
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" Test for using a script-local function for 'findexpr'
|
||||||
|
func Test_findexpr_scriptlocal_func()
|
||||||
|
func! s:FindExprScript()
|
||||||
|
let g:FindExprArg = v:fname
|
||||||
|
return ['xxx']
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
set findexpr=s:FindExprScript()
|
||||||
|
call assert_equal(expand('<SID>') .. 'FindExprScript()', &findexpr)
|
||||||
|
call assert_equal(expand('<SID>') .. 'FindExprScript()', &g:findexpr)
|
||||||
|
new | only
|
||||||
|
let g:FindExprArg = ''
|
||||||
|
find abc
|
||||||
|
call assert_equal('abc', g:FindExprArg)
|
||||||
|
bw!
|
||||||
|
|
||||||
|
set findexpr=<SID>FindExprScript()
|
||||||
|
call assert_equal(expand('<SID>') .. 'FindExprScript()', &findexpr)
|
||||||
|
call assert_equal(expand('<SID>') .. 'FindExprScript()', &g:findexpr)
|
||||||
|
new | only
|
||||||
|
let g:FindExprArg = ''
|
||||||
|
find abc
|
||||||
|
call assert_equal('abc', g:FindExprArg)
|
||||||
|
bw!
|
||||||
|
|
||||||
|
let &findexpr = 's:FindExprScript()'
|
||||||
|
call assert_equal(expand('<SID>') .. 'FindExprScript()', &g:findexpr)
|
||||||
|
new | only
|
||||||
|
let g:FindExprArg = ''
|
||||||
|
find abc
|
||||||
|
call assert_equal('abc', g:FindExprArg)
|
||||||
|
bw!
|
||||||
|
|
||||||
|
let &findexpr = '<SID>FindExprScript()'
|
||||||
|
call assert_equal(expand('<SID>') .. 'FindExprScript()', &g:findexpr)
|
||||||
|
new | only
|
||||||
|
let g:FindExprArg = ''
|
||||||
|
find abc
|
||||||
|
call assert_equal('abc', g:FindExprArg)
|
||||||
|
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)
|
||||||
|
new | only
|
||||||
|
let g:FindExprArg = ''
|
||||||
|
find abc
|
||||||
|
call assert_equal('abc', g:FindExprArg)
|
||||||
|
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 = ''
|
||||||
|
find abc
|
||||||
|
call assert_equal('abc', g:FindExprArg)
|
||||||
|
bw!
|
||||||
|
|
||||||
|
set findexpr=
|
||||||
|
delfunc s:FindExprScript
|
||||||
|
endfunc
|
||||||
|
|
||||||
" vim: shiftwidth=2 sts=2 expandtab
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
@ -208,6 +208,7 @@ func Test_modeline_fails_always()
|
|||||||
call s:modeline_fails('equalprg', 'equalprg=Something()', 'E520:')
|
call s:modeline_fails('equalprg', 'equalprg=Something()', 'E520:')
|
||||||
call s:modeline_fails('errorfile', 'errorfile=Something()', 'E520:')
|
call s:modeline_fails('errorfile', 'errorfile=Something()', 'E520:')
|
||||||
call s:modeline_fails('exrc', 'exrc=Something()', 'E520:')
|
call s:modeline_fails('exrc', 'exrc=Something()', 'E520:')
|
||||||
|
call s:modeline_fails('findexpr', 'findexpr=Something()', 'E520:')
|
||||||
call s:modeline_fails('formatprg', 'formatprg=Something()', 'E520:')
|
call s:modeline_fails('formatprg', 'formatprg=Something()', 'E520:')
|
||||||
call s:modeline_fails('fsync', 'fsync=Something()', 'E520:')
|
call s:modeline_fails('fsync', 'fsync=Something()', 'E520:')
|
||||||
call s:modeline_fails('grepprg', 'grepprg=Something()', 'E520:')
|
call s:modeline_fails('grepprg', 'grepprg=Something()', 'E520:')
|
||||||
|
@ -1570,7 +1570,7 @@ endfunc
|
|||||||
|
|
||||||
" Test for changing options in a sandbox
|
" Test for changing options in a sandbox
|
||||||
func Test_opt_sandbox()
|
func Test_opt_sandbox()
|
||||||
for opt in ['backupdir', 'cdpath', 'exrc']
|
for opt in ['backupdir', 'cdpath', 'exrc', 'findexpr']
|
||||||
call assert_fails('sandbox set ' .. opt .. '?', 'E48:')
|
call assert_fails('sandbox set ' .. opt .. '?', 'E48:')
|
||||||
call assert_fails('sandbox let &' .. opt .. ' = 1', 'E48:')
|
call assert_fails('sandbox let &' .. opt .. ' = 1', 'E48:')
|
||||||
endfor
|
endfor
|
||||||
|
@ -704,6 +704,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
810,
|
||||||
/**/
|
/**/
|
||||||
809,
|
809,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user