patch 9.2.0455: 'findfunc' only allows extra info for cmdline completion
Commit:
https://github.com/vim/vim/commit/9694ff58fe510bf3906a7b6817429e29d5975987
Author: zeertzjq <[email protected]>
Date: Fri May 8 21:09:48 2026 +0000
patch 9.2.0455: 'findfunc' only allows extra info for cmdline completion
Problem: 'findfunc' only allows extra info for cmdline completion, not
for actually finding files (Maxim Kim, after 9.2.0451).
Solution: Handle returning a list of dicts when actually finding files.
Also fix crash on NULL string (zeertzjq).
fixes: #20163
closes: #20164
Signed-off-by: zeertzjq <[email protected]>
Signed-off-by: Christian Brabandt <[email protected]>
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index e82cd3055..969a17c16 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -1,4 +1,4 @@
-*options.txt* For Vim version 9.2. Last change: 2026 May 07
+*options.txt* For Vim version 9.2. Last change: 2026 May 08
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -3983,9 +3983,8 @@ A jump table for the options with a short description can
be found at |Q_op|.
|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, or, in the command-line
- completion case, whatever a |:command-completion-customlist| function
- may return.
+ The function should return a List, which is handled similarly to the
+ return value of a |:command-completion-customlist| function.
The function is called only once per |:find| command invocation.
The function can process all the directories specified in 'path'.
diff --git a/src/cmdexpand.c b/src/cmdexpand.c
index a763456a1..3c660b5ea 100644
--- a/src/cmdexpand.c
+++ b/src/cmdexpand.c
@@ -4172,22 +4172,22 @@ expand_process_user_list(
// Loop over the items in the list.
FOR_ALL_LIST_ITEMS(retlist, li)
{
+ typval_T *tv = &li->li_tv;
char_u *p = NULL;
char_u *abbr = NULL;
char_u *kind = NULL;
char_u *menu = NULL;
char_u *info = NULL;
- if (li->li_tv.v_type == VAR_STRING)
+ if (tv->v_type == VAR_STRING)
{
- if (li->li_tv.vval.v_string == NULL)
+ if (tv->vval.v_string == NULL)
continue; // Skip NULL strings
p = vim_strsave(li->li_tv.vval.v_string);
}
- else if (li->li_tv.v_type == VAR_DICT
- && li->li_tv.vval.v_dict != NULL)
+ else if (tv->v_type == VAR_DICT && tv->vval.v_dict != NULL)
{
- dict_T *d = li->li_tv.vval.v_dict;
+ dict_T *d = tv->vval.v_dict;
char_u *word = dict_get_string(d, "word", FALSE);
if (word == NULL)
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index 7b31bed99..11ea59e3b 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -7119,8 +7119,16 @@ findfunc_find_file(char_u *findarg, int findarg_len, int
count)
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 (li != NULL)
+ {
+ typval_T *tv = &li->li_tv;
+
+ if (tv->v_type == VAR_STRING && tv->vval.v_string != NULL)
+ ret_fname = vim_strsave(tv->vval.v_string);
+ else if (tv->v_type == VAR_DICT && tv->vval.v_dict != NULL)
+ ret_fname = dict_get_string(tv->vval.v_dict, "word", TRUE);
+ }
}
}
diff --git a/src/testdir/test_findfile.vim b/src/testdir/test_findfile.vim
index 42c3fb643..a5f1f6fdd 100644
--- a/src/testdir/test_findfile.vim
+++ b/src/testdir/test_findfile.vim
@@ -329,22 +329,22 @@ func Test_findfunc()
set findfunc=FindFuncBasic
find Xfindfunc3
- call assert_match('Xfindfunc3.c', @%)
+ call assert_match('Xfindfunc3\.c', @%)
bw!
2find Xfind
- call assert_match('Xfindfunc2.c', @%)
+ call assert_match('Xfindfunc2\.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 Xfindfunc2.c
- call assert_match('Xfindfunc2.c', @%)
+ call assert_match('Xfindfunc2\.c', @%)
call assert_equal(2, winnr('$'))
%bw!
call assert_fails('sfind foobar', 'E345: Can''t find file "foobar" in path')
tabfind Xfindfunc3.c
- call assert_match('Xfindfunc3.c', @%)
+ call assert_match('Xfindfunc3\.c', @%)
call assert_equal(2, tabpagenr())
%bw!
call assert_fails('tabfind foobar', 'E345: Can''t find file "foobar" in
path')
@@ -352,12 +352,44 @@ func Test_findfunc()
" Test garbage collection
call test_garbagecollect_now()
find Xfindfunc2
- call assert_match('Xfindfunc2.c', @%)
+ call assert_match('Xfindfunc2\.c', @%)
bw!
delfunc FindFuncBasic
call test_garbagecollect_now()
call assert_fails('find Xfindfunc2', 'E117: Unknown function: FindFuncBasic')
+ " 'findfunc' with dicts in the returned list
+ func FindFuncDict(pat, cmdcomplete)
+ return [
+ \ #{word: 'Xfindfunc1.c', abbr: 'Xff1.c'},
+ \ #{word: 'Xfindfunc2.c'},
+ \ 'Xfindfunc3.c',
+ "\ invalid values
+ \ #{abbr: 'XXX'},
+ \ test_null_dict(),
+ \ test_null_string(),
+ \ ]
+ endfunc
+
+ set findfunc=FindFuncDict
+ find Xfind
+ call assert_match('Xfindfunc1\.c', @%)
+ bw!
+ 2find Xfind
+ call assert_match('Xfindfunc2\.c', @%)
+ bw!
+ 3find Xfind
+ call assert_match('Xfindfunc3\.c', @%)
+ bw!
+ " These invalid values should not crash
+ 4find Xfind
+ 5find Xfind
+ 6find Xfind
+ call assert_fails('7find Xfind', 'E347: No more file "Xfind" found in path')
+ call assert_equal('', @%)
+ %bw!
+ delfunc FindFuncDict
+
" Buffer-local option
func GlobalFindFunc(pat, cmdcomplete)
return ['global']
diff --git a/src/version.c b/src/version.c
index 0103f023e..36f96c055 100644
--- a/src/version.c
+++ b/src/version.c
@@ -729,6 +729,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 455,
/**/
454,
/**/
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion visit
https://groups.google.com/d/msgid/vim_dev/E1wLSXQ-00CfvL-LX%40256bit.org.