From: Andy Gozas Date: Thu, 5 Aug 2021 14:23:27 +0000 (+0200) Subject: patch 8.2.3293: finding completions may cause an endless loop X-Git-Tag: v8.2.3293 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6a230c6b32695393785ae64b440ce5f023a22382;p=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 #8672, closes #8671) --- diff --git a/src/insexpand.c b/src/insexpand.c index 3b58891fc..4f8a62651 100644 --- a/src/insexpand.c +++ b/src/insexpand.c @@ -2712,6 +2712,8 @@ ins_compl_get_exp(pos_T *ini) char_u *dict = NULL; int dict_f = 0; int set_match_pos; + pos_T prev_pos = {0, 0, 0}; + int looped_around = FALSE; if (!compl_started) { @@ -2964,6 +2966,7 @@ ins_compl_get_exp(pos_T *ini) p_ws = FALSE; else if (*e_cpt == '.') p_ws = TRUE; + looped_around = FALSE; for (;;) { int cont_s_ipos = FALSE; @@ -2991,8 +2994,31 @@ ins_compl_get_exp(pos_T *ini) set_match_pos = FALSE; } 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; + } + 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) diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak index 6feeecd3a..3c54087a6 100644 --- a/src/testdir/Make_all.mak +++ b/src/testdir/Make_all.mak @@ -162,6 +162,7 @@ NEW_TESTS = \ test_increment_dbcs \ test_indent \ test_ins_complete \ + test_ins_complete_no_halt \ test_interrupt \ test_job_fails \ test_join \ @@ -405,6 +406,7 @@ NEW_TESTS_RES = \ test_increment_dbcs.res \ test_indent.res \ test_ins_complete.res \ + test_ins_complete_no_halt.res \ test_interrupt.res \ test_job_fails.res \ test_join.res \ diff --git a/src/testdir/test_ins_complete_no_halt.vim b/src/testdir/test_ins_complete_no_halt.vim new file mode 100644 index 000000000..e12925daa --- /dev/null +++ b/src/testdir/test_ins_complete_no_halt.vim @@ -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("\\", "i") + return + endif + if ((v:char >= 'a' && v:char <= 'z') || (v:char >= 'A' && v:char <= 'Z')) && (g:autocompletion == v:true) + call feedkeys("\", "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\", "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("\\", "i") + return + endif + if ((v:char >= 'a' && v:char <= 'z') || (v:char >= 'A' && v:char <= 'Z')) && (g:autocompletion == v:true) + call feedkeys("\", "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\", "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 diff --git a/src/version.c b/src/version.c index 4ad59790c..2db7988ce 100644 --- a/src/version.c +++ b/src/version.c @@ -755,6 +755,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 3293, /**/ 3292, /**/