Compare commits

...

3 commits

Author SHA1 Message Date
c46e830e04
refactor: add Editor.with_cursels_const_repeat 2025-11-27 11:28:00 +01:00
b7613542e7
refactor: CurSel.to_selection is internal 2025-11-26 23:16:50 +01:00
cee0d5b7b9
refactor: don't special case cursor rendering in inclusive mode
This is too confusing. Rendering cursors differently, only in inclusive
mode and only if there is an active selection is too confusing and pushes
a lot of edge cases into otherwise simple commands.

This will likely break a lot of the existing helix commands, but is better
in the long run to fix them anyway.
2025-11-26 23:11:11 +01:00

View file

@ -125,7 +125,7 @@ pub const CurSel = struct {
return if (self.selection) |*sel| sel else unreachable;
}
pub fn to_selection(self: *const Self, root: Buffer.Root, metrics: Buffer.Metrics) Selection {
fn to_selection(self: *const Self, root: Buffer.Root, metrics: Buffer.Metrics) Selection {
return switch (tui.get_selection_style()) {
.normal => self.to_selection_normal(),
.inclusive => self.to_selection_inclusive(root, metrics),
@ -146,13 +146,6 @@ pub const CurSel = struct {
};
}
fn to_cursor_inclusive(self: *const Self, root: Buffer.Root, metrics: Buffer.Metrics) Cursor {
var cursor = self.cursor;
if (self.selection) |sel| if (!sel.is_reversed())
cursor.move_left(root, metrics) catch {};
return cursor;
}
pub fn disable_selection(self: *Self, root: Buffer.Root, metrics: Buffer.Metrics) void {
switch (tui.get_selection_style()) {
.normal => self.disable_selection_normal(),
@ -1181,26 +1174,18 @@ pub const Editor = struct {
}
fn render_cursors(self: *Self, theme: *const Widget.Theme, cell_map: CellMap) !void {
const style = tui.get_selection_style();
const frame = tracy.initZone(@src(), .{ .name = "editor render cursors" });
defer frame.deinit();
if (tui.config().enable_terminal_cursor and tui.rdr().vx.caps.multi_cursor)
tui.rdr().clear_all_multi_cursors() catch {};
for (self.cursels.items[0 .. self.cursels.items.len - 1]) |*cursel_| if (cursel_.*) |*cursel| {
const cursor = self.get_rendered_cursor(style, cursel);
const cursor = cursel.cursor;
try self.render_cursor_secondary(&cursor, theme, cell_map);
};
const cursor = self.get_rendered_cursor(style, self.get_primary());
const cursor = self.get_primary().cursor;
try self.render_cursor_primary(&cursor, theme, cell_map);
}
fn get_rendered_cursor(self: *Self, style: anytype, cursel: anytype) Cursor {
return switch (style) {
.normal => cursel.cursor,
.inclusive => cursel.to_cursor_inclusive(self.buf_root() catch return cursel.cursor, self.metrics),
};
}
fn render_cursor_primary(self: *Self, cursor: *const Cursor, theme: *const Widget.Theme, cell_map: CellMap) !void {
if (!tui.is_mainview_focused() or !self.enable_terminal_cursor) {
if (self.screen_cursor(cursor)) |pos| {
@ -2132,6 +2117,21 @@ pub const Editor = struct {
return if (someone_stopped) error.Stop else {};
}
pub fn with_cursels_const_repeat(self: *Self, root: Buffer.Root, move: cursel_operator_const, ctx: Context) error{Stop}!void {
var someone_stopped = false;
var repeat: usize = 1;
_ = ctx.args.match(.{tp.extract(&repeat)}) catch false;
while (repeat > 0) : (repeat -= 1) {
for (self.cursels.items) |*cursel_| if (cursel_.*) |*cursel|
with_cursel_const(root, move, cursel, self.metrics) catch {
someone_stopped = true;
};
self.collapse_cursors();
if (someone_stopped) break;
}
return if (someone_stopped) error.Stop else {};
}
fn with_cursel_mut_arg(self: *Self, root: Buffer.Root, op: cursel_operator_mut_arg, cursel: *CurSel, allocator: Allocator, ctx: Context) error{Stop}!Buffer.Root {
return op(self, root, cursel, allocator, ctx);
}