Skip to content

Commit 20e045f

Browse files
zeertzjqchrisbra
authored andcommitted
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>
1 parent baab7c0 commit 20e045f

10 files changed

Lines changed: 75 additions & 38 deletions

File tree

runtime/doc/eval.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*eval.txt* For Vim version 9.1. Last change: 2024 Oct 22
1+
*eval.txt* For Vim version 9.1. Last change: 2024 Oct 28
22

33

44
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -2026,6 +2026,11 @@ v:cmdbang Set like v:cmdarg for a file read/write command. When a "!"
20262026
was used the value is 1, otherwise it is 0. Note that this
20272027
can only be used in autocommands. For user commands |<bang>|
20282028
can be used.
2029+
2030+
*v:cmdcomplete* *cmdcomplete-variable*
2031+
v:cmdcomplete When evaluating 'findexpr': if 'findexpr' is used for cmdline
2032+
completion the value is |v:true|, otherwise it is |v:false|.
2033+
20292034
*v:collate* *collate-variable*
20302035
v:collate The current locale setting for collation order of the runtime
20312036
environment. This allows Vim scripts to be aware of the

runtime/doc/options.txt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*options.txt* For Vim version 9.1. Last change: 2024 Oct 22
1+
*options.txt* For Vim version 9.1. Last change: 2024 Oct 28
22

33

44
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|.
35673567
The expression is evaluated only once per |:find| command invocation.
35683568
The expression can process all the directories specified in 'path'.
35693569

3570+
The expression may be evaluated for command-line completion as well,
3571+
in which case the |v:cmdcomplete| variable will be set to |v:true|,
3572+
otherwise it will be set to |v:false|.
3573+
35703574
If a match is found, the expression should return a |List| containing
35713575
one or more file names. If a match is not found, the expression
35723576
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|.
35863590
>
35873591
" Use glob()
35883592
func FindExprGlob()
3589-
return glob(v:fname, v:false, v:true)
3593+
let pat = v:cmdcomplete ? $'{v:fname}*' : v:fname
3594+
return glob(pat, v:false, v:true)
35903595
endfunc
35913596
set findexpr=FindExprGlob()
35923597

runtime/doc/tags

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6510,6 +6510,7 @@ close_cb channel.txt /*close_cb*
65106510
closure eval.txt /*closure*
65116511
cmdarg-variable eval.txt /*cmdarg-variable*
65126512
cmdbang-variable eval.txt /*cmdbang-variable*
6513+
cmdcomplete-variable eval.txt /*cmdcomplete-variable*
65136514
cmdline-arguments vi_diff.txt /*cmdline-arguments*
65146515
cmdline-changed version5.txt /*cmdline-changed*
65156516
cmdline-completion cmdline.txt /*cmdline-completion*
@@ -10933,6 +10934,7 @@ v:charconvert_from eval.txt /*v:charconvert_from*
1093310934
v:charconvert_to eval.txt /*v:charconvert_to*
1093410935
v:cmdarg eval.txt /*v:cmdarg*
1093510936
v:cmdbang eval.txt /*v:cmdbang*
10937+
v:cmdcomplete eval.txt /*v:cmdcomplete*
1093610938
v:collate eval.txt /*v:collate*
1093710939
v:colornames eval.txt /*v:colornames*
1093810940
v:completed_item eval.txt /*v:completed_item*

src/cmdexpand.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ cmdline_fuzzy_completion_supported(expand_T *xp)
5050
&& xp->xp_context != EXPAND_FILES
5151
&& xp->xp_context != EXPAND_FILES_IN_PATH
5252
&& xp->xp_context != EXPAND_FILETYPE
53+
&& xp->xp_context != EXPAND_FINDEXPR
5354
&& xp->xp_context != EXPAND_HELP
5455
&& xp->xp_context != EXPAND_KEYMAP
5556
&& xp->xp_context != EXPAND_OLD_SETTING
@@ -1418,7 +1419,8 @@ addstar(
14181419

14191420
// For help tags the translation is done in find_help_tags().
14201421
// For a tag pattern starting with "/" no translation is needed.
1421-
if (context == EXPAND_HELP
1422+
if (context == EXPAND_FINDEXPR
1423+
|| context == EXPAND_HELP
14221424
|| context == EXPAND_COLORS
14231425
|| context == EXPAND_COMPILER
14241426
|| context == EXPAND_OWNSYNTAX
@@ -2138,7 +2140,8 @@ set_context_by_cmdname(
21382140
case CMD_sfind:
21392141
case CMD_tabfind:
21402142
if (xp->xp_context == EXPAND_FILES)
2141-
xp->xp_context = EXPAND_FILES_IN_PATH;
2143+
xp->xp_context = *get_findexpr() != NUL ? EXPAND_FINDEXPR
2144+
: EXPAND_FILES_IN_PATH;
21422145
break;
21432146
case CMD_cd:
21442147
case CMD_chdir:
@@ -2850,7 +2853,7 @@ expand_files_and_dirs(
28502853
}
28512854
}
28522855

2853-
if (xp->xp_context == EXPAND_FILES_IN_PATH && *get_findexpr() != NUL)
2856+
if (xp->xp_context == EXPAND_FINDEXPR)
28542857
{
28552858
#ifdef FEAT_EVAL
28562859
ret = expand_findexpr(pat, matches, numMatches);
@@ -3119,6 +3122,7 @@ ExpandFromContext(
31193122
if (xp->xp_context == EXPAND_FILES
31203123
|| xp->xp_context == EXPAND_DIRECTORIES
31213124
|| xp->xp_context == EXPAND_FILES_IN_PATH
3125+
|| xp->xp_context == EXPAND_FINDEXPR
31223126
|| xp->xp_context == EXPAND_DIRS_IN_CDPATH)
31233127
return expand_files_and_dirs(xp, pat, matches, numMatches, flags,
31243128
options);

src/errors.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3653,4 +3653,4 @@ EXTERN char e_wrong_character_width_for_field_str[]
36533653
EXTERN char e_winfixbuf_cannot_go_to_buffer[]
36543654
INIT(= N_("E1513: Cannot switch buffer. 'winfixbuf' is enabled"));
36553655
EXTERN char e_invalid_return_type_from_findexpr[]
3656-
INIT(= N_("E1514: findexpr did not return a List type"));
3656+
INIT(= N_("E1514: 'findexpr' did not return a List type"));

src/evalvars.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ static struct vimvar
161161
{VV_NAME("t_typealias", VAR_NUMBER), NULL, VV_RO},
162162
{VV_NAME("t_enum", VAR_NUMBER), NULL, VV_RO},
163163
{VV_NAME("t_enumvalue", VAR_NUMBER), NULL, VV_RO},
164+
{VV_NAME("cmdcomplete", VAR_BOOL), NULL, VV_RO},
164165
};
165166

166167
// shorthand
@@ -234,6 +235,7 @@ evalvars_init(void)
234235
set_vim_var_nr(VV_SEARCHFORWARD, 1L);
235236
set_vim_var_nr(VV_HLSEARCH, 1L);
236237
set_vim_var_nr(VV_EXITING, VVAL_NULL);
238+
set_vim_var_nr(VV_CMDCOMPLETE, VVAL_FALSE);
237239
set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc_lock(VAR_FIXED));
238240
set_vim_var_list(VV_ERRORS, list_alloc());
239241
set_vim_var_dict(VV_EVENT, dict_alloc_lock(VAR_FIXED));

src/ex_docmd.c

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6929,7 +6929,7 @@ ex_wrongmodifier(exarg_T *eap)
69296929
* the expression, v:fname is set to the ":find" command argument.
69306930
*/
69316931
static list_T *
6932-
eval_findexpr(char_u *ptr)
6932+
eval_findexpr(char_u *pat, int cmdcomplete)
69336933
{
69346934
sctx_T saved_sctx = current_sctx;
69356935
char_u *findexpr;
@@ -6939,7 +6939,8 @@ eval_findexpr(char_u *ptr)
69396939

69406940
findexpr = get_findexpr();
69416941

6942-
set_vim_var_string(VV_FNAME, ptr, -1);
6942+
set_vim_var_string(VV_FNAME, pat, -1);
6943+
set_vim_var_nr(VV_CMDCOMPLETE, cmdcomplete ? VVAL_TRUE : VVAL_FALSE);
69436944
current_sctx = curbuf->b_p_script_ctx[BV_FEXPR];
69446945

69456946
arg = skipwhite(findexpr);
@@ -6962,6 +6963,7 @@ eval_findexpr(char_u *ptr)
69626963
clear_evalarg(&EVALARG_EVALUATE, NULL);
69636964

69646965
set_vim_var_string(VV_FNAME, NULL, 0);
6966+
set_vim_var_nr(VV_CMDCOMPLETE, VVAL_FALSE);
69656967
current_sctx = saved_sctx;
69666968

69676969
return retlist;
@@ -6977,21 +6979,11 @@ expand_findexpr(char_u *pat, char_u ***files, int *numMatches)
69776979
{
69786980
list_T *l;
69796981
int len;
6980-
char_u *regpat;
69816982

69826983
*numMatches = 0;
69836984
*files = NULL;
69846985

6985-
// File name expansion uses wildchars. But the 'findexpr' expression
6986-
// expects a regular expression argument. So convert wildchars in the
6987-
// argument to regular expression patterns.
6988-
regpat = file_pat_to_reg_pat(pat, NULL, NULL, FALSE);
6989-
if (regpat == NULL)
6990-
return FAIL;
6991-
6992-
l = eval_findexpr(regpat);
6993-
6994-
vim_free(regpat);
6986+
l = eval_findexpr(pat, TRUE);
69956987

69966988
if (l == NULL)
69976989
return FAIL;
@@ -7037,7 +7029,7 @@ findexpr_find_file(char_u *findarg, int findarg_len, int count)
70377029
cc = findarg[findarg_len];
70387030
findarg[findarg_len] = NUL;
70397031

7040-
fname_list = eval_findexpr(findarg);
7032+
fname_list = eval_findexpr(findarg, FALSE);
70417033
fname_count = list_len(fname_list);
70427034

70437035
if (fname_count == 0)

src/testdir/test_findfile.vim

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ func Test_findexpr()
374374

375375
" Expression returning a string
376376
set findexpr='abc'
377-
call assert_fails('find Xfindexpr1.c', 'E1514: findexpr did not return a List type')
377+
call assert_fails('find Xfindexpr1.c', "E1514: 'findexpr' did not return a List type")
378378

379379
set findexpr&
380380
delfunc! FindExpr1
@@ -454,29 +454,52 @@ endfunc
454454

455455
" Test for expanding the argument to the :find command using 'findexpr'
456456
func Test_findexpr_expand_arg()
457-
func FindExpr1()
458-
let fnames = ['Xfindexpr1.c', 'Xfindexpr2.c', 'Xfindexpr3.c']
459-
return fnames->copy()->filter('v:val =~? v:fname')
457+
let s:fnames = ['Xfindexpr1.c', 'Xfindexpr2.c', 'Xfindexpr3.c']
458+
459+
" 'findexpr' that accepts a regular expression
460+
func FindExprRegexp()
461+
return s:fnames->copy()->filter('v:val =~? v:fname')
460462
endfunc
461-
set findexpr=FindExpr1()
462463

463-
call feedkeys(":find \<Tab>\<C-B>\"\<CR>", "xt")
464-
call assert_equal('"find Xfindexpr1.c', @:)
464+
" 'findexpr' that accepts a glob
465+
func FindExprGlob()
466+
let pat = glob2regpat(v:cmdcomplete ? $'*{v:fname}*' : v:fname)
467+
return s:fnames->copy()->filter('v:val =~? pat')
468+
endfunc
469+
470+
for regexp in [v:true, v:false]
471+
let &findexpr = regexp ? 'FindExprRegexp()' : 'FindExprGlob()'
472+
473+
call feedkeys(":find \<Tab>\<C-B>\"\<CR>", "xt")
474+
call assert_equal('"find Xfindexpr1.c', @:)
475+
476+
call feedkeys(":find Xfind\<Tab>\<Tab>\<C-B>\"\<CR>", "xt")
477+
call assert_equal('"find Xfindexpr2.c', @:)
465478

466-
call feedkeys(":find Xfind\<Tab>\<Tab>\<C-B>\"\<CR>", "xt")
467-
call assert_equal('"find Xfindexpr2.c', @:)
479+
call assert_equal(s:fnames, getcompletion('find ', 'cmdline'))
480+
call assert_equal(s:fnames, getcompletion('find Xfind', 'cmdline'))
468481

469-
call feedkeys(":find *3*\<Tab>\<C-B>\"\<CR>", "xt")
470-
call assert_equal('"find Xfindexpr3.c', @:)
482+
let pat = regexp ? 'X.*1\.c' : 'X*1.c'
483+
call feedkeys($":find {pat}\<Tab>\<C-B>\"\<CR>", "xt")
484+
call assert_equal('"find Xfindexpr1.c', @:)
485+
call assert_equal(['Xfindexpr1.c'], getcompletion($'find {pat}', 'cmdline'))
471486

472-
call feedkeys(":find Xfind\<C-A>\<C-B>\"\<CR>", "xt")
473-
call assert_equal('"find Xfindexpr1.c Xfindexpr2.c Xfindexpr3.c', @:)
487+
call feedkeys(":find 3\<Tab>\<C-B>\"\<CR>", "xt")
488+
call assert_equal('"find Xfindexpr3.c', @:)
489+
call assert_equal(['Xfindexpr3.c'], getcompletion($'find 3', 'cmdline'))
474490

475-
call feedkeys(":find abc\<Tab>\<C-B>\"\<CR>", "xt")
476-
call assert_equal('"find abc', @:)
491+
call feedkeys(":find Xfind\<C-A>\<C-B>\"\<CR>", "xt")
492+
call assert_equal('"find Xfindexpr1.c Xfindexpr2.c Xfindexpr3.c', @:)
493+
494+
call feedkeys(":find abc\<Tab>\<C-B>\"\<CR>", "xt")
495+
call assert_equal('"find abc', @:)
496+
call assert_equal([], getcompletion('find abc', 'cmdline'))
497+
endfor
477498

478499
set findexpr&
479-
delfunc! FindExpr1
500+
delfunc! FindExprRegexp
501+
delfunc! FindExprGlob
502+
unlet s:fnames
480503
endfunc
481504

482505
" vim: shiftwidth=2 sts=2 expandtab

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,8 @@ static char *(features[]) =
704704

705705
static int included_patches[] =
706706
{ /* Add new patch number below this line */
707+
/**/
708+
821,
707709
/**/
708710
820,
709711
/**/

src/vim.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -845,6 +845,7 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring);
845845
#define EXPAND_KEYMAP 58
846846
#define EXPAND_DIRS_IN_CDPATH 59
847847
#define EXPAND_SHELLCMDLINE 60
848+
#define EXPAND_FINDEXPR 61
848849

849850

850851
// Values for exmode_active (0 is no exmode)
@@ -2188,7 +2189,8 @@ typedef int sock_T;
21882189
#define VV_TYPE_TYPEALIAS 107
21892190
#define VV_TYPE_ENUM 108
21902191
#define VV_TYPE_ENUMVALUE 109
2191-
#define VV_LEN 110 // number of v: vars
2192+
#define VV_CMDCOMPLETE 110
2193+
#define VV_LEN 111 // number of v: vars
21922194

21932195
// used for v_number in VAR_BOOL and VAR_SPECIAL
21942196
#define VVAL_FALSE 0L // VAR_BOOL

0 commit comments

Comments
 (0)