mirror of
https://github.com/neovim/neovim
synced 2025-07-16 09:11:51 +00:00
fix(completion): fix inconsistent Enter behavior (#30196)
Problem: Behavior of Enter in completion depends on typing speed. Solution: Don't make whether Enter selects original text depend on whether completion has been interrupted, which can happen interactively with a slow completion function.
This commit is contained in:
@ -1792,6 +1792,13 @@ int ins_compl_bs(void)
|
|||||||
return NUL;
|
return NUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if the complete function returned "always" in the "refresh" dictionary item.
|
||||||
|
static bool ins_compl_refresh_always(void)
|
||||||
|
FUNC_ATTR_PURE
|
||||||
|
{
|
||||||
|
return (ctrl_x_mode_function() || ctrl_x_mode_omni()) && compl_opt_refresh_always;
|
||||||
|
}
|
||||||
|
|
||||||
/// Check that we need to find matches again, ins_compl_restart() is to
|
/// Check that we need to find matches again, ins_compl_restart() is to
|
||||||
/// be called.
|
/// be called.
|
||||||
static bool ins_compl_need_restart(void)
|
static bool ins_compl_need_restart(void)
|
||||||
@ -1799,9 +1806,7 @@ static bool ins_compl_need_restart(void)
|
|||||||
{
|
{
|
||||||
// Return true if we didn't complete finding matches or when the
|
// Return true if we didn't complete finding matches or when the
|
||||||
// "completefunc" returned "always" in the "refresh" dictionary item.
|
// "completefunc" returned "always" in the "refresh" dictionary item.
|
||||||
return compl_was_interrupted
|
return compl_was_interrupted || ins_compl_refresh_always();
|
||||||
|| ((ctrl_x_mode_function() || ctrl_x_mode_omni())
|
|
||||||
&& compl_opt_refresh_always);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called after changing "compl_leader".
|
/// Called after changing "compl_leader".
|
||||||
@ -1834,7 +1839,7 @@ static void ins_compl_new_leader(void)
|
|||||||
|
|
||||||
// Don't let Enter select the original text when there is no popup menu.
|
// Don't let Enter select the original text when there is no popup menu.
|
||||||
// Don't let Enter select when use user function and refresh_always is set
|
// Don't let Enter select when use user function and refresh_always is set
|
||||||
if (compl_match_array == NULL || ins_compl_need_restart()) {
|
if (compl_match_array == NULL || ins_compl_refresh_always()) {
|
||||||
compl_enter_selects = false;
|
compl_enter_selects = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -327,7 +327,7 @@ describe('completion', function()
|
|||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('refresh:always', function()
|
describe('with refresh:always and noselect', function()
|
||||||
before_each(function()
|
before_each(function()
|
||||||
source([[
|
source([[
|
||||||
function! TestCompletion(findstart, base) abort
|
function! TestCompletion(findstart, base) abort
|
||||||
@ -459,6 +459,67 @@ describe('completion', function()
|
|||||||
June
|
June
|
||||||
June]])
|
June]])
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('Enter does not select original text', function()
|
||||||
|
feed('iJ<C-x><C-u>')
|
||||||
|
poke_eventloop()
|
||||||
|
feed('u')
|
||||||
|
poke_eventloop()
|
||||||
|
feed('<CR>')
|
||||||
|
expect([[
|
||||||
|
Ju
|
||||||
|
]])
|
||||||
|
feed('J<C-x><C-u>')
|
||||||
|
poke_eventloop()
|
||||||
|
feed('<CR>')
|
||||||
|
expect([[
|
||||||
|
Ju
|
||||||
|
J
|
||||||
|
]])
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
describe('with noselect but not refresh:always', function()
|
||||||
|
before_each(function()
|
||||||
|
source([[
|
||||||
|
function! TestCompletion(findstart, base) abort
|
||||||
|
if a:findstart
|
||||||
|
let line = getline('.')
|
||||||
|
let start = col('.') - 1
|
||||||
|
while start > 0 && line[start - 1] =~ '\a'
|
||||||
|
let start -= 1
|
||||||
|
endwhile
|
||||||
|
return start
|
||||||
|
else
|
||||||
|
let ret = []
|
||||||
|
for m in split("January February March April May June July August September October November December")
|
||||||
|
if m =~ a:base " match by regex
|
||||||
|
call add(ret, m)
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
return {'words':ret}
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
set completeopt=menuone,noselect
|
||||||
|
set completefunc=TestCompletion
|
||||||
|
]])
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('Enter selects original text after adding leader', function()
|
||||||
|
feed('iJ<C-x><C-u>')
|
||||||
|
poke_eventloop()
|
||||||
|
feed('u')
|
||||||
|
poke_eventloop()
|
||||||
|
feed('<CR>')
|
||||||
|
expect('Ju')
|
||||||
|
feed('<Esc>')
|
||||||
|
poke_eventloop()
|
||||||
|
-- The behavior should be the same when completion has been interrupted,
|
||||||
|
-- which can happen interactively if the completion function is slow.
|
||||||
|
feed('SJ<C-x><C-u>u<CR>')
|
||||||
|
expect('Ju')
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('with a lot of items', function()
|
describe('with a lot of items', function()
|
||||||
|
Reference in New Issue
Block a user