Skip to content

feat: emit multi-cursor positions via kitty protocol with auto-detection#15475

Closed
pierloh wants to merge 3 commits into
helix-editor:masterfrom
pierloh:patch/kitty-multi-cursor
Closed

feat: emit multi-cursor positions via kitty protocol with auto-detection#15475
pierloh wants to merge 3 commits into
helix-editor:masterfrom
pierloh:patch/kitty-multi-cursor

Conversation

@pierloh

@pierloh pierloh commented Mar 20, 2026

Copy link
Copy Markdown

Emits cursor positions to the terminal using the kitty multiple cursors protocol (CSI > 29 ; 2:row:col ... SP q), enabling terminals with custom shader support to render visual effects at cursor locations.

What it does

  • Single cursor + visible terminal cursor (insert mode): no protocol emission, native cursor handles it
  • Multi-selection (any mode): all cursor positions including primary emitted via protocol
  • Normal mode (cursor hidden via DECTCEM): primary cursor emitted via protocol since terminal cursor position is unreliable when hidden
  • Viewport-clipped, capped at 64 cursors with debug logging on truncation
  • Per-frame deduplication: only emits when cursor state changes (avoids redundant writes on every frame)
  • Clears protocol state on exit via restore()

Auto-detection

Probes terminal support at startup by sending the protocol's detection query (CSI > SP q) via /dev/tty with a 100ms timeout. Works through multiplexers like zellij that forward the query.

Config

# Defaults to "auto" -- probes terminal on startup
kitty-multi-cursor = "auto"  # auto | enabled | disabled

Follows the same three-way config pattern as kitty-keyboard-protocol.

Implementation

  • helix-tui/src/backend/mod.rs: sequence builder + Unix probe function
  • helix-tui/src/backend/crossterm.rs: OnceCell-based lazy detection
  • helix-tui/src/backend/termina.rs: detection during capability probing
  • helix-term/src/application.rs: cursor collection + emission with state tracking

Tested with a custom Alacritty build (terminal side) and zellij fork (multiplexer pass-through).

@pierloh

pierloh commented Mar 20, 2026

Copy link
Copy Markdown
Author

@m4rch3n1ng

Copy link
Copy Markdown
Contributor

dupe of #14757

pierloh and others added 2 commits March 20, 2026 22:21
Emit cursor positions via kitty multi-cursor protocol (CSI > 29 ; ... SP q)
after each render frame. Handles normal mode (cursor hidden via DECTCEM),
insert mode single selection (native cursor), and multi-selection (all
cursors via protocol). Viewport-clipped, truncated at 64 cursors.

Config: kitty-multi-cursor (auto/enabled/disabled)
Implemented for both crossterm and termina backends.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add Auto variant to KittyMultiCursorConfig (default), matching
  kitty keyboard protocol config pattern
- Probe terminal via CSI > SP q with 100ms timeout on /dev/tty
- Add supports_multi_cursor_protocol() to crossterm backend (OnceCell)
- Update termina detect_capabilities for Auto probing
- Skip redundant per-frame clear emissions via had_extra_cursors state
- Fix clear sequence to CSI > 0 SP q (drop unnecessary ;4)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@pierloh pierloh force-pushed the patch/kitty-multi-cursor branch from 4948f91 to 83e2f7d Compare March 21, 2026 02:22
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@pierloh pierloh changed the title Emit multi-cursor positions via kitty protocol feat: emit multi-cursor positions via kitty protocol with auto-detection Mar 21, 2026
@archseer archseer requested a review from the-mikedavis March 24, 2026 00:30
@the-mikedavis

Copy link
Copy Markdown
Member

There is existing work on this in #14757, I would prefer to continue there. We should not be writing literal escape sequences in the helix codebase. Instead escape sequences should be covered by types in termina (also see helix-editor/termina#14).

@pierloh

pierloh commented Mar 27, 2026

Copy link
Copy Markdown
Author

Makes sense, thanks for having a look. Will checkout this other PR in coming days.

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.

3 participants