0
0
mirror of https://github.com/vim/vim.git synced 2025-07-26 11:04:33 -04:00

patch 9.1.0821: 'findexpr' completion doesn't set v:fname to cmdline argument

Problem:  'findexpr' completion doesn't set v:fname to cmdline argument.
Solution: Set v:fname to the cmdline argument as-is (zeertzjq).

closes: #15934

Signed-off-by: zeertzjq <zeertzjq@outlook.com>
Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
zeertzjq 2024-10-28 22:05:26 +01:00 committed by Christian Brabandt
parent baab7c0865
commit 20e045f781
No known key found for this signature in database
GPG Key ID: F3F92DA383FDDE09
10 changed files with 75 additions and 38 deletions

View File

@ -1,4 +1,4 @@
*eval.txt* For Vim version 9.1. Last change: 2024 Oct 22 *eval.txt* For Vim version 9.1. Last change: 2024 Oct 28
VIM REFERENCE MANUAL by Bram Moolenaar VIM REFERENCE MANUAL by Bram Moolenaar
@ -2026,6 +2026,11 @@ v:cmdbang Set like v:cmdarg for a file read/write command. When a "!"
was used the value is 1, otherwise it is 0. Note that this was used the value is 1, otherwise it is 0. Note that this
can only be used in autocommands. For user commands |<bang>| can only be used in autocommands. For user commands |<bang>|
can be used. 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* *collate-variable*
v:collate The current locale setting for collation order of the runtime v:collate The current locale setting for collation order of the runtime
environment. This allows Vim scripts to be aware of the environment. This allows Vim scripts to be aware of the

View File

@ -1,4 +1,4 @@
*options.txt* For Vim version 9.1. Last change: 2024 Oct 22 *options.txt* For Vim version 9.1. Last change: 2024 Oct 28
VIM REFERENCE MANUAL by Bram Moolenaar VIM REFERENCE MANUAL by Bram Moolenaar
@ -3567,6 +3567,10 @@ A jump table for the options with a short description can be found at |Q_op|.
The expression is evaluated only once per |:find| command invocation. The expression is evaluated only once per |:find| command invocation.
The expression can process all the directories specified in 'path'. The expression can process all the directories specified in 'path'.
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|.
If a match is found, the expression should return a |List| containing 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 one or more file names. If a match is not found, the expression
should return an empty List. should return an empty List.
@ -3586,7 +3590,8 @@ A jump table for the options with a short description can be found at |Q_op|.
> >
" Use glob() " Use glob()
func FindExprGlob() func FindExprGlob()
return glob(v:fname, v:false, v:true) let pat = v:cmdcomplete ? $'{v:fname}*' : v:fname
return glob(pat, v:false, v:true)
endfunc endfunc
set findexpr=FindExprGlob() set findexpr=FindExprGlob()

View File

@ -6510,6 +6510,7 @@ close_cb channel.txt /*close_cb*
closure eval.txt /*closure* closure eval.txt /*closure*
cmdarg-variable eval.txt /*cmdarg-variable* cmdarg-variable eval.txt /*cmdarg-variable*
cmdbang-variable eval.txt /*cmdbang-variable* cmdbang-variable eval.txt /*cmdbang-variable*
cmdcomplete-variable eval.txt /*cmdcomplete-variable*
cmdline-arguments vi_diff.txt /*cmdline-arguments* cmdline-arguments vi_diff.txt /*cmdline-arguments*
cmdline-changed version5.txt /*cmdline-changed* cmdline-changed version5.txt /*cmdline-changed*
cmdline-completion cmdline.txt /*cmdline-completion* cmdline-completion cmdline.txt /*cmdline-completion*
@ -10933,6 +10934,7 @@ v:charconvert_from eval.txt /*v:charconvert_from*
v:charconvert_to eval.txt /*v:charconvert_to* v:charconvert_to eval.txt /*v:charconvert_to*
v:cmdarg eval.txt /*v:cmdarg* v:cmdarg eval.txt /*v:cmdarg*
v:cmdbang eval.txt /*v:cmdbang* v:cmdbang eval.txt /*v:cmdbang*
v:cmdcomplete eval.txt /*v:cmdcomplete*
v:collate eval.txt /*v:collate* v:collate eval.txt /*v:collate*
v:colornames eval.txt /*v:colornames* v:colornames eval.txt /*v:colornames*
v:completed_item eval.txt /*v:completed_item* v:completed_item eval.txt /*v:completed_item*

View File

@ -50,6 +50,7 @@ cmdline_fuzzy_completion_supported(expand_T *xp)
&& xp->xp_context != EXPAND_FILES && xp->xp_context != EXPAND_FILES
&& xp->xp_context != EXPAND_FILES_IN_PATH && xp->xp_context != EXPAND_FILES_IN_PATH
&& xp->xp_context != EXPAND_FILETYPE && xp->xp_context != EXPAND_FILETYPE
&& xp->xp_context != EXPAND_FINDEXPR
&& xp->xp_context != EXPAND_HELP && xp->xp_context != EXPAND_HELP
&& xp->xp_context != EXPAND_KEYMAP && xp->xp_context != EXPAND_KEYMAP
&& xp->xp_context != EXPAND_OLD_SETTING && xp->xp_context != EXPAND_OLD_SETTING
@ -1418,7 +1419,8 @@ addstar(
// For help tags the translation is done in find_help_tags(). // For help tags the translation is done in find_help_tags().
// For a tag pattern starting with "/" no translation is needed. // For a tag pattern starting with "/" no translation is needed.
if (context == EXPAND_HELP if (context == EXPAND_FINDEXPR
|| context == EXPAND_HELP
|| context == EXPAND_COLORS || context == EXPAND_COLORS
|| context == EXPAND_COMPILER || context == EXPAND_COMPILER
|| context == EXPAND_OWNSYNTAX || context == EXPAND_OWNSYNTAX
@ -2138,7 +2140,8 @@ set_context_by_cmdname(
case CMD_sfind: case CMD_sfind:
case CMD_tabfind: case CMD_tabfind:
if (xp->xp_context == EXPAND_FILES) if (xp->xp_context == EXPAND_FILES)
xp->xp_context = EXPAND_FILES_IN_PATH; xp->xp_context = *get_findexpr() != NUL ? EXPAND_FINDEXPR
: EXPAND_FILES_IN_PATH;
break; break;
case CMD_cd: case CMD_cd:
case CMD_chdir: case CMD_chdir:
@ -2850,7 +2853,7 @@ expand_files_and_dirs(
} }
} }
if (xp->xp_context == EXPAND_FILES_IN_PATH && *get_findexpr() != NUL) if (xp->xp_context == EXPAND_FINDEXPR)
{ {
#ifdef FEAT_EVAL #ifdef FEAT_EVAL
ret = expand_findexpr(pat, matches, numMatches); ret = expand_findexpr(pat, matches, numMatches);
@ -3119,6 +3122,7 @@ ExpandFromContext(
if (xp->xp_context == EXPAND_FILES if (xp->xp_context == EXPAND_FILES
|| xp->xp_context == EXPAND_DIRECTORIES || xp->xp_context == EXPAND_DIRECTORIES
|| xp->xp_context == EXPAND_FILES_IN_PATH || xp->xp_context == EXPAND_FILES_IN_PATH
|| xp->xp_context == EXPAND_FINDEXPR
|| xp->xp_context == EXPAND_DIRS_IN_CDPATH) || xp->xp_context == EXPAND_DIRS_IN_CDPATH)
return expand_files_and_dirs(xp, pat, matches, numMatches, flags, return expand_files_and_dirs(xp, pat, matches, numMatches, flags,
options); options);

View File

@ -3653,4 +3653,4 @@ EXTERN char e_wrong_character_width_for_field_str[]
EXTERN char e_winfixbuf_cannot_go_to_buffer[] EXTERN char e_winfixbuf_cannot_go_to_buffer[]
INIT(= N_("E1513: Cannot switch buffer. 'winfixbuf' is enabled")); INIT(= N_("E1513: Cannot switch buffer. 'winfixbuf' is enabled"));
EXTERN char e_invalid_return_type_from_findexpr[] EXTERN char e_invalid_return_type_from_findexpr[]
INIT(= N_("E1514: findexpr did not return a List type")); INIT(= N_("E1514: 'findexpr' did not return a List type"));

View File

@ -161,6 +161,7 @@ static struct vimvar
{VV_NAME("t_typealias", 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_enum", VAR_NUMBER), NULL, VV_RO},
{VV_NAME("t_enumvalue", VAR_NUMBER), NULL, VV_RO}, {VV_NAME("t_enumvalue", VAR_NUMBER), NULL, VV_RO},
{VV_NAME("cmdcomplete", VAR_BOOL), NULL, VV_RO},
}; };
// shorthand // shorthand
@ -234,6 +235,7 @@ evalvars_init(void)
set_vim_var_nr(VV_SEARCHFORWARD, 1L); set_vim_var_nr(VV_SEARCHFORWARD, 1L);
set_vim_var_nr(VV_HLSEARCH, 1L); set_vim_var_nr(VV_HLSEARCH, 1L);
set_vim_var_nr(VV_EXITING, VVAL_NULL); 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_dict(VV_COMPLETED_ITEM, dict_alloc_lock(VAR_FIXED));
set_vim_var_list(VV_ERRORS, list_alloc()); set_vim_var_list(VV_ERRORS, list_alloc());
set_vim_var_dict(VV_EVENT, dict_alloc_lock(VAR_FIXED)); set_vim_var_dict(VV_EVENT, dict_alloc_lock(VAR_FIXED));

View File

@ -6929,7 +6929,7 @@ ex_wrongmodifier(exarg_T *eap)
* the expression, v:fname is set to the ":find" command argument. * the expression, v:fname is set to the ":find" command argument.
*/ */
static list_T * static list_T *
eval_findexpr(char_u *ptr) eval_findexpr(char_u *pat, int cmdcomplete)
{ {
sctx_T saved_sctx = current_sctx; sctx_T saved_sctx = current_sctx;
char_u *findexpr; char_u *findexpr;
@ -6939,7 +6939,8 @@ eval_findexpr(char_u *ptr)
findexpr = get_findexpr(); findexpr = get_findexpr();
set_vim_var_string(VV_FNAME, ptr, -1); 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]; current_sctx = curbuf->b_p_script_ctx[BV_FEXPR];
arg = skipwhite(findexpr); arg = skipwhite(findexpr);
@ -6962,6 +6963,7 @@ eval_findexpr(char_u *ptr)
clear_evalarg(&EVALARG_EVALUATE, NULL); clear_evalarg(&EVALARG_EVALUATE, NULL);
set_vim_var_string(VV_FNAME, NULL, 0); set_vim_var_string(VV_FNAME, NULL, 0);
set_vim_var_nr(VV_CMDCOMPLETE, VVAL_FALSE);
current_sctx = saved_sctx; current_sctx = saved_sctx;
return retlist; return retlist;
@ -6977,21 +6979,11 @@ expand_findexpr(char_u *pat, char_u ***files, int *numMatches)
{ {
list_T *l; list_T *l;
int len; int len;
char_u *regpat;
*numMatches = 0; *numMatches = 0;
*files = NULL; *files = NULL;
// File name expansion uses wildchars. But the 'findexpr' expression l = eval_findexpr(pat, TRUE);
// expects a regular expression argument. So convert wildchars in the
// argument to regular expression patterns.
regpat = file_pat_to_reg_pat(pat, NULL, NULL, FALSE);
if (regpat == NULL)
return FAIL;
l = eval_findexpr(regpat);
vim_free(regpat);
if (l == NULL) if (l == NULL)
return FAIL; return FAIL;
@ -7037,7 +7029,7 @@ findexpr_find_file(char_u *findarg, int findarg_len, int count)
cc = findarg[findarg_len]; cc = findarg[findarg_len];
findarg[findarg_len] = NUL; findarg[findarg_len] = NUL;
fname_list = eval_findexpr(findarg); fname_list = eval_findexpr(findarg, FALSE);
fname_count = list_len(fname_list); fname_count = list_len(fname_list);
if (fname_count == 0) if (fname_count == 0)

View File

@ -374,7 +374,7 @@ func Test_findexpr()
" Expression returning a string " Expression returning a string
set findexpr='abc' set findexpr='abc'
call assert_fails('find Xfindexpr1.c', 'E1514: findexpr did not return a List type') call assert_fails('find Xfindexpr1.c', "E1514: 'findexpr' did not return a List type")
set findexpr& set findexpr&
delfunc! FindExpr1 delfunc! FindExpr1
@ -454,11 +454,21 @@ endfunc
" Test for expanding the argument to the :find command using 'findexpr' " Test for expanding the argument to the :find command using 'findexpr'
func Test_findexpr_expand_arg() func Test_findexpr_expand_arg()
func FindExpr1() let s:fnames = ['Xfindexpr1.c', 'Xfindexpr2.c', 'Xfindexpr3.c']
let fnames = ['Xfindexpr1.c', 'Xfindexpr2.c', 'Xfindexpr3.c']
return fnames->copy()->filter('v:val =~? v:fname') " 'findexpr' that accepts a regular expression
func FindExprRegexp()
return s:fnames->copy()->filter('v:val =~? v:fname')
endfunc endfunc
set findexpr=FindExpr1()
" 'findexpr' that accepts a glob
func FindExprGlob()
let pat = glob2regpat(v:cmdcomplete ? $'*{v:fname}*' : v:fname)
return s:fnames->copy()->filter('v:val =~? pat')
endfunc
for regexp in [v:true, v:false]
let &findexpr = regexp ? 'FindExprRegexp()' : 'FindExprGlob()'
call feedkeys(":find \<Tab>\<C-B>\"\<CR>", "xt") call feedkeys(":find \<Tab>\<C-B>\"\<CR>", "xt")
call assert_equal('"find Xfindexpr1.c', @:) call assert_equal('"find Xfindexpr1.c', @:)
@ -466,17 +476,30 @@ func Test_findexpr_expand_arg()
call feedkeys(":find Xfind\<Tab>\<Tab>\<C-B>\"\<CR>", "xt") call feedkeys(":find Xfind\<Tab>\<Tab>\<C-B>\"\<CR>", "xt")
call assert_equal('"find Xfindexpr2.c', @:) call assert_equal('"find Xfindexpr2.c', @:)
call feedkeys(":find *3*\<Tab>\<C-B>\"\<CR>", "xt") 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 feedkeys(":find 3\<Tab>\<C-B>\"\<CR>", "xt")
call assert_equal('"find Xfindexpr3.c', @:) call assert_equal('"find Xfindexpr3.c', @:)
call assert_equal(['Xfindexpr3.c'], getcompletion($'find 3', 'cmdline'))
call feedkeys(":find Xfind\<C-A>\<C-B>\"\<CR>", "xt") call feedkeys(":find Xfind\<C-A>\<C-B>\"\<CR>", "xt")
call assert_equal('"find Xfindexpr1.c Xfindexpr2.c Xfindexpr3.c', @:) call assert_equal('"find Xfindexpr1.c Xfindexpr2.c Xfindexpr3.c', @:)
call feedkeys(":find abc\<Tab>\<C-B>\"\<CR>", "xt") call feedkeys(":find abc\<Tab>\<C-B>\"\<CR>", "xt")
call assert_equal('"find abc', @:) call assert_equal('"find abc', @:)
call assert_equal([], getcompletion('find abc', 'cmdline'))
endfor
set findexpr& set findexpr&
delfunc! FindExpr1 delfunc! FindExprRegexp
delfunc! FindExprGlob
unlet s:fnames
endfunc endfunc
" vim: shiftwidth=2 sts=2 expandtab " vim: shiftwidth=2 sts=2 expandtab

View File

@ -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 */
/**/
821,
/**/ /**/
820, 820,
/**/ /**/

View File

@ -845,6 +845,7 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring);
#define EXPAND_KEYMAP 58 #define EXPAND_KEYMAP 58
#define EXPAND_DIRS_IN_CDPATH 59 #define EXPAND_DIRS_IN_CDPATH 59
#define EXPAND_SHELLCMDLINE 60 #define EXPAND_SHELLCMDLINE 60
#define EXPAND_FINDEXPR 61
// Values for exmode_active (0 is no exmode) // Values for exmode_active (0 is no exmode)
@ -2188,7 +2189,8 @@ typedef int sock_T;
#define VV_TYPE_TYPEALIAS 107 #define VV_TYPE_TYPEALIAS 107
#define VV_TYPE_ENUM 108 #define VV_TYPE_ENUM 108
#define VV_TYPE_ENUMVALUE 109 #define VV_TYPE_ENUMVALUE 109
#define VV_LEN 110 // number of v: vars #define VV_CMDCOMPLETE 110
#define VV_LEN 111 // number of v: vars
// used for v_number in VAR_BOOL and VAR_SPECIAL // used for v_number in VAR_BOOL and VAR_SPECIAL
#define VVAL_FALSE 0L // VAR_BOOL #define VVAL_FALSE 0L // VAR_BOOL