vim-patch:9.2.0442: completion: i_CTRL-X_CTRL-V doesn't use dict from customlist (#39614)

Problem:  Completion with i_CTRL-X_CTRL-V doesn't use dict from cmdline
          "customlist" completion.
Solution: Include abbr/kind/menu/info in the completion items
          (zeertzjq).

closes: vim/vim#20139

https://github.com/vim/vim/commit/2bfddbea47e1afa79ecd094040418abdba88bc83
This commit is contained in:
zeertzjq
2026-05-06 07:17:21 +08:00
committed by GitHub
parent 97de5f145a
commit d0582fcc74
4 changed files with 274 additions and 7 deletions
+1 -1
View File
@@ -873,7 +873,7 @@ static char *find_longest_match(expand_T *xp, int options)
return xmemdupz(xp->xp_files[0], len);
}
static void free_xp_files_extra(expand_T *xp, int numfiles)
void free_xp_files_extra(expand_T *xp, int numfiles)
{
if (xp->xp_files_abbr != NULL) {
FreeWild(numfiles, xp->xp_files_abbr);
+28 -1
View File
@@ -4154,7 +4154,34 @@ static void get_next_cmdline_completion(void)
int num_matches;
if (expand_cmdline(&compl_xp, compl_pattern.data,
(int)compl_pattern.size, &num_matches, &matches) == EXPAND_OK) {
ins_compl_add_matches(num_matches, matches, false);
int add_r = OK;
Direction dir = compl_direction;
for (int i = 0; i < num_matches && add_r != FAIL; i++) {
char *(cptext[CPT_COUNT]) = { NULL, NULL, NULL, NULL };
if (compl_xp.xp_files_abbr != NULL) {
cptext[CPT_ABBR] = compl_xp.xp_files_abbr[i];
}
if (compl_xp.xp_files_kind != NULL) {
cptext[CPT_KIND] = compl_xp.xp_files_kind[i];
}
if (compl_xp.xp_files_menu != NULL) {
cptext[CPT_MENU] = compl_xp.xp_files_menu[i];
}
if (compl_xp.xp_files_info != NULL) {
cptext[CPT_INFO] = compl_xp.xp_files_info[i];
}
add_r = ins_compl_add(matches[i], -1, NULL, cptext, false, NULL, dir,
CP_FAST, false, NULL, FUZZY_SCORE_NONE, false);
if (add_r == OK) {
// if dir was BACKWARD then honor it just once
dir = FORWARD;
}
}
FreeWild(num_matches, matches);
free_xp_files_extra(&compl_xp, num_matches);
}
}
+219
View File
@@ -5469,6 +5469,225 @@ describe('builtin popupmenu', function()
:DictCmd ^ |
]])
end
feed('<Esc>')
-- Tests for Insert mode i_CTRL-X_CTRL-V
feed('iDictCmd <C-X><C-V>')
if multigrid then
screen:expect({
grid = [[
## grid 1
[2:-------------------------------------------------------]|*11
[3:-------------------------------------------------------]|
## grid 2
DictCmd apple^ |
{1:~ }|*10
## grid 3
{5:-- Command-line completion (^V^N^P) }{6:match 1 of 4} |
## grid 5
{12: apple f fruit }|
{n: banana f fruit }|
{n: carrot v vegetable }|
{n: plain }|
## grid 6
{n:A red fruit}|
]],
float_pos = {
[5] = { -1, 'NW', 2, 1, 7, false, 100, 2, 1, 7 },
[6] = { 1002, 'NW', 1, 1, 27, true, 50, 1, 1, 27 },
},
})
else
screen:expect([[
DictCmd apple^ |
{1:~ }{12: apple f fruit }{n:A red fruit}{1: }|
{1:~ }{n: banana f fruit }{1: }|
{1:~ }{n: carrot v vegetable }{1: }|
{1:~ }{n: plain }{1: }|
{1:~ }|*6
{5:-- Command-line completion (^V^N^P) }{6:match 1 of 4} |
]])
end
feed('<C-N>')
if multigrid then
screen:expect({
grid = [[
## grid 1
[2:-------------------------------------------------------]|*11
[3:-------------------------------------------------------]|
## grid 2
DictCmd banana^ |
{1:~ }|*10
## grid 3
{5:-- Command-line completion (^V^N^P) }{6:match 2 of 4} |
## grid 5
{n: apple f fruit }|
{12: banana f fruit }|
{n: carrot v vegetable }|
{n: plain }|
## grid 6
{n:A yellow fruit}|
]],
float_pos = {
[5] = { -1, 'NW', 2, 1, 7, false, 100, 2, 1, 7 },
[6] = { 1002, 'NW', 1, 1, 27, true, 50, 1, 1, 27 },
},
})
else
screen:expect([[
DictCmd banana^ |
{1:~ }{n: apple f fruit A yellow fruit}{1: }|
{1:~ }{12: banana f fruit }{1: }|
{1:~ }{n: carrot v vegetable }{1: }|
{1:~ }{n: plain }{1: }|
{1:~ }|*6
{5:-- Command-line completion (^V^N^P) }{6:match 2 of 4} |
]])
end
feed('<C-N>')
if multigrid then
screen:expect({
grid = [[
## grid 1
[2:-------------------------------------------------------]|*11
[3:-------------------------------------------------------]|
## grid 2
DictCmd carrot^ |
{1:~ }|*10
## grid 3
{5:-- Command-line completion (^V^N^P) }{6:match 3 of 4} |
## grid 5
{n: apple f fruit }|
{n: banana f fruit }|
{12: carrot v vegetable }|
{n: plain }|
## grid 6
{n:An orange vegetable}|
]],
float_pos = {
[5] = { -1, 'NW', 2, 1, 7, false, 100, 2, 1, 7 },
[6] = { 1002, 'NW', 1, 1, 27, true, 50, 1, 1, 27 },
},
})
else
screen:expect([[
DictCmd carrot^ |
{1:~ }{n: apple f fruit An orange vegetable}{1: }|
{1:~ }{n: banana f fruit }{1: }|
{1:~ }{12: carrot v vegetable }{1: }|
{1:~ }{n: plain }{1: }|
{1:~ }|*6
{5:-- Command-line completion (^V^N^P) }{6:match 3 of 4} |
]])
end
feed('<C-N>')
if multigrid then
screen:expect({
grid = [[
## grid 1
[2:-------------------------------------------------------]|*11
[3:-------------------------------------------------------]|
## grid 2
DictCmd plain^ |
{1:~ }|*10
## grid 3
{5:-- Command-line completion (^V^N^P) }{6:match 4 of 4} |
## grid 5
{n: apple f fruit }|
{n: banana f fruit }|
{n: carrot v vegetable }|
{12: plain }|
## grid 6 (hidden)
{n:An orange vegetable}|
]],
float_pos = {
[5] = { -1, 'NW', 2, 1, 7, false, 100, 1, 1, 7 },
},
})
else
screen:expect([[
DictCmd plain^ |
{1:~ }{n: apple f fruit }{1: }|
{1:~ }{n: banana f fruit }{1: }|
{1:~ }{n: carrot v vegetable }{1: }|
{1:~ }{12: plain }{1: }|
{1:~ }|*6
{5:-- Command-line completion (^V^N^P) }{6:match 4 of 4} |
]])
end
feed('<C-N>')
if multigrid then
screen:expect({
grid = [[
## grid 1
[2:-------------------------------------------------------]|*11
[3:-------------------------------------------------------]|
## grid 2
DictCmd ^ |
{1:~ }|*10
## grid 3
{5:-- Command-line completion (^V^N^P) }{19:Back at original} |
## grid 5
{n: apple f fruit }|
{n: banana f fruit }|
{n: carrot v vegetable }|
{n: plain }|
## grid 6 (hidden)
{n:An orange vegetable}|
]],
float_pos = {
[5] = { -1, 'NW', 2, 1, 7, false, 100, 1, 1, 7 },
},
})
else
screen:expect([[
DictCmd ^ |
{1:~ }{n: apple f fruit }{1: }|
{1:~ }{n: banana f fruit }{1: }|
{1:~ }{n: carrot v vegetable }{1: }|
{1:~ }{n: plain }{1: }|
{1:~ }|*6
{5:-- Command-line completion (^V^N^P) }{19:Back at original} |
]])
end
-- Starting another i_CTRL-X_CTRL-V completion should not leak memory
feed('<C-U>')
poke_eventloop() -- Allow pum_check_clear() to remove the info popup.
feed('sign un<C-X><C-V>')
if multigrid then
screen:expect({
grid = [[
## grid 1
[2:-------------------------------------------------------]|*11
[3:-------------------------------------------------------]|
## grid 2
sign undefine^ |
{1:~ }|*10
## grid 3
{5:-- Command-line completion (^V^N^P) }{6:match 1 of 2} |
## grid 5
{12: undefine }|
{n: unplace }|
]],
float_pos = {
[5] = { -1, 'NW', 2, 1, 4, false, 100, 1, 1, 4 },
},
})
else
screen:expect([[
sign undefine^ |
{1:~ }{12: undefine }{1: }|
{1:~ }{n: unplace }{1: }|
{1:~ }|*8
{5:-- Command-line completion (^V^N^P) }{6:match 1 of 2} |
]])
end
end)
it("'pumheight'", function()
+26 -5
View File
@@ -4645,25 +4645,46 @@ func Test_customlist_dict_completion_info_popup()
call term_sendkeys(buf, ":DictCmd \<Tab>")
call WaitForTermCurPosAndLinesToMatch(buf, [rows, (strlen(':DictCmd apple') + 1)], g:test_timeout, ((rows - 4), 'A red fruit'))
call VerifyScreenDump(buf, 'Test_customlist_info_popup_1', {})
call VerifyScreenDump(buf, 'Test_customlist_info_popup_01', {})
call term_sendkeys(buf, "\<Tab>")
call WaitForTermCurPosAndLinesToMatch(buf, [rows, (strlen(':DictCmd banana') + 1)], g:test_timeout, ((rows - 3), 'A yellow fruit'))
call VerifyScreenDump(buf, 'Test_customlist_info_popup_2', {})
call VerifyScreenDump(buf, 'Test_customlist_info_popup_02', {})
call term_sendkeys(buf, "\<Tab>")
call WaitForTermCurPosAndLinesToMatch(buf, [rows, (strlen(':DictCmd carrot') + 1)], g:test_timeout, ((rows - 2), 'An orange vegetable'))
call VerifyScreenDump(buf, 'Test_customlist_info_popup_3', {})
call VerifyScreenDump(buf, 'Test_customlist_info_popup_03', {})
call term_sendkeys(buf, "\<Tab>")
call WaitForTermCurPosAndLinesToMatch(buf, [rows, (strlen(':DictCmd plain') + 1)], g:test_timeout, ((rows - 1), '^\~\s\+plain\s\+$'))
call VerifyScreenDump(buf, 'Test_customlist_info_popup_4', {})
call VerifyScreenDump(buf, 'Test_customlist_info_popup_04', {})
call term_sendkeys(buf, "\<Tab>")
call WaitForTermCurPosAndLinesToMatch(buf, [rows, (strlen(':DictCmd ') + 1)], g:test_timeout)
call VerifyScreenDump(buf, 'Test_customlist_info_popup_5', {})
call VerifyScreenDump(buf, 'Test_customlist_info_popup_05', {})
call term_sendkeys(buf, "\<Esc>")
" Tests for Insert mode i_CTRL-X_CTRL-V
call term_sendkeys(buf, "iDictCmd \<C-X>\<C-V>")
call VerifyScreenDump(buf, 'Test_customlist_info_popup_06', {})
call term_sendkeys(buf, "\<C-N>")
call VerifyScreenDump(buf, 'Test_customlist_info_popup_07', {})
call term_sendkeys(buf, "\<C-N>")
call VerifyScreenDump(buf, 'Test_customlist_info_popup_08', {})
call term_sendkeys(buf, "\<C-N>")
call VerifyScreenDump(buf, 'Test_customlist_info_popup_09', {})
call term_sendkeys(buf, "\<C-N>")
call VerifyScreenDump(buf, 'Test_customlist_info_popup_10', {})
" Starting another i_CTRL-X_CTRL-V completion should not leak memory
call term_sendkeys(buf, "\<C-U>sign un\<C-X>\<C-V>")
call VerifyScreenDump(buf, 'Test_customlist_info_popup_11', {})
call StopVimInTerminal(buf)
endfunc