mirror of
https://github.com/neovim/neovim
synced 2025-07-15 16:51:49 +00:00
vim-patch:9.1.1305: completion menu active after switching windows/tabs (#33488)
Problem: When switching to another window or tab page while the
completion menu is active, the menu stays visible, although it
belongs to the previous window/tab page context (Evgeni
Chasnovski).
Solution: Track the window and tab page where completion started. Detect
changes in the main editing loop and cancel completion mode if
the current window or tab page differs from where completion
started.
fixes: vim/vim#17090
closes: vim/vim#17101
cf7f01252f
Co-authored-by: glepnir <glephunter@gmail.com>
This commit is contained in:
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user