mirror of
https://github.com/neovim/neovim.git
synced 2026-05-25 14:28:28 +00:00
vim-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: vim/vim#20163
closes: vim/vim#20164
9694ff58fe
This commit is contained in:
@@ -2935,9 +2935,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'.
|
||||
|
||||
5
runtime/lua/vim/_meta/options.gen.lua
generated
5
runtime/lua/vim/_meta/options.gen.lua
generated
@@ -2625,9 +2625,8 @@ vim.go.fcs = vim.go.fillchars
|
||||
--- `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'.
|
||||
|
||||
@@ -3575,20 +3575,20 @@ void expand_process_user_list(list_T *retlist, char ***matches, int *numMatches,
|
||||
ga_init(&ga_info, sizeof(char *), 3);
|
||||
// Loop over the items in the list.
|
||||
TV_LIST_ITER_CONST(retlist, li, {
|
||||
const typval_T *tv = TV_LIST_ITEM_TV(li);
|
||||
char *p = NULL;
|
||||
char *abbr = NULL;
|
||||
char *kind = NULL;
|
||||
char *menu = NULL;
|
||||
char *info = NULL;
|
||||
|
||||
if (TV_LIST_ITEM_TV(li)->v_type == VAR_STRING) {
|
||||
if (TV_LIST_ITEM_TV(li)->vval.v_string == NULL) {
|
||||
if (tv->v_type == VAR_STRING) {
|
||||
if (tv->vval.v_string == NULL) {
|
||||
continue; // Skip NULL strings
|
||||
}
|
||||
p = xstrdup(TV_LIST_ITEM_TV(li)->vval.v_string);
|
||||
} else if (TV_LIST_ITEM_TV(li)->v_type == VAR_DICT
|
||||
&& TV_LIST_ITEM_TV(li)->vval.v_dict != NULL) {
|
||||
dict_T *d = TV_LIST_ITEM_TV(li)->vval.v_dict;
|
||||
p = xstrdup(tv->vval.v_string);
|
||||
} else if (tv->v_type == VAR_DICT && tv->vval.v_dict != NULL) {
|
||||
dict_T *d = tv->vval.v_dict;
|
||||
char *word = tv_dict_get_string(d, "word", false);
|
||||
|
||||
if (word == NULL) {
|
||||
|
||||
@@ -5694,9 +5694,14 @@ static char *findfunc_find_file(char *findarg, size_t findarg_len, int count)
|
||||
if (count > fname_count) {
|
||||
semsg(_(e_no_more_file_str_found_in_path), findarg);
|
||||
} else {
|
||||
listitem_T *li = tv_list_find(fname_list, count - 1);
|
||||
if (li != NULL && TV_LIST_ITEM_TV(li)->v_type == VAR_STRING) {
|
||||
ret_fname = TO_SLASH_SAVE(TV_LIST_ITEM_TV(li)->vval.v_string);
|
||||
const listitem_T *li = tv_list_find(fname_list, count - 1);
|
||||
if (li != NULL) {
|
||||
const typval_T *tv = TV_LIST_ITEM_TV(li);
|
||||
if (tv->v_type == VAR_STRING && tv->vval.v_string != NULL) {
|
||||
ret_fname = xstrdup(tv->vval.v_string);
|
||||
} else if (tv->v_type == VAR_DICT && tv->vval.v_dict != NULL) {
|
||||
ret_fname = tv_dict_get_string(tv->vval.v_dict, "word", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3297,9 +3297,8 @@ local options = {
|
||||
|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'.
|
||||
|
||||
@@ -335,22 +335,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')
|
||||
@@ -358,12 +358,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'},
|
||||
\ v:_null_dict,
|
||||
\ v:_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']
|
||||
|
||||
Reference in New Issue
Block a user