vim-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 vim/vim#8672, closes vim/vim#8671)
6a230c6b32
This commit is contained in:
Sean Dewar 2021-08-14 00:35:51 +01:00
parent 7ff5f02821
commit 423150dfa0
No known key found for this signature in database
GPG Key ID: 08CC2C83AD41B581
2 changed files with 72 additions and 0 deletions

View File

@ -4127,6 +4127,7 @@ static int ins_compl_get_exp(pos_T *ini)
char_u *dict = NULL;
int dict_f = 0;
bool set_match_pos;
pos_T prev_pos = { 0, 0, 0 };
int l_ctrl_x_mode = ctrl_x_mode;
assert(curbuf != NULL);
@ -4365,6 +4366,7 @@ static int ins_compl_get_exp(pos_T *ini)
} else if (*e_cpt == '.') {
p_ws = true;
}
bool looped_around = false;
for (;; ) {
bool cont_s_ipos = false;
@ -4393,7 +4395,26 @@ static int ins_compl_get_exp(pos_T *ini)
} else if (first_match_pos.lnum == last_match_pos.lnum
&& first_match_pos.col == last_match_pos.col) {
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 (ins_buf == curbuf) {
found_all = true;

View 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