mirror of
https://github.com/neovim/neovim.git
synced 2026-07-13 12:50:31 +00:00
vim-patch:9.2.0451: 'findfunc' can't return extra info for cmdline completion
Problem: 'findfunc' can't return extra info for cmdline completion
(Maxim Kim).
Solution: Handle 'findfunc' return value in cmdline completion like that
of "customlist" functions (zeertzjq).
fixes: vim/vim#20155
closes: vim/vim#20158
58124789aa
This commit is contained in:
@@ -2935,7 +2935,9 @@ 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.
|
||||
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 is called only once per |:find| command invocation.
|
||||
The function can process all the directories specified in 'path'.
|
||||
|
||||
4
runtime/lua/vim/_meta/options.gen.lua
generated
4
runtime/lua/vim/_meta/options.gen.lua
generated
@@ -2625,7 +2625,9 @@ 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.
|
||||
--- 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 is called only once per `:find` command invocation.
|
||||
--- The function can process all the directories specified in 'path'.
|
||||
|
||||
@@ -2735,7 +2735,7 @@ static int expand_files_and_dirs(expand_T *xp, char *pat, char ***matches, int *
|
||||
|
||||
int ret = FAIL;
|
||||
if (xp->xp_context == EXPAND_FINDFUNC) {
|
||||
ret = expand_findfunc(pat, matches, numMatches);
|
||||
ret = expand_findfunc(xp, pat, matches, numMatches);
|
||||
} else {
|
||||
if (xp->xp_context == EXPAND_FILES) {
|
||||
flags |= EW_FILE;
|
||||
@@ -3560,7 +3560,7 @@ static int ExpandUserDefined(const char *const pat, expand_T *xp, regmatch_T *re
|
||||
return OK;
|
||||
}
|
||||
|
||||
static void process_user_list(list_T *retlist, char ***matches, int *numMatches, expand_T *xp)
|
||||
void expand_process_user_list(list_T *retlist, char ***matches, int *numMatches, expand_T *xp)
|
||||
{
|
||||
garray_T ga;
|
||||
garray_T ga_abbr;
|
||||
@@ -3583,7 +3583,7 @@ static void process_user_list(list_T *retlist, char ***matches, int *numMatches,
|
||||
|
||||
if (TV_LIST_ITEM_TV(li)->v_type == VAR_STRING) {
|
||||
if (TV_LIST_ITEM_TV(li)->vval.v_string == NULL) {
|
||||
continue; // Skip empty strings
|
||||
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
|
||||
@@ -3612,7 +3612,6 @@ static void process_user_list(list_T *retlist, char ***matches, int *numMatches,
|
||||
GA_APPEND(char *, &ga_menu, menu);
|
||||
GA_APPEND(char *, &ga_info, info);
|
||||
});
|
||||
tv_list_unref(retlist);
|
||||
|
||||
*matches = ga.ga_data;
|
||||
*numMatches = ga.ga_len;
|
||||
@@ -3652,7 +3651,8 @@ static int ExpandUserList(expand_T *xp, char ***matches, int *numMatches)
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
process_user_list(retlist, matches, numMatches, xp);
|
||||
expand_process_user_list(retlist, matches, numMatches, xp);
|
||||
tv_list_unref(retlist);
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -3667,7 +3667,8 @@ static int ExpandUserLua(expand_T *xp, int *numMatches, char ***matches)
|
||||
|
||||
list_T *const retlist = rettv.vval.v_list;
|
||||
|
||||
process_user_list(retlist, matches, numMatches, xp);
|
||||
expand_process_user_list(retlist, matches, numMatches, xp);
|
||||
tv_list_unref(retlist);
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -5654,7 +5654,7 @@ static list_T *call_findfunc(char *pat, BoolVarValue cmdcomplete)
|
||||
/// Find file names matching "pat" using 'findfunc' and return it in "files".
|
||||
/// Used for expanding the :find, :sfind and :tabfind command argument.
|
||||
/// Returns OK on success and FAIL otherwise.
|
||||
int expand_findfunc(char *pat, char ***files, int *numMatches)
|
||||
int expand_findfunc(expand_T *xp, char *pat, char ***files, int *numMatches)
|
||||
{
|
||||
*numMatches = 0;
|
||||
*files = NULL;
|
||||
@@ -5670,18 +5670,7 @@ int expand_findfunc(char *pat, char ***files, int *numMatches)
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
*files = xmalloc(sizeof(char *) * (size_t)len);
|
||||
|
||||
// Copy all the List items
|
||||
int idx = 0;
|
||||
TV_LIST_ITER_CONST(l, li, {
|
||||
if (TV_LIST_ITEM_TV(li)->v_type == VAR_STRING) {
|
||||
(*files)[idx] = TO_SLASH_SAVE(TV_LIST_ITEM_TV(li)->vval.v_string);
|
||||
idx++;
|
||||
}
|
||||
});
|
||||
|
||||
*numMatches = idx;
|
||||
expand_process_user_list(l, files, numMatches, xp);
|
||||
tv_list_free(l);
|
||||
|
||||
return OK;
|
||||
|
||||
@@ -3297,7 +3297,9 @@ 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.
|
||||
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 is called only once per |:find| command invocation.
|
||||
The function can process all the directories specified in 'path'.
|
||||
|
||||
@@ -5690,6 +5690,99 @@ describe('builtin popupmenu', function()
|
||||
end
|
||||
end)
|
||||
|
||||
-- oldtest: Test_cmdline_complete_findfunc_dict()
|
||||
it("'findfunc' can return extra info for cmdline completion", function()
|
||||
screen:try_resize(55, 12)
|
||||
exec([[
|
||||
set wildmenu wildoptions=pum completeopt=menu,popup
|
||||
func FindComplete(cmdarg, cmdcomplete)
|
||||
return [
|
||||
\ 'Xplain',
|
||||
\ {'word': 'Xfile1', 'kind': 'F', 'menu': 'file', 'info': '1st file'},
|
||||
\ {'word': 'Xfile2', 'kind': 'F', 'menu': 'file', 'info': '2nd file'},
|
||||
\ {'word': 'Xdir1', 'kind': 'D', 'menu': 'dir', 'info': '1st dir'},
|
||||
\ {'word': 'Xdir2', 'kind': 'D', 'menu': 'dir', 'info': '2nd dir'},
|
||||
\ ]
|
||||
endfunc
|
||||
set findfunc=FindComplete
|
||||
]])
|
||||
|
||||
feed(':find <Tab>')
|
||||
if multigrid then
|
||||
screen:expect({
|
||||
grid = [[
|
||||
## grid 1
|
||||
[2:-------------------------------------------------------]|*11
|
||||
[3:-------------------------------------------------------]|
|
||||
## grid 2
|
||||
|
|
||||
{1:~ }|*10
|
||||
## grid 3
|
||||
:find Xplain^ |
|
||||
## grid 4
|
||||
{12: Xplain }|
|
||||
{n: Xfile1 F file }|
|
||||
{n: Xfile2 F file }|
|
||||
{n: Xdir1 D dir }|
|
||||
{n: Xdir2 D dir }|
|
||||
]],
|
||||
float_pos = {
|
||||
[4] = { -1, 'SW', 1, 11, 5, false, 250, 2, 6, 5 },
|
||||
},
|
||||
})
|
||||
else
|
||||
screen:expect([[
|
||||
|
|
||||
{1:~ }|*5
|
||||
{1:~ }{12: Xplain }{1: }|
|
||||
{1:~ }{n: Xfile1 F file }{1: }|
|
||||
{1:~ }{n: Xfile2 F file }{1: }|
|
||||
{1:~ }{n: Xdir1 D dir }{1: }|
|
||||
{1:~ }{n: Xdir2 D dir }{1: }|
|
||||
:find Xplain^ |
|
||||
]])
|
||||
end
|
||||
|
||||
feed('<PageDown>')
|
||||
if multigrid then
|
||||
screen:expect({
|
||||
grid = [[
|
||||
## grid 1
|
||||
[2:-------------------------------------------------------]|*11
|
||||
[3:-------------------------------------------------------]|
|
||||
## grid 2
|
||||
|
|
||||
{1:~ }|*10
|
||||
## grid 3
|
||||
:find Xdir1^ |
|
||||
## grid 4
|
||||
{n: Xplain }|
|
||||
{n: Xfile1 F file }|
|
||||
{n: Xfile2 F file }|
|
||||
{12: Xdir1 D dir }|
|
||||
{n: Xdir2 D dir }|
|
||||
## grid 5
|
||||
{n:1st dir}|
|
||||
]],
|
||||
float_pos = {
|
||||
[4] = { -1, 'SW', 1, 11, 5, false, 250, 3, 6, 5 },
|
||||
[5] = { 1001, 'NW', 1, 6, 21, true, 50, 1, 6, 21 },
|
||||
},
|
||||
})
|
||||
else
|
||||
screen:expect([[
|
||||
|
|
||||
{1:~ }|*5
|
||||
{1:~ }{n: Xplain 1st dir}{1: }|
|
||||
{1:~ }{n: Xfile1 F file }{1: }|
|
||||
{1:~ }{n: Xfile2 F file }{1: }|
|
||||
{1:~ }{12: Xdir1 D dir }{1: }|
|
||||
{1:~ }{n: Xdir2 D dir }{1: }|
|
||||
:find Xdir1^ |
|
||||
]])
|
||||
end
|
||||
end)
|
||||
|
||||
it("'pumheight'", function()
|
||||
screen:try_resize(32, 8)
|
||||
feed('isome long prefix before the ')
|
||||
|
||||
@@ -4688,6 +4688,38 @@ func Test_customlist_dict_completion_info_popup()
|
||||
call StopVimInTerminal(buf)
|
||||
endfunc
|
||||
|
||||
func Test_cmdline_complete_findfunc_dict()
|
||||
CheckScreendump
|
||||
|
||||
let lines =<< trim END
|
||||
set wildmenu wildoptions=pum completeopt=menu,popup
|
||||
func FindComplete(cmdarg, cmdcomplete)
|
||||
return [
|
||||
\ 'Xplain',
|
||||
\ {'word': 'Xfile1', 'kind': 'F', 'menu': 'file', 'info': '1st file'},
|
||||
\ {'word': 'Xfile2', 'kind': 'F', 'menu': 'file', 'info': '2nd file'},
|
||||
\ {'word': 'Xdir1', 'kind': 'D', 'menu': 'dir', 'info': '1st dir'},
|
||||
\ {'word': 'Xdir2', 'kind': 'D', 'menu': 'dir', 'info': '2nd dir'},
|
||||
\ ]
|
||||
endfunc
|
||||
set findfunc=FindComplete
|
||||
END
|
||||
call writefile(lines, 'XTest_compl_findfunc_dict', 'D')
|
||||
let rows = 12
|
||||
let buf = RunVimInTerminal('-S XTest_compl_findfunc_dict', {'rows': rows})
|
||||
|
||||
call term_sendkeys(buf, ":find \<Tab>")
|
||||
call WaitForTermCurPosAndLinesToMatch(buf, [rows, (strlen(':find Xplain') + 1)], g:test_timeout, ((rows - 5), '^\~\s\+Xplain\s\+$'))
|
||||
call VerifyScreenDump(buf, 'Test_compl_findfunc_dict_01', {})
|
||||
|
||||
call term_sendkeys(buf, "\<PageDown>")
|
||||
call WaitForTermCurPosAndLinesToMatch(buf, [rows, (strlen(':find Xdir1') + 1)], g:test_timeout, ((rows - 2), '1st dir'))
|
||||
call VerifyScreenDump(buf, 'Test_compl_findfunc_dict_02', {})
|
||||
|
||||
call term_sendkeys(buf, "\<Esc>")
|
||||
call StopVimInTerminal(buf)
|
||||
endfunc
|
||||
|
||||
func Test_custom_completion_with_glob()
|
||||
func TestGlobComplete(A, L, P)
|
||||
return split(glob('Xglob*'), "\n")
|
||||
|
||||
Reference in New Issue
Block a user