vim-patch:9.2.0750: completion: 'autocompletedelay' deferral leaks state

Problem:  After 'autocompletedelay' was made non-blocking, the deferred
          popup can misbehave: a pending autocomplete survives leaving
          Insert mode and then keeps waking the editor in Normal mode,
          the deferral is recorded into registers while recording a
          macro, the popup appears an extra 'updatetime' late when
          'autocompletedelay' is larger and a CursorHoldI autocommand
          exists, CursorHoldI can fire twice without an intervening
          keypress, and an open balloon is dismissed (after v9.2.0739)
Solution: Treat the deferral like CursorHold: only keep it pending in
          Insert mode and not while recording, with pending typeahead,
          or when completion is already active; drop it when Insert mode
          ends; measure the delay from when the user typed so a
          CursorHold in between does not push the popup back; and do not
          let the deferral re-enable CursorHoldI or dismiss the balloon.
          (Hirohito Higashi).

closes: vim/vim#20669

1f0f14bc2f

Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
zeertzjq
2026-07-01 20:59:25 +08:00
parent 5f47d7ac08
commit 826ca0ccfe
3 changed files with 30 additions and 3 deletions

View File

@@ -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("\<Esc>q", 't') })
call feedkeys("qaSf", 'tx!')
call assert_equal("Sf\<Esc>", @a)
set autocomplete& autocompletedelay&
bwipe!
endfunc
" Preinsert longest prefix when autocomplete
func Test_autocomplete_longest()
func GetLine()