Merge pull request #33589 from zeertzjq/backport

vim-patch:9.1.1305: completion menu active after switching windows/tabs (#33488)
This commit is contained in:
zeertzjq
2025-04-23 11:42:36 +08:00
committed by GitHub
4 changed files with 268 additions and 23 deletions

View File

@@ -381,6 +381,12 @@ static int insert_check(VimState *state)
did_cursorhold = false;
}
// Check if we need to cancel completion mode because the window
// or tab page was changed
if (ins_compl_active() && !ins_compl_win_active(curwin)) {
ins_compl_cancel();
}
// If the cursor was moved we didn't just insert a space
if (arrow_used) {
s->inserted_space = false;

View File

@@ -265,6 +265,9 @@ static extmark_undo_vec_t compl_orig_extmarks;
static int compl_cont_mode = 0;
static expand_T compl_xp;
static win_T *compl_curr_win = NULL; ///< win where completion is active
static buf_T *compl_curr_buf = NULL; ///< buf where completion is active
// List of flags for method of completion.
static int compl_cont_status = 0;
#define CONT_ADDING 1 ///< "normal" or "adding" expansion
@@ -1753,6 +1756,8 @@ void ins_compl_clear(void)
compl_matches = 0;
compl_selected_item = -1;
compl_ins_end_col = 0;
compl_curr_win = NULL;
compl_curr_buf = NULL;
API_CLEAR_STRING(compl_pattern);
API_CLEAR_STRING(compl_leader);
edit_submode_extra = NULL;
@@ -1773,7 +1778,7 @@ bool ins_compl_active(void)
/// Return true when wp is the actual completion window
bool ins_compl_win_active(win_T *wp)
{
return ins_compl_active() && !(wp->w_p_pvw || wp->w_float_is_info);
return ins_compl_active() && wp == compl_curr_win && wp->w_buffer == compl_curr_buf;
}
/// Selected one of the matches. When false the match was edited or using the
@@ -2300,6 +2305,12 @@ static bool ins_compl_stop(const int c, const int prev_mode, bool retval)
return retval;
}
/// Cancel completion.
bool ins_compl_cancel(void)
{
return ins_compl_stop(' ', ctrl_x_mode, true);
}
/// Prepare for Insert mode completion, or stop it.
/// Called just after typing a character in Insert mode.
///
@@ -4851,6 +4862,8 @@ int ins_complete(int c, bool enable_pum)
return FAIL;
}
compl_curr_win = curwin;
compl_curr_buf = curwin->w_buffer;
compl_shown_match = compl_curr_match;
compl_shows_dir = compl_direction;

View File

@@ -1164,6 +1164,7 @@ describe('builtin popupmenu', function()
[8] = { foreground = Screen.colors.Red },
[9] = { foreground = Screen.colors.Yellow, background = Screen.colors.Green },
[10] = { foreground = Screen.colors.White, background = Screen.colors.Green },
[11] = { background = Screen.colors.LightGrey, underline = true },
ks = { foreground = Screen.colors.Red, background = Screen.colors.Grey },
kn = { foreground = Screen.colors.Red, background = Screen.colors.Plum1 },
xs = { foreground = Screen.colors.Black, background = Screen.colors.Grey },
@@ -4343,12 +4344,32 @@ describe('builtin popupmenu', function()
end
end)
if not multigrid then
it('with multiline messages', function()
screen:try_resize(40, 8)
feed('ixx<cr>')
command('imap <f2> <cmd>echoerr "very"\\|echoerr "much"\\|echoerr "error"<cr>')
fn.complete(1, { 'word', 'choice', 'text', 'thing' })
it('with multiline messages', function()
screen:try_resize(40, 8)
feed('ixx<cr>')
command('imap <f2> <cmd>echoerr "very"\\|echoerr "much"\\|echoerr "error"<cr>')
fn.complete(1, { 'word', 'choice', 'text', 'thing' })
if multigrid then
screen:expect({
grid = [[
## grid 1
[2:----------------------------------------]|*7
[3:----------------------------------------]|
## grid 2
xx |
word^ |
{1:~ }|*5
## grid 3
{2:-- INSERT --} |
## grid 4
{s:word }|
{n:choice }|
{n:text }|
{n:thing }|
]],
float_pos = { [4] = { -1, 'NW', 2, 2, 0, false, 100 } },
})
else
screen:expect([[
xx |
word^ |
@@ -4359,8 +4380,33 @@ describe('builtin popupmenu', function()
{1:~ }|
{2:-- INSERT --} |
]])
end
feed('<f2>')
feed('<f2>')
if multigrid then
screen:expect({
grid = [[
## grid 1
[2:----------------------------------------]|*4
[3:----------------------------------------]|*4
## grid 2
xx |
word |
{1:~ }|*5
## grid 3
{6:very} |
{6:much} |
{6:error} |
{5:Press ENTER or type command to continue}^ |
## grid 4
{s:word }|
{n:choice }|
{n:text }|
{n:thing }|
]],
float_pos = { [4] = { -1, 'NW', 2, 2, 0, false, 100 } },
})
else
screen:expect([[
xx |
word |
@@ -4371,8 +4417,30 @@ describe('builtin popupmenu', function()
{6:error} |
{5:Press ENTER or type command to continue}^ |
]])
end
feed('<cr>')
feed('<cr>')
if multigrid then
screen:expect({
grid = [[
## grid 1
[2:----------------------------------------]|*7
[3:----------------------------------------]|
## grid 2
xx |
word^ |
{1:~ }|*5
## grid 3
{2:-- INSERT --} |
## grid 4
{s:word }|
{n:choice }|
{n:text }|
{n:thing }|
]],
float_pos = { [4] = { -1, 'NW', 2, 2, 0, false, 100 } },
})
else
screen:expect([[
xx |
word^ |
@@ -4383,8 +4451,30 @@ describe('builtin popupmenu', function()
{1:~ }|
{2:-- INSERT --} |
]])
end
feed('<c-n>')
feed('<c-n>')
if multigrid then
screen:expect({
grid = [[
## grid 1
[2:----------------------------------------]|*7
[3:----------------------------------------]|
## grid 2
xx |
choice^ |
{1:~ }|*5
## grid 3
{2:-- INSERT --} |
## grid 4
{n:word }|
{s:choice }|
{n:text }|
{n:thing }|
]],
float_pos = { [4] = { -1, 'NW', 2, 2, 0, false, 100 } },
})
else
screen:expect([[
xx |
choice^ |
@@ -4395,35 +4485,92 @@ describe('builtin popupmenu', function()
{1:~ }|
{2:-- INSERT --} |
]])
end
command('split')
command('split')
feed('<c-u>')
fn.complete(1, { 'word', 'choice', 'text', 'thing' })
if multigrid then
screen:expect({
grid = [[
## grid 1
[5:----------------------------------------]|*3
{4:[No Name] [+] }|
[2:----------------------------------------]|*2
{3:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
xx |
word |
## grid 3
{2:-- INSERT --} |
## grid 4
{s:word }|
{n:choice }|
{n:text }|
{n:thing }|
## grid 5
xx |
word^ |
{1:~ }|
]],
float_pos = { [4] = { -1, 'NW', 5, 2, 0, false, 100 } },
})
else
screen:expect([[
xx |
choice^ |
{n:word }{1: }|
{s:choice }{4: }|
word^ |
{s:word }{1: }|
{n:choice }{4: }|
{n:text } |
{n:thing } |
{3:[No Name] [+] }|
{2:-- INSERT --} |
]])
end
api.nvim_input_mouse('wheel', 'down', '', 0, 6, 15)
screen:expect {
api.nvim_input_mouse('wheel', 'down', '', 0, 6, 15)
if multigrid then
screen:expect({
grid = [[
## grid 1
[5:----------------------------------------]|*3
{4:[No Name] [+] }|
[2:----------------------------------------]|*2
{3:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
word |
{1:~ }|
## grid 3
{2:-- INSERT --} |
## grid 4
{s:word }|
{n:choice }|
{n:text }|
{n:thing }|
## grid 5
xx |
choice^ |
{n:word }{1: }|
{s:choice }{4: }|
word^ |
{1:~ }|
]],
float_pos = { [4] = { -1, 'NW', 5, 2, 0, false, 100 } },
})
else
screen:expect([[
xx |
word^ |
{s:word }{1: }|
{n:choice }{4: }|
{n:text } |
{n:thing }{1: }|
{3:[No Name] [+] }|
{2:-- INSERT --} |
]],
unchanged = true,
}
end)
]])
end
end)
if not multigrid then
it('with kind, menu and abbr attributes', function()
screen:try_resize(40, 8)
feed('ixx ')
@@ -7839,6 +7986,53 @@ describe('builtin popupmenu', function()
{2:-- INSERT --} |
]])
end)
-- oldtest: Test_pum_clear_when_switch_tab_or_win()
it('is cleared when switching tab or win', function()
screen:try_resize(55, 20)
exec([[
inoremap <F4> <Cmd>wincmd w<CR>
inoremap <F5> <Cmd>tabnext<CR>
]])
command('tabe')
feed('Aaa aaa <C-X><C-N>')
screen:expect([[
{11: [No Name] }{2: + [No Name] }{3: }{11:X}|
aa aaa aa^ |
{1:~ }{s: aa }{1: }|
{1:~ }{n: aaa }{1: }|
{1:~ }|*15
{2:-- Keyword Local completion (^N^P) }{5:match 1 of 2} |
]])
feed('<F5>')
screen:expect([[
{2: [No Name] }{11: + [No Name] }{3: }{11:X}|
^ |
{1:~ }|*17
{2:-- INSERT --} |
]])
feed('<Esc>')
command('tabclose!')
command('vnew win_b')
feed('Abb bbb <C-X><C-N>')
screen:expect([[
bb bbb bb^ │aa aaa aa |
{1:~ }{s: bb }{1: }│{1:~ }|
{1:~ }{n: bbb }{1: }│{1:~ }|
{1:~ }│{1:~ }|*15
{4:win_b [+] }{3:[No Name] [+] }|
{2:-- Keyword Local completion (^N^P) }{5:match 1 of 2} |
]])
feed('<F4>')
screen:expect([[
bb bbb bb │aa aaa a^a |
{1:~ }│{1:~ }|*17
{3:win_b [+] }{4:[No Name] [+] }|
{2:-- INSERT --} |
]])
end)
end
end

View File

@@ -1966,4 +1966,36 @@ func Test_pum_complete_with_special_characters()
call StopVimInTerminal(buf)
endfunc
func Test_pum_clear_when_switch_tab_or_win()
CheckScreendump
let lines =<< trim END
inoremap <F4> <Cmd>wincmd w<CR>
inoremap <F5> <Cmd>tabnext<CR>
END
call writefile(lines, 'Xtest', 'D')
let buf = RunVimInTerminal('-S Xtest', {})
call term_sendkeys(buf, ":tabe\<CR>")
call TermWait(buf, 50)
call term_sendkeys(buf, "Aaa aaa \<C-N>")
call VerifyScreenDump(buf, 'Test_tabnext_clear_pum_01', {})
call term_sendkeys(buf, "\<F5>")
call TermWait(buf, 50)
call VerifyScreenDump(buf, 'Test_tabnext_clear_pum_02', {})
call term_sendkeys(buf, "\<ESC>:tabclose!\<CR>")
call term_sendkeys(buf, ":vnew win_b\<CR>")
call TermWait(buf, 50)
call term_sendkeys(buf, "Abb bbb \<C-N>")
call VerifyScreenDump(buf, 'Test_switchwin_clear_pum_01', {})
call term_sendkeys(buf, "\<F4>")
call TermWait(buf, 50)
call VerifyScreenDump(buf, 'Test_switchwin_clear_pum_02', {})
call StopVimInTerminal(buf)
endfunc
" vim: shiftwidth=2 sts=2 expandtab