Simulate user keypresses with timeouts

Hey guys, I need quite a specific advice.

Imagine I’d like to have a buffer and a sequence of keys (example: 3iAB<Esc>). I want to simulate these keypresses in a buffer, but not all at once, rather one-by-one with a timeout, and showing the results of each intermediate keypress to the user. The function I’m using to actually send keypresses is nvim_feedkeys, it’s blocking, suits my needs. Assuming all termcodes were escaped properly, that should happen in this case:

  • after 3, nothing in the buffer changes
  • after i, nothing in the buffer changes
  • after A, a single A is inserted
  • after B, a single B is inserted
  • after <Esc>, ABAB is inserted

The problem is: consider I’ve simulated 3iA. At this moment, I need to wait a bit to let the user observe what happened after this prefix. But how do I set timeout? At this moment, I can neither exit the Insert mode (because then AAA gets inserted immediately, which is not a valid state of my key sequence), nor schedule pressing B with defer_fn, because (as I suspect) Neovim eventloop is frozen, textlock is active, and there is really no way to set timeouts or send more keys because of that.

I’ve been thinking on this problem for several days now, it’s an important part of the project. Any help or hints would be appreciated.

I’ll gladly provide more information if needed. At this point I just don’t know what else could be relevant :slight_smile:

For the context: I’ve been thinking about an alternative idea on how to accomplish that.

  • execute prefix (3iA)
  • extract the lines of the buffer BEFORE expansion (with only single A inserted)
  • exit wait-for-character mode (send <Esc>), set buffer lines to BEFORE expansion
  • when time comes to press B, execute 3iAB from starting state, and not from intermediary

That approach has the benefits of not needing to be in insert mode for the duration of timeout between keys.

But that approach encounters a similar problem - I cannot read buffer lines BEFORE insert mode expansion, because, as I suspect, textlock is active and vim.api.nvim_buf_get_lines() is simply unsafe to call at this point.