Ref:
- https://github.com/kovidgoyal/kitty/issues/8927
- https://github.com/kovidgoyal/kitty/blob/master/docs/multiple-cursors-protocol.rst
This implements the multi-cursor protocol, with all features as they exist today (they are subject to change):
- All shapes (copy primary, block, beam, underline)
- Custom colors (all variants, but see limitations below)
- All queries ("global" query for the feature itself, query current "extra" cursors' positions, query "extra" cursors' color)
Implementation details
Existing grid/row/cell data types are not used, hence virtually no additional runtime memory usage when no extra cursors are active. When at least one extra cursor is enabled, we allocate a flattened 2-dimensional array, mapping to the grid. This array tracks each cell's extra cursor type/shape (no cursor/disabled is one such type/shape).
As per the specification, custom colors can be assigned to all extra cursors, but not to each one individually. Hence there's no need to track per-cell cursor color.
While the flattened array does track enabled/disabled state of the extra cursors, we also track this in a pixman region. This is to a) be able to quickly determine if no cursors are active at all, or at least one (by checking if the region is empty), and b) to be able to iterate the enabled cursors without having to scan the entire array (TODO: some use cases might be faster to scan the array - need to benchmark).
All extra cursors are deleted on:
- Terminal reset
- Window resize (we could/should reflow the extra cursors, but we expect the application to redraw anyway, so let's skip that for now)
- Alt/normal screen switches
ED(param 2 and 3 - erase screen, and erase screen and scrollback)
When rendering, the same function is used to render both the extra cursors and the primary cursor. Whether a cell has an extra cursor or not is passed as a new parameter to render_cell(). If a cell has both the primary cursor, and an extra cursor, the primary cursor will be rendered, and the extra cursor will not.
Limitations
The specification says the extra cursors should use the exact same colors as the primary cursor (when set to mirror the primary cursor's colors, and not using custom colors). This includes using the exact same colors as the primary cursor also when the primary cursor has no set colors, but reverses the cell colors. This is currently not happening; when the primary cursor is set to use reversed colors, all extra cursors will also reverse the colors, but of their cells, not the primary cursor's cell.
Should this be merged?
I'm not sure. There's a lot of code for what I consider a small feature. Let's wait a bit, and see if any editors start using this feature.