diff --git a/src/nvim/edit.c b/src/nvim/edit.c index ed723520f3..5e159c4cfe 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -372,6 +372,8 @@ static void insert_enter(InsertState *s) // and return false, causing `state_enter` to be called again. } while (!ins_esc(&s->count, s->cmdchar, s->nomove)); + // Drop a pending autocomplete so it does not outlive Insert mode. + ins_compl_clear_autocomplete_delay(); // Always update o_lnum, so that a "CTRL-O ." that adds a line // still puts the cursor back after the inserted text. if (ins_at_eol) { @@ -1327,8 +1329,9 @@ static void insert_do_cindent(InsertState *s) static void insert_handle_key_post(InsertState *s) { - // If typed something may trigger CursorHoldI again. - if (s->c != K_EVENT + // If typed something may trigger CursorHoldI again; K_COMPLETE_DELAY is + // injected, not typed. + if (s->c != K_EVENT && s->c != K_COMPLETE_DELAY // but not in CTRL-X mode, a script can't restore the state && ctrl_x_mode_normal()) { did_cursorhold = false; diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c index b52e18f91b..84475d4443 100644 --- a/src/nvim/os/input.c +++ b/src/nvim/os/input.c @@ -149,7 +149,13 @@ int input_get(uint8_t *buf, int maxlen, int ms, int tb_change_cnt, MultiQueue *e // When an autocomplete is pending, wake at the sooner of // 'autocompletedelay' and 'updatetime' so the delay does not postpone // CursorHold. Once CursorHold has fired, only the delay is left. - bool delay_pending = ins_compl_autocomplete_pending() && p_acl > 0; + // Gate the injection like trigger_cursorhold() so the deferred key + // cannot fire while recording or outside Insert mode. + bool delay_pending = ins_compl_autocomplete_pending() && p_acl > 0 + && reg_recording == 0 + && typebuf.tb_len == 0 + && !ins_compl_active() + && (get_real_state() & MODE_INSERT) != 0; // Measure the delay from when it was armed (the keystroke), so a // CursorHold returning in between does not push the popup back. int64_t wait_time = p_ut - cursorhold_time; diff --git a/test/old/testdir/test_ins_complete.vim b/test/old/testdir/test_ins_complete.vim index 036706f025..d5b60c789d 100644 --- a/test/old/testdir/test_ins_complete.vim +++ b/test/old/testdir/test_ins_complete.vim @@ -6114,6 +6114,24 @@ func Test_autocompletedelay_ctrl_k() call Run_test_autocompletedelay_ctrl_k(150, 500) endfunc +func Test_autocompletedelay_no_record() + " The K_COMPLETE_DELAY pseudo key must not be recorded into a register while + " recording a macro, like K_CURSORHOLD. + new + call setline(1, 'foobar') + set autocomplete autocompletedelay=100 + + let @a = '' + " Type a char that arms the delay, idle past 'autocompletedelay' so a + " K_COMPLETE_DELAY would be injected, then end Insert mode and stop recording. + call timer_start(200, { -> feedkeys("\q", 't') }) + call feedkeys("qaSf", 'tx!') + call assert_equal("Sf\", @a) + + set autocomplete& autocompletedelay& + bwipe! +endfunc + " Preinsert longest prefix when autocomplete func Test_autocomplete_longest() func GetLine()