diff --git a/src/nvim/edit.c b/src/nvim/edit.c index a19adca942..f02d957079 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -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; diff --git a/src/nvim/testdir/test_ins_complete_no_halt.vim b/src/nvim/testdir/test_ins_complete_no_halt.vim new file mode 100644 index 0000000000..e12925daa9 --- /dev/null +++ b/src/nvim/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