diff --git a/src/nvim/edit.c b/src/nvim/edit.c index c5e25b4acd..da7da8c220 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -581,6 +581,10 @@ static int insert_execute(VimState *state, int key) return 1; // continue } + if (p_ac) { + ins_compl_set_autocomplete(true); + } + // A non-white character that fits in with the current // completion: Add to "compl_leader". if (ins_compl_accept_char(s->c)) { @@ -598,6 +602,10 @@ static int insert_execute(VimState *state, int key) return 1; // continue } + if (p_ac) { + ins_compl_set_autocomplete(false); + } + // Pressing CTRL-Y selects the current match. When // compl_enter_selects is set the Enter key does the same. if ((s->c == Ctrl_Y @@ -849,10 +857,11 @@ static int insert_handle_key(InsertState *s) auto_format(false, true); if (s->did_backspace && p_ac && !char_avail() && curwin->w_cursor.col > 0) { s->c = char_before_cursor(); - if (ins_compl_setup_autocompl(s->c)) { + if (vim_isprintc(s->c)) { redraw_later(curwin, UPD_VALID); update_screen(); // Show char deletion immediately ui_flush(); + ins_compl_set_autocomplete(true); insert_do_complete(s); // Trigger autocompletion return 1; } @@ -1233,10 +1242,11 @@ normalchar: // closed fold. foldOpenCursor(); // Trigger autocompletion - if (p_ac && !char_avail() && ins_compl_setup_autocompl(s->c)) { + if (p_ac && !char_avail() && vim_isprintc(s->c)) { redraw_later(curwin, UPD_VALID); update_screen(); // Show character immediately ui_flush(); + ins_compl_set_autocomplete(true); insert_do_complete(s); } diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c index af7cc6aae2..87c4487965 100644 --- a/src/nvim/insexpand.c +++ b/src/nvim/insexpand.c @@ -6027,6 +6027,7 @@ int ins_complete(int c, bool enable_pum) if (!compl_started) { if (ins_compl_start() == FAIL) { + compl_autocomplete = false; return FAIL; } } else if (insert_match && stop_arrow() == FAIL) { @@ -6109,19 +6110,15 @@ int ins_complete(int c, bool enable_pum) } compl_was_interrupted = compl_interrupted; compl_interrupted = false; + compl_autocomplete = false; return OK; } -/// Returns true if the given character 'c' can be used to trigger -/// autocompletion. -bool ins_compl_setup_autocompl(int c) +/// Enable/disable autocompletion +void ins_compl_set_autocomplete(bool value) { - if (vim_isprintc(c)) { - compl_autocomplete = true; - return true; - } - return false; + compl_autocomplete = value; } /// Remove (if needed) and show the popup menu diff --git a/test/functional/editor/completion_spec.lua b/test/functional/editor/completion_spec.lua index 130914bb29..49fcf18ac1 100644 --- a/test/functional/editor/completion_spec.lua +++ b/test/functional/editor/completion_spec.lua @@ -1417,6 +1417,14 @@ describe('completion', function() set autocomplete ]]) screen:try_resize(60, 10) + screen:expect([[ + ^foo | + foobar | + foobarbaz | + {1:~ }|*6 + | + ]]) + screen.timeout = 200 feed('Gof') screen:expect([[ @@ -1501,6 +1509,57 @@ describe('completion', function() {5:-- Keyword completion (^N^P) }{6:match 1 of 3} | ]]) + -- After the menu is open, ^N/^P and Up/Down should not delay + feed('') + command('set completeopt=menu') + feed('Sf') + screen:expect([[ + foo | + foobar | + foobarbaz | + f^ | + {1:~ }|*5 + {5:-- INSERT --} | + ]]) + vim.uv.sleep(500) + feed('') + screen:expect([[ + foo | + foobar | + foobarbaz | + foobarbaz^ | + {12:foobarbaz }{1: }| + {4:foobar }{1: }| + {4:foo }{1: }| + {1:~ }|*2 + {5:-- INSERT --} | + ]]) + feed('') + screen:expect([[ + foo | + foobar | + foobarbaz | + foobarbaz^ | + {4:foobarbaz }{1: }| + {12:foobar }{1: }| + {4:foo }{1: }| + {1:~ }|*2 + {5:-- INSERT --} | + ]]) + + -- When menu is not open Up/Down moves cursor to different line + feed('Sf') + screen:expect([[ + foo | + foobar | + foobarbaz | + f^ | + {1:~ }|*5 + {5:-- INSERT --} | + ]]) + feed('') + screen:expect_unchanged() + feed('') end) end) diff --git a/test/old/testdir/test_ins_complete.vim b/test/old/testdir/test_ins_complete.vim index aa36147edc..8804921f7d 100644 --- a/test/old/testdir/test_ins_complete.vim +++ b/test/old/testdir/test_ins_complete.vim @@ -5471,7 +5471,7 @@ func Test_autocomplete_timer() call assert_equal(['abc', 'ab'], b:matches->mapnew('v:val.word')) call assert_equal(0, b:selected) call assert_equal(1, g:CallCount) - call assert_equal('abc', getline(4)) + call assert_equal('ab', getline(4)) set completeopt& " Test 8: {func} completes after space, but not '.' @@ -5603,6 +5603,20 @@ func Test_autocompletedelay() call term_sendkeys(buf, "Sf\") call VerifyScreenDump(buf, 'Test_autocompletedelay_7', {}) + " After the menu is open, ^N/^P and Up/Down should not delay + call term_sendkeys(buf, "\:set completeopt=menu noruler\") + call term_sendkeys(buf, "\Sf") + sleep 500ms + call term_sendkeys(buf, "\") + call VerifyScreenDump(buf, 'Test_autocompletedelay_8', {}) + call term_sendkeys(buf, "\") + call VerifyScreenDump(buf, 'Test_autocompletedelay_9', {}) + + " When menu is not open Up/Down moves cursor to different line + call term_sendkeys(buf, "\Sf") + call term_sendkeys(buf, "\") + call VerifyScreenDump(buf, 'Test_autocompletedelay_10', {}) + call term_sendkeys(buf, "\") call StopVimInTerminal(buf) endfunc