Experimental modal text editor built for extensibility and flexibility

feat(runtime): per-cursor selections (multiple selections) #1

Closed amartin.beer
Closed opened by amartin.beer

Summary #

Give each multi-cursor its own anchor/head so N independent selections exist, instead of one shared selection tied to the primary cursor (Helix/Zed model).

Motivation #

Multi-cursor today gives N bare cursors but a single visual selection that only tracks the primary. That blocks the core refactor loop: :select-all-matches drops bare cursors at match starts and can't select each whole match, so you can't see what each cursor covers or operate on all selections at once.

Current behavior #

  • Buffer has :cursors @[offset...] + :primary, plus a single :selection @{:anchor :head} (selection.janet).
  • Select-mode movement runs (move/cursor-*) + (selection/update), which sets the head from the primary cursor only.
  • Render carries one :selection {start,end} (KoaSelection); ui.rs paints one range.
  • search/select-all-matches adds bare cursors at match starts.

Proposed approach #

  • Carry an anchor per cursor, e.g. :cursors @[{:offset o :anchor a}...] (anchor == offset = no selection), or a parallel :selections array aligned with :cursors.
  • selection.janet: range -> ranges; start/update/clear/delete/get-selected-text become multi-aware, mirroring the insert-all/apply-to-all pattern in buffer.janet.
  • Render: :selection becomes a list; ui.rs paints each range (its span logic already loops). Wrap like KoaHighlights/KoaRules (janet_binds has no Vec derive).
  • Select mode: movement already moves all cursors, so heads move while anchors stay.
  • :select-all-matches selects each match (anchor = start, head = end) instead of dropping bare cursors.

Scope / notes #

Real refactor across selection.janet, buffer.janet, render.janet, event.rs, ui.rs. Coordinate with undo/redo (must be multi-aware regardless).

Resolved by a recent commit in the multi-cursor + multi-buffer MVPs branch

Sign up or Sign in to add to the discussion.