Skip to content

fix: a suggestion never outlives insert mode - #13

Merged
teocns merged 1 commit into
mainfrom
fix/insert-only
Sep 2, 2026
Merged

fix: a suggestion never outlives insert mode#13
teocns merged 1 commit into
mainfrom
fix/insert-only

Conversation

@teocns

@teocns teocns commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Closes #10.

TL;DR

A suggestion could sit in Normal mode with a ⟪<Tab> accept · <Esc> dismiss⟫ label that neither key could reach — both are insert mappings. Suggestions now live strictly in insert mode.

Two leak paths

How it got there Why Fix
Reply lands a few hundred ms after <Esc> tick unchanged → stale check passes → painted render_result drops any reply landing outside insert/replace (DROP … outside insert in :NeocursorLog)
<C-c> to leave insert unmapped <C-c> is an interrupt; :h i_CTRL-C — never fires InsertLeave leave handler moved to ModeChanged, which Neovim fires for every exit (deferred past got_int, before any other key)

Leaving insert: what counts

  <Esc> · <C-c> · <C-\><C-n>   dismiss   clears + files the rejection   (as before)
  <C-o>                        detour    clears, files nothing, re-offered on return   (new — was miscounted)
  BufLeave                     buffer    clears + resets the churn budget   (as before)

Before, <C-o>zz twice would hard-reject a suggestion you never said no to.

Tests

New test/modes_spec.lua drives Neovim's real main loop with nvim_input — the blocked-feedkeys harness in flow_spec never reaches normal-mode events, and <C-c> is sent as the real interrupt.

                          pre-fix        this PR
  reply after <Esc>       FAIL (painted) ok
  <C-c> clears + counts   FAIL           ok
  <C-o> not filed         FAIL ×2        ok
                          6 FAILURES     ALL PASS ×5 runs

flow_spec (both hint modes), hints_spec, docs_links and the headless demo harness all still pass.

Docs

README "Saying no" gets the insert-only rule and the <C-o> exception; troubleshooting covers <Tab> in Normal mode and :NeocursorSuggest from the cmdline.

Two ways a suggestion ended up painted in Normal mode, where <Tab>,
<M-Right> and <C-]> — all insert mappings — can't reach it:

- The reply race. The request leaves on the debounce, <Esc> lands a few
  hundred ms later, and the reply was painted into Normal mode anyway:
  the buffer tick hadn't changed, so the stale-response check let it
  through. render_result now drops any reply that lands outside
  insert/replace mode (logged as "DROP … outside insert"); the next
  InsertEnter asks afresh.

- <C-c>. Unmapped, it is an interrupt, and :h i_CTRL-C says it never
  fires InsertLeave — so the leave handler never ran. The handler now
  hangs off ModeChanged, which sees every exit: for an interrupt Neovim
  defers it past got_int and fires it from normal_check, still before
  any other key is read.

While there, how you leave now decides whether it counts. <Esc>, <C-c>
and <C-\><C-n> file the rejection as before. <C-o> is a detour: the
display clears (the command may edit the buffer under it), nothing is
filed, and the return trip re-offers the edit. Before, <C-o>zz twice
would hard-reject a suggestion you never said no to.

test/modes_spec.lua drives Neovim's real main loop with nvim_input —
the blocked-feedkeys harness in flow_spec never reaches normal-mode
events — and covers all three. Against the pre-fix code it fails 6 of
15 assertions.

Closes #10
@teocns
teocns merged commit f820c65 into main Sep 2, 2026
9 of 10 checks passed
@teocns
teocns deleted the fix/insert-only branch September 2, 2026 12:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

How can I disable the hints when in Normal mode?

1 participant