diff options
| author | Justin M. Keyes <justinkz@gmail.com> | 2026-09-01 11:17:22 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-09-01 15:17:22 +0000 |
| commit | 9a29622b545fc76c8b44d0e2b90f318a599eef39 (patch) | |
| tree | 3cad9bf4dafb0b47193c03f3c5561c01ceb276d7 /runtime/lua/vim/hl.lua | |
| parent | 9ebf9b1017c2b7d63e5bb938dfd46c7be1117f98 (diff) | |
| download | rneovim-9a29622b545fc76c8b44d0e2b90f318a599eef39.tar.gz rneovim-9a29622b545fc76c8b44d0e2b90f318a599eef39.tar.bz2 rneovim-9a29622b545fc76c8b44d0e2b90f318a599eef39.zip | |
feat(multicursor): MC HAMMER #41587
Other (squashed) commits:
fix(tui): emit ui_send output atomically with the frame
Problem:
tui_ui_send() writes directly to the TTY, bypassing the output buffer.
Sequences sent via nvim_ui_send() (e.g. kitty multiple-cursors, or
visual-dot-repeat) always arrive in a separate TTY write from the frame
they were computed for. This manifests as "tearing", or e.g. in the case
of multicursor the terminal renders text with stale cursor overlays.
Solution:
- tui_ui_send(): while a frame is being assembled (pending invalid
regions or buffered output), buffer instead of writing directly.
- Out-of-frame sends (tty queries, clear-on-disable) still write
immediately.
- mcursor.lua: emit the terminal-cursor update at the end of the redraw
cycle (`on_end`, when screen positions are final) instead of
vim.schedule().
Diffstat (limited to 'runtime/lua/vim/hl.lua')
| -rw-r--r-- | runtime/lua/vim/hl.lua | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/runtime/lua/vim/hl.lua b/runtime/lua/vim/hl.lua index f6df80deed..1a73a3e4a8 100644 --- a/runtime/lua/vim/hl.lua +++ b/runtime/lua/vim/hl.lua @@ -198,7 +198,9 @@ function M.hl_op(opts) local winid = api.nvim_get_current_win() local state = hl_op_state[state_key] - if state ~= nil and state.timer and not state.timer:is_closing() then + -- Multicursor cascade: accumulate per-cursor, don't cancel the previous event's highlight. + local cascading = api.nvim__mcursor_cascading() + if state ~= nil and state.timer and not state.timer:is_closing() and not cascading then state.timer:close() assert(state.clear) state.clear() |