patch 8.2.3293: finding completions may cause an endless loop
Problem: Finding completions may cause an endless loop.
Solution: Use a better way to check coming back where the search started.
(Andy Gozas, closes #8672, closes #8671)
This commit is contained in:
committed by
Bram Moolenaar
parent
bc67e5a0a4
commit
6a230c6b32
@ -2712,6 +2712,8 @@ ins_compl_get_exp(pos_T *ini)
|
|||||||
char_u *dict = NULL;
|
char_u *dict = NULL;
|
||||||
int dict_f = 0;
|
int dict_f = 0;
|
||||||
int set_match_pos;
|
int set_match_pos;
|
||||||
|
pos_T prev_pos = {0, 0, 0};
|
||||||
|
int looped_around = FALSE;
|
||||||
|
|
||||||
if (!compl_started)
|
if (!compl_started)
|
||||||
{
|
{
|
||||||
@ -2964,6 +2966,7 @@ ins_compl_get_exp(pos_T *ini)
|
|||||||
p_ws = FALSE;
|
p_ws = FALSE;
|
||||||
else if (*e_cpt == '.')
|
else if (*e_cpt == '.')
|
||||||
p_ws = TRUE;
|
p_ws = TRUE;
|
||||||
|
looped_around = FALSE;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
int cont_s_ipos = FALSE;
|
int cont_s_ipos = FALSE;
|
||||||
@ -2992,7 +2995,30 @@ ins_compl_get_exp(pos_T *ini)
|
|||||||
}
|
}
|
||||||
else if (first_match_pos.lnum == last_match_pos.lnum
|
else if (first_match_pos.lnum == last_match_pos.lnum
|
||||||
&& first_match_pos.col == last_match_pos.col)
|
&& first_match_pos.col == last_match_pos.col)
|
||||||
|
{
|
||||||
found_new_match = FAIL;
|
found_new_match = FAIL;
|
||||||
|
}
|
||||||
|
else if ((compl_direction == FORWARD)
|
||||||
|
&& (prev_pos.lnum > pos->lnum
|
||||||
|
|| (prev_pos.lnum == pos->lnum
|
||||||
|
&& prev_pos.col >= pos->col)))
|
||||||
|
{
|
||||||
|
if (looped_around)
|
||||||
|
found_new_match = FAIL;
|
||||||
|
else
|
||||||
|
looped_around = TRUE;
|
||||||
|
}
|
||||||
|
else if ((compl_direction != FORWARD)
|
||||||
|
&& (prev_pos.lnum < pos->lnum
|
||||||
|
|| (prev_pos.lnum == pos->lnum
|
||||||
|
&& prev_pos.col <= pos->col)))
|
||||||
|
{
|
||||||
|
if (looped_around)
|
||||||
|
found_new_match = FAIL;
|
||||||
|
else
|
||||||
|
looped_around = TRUE;
|
||||||
|
}
|
||||||
|
prev_pos = *pos;
|
||||||
if (found_new_match == FAIL)
|
if (found_new_match == FAIL)
|
||||||
{
|
{
|
||||||
if (ins_buf == curbuf)
|
if (ins_buf == curbuf)
|
||||||
|
|||||||
@ -162,6 +162,7 @@ NEW_TESTS = \
|
|||||||
test_increment_dbcs \
|
test_increment_dbcs \
|
||||||
test_indent \
|
test_indent \
|
||||||
test_ins_complete \
|
test_ins_complete \
|
||||||
|
test_ins_complete_no_halt \
|
||||||
test_interrupt \
|
test_interrupt \
|
||||||
test_job_fails \
|
test_job_fails \
|
||||||
test_join \
|
test_join \
|
||||||
@ -405,6 +406,7 @@ NEW_TESTS_RES = \
|
|||||||
test_increment_dbcs.res \
|
test_increment_dbcs.res \
|
||||||
test_indent.res \
|
test_indent.res \
|
||||||
test_ins_complete.res \
|
test_ins_complete.res \
|
||||||
|
test_ins_complete_no_halt.res \
|
||||||
test_interrupt.res \
|
test_interrupt.res \
|
||||||
test_job_fails.res \
|
test_job_fails.res \
|
||||||
test_join.res \
|
test_join.res \
|
||||||
|
|||||||
51
src/testdir/test_ins_complete_no_halt.vim
Normal file
51
src/testdir/test_ins_complete_no_halt.vim
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
" Test insert mode completion does not get stuck when looping around.
|
||||||
|
" In a separate file to avoid the settings to leak to other test cases.
|
||||||
|
|
||||||
|
set complete+=kspell
|
||||||
|
set completeopt+=menu
|
||||||
|
set completeopt+=menuone
|
||||||
|
set completeopt+=noselect
|
||||||
|
set completeopt+=noinsert
|
||||||
|
let g:autocompletion = v:true
|
||||||
|
|
||||||
|
func Test_ins_complete_no_halt()
|
||||||
|
function! OpenCompletion()
|
||||||
|
if pumvisible() && (g:autocompletion == v:true)
|
||||||
|
call feedkeys("\<C-e>\<C-n>", "i")
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
if ((v:char >= 'a' && v:char <= 'z') || (v:char >= 'A' && v:char <= 'Z')) && (g:autocompletion == v:true)
|
||||||
|
call feedkeys("\<C-n>", "i")
|
||||||
|
redraw
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
autocmd InsertCharPre * noautocmd call OpenCompletion()
|
||||||
|
|
||||||
|
setlocal spell! spelllang=en_us
|
||||||
|
|
||||||
|
call feedkeys("iauto-complete-halt-test test test test test test test test test test test test test test test test test test test\<C-c>", "tx!")
|
||||||
|
call assert_equal(["auto-complete-halt-test test test test test test test test test test test test test test test test test test test"], getline(1, "$"))
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func Test_auto_complete_backwards_no_halt()
|
||||||
|
function! OpenCompletion()
|
||||||
|
if pumvisible() && (g:autocompletion == v:true)
|
||||||
|
call feedkeys("\<C-e>\<C-p>", "i")
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
if ((v:char >= 'a' && v:char <= 'z') || (v:char >= 'A' && v:char <= 'Z')) && (g:autocompletion == v:true)
|
||||||
|
call feedkeys("\<C-p>", "i")
|
||||||
|
redraw
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
autocmd InsertCharPre * noautocmd call OpenCompletion()
|
||||||
|
|
||||||
|
setlocal spell! spelllang=en_us
|
||||||
|
|
||||||
|
call feedkeys("iauto-complete-halt-test test test test test test test test test test test test test test test test test test test\<C-c>", "tx!")
|
||||||
|
call assert_equal(["auto-complete-halt-test test test test test test test test test test test test test test test test test test test"], getline(1, "$"))
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
@ -755,6 +755,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
3293,
|
||||||
/**/
|
/**/
|
||||||
3292,
|
3292,
|
||||||
/**/
|
/**/
|
||||||
|
|||||||
Reference in New Issue
Block a user